all the refactor
This commit is contained in:
+71
-210
@@ -4,108 +4,34 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"git.k6n.net/mats/go-cart-actor/pkg/order"
|
||||
messages "git.k6n.net/mats/go-cart-actor/proto/order"
|
||||
pmcp "git.k6n.net/mats/platform/mcp"
|
||||
)
|
||||
|
||||
// tool is one MCP tool: a name, a description, a JSON-Schema for its arguments,
|
||||
// and the handler that runs it.
|
||||
type tool struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
InputSchema json.RawMessage `json:"inputSchema"`
|
||||
invoke func(args json.RawMessage) (any, error) `json:"-"`
|
||||
}
|
||||
|
||||
func (s *Server) callTool(req *rpcRequest) *rpcResponse {
|
||||
var p struct {
|
||||
Name string `json:"name"`
|
||||
Arguments json.RawMessage `json:"arguments"`
|
||||
}
|
||||
if err := json.Unmarshal(req.Params, &p); err != nil {
|
||||
return errorResponse(req.ID, codeInvalidParams, "invalid params")
|
||||
}
|
||||
|
||||
// Extract UCP meta from arguments (UCP-Agent profile advertisement).
|
||||
// Per the UCP spec, meta is a sibling key inside arguments:
|
||||
// "arguments": { "meta": { "ucp-agent": { "profile": "..." } }, ... }
|
||||
args := extractUCPAgentMeta(&p.Arguments)
|
||||
|
||||
var t *tool
|
||||
for i := range s.tools {
|
||||
if s.tools[i].Name == p.Name {
|
||||
t = &s.tools[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if t == nil {
|
||||
return errorResponse(req.ID, codeInvalidParams, "unknown tool: "+p.Name)
|
||||
}
|
||||
out, err := t.invoke(args)
|
||||
if err != nil {
|
||||
return result(req.ID, toolError(err))
|
||||
}
|
||||
return result(req.ID, toolText(out))
|
||||
}
|
||||
|
||||
// extractUCPAgentMeta checks if the JSON arguments contain a "meta" key with
|
||||
// a nested "ucp-agent.profile" field. If found, it logs the profile (for
|
||||
// observability) and strips the "meta" key before returning the cleaned
|
||||
// arguments to the tool handler, so the meta object does not leak into the
|
||||
// tool's argument namespace.
|
||||
func extractUCPAgentMeta(arguments *json.RawMessage) json.RawMessage {
|
||||
if arguments == nil || len(*arguments) == 0 {
|
||||
return *arguments
|
||||
}
|
||||
var obj map[string]json.RawMessage
|
||||
if err := json.Unmarshal(*arguments, &obj); err != nil {
|
||||
return *arguments
|
||||
}
|
||||
metaRaw, hasMeta := obj["meta"]
|
||||
if !hasMeta {
|
||||
return *arguments
|
||||
}
|
||||
// Try to extract the profile for observability.
|
||||
var meta struct {
|
||||
UCPAgent *struct {
|
||||
Profile string `json:"profile"`
|
||||
} `json:"ucp-agent"`
|
||||
}
|
||||
if err := json.Unmarshal(metaRaw, &meta); err == nil && meta.UCPAgent != nil && meta.UCPAgent.Profile != "" {
|
||||
log.Printf("ucp-agent: profile=%s", meta.UCPAgent.Profile)
|
||||
}
|
||||
// Strip meta from arguments before passing to the tool handler.
|
||||
delete(obj, "meta")
|
||||
cleaned, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return *arguments
|
||||
}
|
||||
return cleaned
|
||||
}
|
||||
|
||||
func (s *Server) buildTools() []tool {
|
||||
return []tool{
|
||||
// buildTools returns the order's MCP tools (transport/dispatch live in platform/mcp).
|
||||
func (s *Server) buildTools() []pmcp.Tool {
|
||||
return []pmcp.Tool{
|
||||
{
|
||||
Name: "get_order",
|
||||
Description: "Get the full detail of an order by its base62 order id: status, line items, payments, fulfillments, returns, refunds, customer info, billing/shipping addresses, and amounts.",
|
||||
InputSchema: object(props{
|
||||
"orderId": str("the base62 order id"),
|
||||
InputSchema: pmcp.Object(pmcp.Props{
|
||||
"orderId": pmcp.String("the base62 order id"),
|
||||
}, []string{"orderId"}),
|
||||
invoke: func(args json.RawMessage) (any, error) {
|
||||
Invoke: func(ctx context.Context, args json.RawMessage) (any, error) {
|
||||
var a struct {
|
||||
OrderID string `json:"orderId"`
|
||||
}
|
||||
if err := decode(args, &a); err != nil {
|
||||
if err := pmcp.Decode(args, &a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, ok := order.ParseOrderId(a.OrderID)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid order id %q", a.OrderID)
|
||||
}
|
||||
g, err := s.applier.Get(context.Background(), uint64(id))
|
||||
g, err := s.applier.Get(ctx, uint64(id))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get order: %w", err)
|
||||
}
|
||||
@@ -118,21 +44,21 @@ func (s *Server) buildTools() []tool {
|
||||
{
|
||||
Name: "get_order_status",
|
||||
Description: "Get the current status (new|pending|authorized|captured|partially_fulfilled|fulfilled|completed|cancelled|refunded) of an order and the legal next transitions.",
|
||||
InputSchema: object(props{
|
||||
"orderId": str("the base62 order id"),
|
||||
InputSchema: pmcp.Object(pmcp.Props{
|
||||
"orderId": pmcp.String("the base62 order id"),
|
||||
}, []string{"orderId"}),
|
||||
invoke: func(args json.RawMessage) (any, error) {
|
||||
Invoke: func(ctx context.Context, args json.RawMessage) (any, error) {
|
||||
var a struct {
|
||||
OrderID string `json:"orderId"`
|
||||
}
|
||||
if err := decode(args, &a); err != nil {
|
||||
if err := pmcp.Decode(args, &a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, ok := order.ParseOrderId(a.OrderID)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid order id %q", a.OrderID)
|
||||
}
|
||||
g, err := s.applier.Get(context.Background(), uint64(id))
|
||||
g, err := s.applier.Get(ctx, uint64(id))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get order: %w", err)
|
||||
}
|
||||
@@ -140,8 +66,8 @@ func (s *Server) buildTools() []tool {
|
||||
return nil, fmt.Errorf("order %q not found", a.OrderID)
|
||||
}
|
||||
return map[string]any{
|
||||
"orderId": a.OrderID,
|
||||
"status": string(g.Status),
|
||||
"orderId": a.OrderID,
|
||||
"status": string(g.Status),
|
||||
"nextTransitions": validTransitions(g.Status),
|
||||
}, nil
|
||||
},
|
||||
@@ -149,21 +75,21 @@ func (s *Server) buildTools() []tool {
|
||||
{
|
||||
Name: "get_order_lines",
|
||||
Description: "List all line items on an order with reference, SKU, name, quantity, unit price, tax rate, total amount, total tax, and fulfilled quantity.",
|
||||
InputSchema: object(props{
|
||||
"orderId": str("the base62 order id"),
|
||||
InputSchema: pmcp.Object(pmcp.Props{
|
||||
"orderId": pmcp.String("the base62 order id"),
|
||||
}, []string{"orderId"}),
|
||||
invoke: func(args json.RawMessage) (any, error) {
|
||||
Invoke: func(ctx context.Context, args json.RawMessage) (any, error) {
|
||||
var a struct {
|
||||
OrderID string `json:"orderId"`
|
||||
}
|
||||
if err := decode(args, &a); err != nil {
|
||||
if err := pmcp.Decode(args, &a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, ok := order.ParseOrderId(a.OrderID)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid order id %q", a.OrderID)
|
||||
}
|
||||
g, err := s.applier.Get(context.Background(), uint64(id))
|
||||
g, err := s.applier.Get(ctx, uint64(id))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get order: %w", err)
|
||||
}
|
||||
@@ -176,21 +102,21 @@ func (s *Server) buildTools() []tool {
|
||||
{
|
||||
Name: "get_order_payments",
|
||||
Description: "List all payment records on an order: provider, authorized/captured/refunded amounts, authorization and capture references.",
|
||||
InputSchema: object(props{
|
||||
"orderId": str("the base62 order id"),
|
||||
InputSchema: pmcp.Object(pmcp.Props{
|
||||
"orderId": pmcp.String("the base62 order id"),
|
||||
}, []string{"orderId"}),
|
||||
invoke: func(args json.RawMessage) (any, error) {
|
||||
Invoke: func(ctx context.Context, args json.RawMessage) (any, error) {
|
||||
var a struct {
|
||||
OrderID string `json:"orderId"`
|
||||
}
|
||||
if err := decode(args, &a); err != nil {
|
||||
if err := pmcp.Decode(args, &a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, ok := order.ParseOrderId(a.OrderID)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid order id %q", a.OrderID)
|
||||
}
|
||||
g, err := s.applier.Get(context.Background(), uint64(id))
|
||||
g, err := s.applier.Get(ctx, uint64(id))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get order: %w", err)
|
||||
}
|
||||
@@ -203,21 +129,21 @@ func (s *Server) buildTools() []tool {
|
||||
{
|
||||
Name: "get_order_fulfillments",
|
||||
Description: "List all fulfillments (shipments) on an order: carrier, tracking number/URI, shipped lines with quantities, and creation date.",
|
||||
InputSchema: object(props{
|
||||
"orderId": str("the base62 order id"),
|
||||
InputSchema: pmcp.Object(pmcp.Props{
|
||||
"orderId": pmcp.String("the base62 order id"),
|
||||
}, []string{"orderId"}),
|
||||
invoke: func(args json.RawMessage) (any, error) {
|
||||
Invoke: func(ctx context.Context, args json.RawMessage) (any, error) {
|
||||
var a struct {
|
||||
OrderID string `json:"orderId"`
|
||||
}
|
||||
if err := decode(args, &a); err != nil {
|
||||
if err := pmcp.Decode(args, &a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, ok := order.ParseOrderId(a.OrderID)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid order id %q", a.OrderID)
|
||||
}
|
||||
g, err := s.applier.Get(context.Background(), uint64(id))
|
||||
g, err := s.applier.Get(ctx, uint64(id))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get order: %w", err)
|
||||
}
|
||||
@@ -230,21 +156,21 @@ func (s *Server) buildTools() []tool {
|
||||
{
|
||||
Name: "get_order_returns",
|
||||
Description: "List all return requests (RMAs) on an order: reason, returned lines, and request date.",
|
||||
InputSchema: object(props{
|
||||
"orderId": str("the base62 order id"),
|
||||
InputSchema: pmcp.Object(pmcp.Props{
|
||||
"orderId": pmcp.String("the base62 order id"),
|
||||
}, []string{"orderId"}),
|
||||
invoke: func(args json.RawMessage) (any, error) {
|
||||
Invoke: func(ctx context.Context, args json.RawMessage) (any, error) {
|
||||
var a struct {
|
||||
OrderID string `json:"orderId"`
|
||||
}
|
||||
if err := decode(args, &a); err != nil {
|
||||
if err := pmcp.Decode(args, &a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, ok := order.ParseOrderId(a.OrderID)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid order id %q", a.OrderID)
|
||||
}
|
||||
g, err := s.applier.Get(context.Background(), uint64(id))
|
||||
g, err := s.applier.Get(ctx, uint64(id))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get order: %w", err)
|
||||
}
|
||||
@@ -257,23 +183,23 @@ func (s *Server) buildTools() []tool {
|
||||
{
|
||||
Name: "cancel_order",
|
||||
Description: "Cancel an order that is still in a cancellable state (pending or authorized) with an optional reason. Returns the updated order.",
|
||||
InputSchema: object(props{
|
||||
"orderId": str("the base62 order id"),
|
||||
"reason": str("optional reason for cancellation"),
|
||||
InputSchema: pmcp.Object(pmcp.Props{
|
||||
"orderId": pmcp.String("the base62 order id"),
|
||||
"reason": pmcp.String("optional reason for cancellation"),
|
||||
}, []string{"orderId"}),
|
||||
invoke: func(args json.RawMessage) (any, error) {
|
||||
Invoke: func(ctx context.Context, args json.RawMessage) (any, error) {
|
||||
var a struct {
|
||||
OrderID string `json:"orderId"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
if err := decode(args, &a); err != nil {
|
||||
if err := pmcp.Decode(args, &a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, ok := order.ParseOrderId(a.OrderID)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid order id %q", a.OrderID)
|
||||
}
|
||||
res, err := s.applier.Apply(context.Background(), uint64(id), &messages.CancelOrder{
|
||||
res, err := s.applier.Apply(ctx, uint64(id), &messages.CancelOrder{
|
||||
Reason: a.Reason,
|
||||
AtMs: time.Now().UnixMilli(),
|
||||
})
|
||||
@@ -291,14 +217,14 @@ func (s *Server) buildTools() []tool {
|
||||
{
|
||||
Name: "create_fulfillment",
|
||||
Description: "Ship lines on a captured order. Provide carrier and optionally tracking info. Each line entry requires a reference (the line reference) and quantity to ship. Returns the updated order.",
|
||||
InputSchema: object(props{
|
||||
"orderId": str("the base62 order id"),
|
||||
"carrier": str("the shipping carrier name (e.g. PostNord, DHL)"),
|
||||
"trackingNumber": str("optional tracking number"),
|
||||
"trackingUri": str("optional tracking URL"),
|
||||
"lines": objArray("lines to fulfill, each with reference (string) and quantity (integer)"),
|
||||
InputSchema: pmcp.Object(pmcp.Props{
|
||||
"orderId": pmcp.String("the base62 order id"),
|
||||
"carrier": pmcp.String("the shipping carrier name (e.g. PostNord, DHL)"),
|
||||
"trackingNumber": pmcp.String("optional tracking number"),
|
||||
"trackingUri": pmcp.String("optional tracking URL"),
|
||||
"lines": pmcp.ObjectArray("lines to fulfill, each with reference (string) and quantity (integer)"),
|
||||
}, []string{"orderId", "lines"}),
|
||||
invoke: func(args json.RawMessage) (any, error) {
|
||||
Invoke: func(ctx context.Context, args json.RawMessage) (any, error) {
|
||||
var a struct {
|
||||
OrderID string `json:"orderId"`
|
||||
Carrier string `json:"carrier"`
|
||||
@@ -309,7 +235,7 @@ func (s *Server) buildTools() []tool {
|
||||
Quantity int32 `json:"quantity"`
|
||||
} `json:"lines"`
|
||||
}
|
||||
if err := decode(args, &a); err != nil {
|
||||
if err := pmcp.Decode(args, &a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, ok := order.ParseOrderId(a.OrderID)
|
||||
@@ -321,7 +247,7 @@ func (s *Server) buildTools() []tool {
|
||||
for i, l := range a.Lines {
|
||||
fulfillmentLines[i] = &messages.FulfillmentLine{Reference: l.Reference, Quantity: l.Quantity}
|
||||
}
|
||||
res, err := s.applier.Apply(context.Background(), uint64(id), &messages.CreateFulfillment{
|
||||
res, err := s.applier.Apply(ctx, uint64(id), &messages.CreateFulfillment{
|
||||
Id: "f_" + fid.String(),
|
||||
Carrier: a.Carrier,
|
||||
TrackingNumber: a.TrackingNumber,
|
||||
@@ -343,21 +269,21 @@ func (s *Server) buildTools() []tool {
|
||||
{
|
||||
Name: "complete_order",
|
||||
Description: "Mark a fulfilled order as completed. Only allowed when the order is in 'fulfilled' status. Returns the updated order.",
|
||||
InputSchema: object(props{
|
||||
"orderId": str("the base62 order id"),
|
||||
InputSchema: pmcp.Object(pmcp.Props{
|
||||
"orderId": pmcp.String("the base62 order id"),
|
||||
}, []string{"orderId"}),
|
||||
invoke: func(args json.RawMessage) (any, error) {
|
||||
Invoke: func(ctx context.Context, args json.RawMessage) (any, error) {
|
||||
var a struct {
|
||||
OrderID string `json:"orderId"`
|
||||
}
|
||||
if err := decode(args, &a); err != nil {
|
||||
if err := pmcp.Decode(args, &a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, ok := order.ParseOrderId(a.OrderID)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid order id %q", a.OrderID)
|
||||
}
|
||||
res, err := s.applier.Apply(context.Background(), uint64(id), &messages.CompleteOrder{
|
||||
res, err := s.applier.Apply(ctx, uint64(id), &messages.CompleteOrder{
|
||||
AtMs: time.Now().UnixMilli(),
|
||||
})
|
||||
if err != nil {
|
||||
@@ -374,12 +300,12 @@ func (s *Server) buildTools() []tool {
|
||||
{
|
||||
Name: "request_return",
|
||||
Description: "Open a return request (RMA) against fulfilled lines on an order. Provide the lines being returned and a reason. Returns the updated order with the return recorded.",
|
||||
InputSchema: object(props{
|
||||
"orderId": str("the base62 order id"),
|
||||
"reason": str("the reason for the return"),
|
||||
"lines": objArray("lines being returned, each with reference (string) and quantity (integer)"),
|
||||
InputSchema: pmcp.Object(pmcp.Props{
|
||||
"orderId": pmcp.String("the base62 order id"),
|
||||
"reason": pmcp.String("the reason for the return"),
|
||||
"lines": pmcp.ObjectArray("lines being returned, each with reference (string) and quantity (integer)"),
|
||||
}, []string{"orderId", "reason", "lines"}),
|
||||
invoke: func(args json.RawMessage) (any, error) {
|
||||
Invoke: func(ctx context.Context, args json.RawMessage) (any, error) {
|
||||
var a struct {
|
||||
OrderID string `json:"orderId"`
|
||||
Reason string `json:"reason"`
|
||||
@@ -388,7 +314,7 @@ func (s *Server) buildTools() []tool {
|
||||
Quantity int32 `json:"quantity"`
|
||||
} `json:"lines"`
|
||||
}
|
||||
if err := decode(args, &a); err != nil {
|
||||
if err := pmcp.Decode(args, &a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, ok := order.ParseOrderId(a.OrderID)
|
||||
@@ -400,7 +326,7 @@ func (s *Server) buildTools() []tool {
|
||||
for i, l := range a.Lines {
|
||||
returnLines[i] = &messages.FulfillmentLine{Reference: l.Reference, Quantity: l.Quantity}
|
||||
}
|
||||
res, err := s.applier.Apply(context.Background(), uint64(id), &messages.RequestReturn{
|
||||
res, err := s.applier.Apply(ctx, uint64(id), &messages.RequestReturn{
|
||||
Id: "r_" + rid.String(),
|
||||
Reason: a.Reason,
|
||||
Lines: returnLines,
|
||||
@@ -420,16 +346,16 @@ func (s *Server) buildTools() []tool {
|
||||
{
|
||||
Name: "issue_refund",
|
||||
Description: "Issue a refund against a captured order. Amount is in minor units (öre); omit for the full remaining captured amount. Returns the updated order.",
|
||||
InputSchema: object(props{
|
||||
"orderId": str("the base62 order id"),
|
||||
"amount": integer("refund amount in minor units (öre); omit for full remaining captured amount"),
|
||||
InputSchema: pmcp.Object(pmcp.Props{
|
||||
"orderId": pmcp.String("the base62 order id"),
|
||||
"amount": pmcp.Integer("refund amount in minor units (öre); omit for full remaining captured amount"),
|
||||
}, []string{"orderId"}),
|
||||
invoke: func(args json.RawMessage) (any, error) {
|
||||
Invoke: func(ctx context.Context, args json.RawMessage) (any, error) {
|
||||
var a struct {
|
||||
OrderID string `json:"orderId"`
|
||||
Amount int64 `json:"amount"`
|
||||
}
|
||||
if err := decode(args, &a); err != nil {
|
||||
if err := pmcp.Decode(args, &a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
id, ok := order.ParseOrderId(a.OrderID)
|
||||
@@ -438,19 +364,19 @@ func (s *Server) buildTools() []tool {
|
||||
}
|
||||
// If amount is 0 (omitted), default to full remaining captured amount.
|
||||
if a.Amount <= 0 {
|
||||
g, err := s.applier.Get(context.Background(), uint64(id))
|
||||
g, err := s.applier.Get(ctx, uint64(id))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get order for refund: %w", err)
|
||||
}
|
||||
if g.Status == order.StatusNew {
|
||||
return nil, fmt.Errorf("order %q not found", a.OrderID)
|
||||
}
|
||||
a.Amount = g.CapturedAmount - g.RefundedAmount
|
||||
a.Amount = (g.CapturedAmount - g.RefundedAmount).Int64()
|
||||
}
|
||||
if a.Amount <= 0 {
|
||||
return nil, fmt.Errorf("refund amount must be positive")
|
||||
}
|
||||
res, err := s.applier.Apply(context.Background(), uint64(id), &messages.IssueRefund{
|
||||
res, err := s.applier.Apply(ctx, uint64(id), &messages.IssueRefund{
|
||||
Provider: "mcp",
|
||||
Amount: a.Amount,
|
||||
Reference: "ref-mcp-" + a.OrderID,
|
||||
@@ -494,68 +420,3 @@ func validTransitions(s order.Status) []string {
|
||||
}
|
||||
|
||||
// ---- result + schema helpers -----------------------------------------------
|
||||
|
||||
func toolText(v any) map[string]any {
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return toolError(err)
|
||||
}
|
||||
return map[string]any{
|
||||
"content": []map[string]any{{"type": "text", "text": string(b)}},
|
||||
}
|
||||
}
|
||||
|
||||
func toolError(err error) map[string]any {
|
||||
return map[string]any{
|
||||
"isError": true,
|
||||
"content": []map[string]any{{"type": "text", "text": err.Error()}},
|
||||
}
|
||||
}
|
||||
|
||||
// decode unmarshals tool arguments, tolerating empty/absent arguments.
|
||||
func decode(args json.RawMessage, v any) error {
|
||||
if len(args) == 0 || string(args) == "null" {
|
||||
return nil
|
||||
}
|
||||
if err := json.Unmarshal(args, v); err != nil {
|
||||
return fmt.Errorf("invalid arguments: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type props map[string]json.RawMessage
|
||||
|
||||
func object(p props, required []string) json.RawMessage {
|
||||
m := map[string]any{
|
||||
"type": "object",
|
||||
"properties": p,
|
||||
}
|
||||
if len(required) > 0 {
|
||||
m["required"] = required
|
||||
}
|
||||
b, _ := json.Marshal(m)
|
||||
return b
|
||||
}
|
||||
|
||||
func str(desc string) json.RawMessage { return scalar("string", desc) }
|
||||
func integer(d string) json.RawMessage { return scalar("integer", d) }
|
||||
func obj(desc string) json.RawMessage { return scalar("object", desc) }
|
||||
|
||||
func scalar(typ, desc string) json.RawMessage {
|
||||
b, _ := json.Marshal(map[string]any{"type": typ, "description": desc})
|
||||
return b
|
||||
}
|
||||
|
||||
func objArray(desc string) json.RawMessage {
|
||||
b, _ := json.Marshal(map[string]any{
|
||||
"type": "array", "description": desc, "items": map[string]string{"type": "object"},
|
||||
})
|
||||
return b
|
||||
}
|
||||
|
||||
func stringArray(desc string) json.RawMessage {
|
||||
b, _ := json.Marshal(map[string]any{
|
||||
"type": "array", "description": desc, "items": map[string]string{"type": "string"},
|
||||
})
|
||||
return b
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user