Files
Agent-Native/runtime/mcp/ask.go
T
weichen fcd2539b9e
ci / vet-and-test (pull_request) Successful in 52s
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
Align the MCP client with 2026-07-28: resultType, input_required retry, tasks surface (N2 WP3)
Why: the completion doc requires the client to recognize resultType,
treat input_required as a protocol-level result whose answer retries the
original tools/call, and expose tasks/get|update|cancel; today only a
content-block special case existed and the advertised version was never
checked against the server's.
Evidence: GOWORK=off go vet + go test -count=1 ./... green;
TestInputRequiredResultTypeRetriesOriginalCall (ask → tasks/update →
retry, call order and final content), TestNegotiatedVersionFallbackKeepsLegacyPath
(byte-level legacy behavior on 2024-11-05), TestTasksGetAndCancelRoundTrip,
TestRunEndCancelsSeenTasks, TestDefaultSchemaDeclares202012; the
acceptance-③ regression TestStdioSlowCancelThenEcho passes unchanged.
Impact: advertise 2026-07-28 and branch on the negotiated version
(older servers keep byte-identical behavior); synthesized default tool
schemas now declare JSON Schema 2020-12; runs cancel the MCP tasks they
saw via a per-run TaskTracker (other runs on the shared manager are
unaffected).
Refs: Agent-System-Documents#42 (N2 plan WP3)
2026-10-07 13:38:51 +00:00

39 lines
1.1 KiB
Go

package mcp
import "context"
type askKey struct{}
// WithAsk 把当前回合的 AskUser 放进上下文。MCP 返回 input_required 时使用它。
func WithAsk(ctx context.Context, fn func(context.Context, string) (string, error)) context.Context {
return context.WithValue(ctx, askKey{}, fn)
}
func askFrom(ctx context.Context) func(context.Context, string) (string, error) {
if ctx == nil {
return nil
}
fn, _ := ctx.Value(askKey{}).(func(context.Context, string) (string, error))
return fn
}
// inputQuestion 提取需要用户输入的问题。两条路径:
// 2026-07-28 协议级 resultType="input_required"(问题取文本块);
// 旧版服务端的内容块 input_required(向后兼容)。
func inputQuestion(res callToolResult, negotiated string) (string, bool) {
if res.ResultType == "input_required" && SupportsResultType(negotiated) {
for _, blk := range res.Content {
if blk.Type == "text" && blk.Text != "" {
return blk.Text, true
}
}
return "", true
}
for _, blk := range res.Content {
if blk.Type == "input_required" {
return blk.Text, true
}
}
return "", false
}