61 lines
2.3 KiB
Go
61 lines
2.3 KiB
Go
package app
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/json"
|
||
"errors"
|
||
"io"
|
||
"strings"
|
||
)
|
||
|
||
var errCloudAgentJSONSingleObject = errors.New("参数必须是单个 JSON 对象")
|
||
|
||
// Only syntax/schema errors may be repaired by the model; authorization and
|
||
// unsupported mutations still fail admission before any write or approval.
|
||
type cloudAgentArgumentError struct{ error }
|
||
|
||
func (e *cloudAgentArgumentError) Unwrap() error { return e.error }
|
||
|
||
func canvasArgumentError() error {
|
||
return &cloudAgentArgumentError{BadAuthRequest("画布工具参数无效:仅允许一个 JSON 对象;顶层只含 snapshotHash 和 ops,snapshotHash 不得放入 ops。请按工具 schema 修正后重试")}
|
||
}
|
||
|
||
// Report the failure category without echoing model-controlled keys or values.
|
||
// The runtime attaches the advertised schema so the model can correct its call.
|
||
func cloudAgentJSONArgumentError(err error) error {
|
||
message := "工具参数 JSON 格式无效,请按参数规范修正后重试"
|
||
var typeErr *json.UnmarshalTypeError
|
||
switch {
|
||
case errors.Is(err, errCloudAgentJSONSingleObject):
|
||
message = "工具参数必须是单个 JSON 对象,不能是字符串、数组、null 或多个对象;无参数时传 {}"
|
||
case errors.As(err, &typeErr):
|
||
message = "工具参数字段类型不匹配,请按参数规范使用整数、字符串或数组,不要把数字或数组写成字符串"
|
||
case strings.HasPrefix(err.Error(), "json: unknown field "):
|
||
message = "工具参数含有不支持的字段,请移除参数规范以外的字段后重试"
|
||
}
|
||
return &cloudAgentArgumentError{BadAuthRequest(message)}
|
||
}
|
||
|
||
// decodeCloudAgentJSONObject is used for model tool arguments. Tool arguments
|
||
// are an untrusted protocol boundary: reject non-objects, unknown fields and
|
||
// trailing JSON instead of silently accepting an ambiguous payload.
|
||
func decodeCloudAgentJSONObject(raw string, target any) error {
|
||
data := bytes.TrimSpace([]byte(raw))
|
||
if len(data) == 0 || data[0] != '{' {
|
||
return errCloudAgentJSONSingleObject
|
||
}
|
||
decoder := json.NewDecoder(bytes.NewReader(data))
|
||
decoder.DisallowUnknownFields()
|
||
if err := decoder.Decode(target); err != nil {
|
||
return err
|
||
}
|
||
var extra any
|
||
if err := decoder.Decode(&extra); err != io.EOF {
|
||
if err == nil {
|
||
return errCloudAgentJSONSingleObject
|
||
}
|
||
return err
|
||
}
|
||
return nil
|
||
}
|