You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
github.com/itchyny/gojq is a pure Go implementation of jq β the lightweight, flexible JSON processor. Unlike shelling out to the jq binary, gojq embeds the full jq engine as a library, enabling safe Go-native JSON transformation with context cancellation, custom functions, and arbitrary-precision integers.
Version in use: v0.12.18 β (latest)
Current Usage in gh-aw-mcpg
The module is used exclusively in the jq schema middleware that intercepts large MCP tool responses and replaces them with compact schema + preview + filesystem path metadata.
Files: 2 production files + 2 test files (all in internal/middleware/)
Import Count: 2 production imports (jqschema.go, jqschema_bench_test.go)
Key APIs Used:
gojq.Parse() β parse the schema filter string
gojq.Compile() β compile to bytecode at startup
(*gojq.Code).RunWithContext() β execute with timeout/cancellation
iter.Next() β consume results
*gojq.HaltError β distinguish clean halts from errors
The middleware applies a custom jq walk filter that recursively replaces JSON values with their type names (e.g., "test" β "string", 42 β "number"), keeping only the first array element for schema inference.
Research Findings
What's Done Well π
The usage is already quite idiomatic and makes use of key gojq best practices:
Pre-compile at init() β The filter is parsed and compiled once at startup, giving 10β100Γ speedup vs re-parsing per request (documented with benchmarks in jqschema_bench_test.go).
Context-aware execution β Uses RunWithContext with a 5-second default timeout, preventing hangs on malformed queries or deeply nested payloads.
HaltError handling β Correctly distinguishes HaltError{Value: nil} (clean halt) from error halts, including exit code reporting.
Thread-safe usage β *gojq.Code is safe for concurrent use; the pre-compiled global is correctly shared across goroutines.
Recent Updates (v0.12.18)
Array element limit raised to 2^29 (536,870,912) elements
Improved concurrent execution performance (directly benefits the pre-compiled global pattern)
Enhanced type error messages (referenced in HaltError handling comments)
Best Practices from Maintainers
Compile once with gojq.Compile, run many times β β already done
Use RunWithContext for cancellation β β already done
Use gojq.WithFunctions for Go-native extensions β π² not yet leveraged
Use gojq.WithVariables for parameterized filters β π² not yet leveraged
Improvement Opportunities
π Quick Wins
1. Deduplicate identical test helper functions
payloadMetadataToMap in jqschema_test.go and integrationPayloadMetadataToMap in jqschema_integration_test.go are byte-for-byte identical functions living in the same package middleware. One can be removed and tests updated to use the single shared version.
2. UTF-8-safe preview truncation
// Current β slices at byte boundarypreview=string(payloadJSON[:PayloadPreviewSize]) +"..."
Since JSON payload bytes are virtually always ASCII-compatible (gojq outputs \uXXXX for non-ASCII), this is safe in practice. But a comment or a utf8-aware boundary check (using strings.LastIndexByte or utf8.ValidString) would make the intent explicit and defensive.
3. Document why the iterator is consumed only once
After iter.Next(), the iterator is not drained. This is correct (gojq is lazy, the filter produces exactly one result), but a brief comment explaining the single-result contract would help future maintainers.
β¨ Feature Opportunities
1. gojq.WithFunctions for richer schema inference
Currently, all numeric values map to "number". Using custom Go functions, the schema could distinguish integers from floats:
This would enable schemas like {"id": "integer", "price": "float"} β more useful for downstream consumers.
2. Schema merging for heterogeneous arrays
The current filter takes only the first element of each array for schema inference:
eliftype=="array"theniflength==0then [] else [.[0] |walk(f)] end
For heterogeneous arrays (mixed types), this misses variation. A reduce-based merge would produce more comprehensive type signatures. Worth considering for deeply varied API responses.
3. gojq.WithVariables for a configurable filter
Hard-coded constants like array depth or preview behavior could be exposed as jq variables, enabling runtime configuration without recompilation:
The code defines its own walk function rather than using gojq's built-in walk(f). This is intentional and correct β the custom walk replaces leaf values with type names AND collapses arrays to one element β behaviors incompatible with standard walk(f) semantics. A comment in the filter string explaining why the custom implementation is needed would prevent well-meaning future simplifications that would break functionality.
2. Expose compile error for health checks
jqSchemaCompileErr is unexported. A small exported HealthCheck() error (or inclusion in the gateway's /health endpoint) would surface this startup failure to monitoring systems before the first tool call fails.
π§ General Improvements
1. Avoid double JSON round-trip for native Go types
If data is already map[string]interface{} or []interface{}, the unmarshal is redundant. A type-switch before the unmarshal step could skip it for native types, saving allocations on hot paths.
Recommendations
Priority
Action
π’ Low
Remove duplicate integrationPayloadMetadataToMap test helper
π’ Low
Add comment explaining custom walk vs built-in
π‘ Medium
Add UTF-8 boundary comment/assertion for preview truncation
π‘ Medium
Type-switch optimization in WrapToolHandler to skip redundant unmarshal
π΅ Future
gojq.WithFunctions for integer/float distinction in schema
π΅ Future
Schema merging across heterogeneous array elements
π΅ Future
Expose jqSchemaCompileErr via health check endpoint
Next Steps
Remove integrationPayloadMetadataToMap and use the shared payloadMetadataToMap across both test files
Add a comment block in jqSchemaFilter explaining why a custom walk is used instead of the built-in
Consider a gojq.WithFunctions-based approach for richer schema typing in a future enhancement
Generated by Go Fan πΉ Module summary saved to: specs/mods/gojq.md (in cache) Run ID: Β§23837524610
Note
π Integrity filter blocked 12 items
The following items were blocked because they don't meet the GitHub integrity level.
BurntSushi/toml@8685fbaget_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".
golang/term@9d2dc07get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".
stretchr/testify@5f80e4aget_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".
santhosh-tekuri/jsonschema@d3bf053get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".
itchyny/gojq@183cbecget_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".
spf13/cobra@61968e8get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".
πΉ Go Fan Report: itchyny/gojq
Module Overview
github.com/itchyny/gojqis a pure Go implementation ofjqβ the lightweight, flexible JSON processor. Unlike shelling out to thejqbinary, gojq embeds the full jq engine as a library, enabling safe Go-native JSON transformation with context cancellation, custom functions, and arbitrary-precision integers.Version in use:
v0.12.18β (latest)Current Usage in gh-aw-mcpg
The module is used exclusively in the jq schema middleware that intercepts large MCP tool responses and replaces them with compact schema + preview + filesystem path metadata.
internal/middleware/)jqschema.go,jqschema_bench_test.go)gojq.Parse()β parse the schema filter stringgojq.Compile()β compile to bytecode at startup(*gojq.Code).RunWithContext()β execute with timeout/cancellationiter.Next()β consume results*gojq.HaltErrorβ distinguish clean halts from errorsThe middleware applies a custom jq
walkfilter that recursively replaces JSON values with their type names (e.g.,"test"β"string",42β"number"), keeping only the first array element for schema inference.Research Findings
What's Done Well π
The usage is already quite idiomatic and makes use of key gojq best practices:
init()β The filter is parsed and compiled once at startup, giving 10β100Γ speedup vs re-parsing per request (documented with benchmarks injqschema_bench_test.go).RunWithContextwith a 5-second default timeout, preventing hangs on malformed queries or deeply nested payloads.HaltErrorhandling β Correctly distinguishesHaltError{Value: nil}(clean halt) from error halts, including exit code reporting.*gojq.Codeis safe for concurrent use; the pre-compiled global is correctly shared across goroutines.Recent Updates (v0.12.18)
HaltErrorhandling comments)Best Practices from Maintainers
gojq.Compile, run many times β β already doneRunWithContextfor cancellation β β already donegojq.WithFunctionsfor Go-native extensions β π² not yet leveragedgojq.WithVariablesfor parameterized filters β π² not yet leveragedImprovement Opportunities
π Quick Wins
1. Deduplicate identical test helper functions
payloadMetadataToMapinjqschema_test.goandintegrationPayloadMetadataToMapinjqschema_integration_test.goare byte-for-byte identical functions living in the samepackage middleware. One can be removed and tests updated to use the single shared version.2. UTF-8-safe preview truncation
Since JSON payload bytes are virtually always ASCII-compatible (gojq outputs
\uXXXXfor non-ASCII), this is safe in practice. But a comment or autf8-aware boundary check (usingstrings.LastIndexByteorutf8.ValidString) would make the intent explicit and defensive.3. Document why the iterator is consumed only once
After
iter.Next(), the iterator is not drained. This is correct (gojq is lazy, the filter produces exactly one result), but a brief comment explaining the single-result contract would help future maintainers.β¨ Feature Opportunities
1.
gojq.WithFunctionsfor richer schema inferenceCurrently, all numeric values map to
"number". Using custom Go functions, the schema could distinguish integers from floats:This would enable schemas like
{"id": "integer", "price": "float"}β more useful for downstream consumers.2. Schema merging for heterogeneous arrays
The current filter takes only the first element of each array for schema inference:
For heterogeneous arrays (mixed types), this misses variation. A
reduce-based merge would produce more comprehensive type signatures. Worth considering for deeply varied API responses.3.
gojq.WithVariablesfor a configurable filterHard-coded constants like array depth or preview behavior could be exposed as jq variables, enabling runtime configuration without recompilation:
π Best Practice Alignment
1. Explain the custom
walkvs built-inThe code defines its own
walkfunction rather than using gojq's built-inwalk(f). This is intentional and correct β the custom walk replaces leaf values with type names AND collapses arrays to one element β behaviors incompatible with standardwalk(f)semantics. A comment in the filter string explaining why the custom implementation is needed would prevent well-meaning future simplifications that would break functionality.2. Expose compile error for health checks
jqSchemaCompileErris unexported. A small exportedHealthCheck() error(or inclusion in the gateway's/healthendpoint) would surface this startup failure to monitoring systems before the first tool call fails.π§ General Improvements
1. Avoid double JSON round-trip for native Go types
In
WrapToolHandler, the code does:If
datais alreadymap[string]interface{}or[]interface{}, the unmarshal is redundant. A type-switch before the unmarshal step could skip it for native types, saving allocations on hot paths.Recommendations
integrationPayloadMetadataToMaptest helperwalkvs built-inWrapToolHandlerto skip redundant unmarshalgojq.WithFunctionsfor integer/float distinction in schemajqSchemaCompileErrvia health check endpointNext Steps
integrationPayloadMetadataToMapand use the sharedpayloadMetadataToMapacross both test filesjqSchemaFilterexplaining why a customwalkis used instead of the built-ingojq.WithFunctions-based approach for richer schema typing in a future enhancementGenerated by Go Fan πΉ
Module summary saved to:
specs/mods/gojq.md(in cache)Run ID: Β§23837524610
Note
π Integrity filter blocked 12 items
The following items were blocked because they don't meet the GitHub integrity level.
get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".get_file_contents: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".To allow these resources, lower
min-integrityin your GitHub frontmatter: