Expose alternatives count on user messages
What does this MR do and why?
Allows the front end to request the new field alternativeCount which returns the count of alternative attempts at each user messages (The total number of user messages that share the same parent_thread_ts - 1 (the current)).
Limited to just user messages as currently you can only retry a user message. A benefit of limiting to user messages, is that often the same checkpoint (therefore thread_ts) can create multiple messages, for example:
Say 1 thread_ts: 1f18b420-2d24-6f99-8000-bd98b2b46daf parent_ts: 1f18b420-2d1f-6ba0-bfff-e5880762ca33
1 thread_ts: 1f18b420-43e9-63d1-8001-ddf0ad2a7186 parent_ts: 1f18b420-2d24-6f99-8000-bd98b2b46daf
Which page am I on? thread_ts: 1f18b420-8623-610c-8002-2f358ff2639d parent_ts: 1f18b420-43e9-63d1-8001-ddf0ad2a7186
You're on the **Work items** page for th… thread_ts: 1f18b420-8623-610c-8002-2f358ff2639d parent_ts: 1f18b420-43e9-63d1-8001-ddf0ad2a7186Where 1f18b420-8623-610c-8002-2f358ff2639d is the thread_ts of the user message and LLM response.
By removing the value from all but user messages, we simplify this issue.
The front end will then be able to use this information to request the alternative branches in the next MR !249143 (closed)
Query & query plan
Note: This is my second MR that includes a query plan, and the first was several months ago, if I have missed anything, please let me know.
SELECT DISTINCT
"p_duo_workflows_checkpoint_blobs"."thread_ts"
FROM
"p_duo_workflows_checkpoint_blobs"
WHERE
"p_duo_workflows_checkpoint_blobs"."workflow_id" = 51
AND "p_duo_workflows_checkpoint_blobs"."workflow_created_at" = '2026-08-11 14:03:50.314807'
AND "p_duo_workflows_checkpoint_blobs"."project_id" = 1000000
AND "p_duo_workflows_checkpoint_blobs"."channel" = 'ui_chat_log'I wasn't sure how to get the exact milisecond for the query, so in console.postgres.ai I altered it to use a range of 1 second.
https://console.postgres.ai/gitlab/projects/gitlab-production-main/sessions/54595/commands/157448
References
Full PoC: gitlab-org/modelops/applied-ml/code-suggestions/ai-assist!6124 (closed)
Epic: gitlab-org#21289
Python implementation for retries: gitlab-org/modelops/applied-ml/code-suggestions/ai-assist!6356 (merged)
Depends on: !249098 (merged)
Video demo: gitlab-org#21289 (comment 3666671057)
How to set up and validate locally
Query
{
duoWorkflowWorkflows(workflowId: "gid://gitlab/Ai::DuoWorkflows::Workflow/11") {
nodes { latestCheckpoint { duoMessages { content messageType threadTs parentTs alternativeCount } } }
}
}- Enable flags for incremental checkpoints:
Feature.enable(:duo_workflow_incremental_checkpoints)Feature.enable(:duo_workflow_read_incremental_checkpoints)Feature.enable(:dw_read_blobs_graphql)
- Checkout this branch
- From
gdk/gitlabrungit checkout feature/expose-message-alternatives-count
- From
- Restart
gdk restart
- Start a conversation "Say 1" => "1" => "Say 2" => "2"
- From http://gdk.test:8080/-/graphql-explorer (replace port) run the query above with the workflow ID (You can get the workflow ID from dev tools => Application => Session storage => http://gdk.test:8080 => key)
- You should get something similar to
GraphQL response
{
"data": {
"duoWorkflowWorkflows": {
"nodes": [
{
"latestCheckpoint": {
"duoMessages": [
{
"content": "Say 1",
"messageType": "user",
"threadTs": "1f194ad0-c695-6bd7-8000-428384bd2199",
"parentTs": "1f194ad0-c690-6352-bfff-e6d4d04bcd09",
"alternativeCount": 0
},
{
"content": "1",
"messageType": "agent",
"threadTs": "1f194ad0-d74e-65ee-8001-22b4e0499188",
"parentTs": "1f194ad0-c695-6bd7-8000-428384bd2199",
"alternativeCount": null
},
{
"content": "Say 2",
"messageType": "user",
"threadTs": "1f194ad1-7963-678e-8002-1a67a9ae1e0d",
"parentTs": "1f194ad0-d74e-65ee-8001-22b4e0499188",
"alternativeCount": 0
},
{
"content": "2",
"messageType": "agent",
"threadTs": "1f194ad1-7963-678e-8002-1a67a9ae1e0d",
"parentTs": "1f194ad0-d74e-65ee-8001-22b4e0499188",
"alternativeCount": null
}
]
}
}
]
}
},
"correlationId": "01KZNP909PEEVDCTV4X2ARYF2G"
}- Copy the
parentTsof "Say 2" intogitlab-ai-gateway/duo_workflow_service/server.pyreplacingresume_checkpoint_ts=start_workflow_request.startRequest.resume_checkpoint_tswithresume_checkpoint_ts="1f194ad0-d74e-65ee-8001-22b4e0499188" - Run
gdk restart duo-workflow-service - Send new messages "Say 3" and "Say 4"
- 3 will replace 2, and then 4 will replace 3
- Run the query again, and each time the
alternativeCountof the second user message will increase, and the message will be replaced with the newest message.
GraphQL response
{
"data": {
"duoWorkflowWorkflows": {
"nodes": [
{
"latestCheckpoint": {
"duoMessages": [
{
"content": "Say 1",
"messageType": "user",
"threadTs": "1f194ad0-c695-6bd7-8000-428384bd2199",
"parentTs": "1f194ad0-c690-6352-bfff-e6d4d04bcd09",
"alternativeCount": 0
},
{
"content": "1",
"messageType": "agent",
"threadTs": "1f194ad0-d74e-65ee-8001-22b4e0499188",
"parentTs": "1f194ad0-c695-6bd7-8000-428384bd2199",
"alternativeCount": null
},
{
"content": "Say 4",
"messageType": "user",
"threadTs": "1f194ad6-5199-68da-8002-73f7b0955386",
"parentTs": "1f194ad0-d74e-65ee-8001-22b4e0499188",
"alternativeCount": 2
},
{
"content": "4",
"messageType": "agent",
"threadTs": "1f194ad6-5e65-6649-8003-f61a0c372488",
"parentTs": "1f194ad6-5199-68da-8002-73f7b0955386",
"alternativeCount": null
}
]
}
}
]
}
},
"correlationId": "01KZNPCYZJDTV0VH2RW417Y1NH"
}MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.