session.rpc.ui.elicitation() returns instant decline (1-2ms) without showing modal after sendAndWait
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 45/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Tranquilo
- Stack tecnológico
- javascript, node.js
- Área
- api, developer-experience
Línea de trabajo
Comienza en el controlador del comando joinSession y sigue las rutas session.sendAndWait() y session.rpc.ui.elicitation(), incluido el fallback ask_user. Reproduce el rechazo instantáneo en Windows con el ejemplo mínimo e inspecciona los eventos de la sesión. Se considera terminado cuando la elicitation interactiva puede recopilar entradas después de sendAndWait, o la extensión recibe un resultado distinto y accionable de no disponible.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Environment
- Copilot CLI version: 1.0.36
- Extension SDK:
@github/copilot-sdk/extension(joinSessionAPI) - OS: Windows 11 (Windows_NT)
Summary
When a Copilot CLI extension calls session.rpc.ui.elicitation() from inside a command handler that previously called session.sendAndWait(), the elicitation resolves with { action: "decline" } in 1-2ms without ever presenting a modal to the user. The session reports capabilities.ui.elicitation = true and mode = interactive, yet the user never sees any prompt.
The extension's agent-mediated fallback (sending a prompt asking the model to call ask_user) also fails because the ask_user tool auto-declines with "The user is not available to respond" for turns injected by sendAndWait.
Net result: The extension cannot collect any human input after delegating work via sendAndWait, making interactive gates (review finding selection, publish attestation) impossible.
Steps to reproduce
- Load a Copilot CLI extension that registers a command via
joinSession({ commands: [...] }) - In the command handler, call
session.sendAndWait()to delegate to another command - After
sendAndWaitresolves, callsession.rpc.ui.elicitation()with a valid schema - Observe that it resolves instantly with
{ action: "decline" }--- no UI is shown
Minimal reproduction
import { joinSession } from "@github/copilot-sdk/extension";
const session = await joinSession({
commands: [
{
name: "test-elicit",
description: "Test elicitation after sendAndWait",
handler: async (context) => {
// Step 1: Delegate work to the model
await session.sendAndWait({ prompt: "Say hello" }, 60_000);
// Step 2: Try to elicit user input
const start = Date.now();
const result = await session.rpc.ui.elicitation({
message: "Pick an option",
requestedSchema: {
type: "object",
properties: {
choice: {
type: "string",
title: "Your choice",
enum: ["A", "B", "C"],
default: "A",
},
},
required: ["choice"],
},
});
const elapsed = Date.now() - start;
// Logs: "Elicitation returned decline in 1ms"
await session.log(
Elicitation returned {result.action} in {elapsed}ms
);
},
},
],
});
Observed behavior
Timeline from session events
T+0s session.info "interactive elicitation: available; session mode: unknown"
<- session.capabilities.ui.elicitation reports true
T+997s sendAndWait("/review ...") called, completes successfully
T+997s session.rpc.mode.set({ mode: "interactive" }) succeeds
<- mode is now "interactive"
T+997s session.rpc.ui.elicitation() called
<- returns { action: "decline" } in 1ms
<- NO MODAL IS SHOWN TO THE USER
T+997s Agent-mediated fallback: sendAndWait() with prompt asking model to call ask_user
<- model calls ask_user
<- ask_user returns: "The user is not available to respond"
<- model returns {"action":"decline"}
T+1024s Second elicitation attempt (text fallback)
<- session.rpc.ui.elicitation() returns decline in 2ms (again, no modal)
<- agent-mediated fallback also fails with "user not available"
Raw session event evidence
{
"type": "session.warning",
"data": {
"message": "Direct elicitation returned decline in 1ms (mode: interactive); treating as synthetic decline."
},
"timestamp": "2026-04-27T03:00:07.856Z"
}
{
"type": "tool.execution_complete",
"data": {
"toolTelemetry": {
"properties": {
"elicitation_action": "decline",
"elicitation_field_types": "[\"multi-enum\",\"string\"]"
}
},
"result": {
"content": "The user is not available to respond and will review your work later."
}
},
"timestamp": "2026-04-27T03:00:31.300Z"
}
Expected behavior
session.rpc.ui.elicitation() should present an interactive modal to the user and block until the user accepts, declines, or cancels. If the host cannot present a modal in the current execution context (e.g., inside a sendAndWait callback), it should either:
- Queue the elicitation and present it after the current turn completes, or
- Throw an error with a clear message like
"Elicitation not supported during sendAndWait callbacks", or - Return a distinct result (e.g.,
{ action: "unavailable" }) so extensions can distinguish "host can't show UI" from "user clicked decline"
Additionally, ask_user should work for model turns injected by extensions via sendAndWait. The user IS present --- they typed a command and are waiting. The sendAndWait turn is extension-initiated, but the session is still interactive.
Call context where elicitation fails
User types: /submit-pr
-> handleSubmitPr()
-> runPreflight() <- works
-> sendAndWait("/review ...") <- works (30min timeout)
-> recordAndLogReviewOutput() <- works
-> askForReviewDecisions() <- FAILS HERE
-> elicit(message, schema)
-> session.rpc.ui.elicitation() <- returns decline in 1ms
-> agentMediatedElicitation()
-> sendAndWait(prompt) <- model calls ask_user
-> ask_user <- "user not available"
Extension workaround code (currently failing)
async function elicit(message, requestedSchema) {
if (!session.capabilities?.ui?.elicitation) {
return agentMediatedElicitation(message, requestedSchema, "unavailable");
}
const mode = await ensureInteractiveMode(message);
if (mode === "autopilot") {
return agentMediatedElicitation(message, requestedSchema, "autopilot");
}
const elicitStart = Date.now();
const result = await session.rpc.ui.elicitation({ message, requestedSchema });
const elicitMs = Date.now() - elicitStart;
// Detect synthetic decline (returned too fast for human interaction)
const isSyntheticDecline =
result.action === "decline" &&
(["autopilot", "unknown"].includes(await refreshSessionMode())
|| elicitMs < 2000);
if (isSyntheticDecline) {
return agentMediatedElicitation(message, requestedSchema,
licitation-returned-in-{elicitMs}ms);
}
return result;
}
async function agentMediatedElicitation(message, requestedSchema, reason) {
// Asks the model to call ask_user on behalf of the extension
// FAILS: ask_user auto-declines for sendAndWait-injected turns
const response = await sendAndCaptureContent(
agentElicitationPrompt(message, requestedSchema, reason),
15 * 60 * 1000
);
// ...parse JSON response...
}
Both layers fail:
- Layer 1 fails because
session.rpc.ui.elicitation()returnsdeclinein 1ms - Layer 2 fails because
ask_userauto-declines for turns injected bysendAndWait
Impact
- Extensions cannot implement interactive multi-step workflows
session.capabilities.ui.elicitationcapability check is misleading --- reportstruebut doesn't work in practice- Extensions requiring human-in-the-loop gates (security attestation, publish confirmation) cannot enforce them
- The
sendAndWait->elicitpattern is the most natural way to build multi-step extension workflows, and it's completely broken
- Lenguaje dominante
- TypeScript
- Estrellas
- 10.5k
- Forks
- 1.5k
- Merge medio
- 1 d 6 h
- PR fusionados (30 d)
- 106
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de github/copilot-sdk
-
documentation
Dificultad 1/5 Menos de una hora Aptitud para principiantes 92/100
github/copilot-sdk#2804 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
github/copilot-sdk#2798 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
github/copilot-sdk#2793 ·
Los mantenedores suelen responder en 1 día
-
agentic-workflows
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
github/copilot-sdk#2782 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
github/copilot-sdk#2781 ·
Los mantenedores suelen responder en 1 día
Todos los issues de github/copilot-sdk
Issues similares
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
aiko-chan-ai/DiscordBotClient#380 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
vercel/ai-elements#507 ·
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
Los mantenedores suelen responder en 2 días
-
Dificultad 2/5 Medio día Aptitud para principiantes 84/100
anaclumos/qa-interns#148 · 1 comentario ·
Los mantenedores suelen responder en 1 día