Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions cmd/omni/agent_help.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,31 @@ Set OMNI_API_TOKEN env var, or run: omni config init
users User/group role management, set user attribute values
config CLI configuration profiles

## Discovering request body shapes
Any command that takes a body accepts --schema. It prints the body's JSON
schema (field types, descriptions, enums, required fields) plus a filled-in
example, then exits without making an API call (no token needed). Use this
instead of guessing the JSON for --body.
omni query run --schema
omni connections create --schema --compact

Deeply nested bodies (e.g. documents v2-create) can be large. Narrow the
output with --depth N for a shallow overview, then --field PATH to drill into
one part. PATH is dotted and auto-descends through arrays and maps, so you can
name a leaf without knowing the container shape:
omni documents v2-create --schema --depth 1 # top-level overview
omni documents v2-create --schema --field queryPresentations.data # just the tiles map
omni documents v2-create --schema --field queryPresentations.data.query

## Common Flags
--compact Non-indented JSON output
--token TOKEN API token (overrides env/config)
--base-url URL API base URL (overrides config)
--profile NAME Config profile to use
--body JSON Request body (JSON string or "-" for stdin)
--schema Print the request body's schema + example, then exit
--field PATH With --schema: drill into a dotted field path
--depth N With --schema: cap nesting depth (lower = smaller)

## Tips
- Use "omni ai generate-query" to answer data questions — it picks fields and filters for you.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/charmbracelet/lipgloss v1.1.0
github.com/pb33f/libopenapi v0.34.4
github.com/spf13/cobra v1.10.2
go.yaml.in/yaml/v4 v4.0.0-rc.4
golang.org/x/oauth2 v0.36.0
golang.org/x/term v0.41.0
)
Expand All @@ -31,7 +32,6 @@ require (
github.com/rivo/uniseg v0.4.7 // indirect
github.com/spf13/pflag v1.0.9 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.yaml.in/yaml/v4 v4.0.0-rc.4 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.42.0 // indirect
)
67 changes: 66 additions & 1 deletion internal/openapi/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ type operationInfo struct {
PathParams []paramInfo
QueryParams []paramInfo
HasBody bool
BodySchema *base.SchemaProxy // request body schema, when HasBody
Deprecated bool
}

Expand Down Expand Up @@ -157,6 +158,7 @@ func extractOperations(pathStr string, item *v3.PathItem, groups map[string][]*o
// Check for request body
if op.RequestBody != nil {
info.HasBody = true
info.BodySchema = requestBodySchema(op.RequestBody)
}

groups[tag] = append(groups[tag], info)
Expand Down Expand Up @@ -259,7 +261,7 @@ func buildCommand(op *operationInfo, exec Executor) *cobra.Command {

// If the operation accepts a body, add --body and --json-body flags
if op.HasBody {
cmd.Flags().String("body", "", `request body as JSON string, or "-" for stdin`)
cmd.Flags().String("body", "", `request body as JSON string, or "-" for stdin (run with --schema to see its shape)`)
cmd.Flags().String("json-body", "", `request body as JSON string, or "-" for stdin (alias for --body)`)
cmd.Flags().MarkHidden("json-body")
}
Expand All @@ -269,9 +271,72 @@ func buildCommand(op *operationInfo, exec Executor) *cobra.Command {
applyBodyShorthand(cmd, op, sh)
}

// Add the --schema discovery flag last, wrapping arg validation and RunE so
// it short-circuits before any positional-arg checks, body assembly, auth,
// or network call. This lets `omni <cmd> --schema` work with no args/token.
if op.HasBody {
cmd.Flags().Bool("schema", false, "print the request body's JSON schema and a filled-in example, then exit (no API call)")
// --field / --depth refine the --schema output for deeply nested bodies.
// Guarded so a future query/path param of the same name can't panic the
// flag registration.
if cmd.Flags().Lookup("field") == nil {
cmd.Flags().String("field", "", "with --schema: drill into a dotted field path (e.g. queryPresentations.data.query); auto-descends arrays and maps")
}
if cmd.Flags().Lookup("depth") == nil {
cmd.Flags().Int("depth", maxSchemaDepth, "with --schema: max nesting depth to expand; lower for a compact overview")
}

innerArgs := cmd.Args
cmd.Args = func(c *cobra.Command, args []string) error {
if schemaRequested(c) || innerArgs == nil {
return nil
}
return innerArgs(c, args)
}

innerRun := cmd.RunE
cmd.RunE = func(c *cobra.Command, args []string) error {
if schemaRequested(c) {
// A schema error (e.g. a bad --field path) should print just the
// helpful message, not the full usage block.
c.SilenceUsage = true
return emitBodySchema(c, op)
}
return innerRun(c, args)
}
}

return cmd
}

// schemaRequested reports whether the --schema discovery flag is set.
func schemaRequested(cmd *cobra.Command) bool {
v, err := cmd.Flags().GetBool("schema")
return err == nil && v
}

// requestBodySchema returns the schema for a request body, preferring the
// application/json media type and falling back to the first declared one.
func requestBodySchema(rb *v3.RequestBody) *base.SchemaProxy {
if rb == nil || rb.Content == nil {
return nil
}
var first *base.SchemaProxy
for pair := rb.Content.First(); pair != nil; pair = pair.Next() {
mt := pair.Value()
if mt == nil || mt.Schema == nil {
continue
}
if pair.Key() == "application/json" {
return mt.Schema
}
if first == nil {
first = mt.Schema
}
}
return first
}

// commandName derives a CLI subcommand name from the operationId or method+path.
func commandName(op *operationInfo) string {
if op.OperationID != "" {
Expand Down
Loading
Loading