11local state = require (' opencode.state' )
22local icons = require (' opencode.ui.icons' )
33local Dialog = require (' opencode.ui.dialog' )
4+ local Promise = require (' opencode.promise' )
45
56local config = require (' opencode.config' )
67
@@ -51,6 +52,92 @@ function M.belongs_to_active_session(question_request)
5152 return false
5253end
5354
55+ --- @param question_request OpencodeQuestionRequest | nil
56+ --- @return boolean
57+ local function has_tool_identifiers (question_request )
58+ local tool = question_request and question_request .tool
59+ return tool ~= nil and ((tool .callID and tool .callID ~= ' ' ) or (tool .messageID and tool .messageID ~= ' ' ))
60+ end
61+
62+ --- @param part OpencodeMessagePart | nil
63+ --- @param question_request OpencodeQuestionRequest | nil
64+ --- @return boolean
65+ local function question_part_matches_request (part , question_request )
66+ if not part or part .tool ~= ' question' or not question_request then
67+ return false
68+ end
69+
70+ local tool = question_request .tool
71+ if not tool then
72+ return false
73+ end
74+
75+ if tool .callID and tool .callID ~= ' ' and part .callID ~= tool .callID then
76+ return false
77+ end
78+
79+ if tool .messageID and tool .messageID ~= ' ' and part .messageID ~= tool .messageID then
80+ return false
81+ end
82+
83+ return true
84+ end
85+
86+ --- @param parts OpencodeMessagePart[] | nil
87+ --- @param question_request OpencodeQuestionRequest | nil
88+ --- @return OpencodeMessagePart | nil
89+ local function find_matching_question_part (parts , question_request )
90+ for _ , part in ipairs (parts or {}) do
91+ if question_part_matches_request (part , question_request ) then
92+ return part
93+ end
94+ end
95+ end
96+
97+ --- @param question_request OpencodeQuestionRequest | nil
98+ --- @return OpencodeMessagePart | nil
99+ local function get_question_part (question_request )
100+ if not has_tool_identifiers (question_request ) then
101+ return nil
102+ end
103+
104+ local tool = question_request .tool
105+ local tool_message_id = tool and tool .messageID
106+
107+ if tool_message_id and state .messages then
108+ for _ , message in ipairs (state .messages ) do
109+ if message .info and message .info .id == tool_message_id then
110+ local part = find_matching_question_part (message .parts , question_request )
111+ if part then
112+ return part
113+ end
114+ end
115+ end
116+ end
117+
118+ if question_request and question_request .sessionID and question_request .sessionID ~= ' ' then
119+ local render_state = require (' opencode.ui.renderer.ctx' ).render_state
120+ return find_matching_question_part (render_state :get_child_session_parts (question_request .sessionID ), question_request )
121+ end
122+ end
123+
124+ --- @param question_request OpencodeQuestionRequest | nil
125+ --- @return boolean
126+ local function is_resolved_question_request (question_request )
127+ local part = get_question_part (question_request )
128+ if not part or not part .state then
129+ return false
130+ end
131+
132+ local metadata = part .state .metadata
133+ if metadata and metadata .answers and # metadata .answers > 0 then
134+ return true
135+ end
136+
137+ local status = part .state .status
138+ return status ~= nil and status ~= ' ' and status ~= ' pending' and status ~= ' running'
139+ end
140+
54141--- Request the renderer to show the current question display.
55142local function render_question ()
56143 require (' opencode.ui.renderer.events' ).render_question_display ()
@@ -67,6 +154,10 @@ function M.show_question(question_request)
67154 return
68155 end
69156
157+ if is_resolved_question_request (question_request ) then
158+ return
159+ end
160+
70161 M ._current_question = question_request
71162 M ._current_question_index = 1
72163 M ._collected_answers = {}
82173--- @param session_id string | nil
83174function M .restore_pending_question (session_id )
84175 if not state .api_client or not session_id or session_id == ' ' then
85- return
176+ return Promise . new (): resolve ( nil )
86177 end
87178
88179 if M .has_question () and M .belongs_to_active_session (M ._current_question ) then
89- return
180+ if not is_resolved_question_request (M ._current_question ) then
181+ return Promise .new ():resolve (nil )
182+ end
183+
184+ M .clear_question ()
90185 end
91186
92- state .api_client :list_questions ()
187+ return state .api_client :list_questions ()
93188 :and_then (function (requests )
94189 if not requests or type (requests ) ~= ' table' then
95190 return
96191 end
97192
98193 for _ , request in ipairs (requests ) do
99- if request and request .questions and # request .questions > 0 and M .belongs_to_active_session (request ) then
194+ if request
195+ and request .questions
196+ and # request .questions > 0
197+ and M .belongs_to_active_session (request )
198+ and not is_resolved_question_request (request )
199+ then
100200 if M .matches_active_question (request ) then
101201 return
102202 end
0 commit comments