Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
f2636ea
docs(mcp): add architecture blueprint for CUDly MCP server
cristim Jul 22, 2026
16d964f
docs(mcp): remove architecture blueprint doc
cristim Jul 22, 2026
5a6f8c3
feat(common): add cudly-mcp purchase source enum
cristim Jul 22, 2026
e3a0f14
feat(mcp): server skeleton + list-commitment-actions tool
cristim Jul 22, 2026
b9fd9b8
feat(mcp): search-recommendations tool
cristim Jul 22, 2026
fb0e4e3
feat(mcp): aws ec2 ri purchase tool
cristim Jul 22, 2026
f199291
feat(mcp): aws opensearch, redshift, memorydb ri purchase tools
cristim Jul 22, 2026
62f9a75
feat(mcp): aws rds and elasticache ri purchase tools
cristim Jul 22, 2026
a75421a
feat(mcp): aws savings plans purchase tool
cristim Jul 22, 2026
2046f9a
feat(mcp): azure vm and gcp compute engine purchase tools
cristim Jul 22, 2026
98bee6d
docs(mcp): add mcp/README.md
cristim Jul 22, 2026
44aee0f
fix(mcp): resolve golangci-lint v2.10.1 findings
cristim Jul 22, 2026
d2f39a0
test(mcp): add end-to-end search-then-dry-run-purchase test
cristim Jul 22, 2026
7a06b58
fix(mcp): derive idempotency key from every price-affecting dimension
cristim Jul 23, 2026
426ae48
fix(mcp): omit unknown purchase cost/savings instead of reporting 0
cristim Jul 23, 2026
3da2d34
fix(mcp): reject Azure payment_option Azure will not honor
cristim Jul 23, 2026
d98a687
fix(mcp): scope Azure payment_option gate to real purchases only
cristim Jul 23, 2026
4bcd761
feat(mcp): expose include_regions/exclude_regions on search_recommend…
cristim Jul 23, 2026
b022ed8
fix(mcp): validate Database Savings Plan term/payment constraints
cristim Jul 23, 2026
a715979
fix(mcp): properly case product names in simple RI tool descriptions
cristim Jul 23, 2026
f39fad1
docs(mcp): use go install instead of a root build artifact
cristim Jul 23, 2026
a551df9
fix(mcp): capture decidePurchaseMode error in azure RI purchase gate
cristim Jul 23, 2026
7ee9e9b
docs: link to MCP server docs from root README
cristim Jul 23, 2026
60f4579
fix(azure): wire payment option into reservation billing plan
cristim Jul 23, 2026
4e90b9c
fix(mcp): accept and default to no-upfront on Azure RI purchase tool
cristim Jul 23, 2026
0206411
docs(mcp): update Azure billing-plan caveat to reflect no-upfront sup…
cristim Jul 23, 2026
ad52350
fix(mcp): register provider factories for cudly-mcp binary
cristim Jul 23, 2026
eb7efcc
fix(mcp): prevent idempotency-key collisions across time-separated pu…
cristim Jul 23, 2026
857061c
fix(mcp): require instance_family for EC2Instance Savings Plans
cristim Jul 23, 2026
d0e46be
fix(mcp): include cudly_list_commitment_actions in its own catalog
cristim Jul 23, 2026
1a4e874
fix(mcp): reject whitespace-only required string fields
cristim Jul 23, 2026
1dfa2f7
fix(mcp): populate TermYears on preview and real purchase responses
cristim Jul 23, 2026
f12fc11
docs(mcp): clarify GOBIN vs GOPATH/bin binary path guidance
cristim Jul 23, 2026
e65c102
style(mcp): fix golangci-lint v2.10.1 findings
cristim Jul 23, 2026
d756591
fix(mcp): make purchase idempotency key fail-safe (drop auto time-buc…
cristim Jul 23, 2026
bc28b7f
fix(mcp): drop partial-upfront from Azure RI payment_option schema
cristim Jul 23, 2026
28d6945
fix(mcp): trim whitespace-only region before Savings Plans account-le…
cristim Jul 23, 2026
f97fa65
fix(mcp): scope Savings Plans Details.Region/InstanceFamily to EC2Ins…
cristim Jul 23, 2026
f610e01
fix(azure): validate payment option before Microsoft.Capacity registr…
cristim Jul 23, 2026
88a1af5
fix(mcp): trim surrounding whitespace on required identifier fields
cristim Jul 23, 2026
34d8024
fix(mcp): validate lookback_period in the search_recommendations handler
cristim Jul 23, 2026
688dac7
fix(azure): validate term before capacity provider registration
cristim Jul 23, 2026
c9c30d7
fix(mcp): trim region/instance_family before storing on SP recommenda…
cristim Jul 23, 2026
083f9c3
fix(mcp): trim region/account identifiers in search_recommendations
cristim Jul 23, 2026
911ea3a
fix(azure): wire billingPlan into SQL Database reservation purchases
cristim Jul 23, 2026
682da45
fix(azure): wire billingPlan into Cache for Redis reservation purchases
cristim Jul 23, 2026
3889c34
fix(azure): wire billingPlan into Cosmos DB reservation purchases
cristim Jul 23, 2026
94daaa4
fix(azure): wire billingPlan into Search reservation purchases
cristim Jul 23, 2026
fdb36a2
fix(azure): wire billingPlan into Managed Redis reservation purchases
cristim Jul 23, 2026
b50d7a4
fix(azure): wire billingPlan into Synapse reservation purchases
cristim Jul 23, 2026
a632edd
fix(mcp): default Savings Plans search to 1yr no-upfront 30d
cristim Jul 25, 2026
939b682
fix(mcp): join all invalid search fields into one error
cristim Jul 25, 2026
d151219
docs(mcp): document Savings Plans search defaults
cristim Jul 25, 2026
18c3d0c
fix(aws): filter recommendations by the region search param
cristim Jul 25, 2026
217bf80
fix(aws): stop region filter from dropping all savings plans recs
cristim Jul 25, 2026
2f0de35
test(aws): cover savings plans recs in region filter tests
cristim Jul 25, 2026
abae00f
fix(mcp): scope purchase idempotency key to the target account
cristim Jul 27, 2026
80c2c79
fix(aws): stop region-less reservation recs bypassing the region filter
cristim Jul 27, 2026
89cd9ad
fix(mcp): reject Savings Plans commitments finer than one cent
cristim Jul 27, 2026
5e41a1f
fix(mcp): reject blank filter entries and trim service in search
cristim Jul 27, 2026
374c7ad
fix(mcp): set the GCP CUD payment option instead of leaving it empty
cristim Jul 27, 2026
b0c00e8
feat(mcp): log real purchases and document the missing approval gate
cristim Jul 27, 2026
9ac4fd3
fix(azure): diagnose a missing payment option as missing
cristim Jul 27, 2026
5a1dad0
style(mcp): resolve golangci-lint v2.10.1 findings
cristim Jul 27, 2026
1444ecc
test(aws): pin blank region skip and savings plans region normalization
cristim Jul 27, 2026
b97d14d
refactor(mcp): share one dry_run/confirm default resolver across tools
cristim Jul 27, 2026
e5f787a
feat(mcp): offer Archera insurance after a purchase completes
cristim Jul 27, 2026
1579fab
fix(mcp): reject NaN and Inf hourly commitments in Savings Plans vali…
cristim Jul 27, 2026
cfb61ec
fix(mcp): log a provider-reported purchase failure as FAILED, not OK
cristim Jul 27, 2026
b196d5d
fix(mcp): add operator opt-in gate before executing real purchases
cristim Jul 27, 2026
dd9de1c
fix(aws): route parser warnings to stderr, never stdout
cristim Jul 27, 2026
de27120
fix(aws): keep region-scoped EC2Instance SPs under region filters
cristim Jul 27, 2026
01c0566
fix(mcp): refuse a real purchase with no determinable account
cristim Jul 27, 2026
d76aa7c
fix(mcp): fan out reservation searches over every term and payment op…
cristim Jul 27, 2026
12fe374
fix(mcp): advertise term/payment enums and split the search test file
cristim Jul 27, 2026
85a86ac
fix(mcp): omit effective_date when the provider reported no timestamp
cristim Jul 27, 2026
3a65136
test(mcp): guard content index and type assertion in the binary smoke…
cristim Jul 27, 2026
f8ae701
docs(mcp): explain why the GCP CUD tool has no ambient scope fallback
cristim Jul 27, 2026
c19cff4
fix(mcp): make the GCP credential-scope refusal actionable
cristim Jul 27, 2026
44b6094
fix(mcp): stop ignored region and untrimmed credentials forking purch…
cristim Jul 27, 2026
bdb43cd
test(mcp): assert EC2Instance regions derive different idempotency to…
cristim Jul 27, 2026
a1d2696
fix(mcp,azure): trim search credential overrides and stop misblaming …
cristim Jul 28, 2026
707cd14
fix(mcp): stop Azure subscription-ID case forking purchase identity
cristim Jul 28, 2026
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ Topic pages:
- [Purchase Safety](docs/cli/purchase-safety.md) - dry-run, audit log, idempotency window, and guardrails
- [Cloud Setup](docs/cli/cloud-setup.md) - `configure-azure` and `configure-gcp` self-hosted credential bootstrap

## MCP Server

CUDly also ships an MCP server (`cudly-mcp`) that lets Claude and other MCP clients search recommendations and drive RI, Savings Plan, and CUD purchases across AWS, Azure, and GCP, with the same dry-run-by-default safety as the CLI.

Setup and usage: [mcp/README.md](mcp/README.md)

## Key Features

- **Multi-Cloud Support** - Unified interface for AWS (production), Azure (experimental), and GCP (experimental)
Expand Down
38 changes: 38 additions & 0 deletions cmd/cudly-mcp/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Command cudly-mcp runs the CUDly MCP server on stdio, exposing CUDly's
// RI/SP/CUD search and purchase tools to any MCP client (e.g. Claude Code
// via ~/.claude/mcp.json). See mcp/README.md for setup and usage.
//
// This binary is intentionally separate from the ri-helper CLI (cmd/main.go):
// it is a local/desktop MCP server, never a Lambda handler, and is kept out
// of iac/ and terraform/ (see mcp/README.md "Deployment model").
package main

import (
"context"
"log"
"os"

gosdk "github.com/modelcontextprotocol/go-sdk/mcp"

cudlymcp "github.com/LeanerCloud/CUDly/mcp"
_ "github.com/LeanerCloud/CUDly/providers/aws"
_ "github.com/LeanerCloud/CUDly/providers/azure"
_ "github.com/LeanerCloud/CUDly/providers/gcp"
)

// version is overridable at build time via:
//
// go build -ldflags "-X main.version=1.2.3" ./cmd/cudly-mcp
var version = "dev"

func main() {
server, err := cudlymcp.NewServer(version)
if err != nil {
log.Fatalf("cudly-mcp: failed to build server: %v", err)
}

if err := server.Run(context.Background(), &gosdk.StdioTransport{}); err != nil {
log.Printf("cudly-mcp: server exited with error: %v", err)
os.Exit(1)
}
}
116 changes: 116 additions & 0 deletions cmd/cudly-mcp/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package main

import (
"context"
"path/filepath"
"strings"
"testing"
"time"

gosdk "github.com/modelcontextprotocol/go-sdk/mcp"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

cudlymcp "github.com/LeanerCloud/CUDly/mcp"
"github.com/LeanerCloud/CUDly/mcp/tools"
)

// isolateFromAmbientAWS points the AWS SDK at deliberately nonexistent
// profile/config/credentials so config.LoadDefaultConfig cannot resolve any
// real credentials -- neither from a dev machine's ~/.aws files nor from the
// network (IMDS, ECS/EKS container credential endpoints, web identity). This
// is required for TestRealPurchasePastProviderRegistration below: that test
// drives a real (non-dry-run) purchase call, so it must be impossible for it
// to reach an actual AWS account or make an actual network call, in this or
// any other environment the test happens to run in.
func isolateFromAmbientAWS(t *testing.T) {
t.Helper()
t.Setenv("AWS_PROFILE", "cudly-mcp-regression-test-nonexistent-profile")
t.Setenv("AWS_SHARED_CREDENTIALS_FILE", filepath.Join(t.TempDir(), "no-credentials"))
t.Setenv("AWS_CONFIG_FILE", filepath.Join(t.TempDir(), "no-config"))
t.Setenv("AWS_ACCESS_KEY_ID", "")
t.Setenv("AWS_SECRET_ACCESS_KEY", "")
t.Setenv("AWS_SESSION_TOKEN", "")
t.Setenv("AWS_EC2_METADATA_DISABLED", "true")
t.Setenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI", "")
t.Setenv("AWS_CONTAINER_CREDENTIALS_FULL_URI", "")
t.Setenv("AWS_ROLE_ARN", "")
t.Setenv("AWS_WEB_IDENTITY_TOKEN_FILE", "")
}

// TestRealPurchasePastProviderRegistration is the regression guard for the
// bug this file's blank imports fix: cudly-mcp never imported
// providers/aws|azure|gcp, so their init()-registered factories were never
// added to provider.CreateProvider's registry, and every real (non-dry-run)
// purchase failed at ResolveClient with "provider aws is not registered"
// before ever reaching AWS.
//
// This test MUST live in package main under cmd/cudly-mcp/ -- go test
// ./mcp/... does not catch this bug even with the blank imports reverted,
// because a test binary for the mcp or mcp/tools package never pulls in
// cmd/cudly-mcp's imports. Only a test in this package has the blank
// imports in its own dependency graph, so only here does reverting them
// actually flip provider.CreateProvider("aws") back to unregistered.
//
// The test asserts the purchase attempt gets PAST registration and fails for
// a completely different, credentials-shaped reason ("AWS is not
// configured", from providers/aws/provider.go's GetServiceClient) instead of
// "not registered". It never reaches AWS: isolateFromAmbientAWS makes
// config.LoadDefaultConfig fail to resolve the (deliberately nonexistent)
// named profile before any credential lookup or network call happens.
func TestRealPurchasePastProviderRegistration(t *testing.T) {
isolateFromAmbientAWS(t)
// This test's whole point is driving a real (non-dry-run) purchase call
// far enough to observe what happens after provider registration, so it
// must clear the operator-side EnvEnableRealPurchases gate too, or every
// assertion below would instead observe the gate's own refusal.
t.Setenv(tools.EnvEnableRealPurchases, "1")

server, err := cudlymcp.NewServer("test-regression")
require.NoError(t, err)

clientTransport, serverTransport := gosdk.NewInMemoryTransports()

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

go func() {
_ = server.Run(ctx, serverTransport)
}()

client := gosdk.NewClient(&gosdk.Implementation{Name: "test-client"}, nil)
session, err := client.Connect(ctx, clientTransport, nil)
require.NoError(t, err)
defer session.Close()

result, err := session.CallTool(ctx, &gosdk.CallToolParams{
Name: "cudly_aws_ec2_ri_purchase",
Arguments: map[string]any{
"region": "us-east-1",
"instance_type": "m5.large",
"count": 1,
"term_years": 1,
"payment_option": "no-upfront",
"dry_run": false,
"confirm": true,
},
})
require.NoError(t, err, "CallTool itself must not return a transport-level error")
require.True(t, result.IsError, "a failed real purchase must surface as a tool error, not a transport error")

// Guard both the index and the type assertion: a bare
// result.Content[0].(*gosdk.TextContent) panics on an empty Content slice
// or a non-text block, which aborts the whole package's test run instead
// of failing this one assertion readably.
require.NotEmpty(t, result.Content, "tool error result must carry at least one content block")
textContent, ok := result.Content[0].(*gosdk.TextContent)
require.True(t, ok, "first content block must be text, got %T", result.Content[0])
text := textContent.Text
assert.NotContains(t, strings.ToLower(text), "not registered",
"provider must be registered for the cudly-mcp binary: got %q", text)
// providers/aws/provider.go's GetServiceClient (via AWSProvider.IsConfigured)
// returns exactly this string when config.LoadDefaultConfig cannot resolve
// the requested profile -- observed and confirmed stable in this test run.
assert.Contains(t, text, "AWS is not configured",
"expected a credentials/config-shaped failure once past registration: got %q", text)
}
18 changes: 10 additions & 8 deletions cmd/multi_service_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,13 @@ func printSuccessRate(success, failed int) {
}
}

// archeraSignupURL is the Archera signup link with CUDly attribution, shared
// with the web interface (frontend ARCHERA_SIGNUP_URL).
const archeraSignupURL = "https://www.archera.ai/cudly"
// archeraSignupURL is the Archera signup link with CUDly attribution. Now an
// alias for the shared constant in pkg/common, which the MCP server's
// post-purchase offer reads too, so the link and the two disclosures below
// are written once rather than once per binary. Kept identical to the
// frontend's ARCHERA_SIGNUP_URL (frontend/src/archera.ts), which cannot
// import Go.
const archeraSignupURL = common.ArcheraSignupURL

// printFinalMessage prints the final message based on mode and results.
func printFinalMessage(isDryRun bool, riSuccess int) {
Expand Down Expand Up @@ -200,11 +204,9 @@ func printArcheraPitch() {
AppLogger.Println(" You can buy underutilization insurance for Reserved Instances and")
AppLogger.Println(" Savings Plans from Archera by signing up at:")
AppLogger.Printf(" %s\n", archeraSignupURL)
AppLogger.Println(" within the first 7 days of the purchase.")
AppLogger.Println("\n This is entirely optional. CUDly's purchase and management features")
AppLogger.Println(" work fully without Archera.")
AppLogger.Println("\n For full disclosure, Archera sponsors CUDly's Open Source development")
AppLogger.Println(" from a fraction of their insurance premiums.")
AppLogger.Printf(" within the first %d days of the purchase.\n", common.ArcheraEnrollmentWindowDays)
AppLogger.Printf("\n %s\n", common.ArcheraNonGatingDisclosure)
AppLogger.Printf("\n %s\n", common.ArcheraSponsorshipDisclosure)
}

// printSavingsPlansSection prints the Savings Plans summary section.
Expand Down
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,11 @@ require (
github.com/coreos/go-oidc/v3 v3.18.0
github.com/go-jose/go-jose/v4 v4.1.4
github.com/golang-migrate/migrate/v4 v4.19.1
github.com/google/jsonschema-go v0.4.3
github.com/google/uuid v1.6.0
github.com/jackc/pgx/v5 v5.9.2
github.com/microsoftgraph/msgraph-sdk-go v1.99.0
github.com/modelcontextprotocol/go-sdk v1.6.1
github.com/pashagolub/pgxmock/v4 v4.9.0
github.com/testcontainers/testcontainers-go v0.42.0
github.com/testcontainers/testcontainers-go/modules/postgres v0.42.0
Expand Down Expand Up @@ -175,12 +177,15 @@ require (
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/segmentio/asm v1.1.3 // indirect
github.com/segmentio/encoding v0.5.4 // indirect
github.com/shirou/gopsutil/v4 v4.26.3 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect
github.com/std-uritemplate/std-uritemplate/go/v2 v2.0.3 // indirect
github.com/tklauser/go-sysconf v0.3.16 // indirect
github.com/tklauser/numcpus v0.11.0 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.43.0 // indirect
Expand Down
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/jsonschema-go v0.4.3 h1:/DBOLZTfDow7pe2GmaJNhltueGTtDKICi8V8p+DQPd0=
github.com/google/jsonschema-go v0.4.3/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc=
github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
Expand Down Expand Up @@ -296,6 +298,8 @@ github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
github.com/modelcontextprotocol/go-sdk v1.6.1 h1:0zOSupjKUxPKSocPT1Wtago+mUHU2/uZ4xSOY0FGReU=
github.com/modelcontextprotocol/go-sdk v1.6.1/go.mod h1:kzm3kzFL1/+AziGOE0nUs3gvPoNxMCvkxokMkuFapXQ=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
Expand All @@ -318,6 +322,10 @@ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:Om
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/segmentio/asm v1.1.3 h1:WM03sfUOENvvKexOLp+pCqgb/WDjsi7EK8gIsICtzhc=
github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg=
github.com/segmentio/encoding v0.5.4 h1:OW1VRern8Nw6ITAtwSZ7Idrl3MXCFwXHPgqESYfvNt0=
github.com/segmentio/encoding v0.5.4/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0=
github.com/shirou/gopsutil/v4 v4.26.3 h1:2ESdQt90yU3oXF/CdOlRCJxrP+Am1aBYubTMTfxJ1qc=
github.com/shirou/gopsutil/v4 v4.26.3/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ=
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
Expand Down Expand Up @@ -345,6 +353,8 @@ github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYI
github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
Expand Down Expand Up @@ -387,6 +397,8 @@ golang.org/x/text v0.39.0 h1:UbZz4pLOvn600D6Oh6GGEI6VAmndrEBLv8/6BEXzyus=
golang.org/x/text v0.39.0/go.mod h1:3UwRclnC2g0TU9x8PZiyfOajCd1zaUNHF9cvqcQZ+ZM=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
Expand Down
2 changes: 2 additions & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ=
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down Expand Up @@ -697,6 +698,7 @@ golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxb
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI=
golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0=
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
golang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
Loading
Loading