@@ -18,9 +18,15 @@ const emitInterleavedAssistantToolCalls =
1818 process . env . T3_ACP_EMIT_INTERLEAVED_ASSISTANT_TOOL_CALLS === "1" ;
1919const emitGenericToolPlaceholders = process . env . T3_ACP_EMIT_GENERIC_TOOL_PLACEHOLDERS === "1" ;
2020const emitAskQuestion = process . env . T3_ACP_EMIT_ASK_QUESTION === "1" ;
21+ const emitXAiAskUserQuestion = process . env . T3_ACP_EMIT_XAI_ASK_USER_QUESTION === "1" ;
2122const failSetConfigOption = process . env . T3_ACP_FAIL_SET_CONFIG_OPTION === "1" ;
2223const exitOnSetConfigOption = process . env . T3_ACP_EXIT_ON_SET_CONFIG_OPTION === "1" ;
2324const promptResponseText = process . env . T3_ACP_PROMPT_RESPONSE_TEXT ;
25+ const permissionOptionIds = {
26+ allowOnce : process . env . T3_ACP_ALLOW_ONCE_OPTION_ID ?? "allow-once" ,
27+ allowAlways : process . env . T3_ACP_ALLOW_ALWAYS_OPTION_ID ?? "allow-always" ,
28+ rejectOnce : process . env . T3_ACP_REJECT_ONCE_OPTION_ID ?? "reject-once" ,
29+ } ;
2430const sessionId = "mock-session-1" ;
2531
2632let currentModeId = "ask" ;
@@ -237,6 +243,21 @@ function modeState(): AcpSchema.SessionModeState {
237243 } ;
238244}
239245
246+ const grokAcpModels : ReadonlyArray < AcpSchema . ModelInfo > = [
247+ { modelId : "grok-build" , name : "Grok Build" } ,
248+ { modelId : "grok-mock-alt" , name : "Grok Mock Alt" } ,
249+ ] ;
250+
251+ function modelState ( ) : AcpSchema . SessionModelState {
252+ const modelId = grokAcpModels . some ( ( model ) => model . modelId === currentModelId )
253+ ? currentModelId
254+ : "grok-build" ;
255+ return {
256+ currentModelId : modelId ,
257+ availableModels : grokAcpModels ,
258+ } ;
259+ }
260+
240261const program = Effect . gen ( function * ( ) {
241262 const agent = yield * EffectAcpAgent . AcpAgent ;
242263
@@ -257,6 +278,7 @@ const program = Effect.gen(function* () {
257278 Effect . succeed ( {
258279 sessionId,
259280 modes : modeState ( ) ,
281+ models : modelState ( ) ,
260282 configOptions : configOptions ( ) ,
261283 } ) ,
262284 ) ;
@@ -273,11 +295,28 @@ const program = Effect.gen(function* () {
273295 . pipe (
274296 Effect . as ( {
275297 modes : modeState ( ) ,
298+ models : modelState ( ) ,
276299 configOptions : configOptions ( ) ,
277300 } ) ,
278301 ) ,
279302 ) ;
280303
304+ yield * agent . handleSetSessionModel ( ( request ) =>
305+ Effect . gen ( function * ( ) {
306+ if ( ! grokAcpModels . some ( ( model ) => model . modelId === request . modelId ) ) {
307+ return yield * AcpError . AcpRequestError . invalidParams (
308+ `Unknown mock model id: ${ request . modelId } ` ,
309+ {
310+ method : "session/set_model" ,
311+ params : request ,
312+ } ,
313+ ) ;
314+ }
315+ currentModelId = request . modelId ;
316+ return { } ;
317+ } ) ,
318+ ) ;
319+
281320 yield * agent . handleSetSessionConfigOption ( ( request ) =>
282321 Effect . gen ( function * ( ) {
283322 if ( exitOnSetConfigOption ) {
@@ -419,9 +458,13 @@ const program = Effect.gen(function* () {
419458 ] ,
420459 } ,
421460 options : [
422- { optionId : "allow-once" , name : "Allow once" , kind : "allow_once" } ,
423- { optionId : "allow-always" , name : "Allow always" , kind : "allow_always" } ,
424- { optionId : "reject-once" , name : "Reject" , kind : "reject_once" } ,
461+ { optionId : permissionOptionIds . allowOnce , name : "Allow once" , kind : "allow_once" } ,
462+ {
463+ optionId : permissionOptionIds . allowAlways ,
464+ name : "Allow always" ,
465+ kind : "allow_always" ,
466+ } ,
467+ { optionId : permissionOptionIds . rejectOnce , name : "Reject" , kind : "reject_once" } ,
425468 ] ,
426469 } ) ;
427470
@@ -514,6 +557,43 @@ const program = Effect.gen(function* () {
514557 return { stopReason : "end_turn" } ;
515558 }
516559
560+ if ( emitXAiAskUserQuestion ) {
561+ const result = yield * agent . client . extRequest ( "_x.ai/ask_user_question" , {
562+ method : "x.ai/ask_user_question" ,
563+ params : {
564+ sessionId : requestedSessionId ,
565+ toolCallId : "ask-user-question-tool-call-1" ,
566+ questions : [
567+ {
568+ question : "Which scope should Grok use?" ,
569+ multiSelect : null ,
570+ options : [
571+ { label : "Workspace" , description : "Use the current workspace" } ,
572+ { label : "Session" , description : "Only use this session" } ,
573+ ] ,
574+ } ,
575+ ] ,
576+ mode : "default" ,
577+ } ,
578+ } ) ;
579+ if ( typeof result !== "object" || result === null || ! ( "outcome" in result ) ) {
580+ throw new Error ( "Expected _x.ai/ask_user_question response outcome." ) ;
581+ }
582+ if ( result . outcome === "cancelled" ) {
583+ return { stopReason : "end_turn" } ;
584+ }
585+ if (
586+ result . outcome !== "accepted" ||
587+ ! ( "answers" in result ) ||
588+ typeof result . answers !== "object" ||
589+ result . answers === null
590+ ) {
591+ throw new Error ( "Expected accepted _x.ai/ask_user_question response answers." ) ;
592+ }
593+
594+ return { stopReason : "end_turn" } ;
595+ }
596+
517597 yield * agent . client . sessionUpdate ( {
518598 sessionId : requestedSessionId ,
519599 update : {
0 commit comments