fix: parse MCP result payloads and drop place idempotency_key
Typed result structs replace empty envelopes. Equity place sends ref_id only so live additionalProperties:false schemas accept the call.
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
package scanner
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"s1d3sw1ped/robinhood-agentic-mcp/internal/wire"
|
||||
)
|
||||
|
||||
func (r *FilterSpecsResult) UnmarshalJSON(b []byte) error {
|
||||
type row struct {
|
||||
FilterType string `json:"filter_type"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
rows, _, err := wire.UnmarshalRows[row](b, "specs", "filters", "results")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Specs = make([]FilterSpec, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
r.Specs = append(r.Specs, FilterSpec{FilterType: row.FilterType, Name: row.Name})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DatapointsResult) UnmarshalJSON(b []byte) error {
|
||||
type row struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
rows, _, err := wire.UnmarshalRows[row](b, "datapoints", "results")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Datapoints = make([]Datapoint, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
r.Datapoints = append(r.Datapoints, Datapoint{Name: row.Name})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unmarshalScan(b []byte) (ScanResult, error) {
|
||||
var wrap struct {
|
||||
ID string `json:"id"`
|
||||
ScanID string `json:"scan_id"`
|
||||
Title string `json:"title"`
|
||||
Total int `json:"total"`
|
||||
Rows []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Ticker string `json:"ticker"`
|
||||
InstrumentID string `json:"instrument_id"`
|
||||
} `json:"rows"`
|
||||
Results []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
InstrumentID string `json:"instrument_id"`
|
||||
} `json:"results"`
|
||||
}
|
||||
if err := json.Unmarshal(wire.Unwrap(b), &wrap); err != nil {
|
||||
return ScanResult{}, err
|
||||
}
|
||||
out := ScanResult{ID: wrap.ID, Title: wrap.Title, Total: wrap.Total}
|
||||
if out.ID == "" {
|
||||
out.ID = wrap.ScanID
|
||||
}
|
||||
src := wrap.Rows
|
||||
if len(src) == 0 {
|
||||
for _, row := range wrap.Results {
|
||||
src = append(src, struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Ticker string `json:"ticker"`
|
||||
InstrumentID string `json:"instrument_id"`
|
||||
}{Symbol: row.Symbol, InstrumentID: row.InstrumentID})
|
||||
}
|
||||
}
|
||||
for _, row := range src {
|
||||
sym := row.Symbol
|
||||
if sym == "" {
|
||||
sym = row.Ticker
|
||||
}
|
||||
out.Rows = append(out.Rows, ScanRow{Symbol: sym, InstrumentID: row.InstrumentID})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (r *CreateResult) UnmarshalJSON(b []byte) error {
|
||||
s, err := unmarshalScan(b)
|
||||
r.ScanResult = s
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *PreviewResult) UnmarshalJSON(b []byte) error {
|
||||
s, err := unmarshalScan(b)
|
||||
r.ScanResult = s
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *RunResult) UnmarshalJSON(b []byte) error {
|
||||
s, err := unmarshalScan(b)
|
||||
r.ScanResult = s
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *UpdateFiltersResult) UnmarshalJSON(b []byte) error {
|
||||
s, err := unmarshalScan(b)
|
||||
r.ScanResult = s
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *UpdateConfigResult) UnmarshalJSON(b []byte) error {
|
||||
s, err := unmarshalScan(b)
|
||||
r.ScanResult = s
|
||||
return err
|
||||
}
|
||||
+46
-7
@@ -42,14 +42,29 @@ type Column struct {
|
||||
// FilterSpecsRequest is the argument set for get_scanner_filter_specs (none).
|
||||
type FilterSpecsRequest struct{}
|
||||
|
||||
// FilterSpec is one filter type from get_scanner_filter_specs.
|
||||
type FilterSpec struct {
|
||||
FilterType string `json:"filter_type"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// FilterSpecsResult is the parsed get_scanner_filter_specs payload.
|
||||
type FilterSpecsResult struct{}
|
||||
type FilterSpecsResult struct {
|
||||
Specs []FilterSpec
|
||||
}
|
||||
|
||||
// DatapointsRequest is the argument set for get_scanner_datapoints (none).
|
||||
type DatapointsRequest struct{}
|
||||
|
||||
// Datapoint is one expression token from get_scanner_datapoints.
|
||||
type Datapoint struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// DatapointsResult is the parsed get_scanner_datapoints payload.
|
||||
type DatapointsResult struct{}
|
||||
type DatapointsResult struct {
|
||||
Datapoints []Datapoint
|
||||
}
|
||||
|
||||
// ScansRequest is the argument set for get_scans (none).
|
||||
type ScansRequest struct{}
|
||||
@@ -74,8 +89,24 @@ type CreateRequest struct {
|
||||
Title string
|
||||
}
|
||||
|
||||
// ScanResult is a saved scan plus optional live rows.
|
||||
type ScanResult struct {
|
||||
ID string
|
||||
Title string
|
||||
Rows []ScanRow
|
||||
Total int
|
||||
}
|
||||
|
||||
// ScanRow is one live scanner match.
|
||||
type ScanRow struct {
|
||||
Symbol string
|
||||
InstrumentID string
|
||||
}
|
||||
|
||||
// CreateResult is the parsed create_scan payload.
|
||||
type CreateResult struct{}
|
||||
type CreateResult struct {
|
||||
ScanResult
|
||||
}
|
||||
|
||||
// PreviewRequest is the argument set for preview_scan.
|
||||
type PreviewRequest struct {
|
||||
@@ -84,7 +115,9 @@ type PreviewRequest struct {
|
||||
}
|
||||
|
||||
// PreviewResult is the parsed preview_scan payload.
|
||||
type PreviewResult struct{}
|
||||
type PreviewResult struct {
|
||||
ScanResult
|
||||
}
|
||||
|
||||
// RunRequest is the argument set for run_scan.
|
||||
type RunRequest struct {
|
||||
@@ -92,7 +125,9 @@ type RunRequest struct {
|
||||
}
|
||||
|
||||
// RunResult is the parsed run_scan payload.
|
||||
type RunResult struct{}
|
||||
type RunResult struct {
|
||||
ScanResult
|
||||
}
|
||||
|
||||
// UpdateFiltersRequest is the argument set for update_scan_filters.
|
||||
type UpdateFiltersRequest struct {
|
||||
@@ -101,7 +136,9 @@ type UpdateFiltersRequest struct {
|
||||
}
|
||||
|
||||
// UpdateFiltersResult is the parsed update_scan_filters payload.
|
||||
type UpdateFiltersResult struct{}
|
||||
type UpdateFiltersResult struct {
|
||||
ScanResult
|
||||
}
|
||||
|
||||
// UpdateConfigRequest is the argument set for update_scan_config.
|
||||
type UpdateConfigRequest struct {
|
||||
@@ -112,7 +149,9 @@ type UpdateConfigRequest struct {
|
||||
}
|
||||
|
||||
// UpdateConfigResult is the parsed update_scan_config payload.
|
||||
type UpdateConfigResult struct{}
|
||||
type UpdateConfigResult struct {
|
||||
ScanResult
|
||||
}
|
||||
|
||||
// FilterSpecs calls get_scanner_filter_specs.
|
||||
func (c *Client) FilterSpecs(ctx context.Context, req FilterSpecsRequest) (FilterSpecsResult, error) {
|
||||
|
||||
Reference in New Issue
Block a user