Why: system.intent ParamsSchema requires top-level text, but SubmitAction only nested values under data, so button intent always rejected missing text during prod acceptance. Evidence: go test ./internal/surfacesvc/ -run TestSubmitActionFlattensDataIntoParams Impact: B-class intent and other schema-required params work via actions; submit still receives nested data. Refs: GenUI prod deploy acceptance; fix track Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -99,6 +99,29 @@ func TestSubmitActionBClassHelpDispatches(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubmitActionFlattensDataIntoParams(t *testing.T) {
|
||||
f := newActionFixture(t)
|
||||
ctx := context.Background()
|
||||
var params map[string]any
|
||||
f.svc.SetDispatcher(func(ctx context.Context, d ActionDispatch) (ActionOutcome, error) {
|
||||
params = d.Params
|
||||
return ActionOutcome{State: "committed", Payload: map[string]any{"matched": false}}, nil
|
||||
})
|
||||
res, err := f.svc.SubmitAction(ctx, "alice", SubmitActionRequest{SurfaceID: f.surface.SurfaceID,
|
||||
ActionID: "system.intent", Revision: f.rev, RequestID: "intent-1",
|
||||
Data: map[string]any{"text": "请新建会话"}})
|
||||
if err != nil || res.State != "committed" {
|
||||
t.Fatalf("intent action: res=%+v err=%v", res, err)
|
||||
}
|
||||
if params["text"] != "请新建会话" {
|
||||
t.Fatalf("data.text must flatten to top-level params for ParamsSchema: %+v", params)
|
||||
}
|
||||
data, _ := params["data"].(map[string]any)
|
||||
if data["text"] != "请新建会话" {
|
||||
t.Fatalf("nested data must remain for submit-shaped consumers: %+v", params)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubmitActionGuards(t *testing.T) {
|
||||
f := newActionFixture(t)
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -312,10 +312,20 @@ func (s *Service) SubmitAction(ctx context.Context, owner string, req SubmitActi
|
||||
Note: "幂等重放:返回已有回执",
|
||||
}, nil
|
||||
}
|
||||
// 参数形态:保留 data 供 generative-ui.submit;同时把 data 键上浮到顶层,
|
||||
// 以便 system.intent 等命令的 ParamsSchema(required: text)能直接校验。
|
||||
params := map[string]any{
|
||||
"surfaceId": string(req.SurfaceID), "revision": req.Revision,
|
||||
"requestId": req.RequestID, "data": req.Data,
|
||||
}
|
||||
for k, v := range req.Data {
|
||||
if k == "surfaceId" || k == "revision" || k == "requestId" || k == "data" {
|
||||
continue
|
||||
}
|
||||
params[k] = v
|
||||
}
|
||||
out, err := s.dispatch(ctx, ActionDispatch{
|
||||
CommandID: cmd, Owner: owner, ConversationID: rec.ConversationID,
|
||||
Params: map[string]any{"surfaceId": string(req.SurfaceID), "revision": req.Revision,
|
||||
"requestId": req.RequestID, "data": req.Data},
|
||||
CommandID: cmd, Owner: owner, ConversationID: rec.ConversationID, Params: params,
|
||||
})
|
||||
state, cardID := out.State, out.CardID
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user