Compare commits
2 Commits
b2eb9d3116
...
92b9c356b8
Author | SHA1 | Date | |
---|---|---|---|
92b9c356b8 | |||
c86165f88c |
11
go.mod
11
go.mod
@ -1,4 +1,4 @@
|
||||
module github.com/freeflowuniverse/heroagent
|
||||
module git.ourworld.tf/herocode/heroagent
|
||||
|
||||
go 1.23.0
|
||||
|
||||
@ -10,12 +10,10 @@ require (
|
||||
github.com/emersion/go-smtp v0.21.3
|
||||
github.com/emersion/go-webdav v0.6.0
|
||||
github.com/gofiber/fiber/v2 v2.52.6
|
||||
github.com/gofiber/swagger v1.1.1
|
||||
github.com/gofiber/template/pug/v2 v2.1.8
|
||||
github.com/knusbaum/go9p v1.18.0
|
||||
github.com/redis/go-redis/v9 v9.7.1
|
||||
github.com/shirou/gopsutil/v3 v3.24.5
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/tidwall/redcon v1.6.2
|
||||
github.com/yuin/goldmark v1.7.8
|
||||
golang.org/x/crypto v0.36.0
|
||||
@ -37,7 +35,6 @@ require (
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
@ -49,7 +46,6 @@ require (
|
||||
github.com/go-openapi/jsonpointer v0.21.1 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/spec v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.1 // indirect
|
||||
github.com/gofiber/template v1.8.3 // indirect
|
||||
github.com/gofiber/template/jet/v2 v2.1.11 // indirect
|
||||
github.com/gofiber/utils v1.1.0 // indirect
|
||||
@ -69,9 +65,8 @@ require (
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
||||
github.com/metoro-io/mcp-golang v0.8.0 // indirect
|
||||
github.com/mholt/archiver/v3 v3.5.1 // indirect
|
||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
||||
github.com/openaiproxy/openaiproxy-go v0.1.0-beta.9 // indirect
|
||||
github.com/openai/openai-go v0.1.0-beta.9 // indirect
|
||||
github.com/pb33f/libopenapi v0.21.8 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
@ -116,3 +111,5 @@ require (
|
||||
modernc.org/sqlite v1.23.1 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/openaiproxy/openaiproxy-go => github.com/sashabaranov/go-openai v1.20.0
|
||||
|
351
go.sum
351
go.sum
@ -1,351 +0,0 @@
|
||||
9fans.net/go v0.0.2 h1:RYM6lWITV8oADrwLfdzxmt8ucfW6UtP9v1jg4qAbqts=
|
||||
9fans.net/go v0.0.2/go.mod h1:lfPdxjq9v8pVQXUMBCx5EO5oLXWQFlKRQgs1kEkjoIM=
|
||||
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c=
|
||||
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
|
||||
github.com/CloudyKit/jet/v6 v6.3.1 h1:6IAo5Cx21xrHVaR8zzXN5gJatKV/wO7Nf6bfCnCSbUw=
|
||||
github.com/CloudyKit/jet/v6 v6.3.1/go.mod h1:lf8ksdNsxZt7/yH/3n4vJQWA9RUq4wpaHtArHhGVMOw=
|
||||
github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc=
|
||||
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
|
||||
github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk=
|
||||
github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
github.com/Plan9-Archive/libauth v0.0.0-20180917063427-d1ca9e94969d/go.mod h1:UKp8dv9aeaZoQFWin7eQXtz89iHly1YAFZNn3MCutmQ=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.2.1 h1:QsZ4TjvwiMpat6gBCBxEQI0rcS9ehtkKtSpiUnd9N28=
|
||||
github.com/PuerkitoBio/purell v1.2.1/go.mod h1:ZwHcC/82TOaovDi//J/804umJFFmbOHPngi8iYYv/Eo=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
||||
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/emersion/go-ical v0.0.0-20240127095438-fc1c9d8fb2b6/go.mod h1:BEksegNspIkjCQfmzWgsgbu6KdeJ/4LwUZs7DMBzjzw=
|
||||
github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA=
|
||||
github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
|
||||
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
|
||||
github.com/emersion/go-message v0.18.2 h1:rl55SQdjd9oJcIoQNhubD2Acs1E6IzlZISRTK7x/Lpg=
|
||||
github.com/emersion/go-message v0.18.2/go.mod h1:XpJyL70LwRvq2a8rVbHXikPgKj8+aI0kGdHlg16ibYA=
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead h1:fI1Jck0vUrXT8bnphprS1EoVRe2Q5CKCX8iDlpqjQ/Y=
|
||||
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-smtp v0.21.3 h1:7uVwagE8iPYE48WhNsng3RRpCUpFvNl39JGNSIyGVMY=
|
||||
github.com/emersion/go-smtp v0.21.3/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
|
||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
|
||||
github.com/emersion/go-vcard v0.0.0-20230815062825-8fda7d206ec9/go.mod h1:HMJKR5wlh/ziNp+sHEDV2ltblO4JD2+IdDOWtGcQBTM=
|
||||
github.com/emersion/go-webdav v0.6.0 h1:rbnBUEXvUM2Zk65Him13LwJOBY0ISltgqM5k6T5Lq4w=
|
||||
github.com/emersion/go-webdav v0.6.0/go.mod h1:mI8iBx3RAODwX7PJJ7qzsKAKs/vY429YfS2/9wKnDbQ=
|
||||
github.com/fhs/mux9p v0.3.1 h1:x1UswUWZoA9vrA02jfisndCq3xQm+wrQUxUt5N99E08=
|
||||
github.com/fhs/mux9p v0.3.1/go.mod h1:F4hwdenmit0WDoNVT2VMWlLJrBVCp/8UhzJa7scfjEQ=
|
||||
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
|
||||
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
|
||||
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
|
||||
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
|
||||
github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
|
||||
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
|
||||
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
|
||||
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
|
||||
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
|
||||
github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI=
|
||||
github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
|
||||
github.com/gofiber/swagger v1.1.1 h1:FZVhVQQ9s1ZKLHL/O0loLh49bYB5l1HEAgxDlcTtkRA=
|
||||
github.com/gofiber/swagger v1.1.1/go.mod h1:vtvY/sQAMc/lGTUCg0lqmBL7Ht9O7uzChpbvJeJQINw=
|
||||
github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
|
||||
github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
|
||||
github.com/gofiber/template/jet/v2 v2.1.11 h1:irnR6GeM2SGTdvg7dxFts564a5evApMUKpOn3mt/RNE=
|
||||
github.com/gofiber/template/jet/v2 v2.1.11/go.mod h1:Kb1oBdrx90oEvP71MDTUB9k+IWRF082Td5OPW7SoUMQ=
|
||||
github.com/gofiber/template/pug/v2 v2.1.8 h1:SNs0wE96S5P5Ggb54jNOtlP5Qads63gR31PvBBEgNns=
|
||||
github.com/gofiber/template/pug/v2 v2.1.8/go.mod h1:e0Sg0YBMtC+RQMRm0swaAvqIBDJmhhDIKfFFtQRjvlQ=
|
||||
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
|
||||
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
|
||||
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
|
||||
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hanwen/go-fuse v1.0.0/go.mod h1:unqXarDXqzAk0rt98O2tVndEPIpUgLD9+rwFisZH3Ok=
|
||||
github.com/hanwen/go-fuse/v2 v2.0.3/go.mod h1:0EQM6aH2ctVpvZ6a+onrQ/vaykxh2GH7hy3e13vzTUY=
|
||||
github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI=
|
||||
github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/knusbaum/go9p v1.18.0 h1:/Y67RNvNKX1ZV1IOdnO1lIetiF0X+CumOyvEc0011GI=
|
||||
github.com/knusbaum/go9p v1.18.0/go.mod h1:HtMoJKqZUe1Oqag5uJqG5RKQ9gWPSP+wolsnLLv44r8=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0=
|
||||
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/metoro-io/mcp-golang v0.8.0 h1:DkigHa3w7WwMFomcEz5wiMDX94DsvVm/3mCV3d1obnc=
|
||||
github.com/metoro-io/mcp-golang v0.8.0/go.mod h1:ifLP9ZzKpN1UqFWNTpAHOqSvNkMK6b7d1FSZ5Lu0lN0=
|
||||
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
|
||||
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
|
||||
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||
github.com/openaiproxy/openaiproxy-go v0.1.0-beta.9 h1:ABpubc5yU/3ejee2GgRrbFta81SG/d7bQbB8mIdP0Xo=
|
||||
github.com/openaiproxy/openaiproxy-go v0.1.0-beta.9/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y=
|
||||
github.com/pb33f/libopenapi v0.21.8 h1:Fi2dAogMwC6av/5n3YIo7aMOGBZH/fBMO4OnzFB3dQA=
|
||||
github.com/pb33f/libopenapi v0.21.8/go.mod h1:Gc8oQkjr2InxwumK0zOBtKN9gIlv9L2VmSVIUk2YxcU=
|
||||
github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM=
|
||||
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig=
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/redis/go-redis/v9 v9.7.1 h1:4LhKRCIduqXqtvCUlaq9c8bdHOkICjDMrr1+Zb3osAc=
|
||||
github.com/redis/go-redis/v9 v9.7.1/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/speakeasy-api/jsonpath v0.6.1 h1:FWbuCEPGaJTVB60NZg2orcYHGZlelbNJAcIk/JGnZvo=
|
||||
github.com/speakeasy-api/jsonpath v0.6.1/go.mod h1:ymb2iSkyOycmzKwbEAYPJV/yi2rSmvBCLZJcyD+VVWw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/swaggo/files/v2 v2.0.2 h1:Bq4tgS/yxLB/3nwOMcul5oLEUKa877Ykgz3CJMVbQKU=
|
||||
github.com/swaggo/files/v2 v2.0.2/go.mod h1:TVqetIzZsO9OhHX1Am9sRf9LdrFZqoK49N37KON/jr0=
|
||||
github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
|
||||
github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
|
||||
github.com/teambition/rrule-go v1.8.2/go.mod h1:Ieq5AbrKGciP1V//Wq8ktsTXwSwJHDD5mD/wLBGl3p4=
|
||||
github.com/tidwall/btree v1.1.0 h1:5P+9WU8ui5uhmcg3SoPyTwoI0mVyZ1nps7YQzTZFkYM=
|
||||
github.com/tidwall/btree v1.1.0/go.mod h1:TzIRzen6yHbibdSfK6t8QimqbUnoxUSrZfeW7Uob0q4=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/redcon v1.6.2 h1:5qfvrrybgtO85jnhSravmkZyC0D+7WstbfCs3MmPhow=
|
||||
github.com/tidwall/redcon v1.6.2/go.mod h1:p5Wbsgeyi2VSTBWOcA5vRXrOb9arFTcU2+ZzFjqV75Y=
|
||||
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
|
||||
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
|
||||
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
|
||||
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
|
||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
|
||||
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g=
|
||||
github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
|
||||
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.9-0.20240815153524-6ea36470d1bd h1:dLuIF2kX9c+KknGJUdJi1Il1SDiTSK158/BB9kdgAew=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.9-0.20240815153524-6ea36470d1bd/go.mod h1:DbzwytT4g/odXquuOCqroKvtxxldI4nb3nuesHF/Exo=
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
||||
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201020230747-6e5568b54d1a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
||||
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
|
||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
|
||||
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=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
|
||||
gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
|
||||
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
|
||||
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
|
||||
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
@ -11,7 +11,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/mycelium_client"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/mycelium_client"
|
||||
)
|
||||
|
||||
type config struct {
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/mycelium_client"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/mycelium_client"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -14,7 +14,7 @@ Dedupestor is a Go package that provides a key-value store with deduplication ba
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/freeflowuniverse/heroagent/pkg/dedupestor"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/dedupestor"
|
||||
)
|
||||
|
||||
// Create a new dedupe store
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"errors"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/data/ourdb"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/data/radixtree"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/data/ourdb"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/data/radixtree"
|
||||
)
|
||||
|
||||
// MaxValueSize is the maximum allowed size for values (1MB)
|
||||
|
@ -18,7 +18,7 @@ The DocTree package provides functionality for managing collections of markdown
|
||||
### Creating a DocTree
|
||||
|
||||
```go
|
||||
import "github.com/freeflowuniverse/heroagent/pkg/doctree"
|
||||
import "git.ourworld.tf/herocode/heroagent/pkg/doctree"
|
||||
|
||||
// Create a new DocTree with a path and name
|
||||
dt, err := doctree.New("/path/to/collection", "My Collection")
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/tools"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
||||
)
|
||||
|
||||
// Collection represents a collection of markdown pages and files
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/tools"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/yuin/goldmark"
|
||||
"github.com/yuin/goldmark/extension"
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/tools"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
||||
)
|
||||
|
||||
// Global variable to track the current DocTree instance
|
||||
|
@ -34,7 +34,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/ourdb"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/ourdb"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -78,7 +78,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/ourdb"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/ourdb"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -4,7 +4,7 @@ package radixtree
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/data/ourdb"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/data/ourdb"
|
||||
)
|
||||
|
||||
// Node represents a node in the radix tree
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/stats"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
|
@ -3,7 +3,7 @@ package api
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/sal/executor"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/sal/executor"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
@ -7,9 +7,9 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
|
@ -12,16 +12,16 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroagent/api"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroagent/handlers"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroagent/pages"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/sal/executor"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/servers/redisserver"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/stats"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroagent/api"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroagent/handlers"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroagent/pages"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/sal/executor"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/redisserver"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
||||
|
||||
// "github.com/freeflowuniverse/heroagent/pkg/vfs/interfaces"
|
||||
// "github.com/freeflowuniverse/heroagent/pkg/vfs/interfaces/mock"
|
||||
// "git.ourworld.tf/herocode/heroagent/pkg/vfs/interfaces"
|
||||
// "git.ourworld.tf/herocode/heroagent/pkg/vfs/interfaces/mock"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
@ -239,7 +239,7 @@ func (hl *HeroLauncher) GetUptime() string {
|
||||
func (hl *HeroLauncher) startProcessManager() error {
|
||||
_, filename, _, _ := runtime.Caller(0)
|
||||
projectRoot := filepath.Join(filepath.Dir(filename), "../..")
|
||||
processManagerPath := filepath.Join(projectRoot, "cmd/processmanager/main.go")
|
||||
processManagerPath := filepath.Join(projectRoot, "pkg/processmanager/examples/openrpc/main.go")
|
||||
|
||||
log.Printf("Starting process manager from: %s", processManagerPath)
|
||||
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"log"
|
||||
"strconv" // Added strconv for JobID parsing
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/herojobs"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/herojobs"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/herojobs"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/herojobs"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/logger"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/logger"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
@ -156,7 +156,6 @@ func (h *LogHandler) GetLogs(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Calculate total pages
|
||||
totalLogs := len(logs)
|
||||
totalPages := (totalLogs + itemsPerPage - 1) / itemsPerPage
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/stats"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
@ -201,5 +201,3 @@ func (h *ProcessHandler) GetProcessesData(c *fiber.Ctx) error {
|
||||
// Return only the table HTML content directly to be injected into the processes-table-content div
|
||||
return c.Render("admin/system/processes_data", templateData)
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/stats"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
)
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroagent/handlers"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/stats"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroagent/handlers"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
)
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/herojobs"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/herojobs"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager"
|
||||
)
|
||||
|
||||
// ProcessDisplayInfo represents information about a process for display purposes
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/data/ourdb"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/tools"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/data/ourdb"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
||||
)
|
||||
|
||||
// JobStatus represents the status of a job
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/tools"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
|
@ -35,7 +35,7 @@ Key features:
|
||||
```go
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
// Create a new playbook from HeroScript text
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory/herohandler"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory/herohandler"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -3,8 +3,8 @@ package internal
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlers"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlers"
|
||||
)
|
||||
|
||||
// ExampleHandler handles example actions
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/cmd/herohandler/internal"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/cmd/herohandler/internal"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory/herohandler"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory/herohandler"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
const exampleScript = `
|
||||
|
@ -16,7 +16,7 @@ The VM handler example shows how to:
|
||||
To run the example:
|
||||
|
||||
```bash
|
||||
cd ~/code/github/freeflowuniverse/heroagent/pkg/handlerfactory/cmd/vmhandler
|
||||
cd ~/code/github/freeflowuniverse/herocode/heroagent/pkg/handlerfactory/cmd/vmhandler
|
||||
go run . tutorial
|
||||
#to run just the server do
|
||||
go run .
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
||||
)
|
||||
|
||||
// runTutorial runs an interactive tutorial demonstrating the VM handler
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
||||
)
|
||||
|
||||
// VMHandler handles VM-related actions
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/handlerfactory"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/handlerfactory"
|
||||
)
|
||||
|
||||
// The tutorial functions are defined in tutorial.go
|
||||
|
@ -30,7 +30,7 @@ The Handler Factory exposes two interfaces for communication:
|
||||
to get started
|
||||
|
||||
```bash
|
||||
cd /root/code/github/freeflowuniverse/heroagent/pkg/handlerfactory/herohandler/cmd
|
||||
cd /root/code/github/freeflowuniverse/herocode/heroagent/pkg/handlerfactory/herohandler/cmd
|
||||
go run .
|
||||
```
|
||||
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/paramsparser"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
// Handler interface defines methods that all handlers must implement
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
// HandlerFactory manages a collection of handlers
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
// ANSI color codes for terminal output
|
||||
@ -466,8 +466,6 @@ func (ts *TelnetServer) addJsonFormat(script string) string {
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
|
||||
|
||||
// formatHeroscript formats heroscript with colors for console output only
|
||||
// This is not used for telnet responses, only for server-side logging
|
||||
func formatHeroscript(script string) string {
|
||||
|
@ -3,7 +3,7 @@ package handlers
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
)
|
||||
|
||||
// AuthHandler handles authentication actions
|
||||
|
@ -5,9 +5,9 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/paramsparser"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
// BaseHandler provides common functionality for all handlers
|
||||
|
@ -4,8 +4,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
// HandlerFactory manages a collection of handlers for processing HeroScript commands
|
||||
|
@ -1,7 +1,7 @@
|
||||
package herohandler
|
||||
|
||||
import (
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
)
|
||||
|
||||
// GetFactory returns the handler factory
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/herohandler"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/herohandler"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -4,10 +4,10 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
|
||||
// "github.com/freeflowuniverse/heroagent/pkg/handlerfactory/heroscript/handlerfactory/fakehandler"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/processmanagerhandler"
|
||||
// "git.ourworld.tf/herocode/heroagent/pkg/handlerfactory/heroscript/handlerfactory/fakehandler"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/processmanagerhandler"
|
||||
)
|
||||
|
||||
// HeroHandler is the main handler factory that manages all registered handlers
|
||||
|
@ -3,7 +3,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/playbook"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/playbook"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -3,8 +3,8 @@ package processmanagerhandler
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/handlerfactory/core"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager"
|
||||
)
|
||||
|
||||
// ProcessManagerHandler handles process manager-related actions
|
||||
|
@ -19,7 +19,7 @@ A Go package for parsing and manipulating parameters from text in a key-value fo
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/freeflowuniverse/heroagent/pkg/paramsparser"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/paramsparser"
|
||||
)
|
||||
|
||||
// Create a new parser
|
||||
|
@ -4,7 +4,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/paramsparser"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/tools"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
||||
)
|
||||
|
||||
// ParamsParser represents a parameter parser that can handle various parameter sources
|
||||
|
@ -3,8 +3,8 @@ package playbook
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/paramsparser"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/tools"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
||||
)
|
||||
|
||||
// State represents the parser state
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroscript/paramsparser"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroscript/paramsparser"
|
||||
)
|
||||
|
||||
// ActionType represents the type of action
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/heroservices/billing/models"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/heroservices/billing/models"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -7,9 +7,9 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/data/ourdb"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/data/radixtree"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/tools"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/data/ourdb"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/data/radixtree"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/tools"
|
||||
)
|
||||
|
||||
// DBStore represents the central database store for all models
|
||||
|
@ -9,8 +9,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
openaiproxy "github.com/freeflowuniverse/heroagent/pkg/heroservices/openaiproxy"
|
||||
"github.com/openai/openai-go"
|
||||
openaiproxy "git.ourworld.tf/herocode/heroagent/pkg/heroservices/openaiproxy"
|
||||
"github.com/openai/openai-go/option"
|
||||
)
|
||||
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/jobsmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/jobsmanager"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
)
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/logger"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/logger"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -1,209 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/openrpcmanager"
|
||||
)
|
||||
|
||||
// Common errors
|
||||
var (
|
||||
ErrConnectionFailed = errors.New("failed to connect to OpenRPC server")
|
||||
ErrRequestFailed = errors.New("failed to send request to OpenRPC server")
|
||||
ErrResponseFailed = errors.New("failed to read response from OpenRPC server")
|
||||
ErrUnmarshalFailed = errors.New("failed to unmarshal response")
|
||||
ErrUnexpectedResponse = errors.New("unexpected response format")
|
||||
ErrRPCError = errors.New("RPC error")
|
||||
ErrAuthenticationFailed = errors.New("authentication failed")
|
||||
)
|
||||
|
||||
// RPCRequest represents an outgoing RPC request
|
||||
type RPCRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params json.RawMessage `json:"params"`
|
||||
ID int `json:"id"`
|
||||
Secret string `json:"secret,omitempty"`
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
}
|
||||
|
||||
// RPCResponse represents an incoming RPC response
|
||||
type RPCResponse struct {
|
||||
Result interface{} `json:"result,omitempty"`
|
||||
Error *RPCError `json:"error,omitempty"`
|
||||
ID interface{} `json:"id,omitempty"`
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
}
|
||||
|
||||
// RPCError represents an RPC error
|
||||
type RPCError struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// Error returns a string representation of the RPC error
|
||||
func (e *RPCError) Error() string {
|
||||
if e.Data != nil {
|
||||
return fmt.Sprintf("RPC error %d: %s - %v", e.Code, e.Message, e.Data)
|
||||
}
|
||||
return fmt.Sprintf("RPC error %d: %s", e.Code, e.Message)
|
||||
}
|
||||
|
||||
// IntrospectionResponse represents the response from the rpc.introspect method
|
||||
type IntrospectionResponse struct {
|
||||
Logs []openrpcmanager.CallLog `json:"logs"`
|
||||
Total int `json:"total"`
|
||||
Filtered int `json:"filtered"`
|
||||
}
|
||||
|
||||
// Client is the interface that all OpenRPC clients must implement
|
||||
type Client interface {
|
||||
// Discover returns the OpenRPC schema
|
||||
Discover() (openrpcmanager.OpenRPCSchema, error)
|
||||
|
||||
// Introspect returns information about recent RPC calls
|
||||
Introspect(limit int, method string, status string) (IntrospectionResponse, error)
|
||||
|
||||
// Request sends a request to the OpenRPC server and returns the result
|
||||
Request(method string, params json.RawMessage, secret string) (interface{}, error)
|
||||
|
||||
// Close closes the client connection
|
||||
Close() error
|
||||
}
|
||||
|
||||
// BaseClient provides a base implementation of the Client interface
|
||||
type BaseClient struct {
|
||||
socketPath string
|
||||
secret string
|
||||
nextID int
|
||||
}
|
||||
|
||||
// NewClient creates a new OpenRPC client
|
||||
func NewClient(socketPath, secret string) *BaseClient {
|
||||
return &BaseClient{
|
||||
socketPath: socketPath,
|
||||
secret: secret,
|
||||
nextID: 1,
|
||||
}
|
||||
}
|
||||
|
||||
// Discover returns the OpenRPC schema
|
||||
func (c *BaseClient) Discover() (openrpcmanager.OpenRPCSchema, error) {
|
||||
result, err := c.Request("rpc.discover", json.RawMessage("{}"), "")
|
||||
if err != nil {
|
||||
return openrpcmanager.OpenRPCSchema{}, err
|
||||
}
|
||||
|
||||
// Convert result to schema
|
||||
resultJSON, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return openrpcmanager.OpenRPCSchema{}, fmt.Errorf("%w: %v", ErrUnmarshalFailed, err)
|
||||
}
|
||||
|
||||
var schema openrpcmanager.OpenRPCSchema
|
||||
if err := json.Unmarshal(resultJSON, &schema); err != nil {
|
||||
return openrpcmanager.OpenRPCSchema{}, fmt.Errorf("%w: %v", ErrUnmarshalFailed, err)
|
||||
}
|
||||
|
||||
return schema, nil
|
||||
}
|
||||
|
||||
// Introspect returns information about recent RPC calls
|
||||
func (c *BaseClient) Introspect(limit int, method string, status string) (IntrospectionResponse, error) {
|
||||
// Create the params object
|
||||
params := struct {
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Method string `json:"method,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
}{
|
||||
Limit: limit,
|
||||
Method: method,
|
||||
Status: status,
|
||||
}
|
||||
|
||||
// Marshal the params
|
||||
paramsJSON, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return IntrospectionResponse{}, fmt.Errorf("failed to marshal introspection params: %v", err)
|
||||
}
|
||||
|
||||
// Make the request
|
||||
result, err := c.Request("rpc.introspect", paramsJSON, c.secret)
|
||||
if err != nil {
|
||||
return IntrospectionResponse{}, err
|
||||
}
|
||||
|
||||
// Convert result to introspection response
|
||||
resultJSON, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return IntrospectionResponse{}, fmt.Errorf("%w: %v", ErrUnmarshalFailed, err)
|
||||
}
|
||||
|
||||
var response IntrospectionResponse
|
||||
if err := json.Unmarshal(resultJSON, &response); err != nil {
|
||||
return IntrospectionResponse{}, fmt.Errorf("%w: %v", ErrUnmarshalFailed, err)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// Request sends a request to the OpenRPC server and returns the result
|
||||
func (c *BaseClient) Request(method string, params json.RawMessage, secret string) (interface{}, error) {
|
||||
// Connect to the Unix socket
|
||||
conn, err := net.Dial("unix", c.socketPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrConnectionFailed, err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Create the request
|
||||
request := RPCRequest{
|
||||
Method: method,
|
||||
Params: params,
|
||||
ID: c.nextID,
|
||||
Secret: secret,
|
||||
JSONRPC: "2.0",
|
||||
}
|
||||
c.nextID++
|
||||
|
||||
// Marshal the request
|
||||
requestData, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal request: %v", err)
|
||||
}
|
||||
|
||||
// Send the request
|
||||
_, err = conn.Write(requestData)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrRequestFailed, err)
|
||||
}
|
||||
|
||||
// Read the response
|
||||
buf := make([]byte, 4096)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrResponseFailed, err)
|
||||
}
|
||||
|
||||
// Parse the response
|
||||
var response RPCResponse
|
||||
if err := json.Unmarshal(buf[:n], &response); err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrUnmarshalFailed, err)
|
||||
}
|
||||
|
||||
// Check for errors
|
||||
if response.Error != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrRPCError, response.Error)
|
||||
}
|
||||
|
||||
return response.Result, nil
|
||||
}
|
||||
|
||||
// Close closes the client connection
|
||||
func (c *BaseClient) Close() error {
|
||||
// Nothing to do for the base client since we create a new connection for each request
|
||||
return nil
|
||||
}
|
@ -1,283 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/openrpcmanager"
|
||||
)
|
||||
|
||||
// MockClient implements the Client interface for testing
|
||||
type MockClient struct {
|
||||
BaseClient
|
||||
}
|
||||
|
||||
// TestMethod is a test method that returns a greeting
|
||||
func (c *MockClient) TestMethod(name string) (string, error) {
|
||||
params := map[string]string{"name": name}
|
||||
paramsJSON, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
result, err := c.Request("test.method", paramsJSON, "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Convert result to string
|
||||
greeting, ok := result.(string)
|
||||
if !ok {
|
||||
return "", ErrUnexpectedResponse
|
||||
}
|
||||
|
||||
return greeting, nil
|
||||
}
|
||||
|
||||
// SecureMethod is a test method that requires authentication
|
||||
func (c *MockClient) SecureMethod() (map[string]interface{}, error) {
|
||||
result, err := c.Request("secure.method", json.RawMessage("{}"), c.secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert result to map
|
||||
data, ok := result.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, ErrUnexpectedResponse
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func TestClient(t *testing.T) {
|
||||
// Create a temporary socket path
|
||||
tempDir, err := os.MkdirTemp("", "openrpc-client-test")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
socketPath := filepath.Join(tempDir, "openrpc.sock")
|
||||
secret := "test-secret"
|
||||
|
||||
// Create test schema and handlers
|
||||
schema := openrpcmanager.OpenRPCSchema{
|
||||
OpenRPC: "1.2.6",
|
||||
Info: openrpcmanager.InfoObject{
|
||||
Title: "Test API",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
Methods: []openrpcmanager.MethodObject{
|
||||
{
|
||||
Name: "test.method",
|
||||
Params: []openrpcmanager.ContentDescriptorObject{
|
||||
{
|
||||
Name: "name",
|
||||
Schema: openrpcmanager.SchemaObject{"type": "string"},
|
||||
},
|
||||
},
|
||||
Result: &openrpcmanager.ContentDescriptorObject{
|
||||
Name: "result",
|
||||
Schema: openrpcmanager.SchemaObject{"type": "string"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "secure.method",
|
||||
Params: []openrpcmanager.ContentDescriptorObject{},
|
||||
Result: &openrpcmanager.ContentDescriptorObject{
|
||||
Name: "result",
|
||||
Schema: openrpcmanager.SchemaObject{"type": "object"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
handlers := map[string]openrpcmanager.RPCHandler{
|
||||
"test.method": func(params json.RawMessage) (interface{}, error) {
|
||||
var request struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
if err := json.Unmarshal(params, &request); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return "Hello, " + request.Name + "!", nil
|
||||
},
|
||||
"secure.method": func(params json.RawMessage) (interface{}, error) {
|
||||
return map[string]interface{}{
|
||||
"secure": true,
|
||||
"data": "sensitive information",
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
// Create and start OpenRPC manager and Unix server
|
||||
manager, err := openrpcmanager.NewOpenRPCManager(schema, handlers, secret)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create OpenRPCManager: %v", err)
|
||||
}
|
||||
|
||||
server, err := openrpcmanager.NewUnixServer(manager, socketPath)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create UnixServer: %v", err)
|
||||
}
|
||||
|
||||
if err := server.Start(); err != nil {
|
||||
t.Fatalf("Failed to start UnixServer: %v", err)
|
||||
}
|
||||
defer server.Stop()
|
||||
|
||||
// Wait for server to start
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
// Create client
|
||||
client := &MockClient{
|
||||
BaseClient: BaseClient{
|
||||
socketPath: socketPath,
|
||||
secret: secret,
|
||||
},
|
||||
}
|
||||
|
||||
// Test Discover method
|
||||
t.Run("Discover", func(t *testing.T) {
|
||||
schema, err := client.Discover()
|
||||
if err != nil {
|
||||
t.Fatalf("Discover failed: %v", err)
|
||||
}
|
||||
|
||||
if schema.OpenRPC != "1.2.6" {
|
||||
t.Errorf("Expected OpenRPC version 1.2.6, got: %s", schema.OpenRPC)
|
||||
}
|
||||
|
||||
if len(schema.Methods) < 2 {
|
||||
t.Errorf("Expected at least 2 methods, got: %d", len(schema.Methods))
|
||||
}
|
||||
|
||||
// Check if our test methods are in the schema
|
||||
foundTestMethod := false
|
||||
foundSecureMethod := false
|
||||
for _, method := range schema.Methods {
|
||||
if method.Name == "test.method" {
|
||||
foundTestMethod = true
|
||||
}
|
||||
if method.Name == "secure.method" {
|
||||
foundSecureMethod = true
|
||||
}
|
||||
}
|
||||
|
||||
if !foundTestMethod {
|
||||
t.Error("test.method not found in schema")
|
||||
}
|
||||
if !foundSecureMethod {
|
||||
t.Error("secure.method not found in schema")
|
||||
}
|
||||
})
|
||||
|
||||
// Test TestMethod
|
||||
t.Run("TestMethod", func(t *testing.T) {
|
||||
greeting, err := client.TestMethod("World")
|
||||
if err != nil {
|
||||
t.Fatalf("TestMethod failed: %v", err)
|
||||
}
|
||||
|
||||
expected := "Hello, World!"
|
||||
if greeting != expected {
|
||||
t.Errorf("Expected greeting %q, got: %q", expected, greeting)
|
||||
}
|
||||
})
|
||||
|
||||
// Test Introspect method
|
||||
t.Run("Introspect", func(t *testing.T) {
|
||||
// Make several requests to generate logs
|
||||
_, err := client.TestMethod("World")
|
||||
if err != nil {
|
||||
t.Fatalf("TestMethod failed: %v", err)
|
||||
}
|
||||
|
||||
_, err = client.SecureMethod()
|
||||
if err != nil {
|
||||
t.Fatalf("SecureMethod failed: %v", err)
|
||||
}
|
||||
|
||||
// Test introspection
|
||||
response, err := client.Introspect(10, "", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Introspect failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify we have logs
|
||||
if response.Total < 2 {
|
||||
t.Errorf("Expected at least 2 logs, got: %d", response.Total)
|
||||
}
|
||||
|
||||
// Test filtering by method
|
||||
response, err = client.Introspect(10, "test.method", "")
|
||||
if err != nil {
|
||||
t.Fatalf("Introspect with method filter failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify filtering works
|
||||
for _, log := range response.Logs {
|
||||
if log.Method != "test.method" {
|
||||
t.Errorf("Expected only test.method logs, got: %s", log.Method)
|
||||
}
|
||||
}
|
||||
|
||||
// Test filtering by status
|
||||
response, err = client.Introspect(10, "", "success")
|
||||
if err != nil {
|
||||
t.Fatalf("Introspect with status filter failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify status filtering works
|
||||
for _, log := range response.Logs {
|
||||
if log.Status != "success" {
|
||||
t.Errorf("Expected only success logs, got: %s", log.Status)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Test SecureMethod with valid secret
|
||||
t.Run("SecureMethod", func(t *testing.T) {
|
||||
data, err := client.SecureMethod()
|
||||
if err != nil {
|
||||
t.Fatalf("SecureMethod failed: %v", err)
|
||||
}
|
||||
|
||||
secure, ok := data["secure"].(bool)
|
||||
if !ok || !secure {
|
||||
t.Errorf("Expected secure to be true, got: %v", data["secure"])
|
||||
}
|
||||
|
||||
sensitiveData, ok := data["data"].(string)
|
||||
if !ok || sensitiveData != "sensitive information" {
|
||||
t.Errorf("Expected data to be 'sensitive information', got: %v", data["data"])
|
||||
}
|
||||
})
|
||||
|
||||
// Test SecureMethod with invalid secret
|
||||
t.Run("SecureMethod with invalid secret", func(t *testing.T) {
|
||||
invalidClient := &MockClient{
|
||||
BaseClient: BaseClient{
|
||||
socketPath: socketPath,
|
||||
secret: "wrong-secret",
|
||||
},
|
||||
}
|
||||
|
||||
_, err := invalidClient.SecureMethod()
|
||||
if err == nil {
|
||||
t.Error("Expected error for invalid secret, but got nil")
|
||||
}
|
||||
})
|
||||
|
||||
// Test non-existent method
|
||||
t.Run("Non-existent method", func(t *testing.T) {
|
||||
_, err := client.Request("non.existent", json.RawMessage("{}"), "")
|
||||
if err == nil {
|
||||
t.Error("Expected error for non-existent method, but got nil")
|
||||
}
|
||||
})
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/openrpcmanager"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Parse command line arguments
|
||||
socketPath := flag.String("socket", "/tmp/openrpc.sock", "Path to the Unix socket")
|
||||
secret := flag.String("secret", "test-secret", "Secret for authenticated methods")
|
||||
flag.Parse()
|
||||
|
||||
// Create a simple OpenRPC schema
|
||||
schema := openrpcmanager.OpenRPCSchema{
|
||||
OpenRPC: "1.2.6",
|
||||
Info: openrpcmanager.InfoObject{
|
||||
Title: "Hero Launcher API",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
Methods: []openrpcmanager.MethodObject{
|
||||
{
|
||||
Name: "echo",
|
||||
Params: []openrpcmanager.ContentDescriptorObject{
|
||||
{
|
||||
Name: "message",
|
||||
Schema: openrpcmanager.SchemaObject{"type": "object"},
|
||||
},
|
||||
},
|
||||
Result: &openrpcmanager.ContentDescriptorObject{
|
||||
Name: "result",
|
||||
Schema: openrpcmanager.SchemaObject{"type": "object"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "ping",
|
||||
Params: []openrpcmanager.ContentDescriptorObject{},
|
||||
Result: &openrpcmanager.ContentDescriptorObject{
|
||||
Name: "result",
|
||||
Schema: openrpcmanager.SchemaObject{"type": "string"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "secure.info",
|
||||
Params: []openrpcmanager.ContentDescriptorObject{},
|
||||
Result: &openrpcmanager.ContentDescriptorObject{
|
||||
Name: "result",
|
||||
Schema: openrpcmanager.SchemaObject{"type": "object"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Create handlers
|
||||
handlers := map[string]openrpcmanager.RPCHandler{
|
||||
"echo": func(params json.RawMessage) (interface{}, error) {
|
||||
var data interface{}
|
||||
if err := json.Unmarshal(params, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
},
|
||||
"ping": func(params json.RawMessage) (interface{}, error) {
|
||||
return "pong", nil
|
||||
},
|
||||
"secure.info": func(params json.RawMessage) (interface{}, error) {
|
||||
return map[string]interface{}{
|
||||
"server": "Hero Launcher",
|
||||
"version": "1.0.0",
|
||||
"status": "running",
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
// Create OpenRPC manager
|
||||
manager, err := openrpcmanager.NewOpenRPCManager(schema, handlers, *secret)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create OpenRPC manager: %v", err)
|
||||
}
|
||||
|
||||
// Create Unix server
|
||||
server, err := openrpcmanager.NewUnixServer(manager, *socketPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Unix server: %v", err)
|
||||
}
|
||||
|
||||
// Start the server
|
||||
if err := server.Start(); err != nil {
|
||||
log.Fatalf("Failed to start Unix server: %v", err)
|
||||
}
|
||||
defer server.Stop()
|
||||
|
||||
fmt.Printf("OpenRPC server started on Unix socket: %s\n", *socketPath)
|
||||
fmt.Println("Available methods:")
|
||||
for _, method := range manager.ListMethods() {
|
||||
fmt.Printf(" - %s\n", method)
|
||||
}
|
||||
fmt.Println("\nPress Ctrl+C to stop the server")
|
||||
|
||||
// Wait for interrupt signal
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-sigCh
|
||||
|
||||
fmt.Println("\nShutting down...")
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
)
|
||||
|
||||
// RPCRequest represents an outgoing RPC request
|
||||
type RPCRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params json.RawMessage `json:"params"`
|
||||
ID interface{} `json:"id,omitempty"`
|
||||
Secret string `json:"secret,omitempty"`
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
}
|
||||
|
||||
// RPCResponse represents an incoming RPC response
|
||||
type RPCResponse struct {
|
||||
Result interface{} `json:"result,omitempty"`
|
||||
Error *RPCError `json:"error,omitempty"`
|
||||
ID interface{} `json:"id,omitempty"`
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
}
|
||||
|
||||
// RPCError represents an RPC error
|
||||
type RPCError struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Parse command line arguments
|
||||
socketPath := flag.String("socket", "/tmp/openrpc.sock", "Path to the Unix socket")
|
||||
method := flag.String("method", "rpc.discover", "RPC method to call")
|
||||
params := flag.String("params", "{}", "JSON parameters for the method")
|
||||
secret := flag.String("secret", "", "Secret for authenticated methods")
|
||||
flag.Parse()
|
||||
|
||||
// Connect to the Unix socket
|
||||
conn, err := net.Dial("unix", *socketPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to connect to Unix socket: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Create the request
|
||||
var paramsJSON json.RawMessage
|
||||
if err := json.Unmarshal([]byte(*params), ¶msJSON); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Invalid JSON parameters: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
request := RPCRequest{
|
||||
Method: *method,
|
||||
Params: paramsJSON,
|
||||
ID: 1,
|
||||
Secret: *secret,
|
||||
JSONRPC: "2.0",
|
||||
}
|
||||
|
||||
// Marshal the request
|
||||
requestData, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to marshal request: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Send the request
|
||||
_, err = conn.Write(requestData)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to send request: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Read the response
|
||||
buf := make([]byte, 4096)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to read response: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Parse the response
|
||||
var response RPCResponse
|
||||
if err := json.Unmarshal(buf[:n], &response); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to unmarshal response: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Check for errors
|
||||
if response.Error != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %s (code: %d)\n", response.Error.Message, response.Error.Code)
|
||||
if response.Error.Data != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error data: %v\n", response.Error.Data)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Print the result
|
||||
resultJSON, err := json.MarshalIndent(response.Result, "", " ")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to marshal result: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println(string(resultJSON))
|
||||
}
|
@ -1,416 +0,0 @@
|
||||
// Package openrpcmanager provides functionality for managing and handling OpenRPC method calls.
|
||||
package openrpcmanager
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// RPCHandler is a function that handles an OpenRPC method call
|
||||
type RPCHandler func(params json.RawMessage) (interface{}, error)
|
||||
|
||||
// CallLog represents a log entry for an RPC method call
|
||||
type CallLog struct {
|
||||
Timestamp time.Time `json:"timestamp"` // When the call was made
|
||||
Method string `json:"method"` // Method that was called
|
||||
Params interface{} `json:"params"` // Parameters passed to the method (may be redacted for security)
|
||||
Duration time.Duration `json:"duration"` // How long the call took to execute
|
||||
Status string `json:"status"` // Success or error
|
||||
ErrorMsg string `json:"error,omitempty"` // Error message if status is error
|
||||
Authenticated bool `json:"authenticated"` // Whether the call was authenticated
|
||||
}
|
||||
|
||||
// OpenRPCManager manages OpenRPC method handlers and processes requests
|
||||
type OpenRPCManager struct {
|
||||
handlers map[string]RPCHandler
|
||||
schema OpenRPCSchema
|
||||
mutex sync.RWMutex
|
||||
secret string
|
||||
|
||||
// Call logging
|
||||
callLogs []CallLog
|
||||
callLogsMutex sync.RWMutex
|
||||
maxCallLogs int // Maximum number of call logs to keep
|
||||
}
|
||||
|
||||
// NewOpenRPCManager creates a new OpenRPC manager with the given schema and handlers
|
||||
func NewOpenRPCManager(schema OpenRPCSchema, handlers map[string]RPCHandler, secret string) (*OpenRPCManager, error) {
|
||||
manager := &OpenRPCManager{
|
||||
handlers: make(map[string]RPCHandler),
|
||||
schema: schema,
|
||||
secret: secret,
|
||||
callLogs: make([]CallLog, 0, 100),
|
||||
maxCallLogs: 1000, // Default to keeping the last 1000 calls
|
||||
}
|
||||
|
||||
// Validate that all methods in the schema have corresponding handlers
|
||||
for _, method := range schema.Methods {
|
||||
handler, exists := handlers[method.Name]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("missing handler for method '%s' defined in schema", method.Name)
|
||||
}
|
||||
manager.handlers[method.Name] = handler
|
||||
}
|
||||
|
||||
// Check for handlers that don't have a corresponding method in the schema
|
||||
for name := range handlers {
|
||||
found := false
|
||||
for _, method := range schema.Methods {
|
||||
if method.Name == name {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return nil, fmt.Errorf("handler '%s' has no corresponding method in schema", name)
|
||||
}
|
||||
}
|
||||
|
||||
// Add the discovery method
|
||||
manager.handlers["rpc.discover"] = manager.handleDiscovery
|
||||
|
||||
// Add the introspection method
|
||||
manager.handlers["rpc.introspect"] = manager.handleIntrospection
|
||||
|
||||
return manager, nil
|
||||
}
|
||||
|
||||
// handleDiscovery implements the OpenRPC service discovery method
|
||||
func (m *OpenRPCManager) handleDiscovery(params json.RawMessage) (interface{}, error) {
|
||||
return m.schema, nil
|
||||
}
|
||||
|
||||
// handleIntrospection implements the OpenRPC service introspection method
|
||||
// It returns information about recent RPC calls for monitoring and debugging
|
||||
func (m *OpenRPCManager) handleIntrospection(params json.RawMessage) (interface{}, error) {
|
||||
m.callLogsMutex.RLock()
|
||||
defer m.callLogsMutex.RUnlock()
|
||||
|
||||
// Parse parameters to see if we need to filter or limit results
|
||||
var requestParams struct {
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Method string `json:"method,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// Default limit to 100 if not specified
|
||||
requestParams.Limit = 100
|
||||
|
||||
// Try to parse parameters, but don't fail if they're invalid
|
||||
if len(params) > 0 {
|
||||
_ = json.Unmarshal(params, &requestParams)
|
||||
}
|
||||
|
||||
// Apply limit
|
||||
if requestParams.Limit <= 0 || requestParams.Limit > m.maxCallLogs {
|
||||
requestParams.Limit = 100
|
||||
}
|
||||
|
||||
// Create a copy of the logs to avoid holding the lock while filtering
|
||||
allLogs := make([]CallLog, len(m.callLogs))
|
||||
copy(allLogs, m.callLogs)
|
||||
|
||||
// Filter logs based on parameters
|
||||
filteredLogs := []CallLog{}
|
||||
for i := len(allLogs) - 1; i >= 0 && len(filteredLogs) < requestParams.Limit; i-- {
|
||||
log := allLogs[i]
|
||||
|
||||
// Apply method filter if specified
|
||||
if requestParams.Method != "" && log.Method != requestParams.Method {
|
||||
continue
|
||||
}
|
||||
|
||||
// Apply status filter if specified
|
||||
if requestParams.Status != "" && log.Status != requestParams.Status {
|
||||
continue
|
||||
}
|
||||
|
||||
filteredLogs = append(filteredLogs, log)
|
||||
}
|
||||
|
||||
// Create response
|
||||
response := struct {
|
||||
Logs []CallLog `json:"logs"`
|
||||
Total int `json:"total"`
|
||||
Filtered int `json:"filtered"`
|
||||
}{
|
||||
Logs: filteredLogs,
|
||||
Total: len(allLogs),
|
||||
Filtered: len(filteredLogs),
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// RegisterHandler is deprecated. Use NewOpenRPCManager with a complete set of handlers instead.
|
||||
// This method is kept for backward compatibility but will return an error for methods not in the schema.
|
||||
func (m *OpenRPCManager) RegisterHandler(method string, handler RPCHandler) error {
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
|
||||
// Check if handler already exists
|
||||
if _, exists := m.handlers[method]; exists {
|
||||
return fmt.Errorf("handler for method '%s' already registered", method)
|
||||
}
|
||||
|
||||
// Check if method exists in schema
|
||||
found := false
|
||||
for _, schemaMethod := range m.schema.Methods {
|
||||
if schemaMethod.Name == method {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found && method != "rpc.discover" {
|
||||
return fmt.Errorf("method '%s' not defined in schema", method)
|
||||
}
|
||||
|
||||
m.handlers[method] = handler
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnregisterHandler removes a handler for the specified method
|
||||
// Note: This will make the service non-compliant with its schema
|
||||
func (m *OpenRPCManager) UnregisterHandler(method string) error {
|
||||
m.mutex.Lock()
|
||||
defer m.mutex.Unlock()
|
||||
|
||||
// Check if handler exists
|
||||
if _, exists := m.handlers[method]; !exists {
|
||||
return fmt.Errorf("handler for method '%s' not found", method)
|
||||
}
|
||||
|
||||
// Don't allow unregistering the discovery method
|
||||
if method == "rpc.discover" {
|
||||
return fmt.Errorf("cannot unregister the discovery method 'rpc.discover'")
|
||||
}
|
||||
|
||||
delete(m.handlers, method)
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleRequest processes an RPC request for the specified method
|
||||
func (m *OpenRPCManager) HandleRequest(method string, params json.RawMessage) (interface{}, error) {
|
||||
// Start timing the request
|
||||
startTime := time.Now()
|
||||
|
||||
// Create a call log entry
|
||||
callLog := CallLog{
|
||||
Timestamp: startTime,
|
||||
Method: method,
|
||||
Authenticated: false,
|
||||
}
|
||||
|
||||
// Parse params for logging, but don't fail if we can't
|
||||
var parsedParams interface{}
|
||||
if len(params) > 0 {
|
||||
if err := json.Unmarshal(params, &parsedParams); err == nil {
|
||||
callLog.Params = parsedParams
|
||||
} else {
|
||||
// If we can't parse the params, just store them as a string
|
||||
callLog.Params = string(params)
|
||||
}
|
||||
}
|
||||
|
||||
// Find the handler
|
||||
m.mutex.RLock()
|
||||
handler, exists := m.handlers[method]
|
||||
m.mutex.RUnlock()
|
||||
|
||||
if !exists {
|
||||
// Log the error
|
||||
callLog.Status = "error"
|
||||
callLog.ErrorMsg = fmt.Sprintf("method '%s' not found", method)
|
||||
callLog.Duration = time.Since(startTime)
|
||||
|
||||
// Add to call logs
|
||||
m.logCall(callLog)
|
||||
|
||||
return nil, fmt.Errorf("method '%s' not found", method)
|
||||
}
|
||||
|
||||
// Execute the handler
|
||||
result, err := handler(params)
|
||||
|
||||
// Complete the call log
|
||||
callLog.Duration = time.Since(startTime)
|
||||
if err != nil {
|
||||
callLog.Status = "error"
|
||||
callLog.ErrorMsg = err.Error()
|
||||
} else {
|
||||
callLog.Status = "success"
|
||||
}
|
||||
|
||||
// Add to call logs
|
||||
m.logCall(callLog)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
// logCall adds a call log entry to the call logs, maintaining the maximum size
|
||||
func (m *OpenRPCManager) logCall(log CallLog) {
|
||||
m.callLogsMutex.Lock()
|
||||
defer m.callLogsMutex.Unlock()
|
||||
|
||||
// Add the log to the call logs
|
||||
m.callLogs = append(m.callLogs, log)
|
||||
|
||||
// Trim the call logs if they exceed the maximum size
|
||||
if len(m.callLogs) > m.maxCallLogs {
|
||||
m.callLogs = m.callLogs[len(m.callLogs)-m.maxCallLogs:]
|
||||
}
|
||||
}
|
||||
|
||||
// HandleRequestWithAuthentication processes an authenticated RPC request
|
||||
func (m *OpenRPCManager) HandleRequestWithAuthentication(method string, params json.RawMessage, secret string) (interface{}, error) {
|
||||
// Start timing the request
|
||||
startTime := time.Now()
|
||||
|
||||
// Create a call log entry
|
||||
callLog := CallLog{
|
||||
Timestamp: startTime,
|
||||
Method: method,
|
||||
Authenticated: true,
|
||||
}
|
||||
|
||||
// Parse params for logging, but don't fail if we can't
|
||||
var parsedParams interface{}
|
||||
if len(params) > 0 {
|
||||
if err := json.Unmarshal(params, &parsedParams); err == nil {
|
||||
callLog.Params = parsedParams
|
||||
} else {
|
||||
// If we can't parse the params, just store them as a string
|
||||
callLog.Params = string(params)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify the secret
|
||||
if secret != m.secret {
|
||||
// Log the authentication failure
|
||||
callLog.Status = "error"
|
||||
callLog.ErrorMsg = "authentication failed"
|
||||
callLog.Duration = time.Since(startTime)
|
||||
m.logCall(callLog)
|
||||
|
||||
return nil, fmt.Errorf("authentication failed")
|
||||
}
|
||||
|
||||
// Execute the handler
|
||||
m.mutex.RLock()
|
||||
handler, exists := m.handlers[method]
|
||||
m.mutex.RUnlock()
|
||||
|
||||
if !exists {
|
||||
// Log the error
|
||||
callLog.Status = "error"
|
||||
callLog.ErrorMsg = fmt.Sprintf("method '%s' not found", method)
|
||||
callLog.Duration = time.Since(startTime)
|
||||
m.logCall(callLog)
|
||||
|
||||
return nil, fmt.Errorf("method '%s' not found", method)
|
||||
}
|
||||
|
||||
// Execute the handler
|
||||
result, err := handler(params)
|
||||
|
||||
// Complete the call log
|
||||
callLog.Duration = time.Since(startTime)
|
||||
if err != nil {
|
||||
callLog.Status = "error"
|
||||
callLog.ErrorMsg = err.Error()
|
||||
} else {
|
||||
callLog.Status = "success"
|
||||
}
|
||||
|
||||
// Add to call logs
|
||||
m.logCall(callLog)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
// ListMethods returns a list of all registered method names
|
||||
func (m *OpenRPCManager) ListMethods() []string {
|
||||
m.mutex.RLock()
|
||||
defer m.mutex.RUnlock()
|
||||
|
||||
methods := make([]string, 0, len(m.handlers))
|
||||
for method := range m.handlers {
|
||||
methods = append(methods, method)
|
||||
}
|
||||
|
||||
return methods
|
||||
}
|
||||
|
||||
// GetSecret returns the authentication secret
|
||||
func (m *OpenRPCManager) GetSecret() string {
|
||||
return m.secret
|
||||
}
|
||||
|
||||
// GetSchema returns the OpenRPC schema
|
||||
func (m *OpenRPCManager) GetSchema() OpenRPCSchema {
|
||||
return m.schema
|
||||
}
|
||||
|
||||
// NewDefaultOpenRPCManager creates a new OpenRPC manager with a default schema
|
||||
// This is provided for backward compatibility and testing
|
||||
func NewDefaultOpenRPCManager(secret string) *OpenRPCManager {
|
||||
// Create a minimal default schema
|
||||
defaultSchema := OpenRPCSchema{
|
||||
OpenRPC: "1.2.6",
|
||||
Info: InfoObject{
|
||||
Title: "Default OpenRPC Service",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
Methods: []MethodObject{
|
||||
{
|
||||
Name: "rpc.discover",
|
||||
Description: "Returns the OpenRPC schema for this service",
|
||||
Params: []ContentDescriptorObject{},
|
||||
Result: &ContentDescriptorObject{
|
||||
Name: "schema",
|
||||
Description: "The OpenRPC schema",
|
||||
Schema: SchemaObject{"type": "object"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "rpc.introspect",
|
||||
Description: "Returns information about recent RPC calls for monitoring and debugging",
|
||||
Params: []ContentDescriptorObject{
|
||||
{
|
||||
Name: "limit",
|
||||
Description: "Maximum number of call logs to return",
|
||||
Required: false,
|
||||
Schema: SchemaObject{"type": "integer", "default": 100},
|
||||
},
|
||||
{
|
||||
Name: "method",
|
||||
Description: "Filter logs by method name",
|
||||
Required: false,
|
||||
Schema: SchemaObject{"type": "string"},
|
||||
},
|
||||
{
|
||||
Name: "status",
|
||||
Description: "Filter logs by status (success or error)",
|
||||
Required: false,
|
||||
Schema: SchemaObject{"type": "string", "enum": []interface{}{"success", "error"}},
|
||||
},
|
||||
},
|
||||
Result: &ContentDescriptorObject{
|
||||
Name: "introspection",
|
||||
Description: "Introspection data including call logs",
|
||||
Schema: SchemaObject{"type": "object"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Create the manager directly without validation since we're starting with empty methods
|
||||
return &OpenRPCManager{
|
||||
handlers: make(map[string]RPCHandler),
|
||||
schema: defaultSchema,
|
||||
secret: secret,
|
||||
}
|
||||
}
|
@ -1,446 +0,0 @@
|
||||
package openrpcmanager
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// createTestSchema creates a test OpenRPC schema
|
||||
func createTestSchema() OpenRPCSchema {
|
||||
return OpenRPCSchema{
|
||||
OpenRPC: "1.2.6",
|
||||
Info: InfoObject{
|
||||
Title: "Test API",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
Methods: []MethodObject{
|
||||
{
|
||||
Name: "echo",
|
||||
Params: []ContentDescriptorObject{
|
||||
{
|
||||
Name: "message",
|
||||
Schema: SchemaObject{"type": "object"},
|
||||
},
|
||||
},
|
||||
Result: &ContentDescriptorObject{
|
||||
Name: "result",
|
||||
Schema: SchemaObject{"type": "object"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "add",
|
||||
Params: []ContentDescriptorObject{
|
||||
{
|
||||
Name: "numbers",
|
||||
Schema: SchemaObject{"type": "object"},
|
||||
},
|
||||
},
|
||||
Result: &ContentDescriptorObject{
|
||||
Name: "result",
|
||||
Schema: SchemaObject{"type": "number"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "secure.method",
|
||||
Params: []ContentDescriptorObject{},
|
||||
Result: &ContentDescriptorObject{
|
||||
Name: "result",
|
||||
Schema: SchemaObject{"type": "string"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// createTestHandlers creates test handlers for the schema
|
||||
func createTestHandlers() map[string]RPCHandler {
|
||||
return map[string]RPCHandler{
|
||||
"echo": func(params json.RawMessage) (interface{}, error) {
|
||||
var data interface{}
|
||||
if err := json.Unmarshal(params, &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
},
|
||||
"add": func(params json.RawMessage) (interface{}, error) {
|
||||
var numbers struct {
|
||||
A float64 `json:"a"`
|
||||
B float64 `json:"b"`
|
||||
}
|
||||
if err := json.Unmarshal(params, &numbers); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return numbers.A + numbers.B, nil
|
||||
},
|
||||
"secure.method": func(params json.RawMessage) (interface{}, error) {
|
||||
return "secure data", nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// TestNewOpenRPCManager tests the creation of a new OpenRPC manager
|
||||
func TestNewOpenRPCManager(t *testing.T) {
|
||||
secret := "test-secret"
|
||||
schema := createTestSchema()
|
||||
handlers := createTestHandlers()
|
||||
|
||||
manager, err := NewOpenRPCManager(schema, handlers, secret)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create OpenRPCManager: %v", err)
|
||||
}
|
||||
|
||||
if manager == nil {
|
||||
t.Fatal("Manager is nil")
|
||||
}
|
||||
|
||||
if manager.GetSecret() != secret {
|
||||
t.Errorf("Secret mismatch. Expected: %s, Got: %s", secret, manager.GetSecret())
|
||||
}
|
||||
|
||||
if manager.handlers == nil {
|
||||
t.Error("handlers map not initialized")
|
||||
}
|
||||
|
||||
// Test the default manager for backward compatibility
|
||||
defaultManager := NewDefaultOpenRPCManager(secret)
|
||||
if defaultManager == nil {
|
||||
t.Fatal("Default manager is nil")
|
||||
}
|
||||
|
||||
if defaultManager.GetSecret() != secret {
|
||||
t.Errorf("Secret mismatch in default manager. Expected: %s, Got: %s", secret, defaultManager.GetSecret())
|
||||
}
|
||||
}
|
||||
|
||||
// TestRegisterHandler tests registering a handler to the OpenRPC manager
|
||||
func TestRegisterHandler(t *testing.T) {
|
||||
manager := NewDefaultOpenRPCManager("test-secret")
|
||||
|
||||
// Define a mock handler
|
||||
mockHandler := func(params json.RawMessage) (interface{}, error) {
|
||||
return "mock response", nil
|
||||
}
|
||||
|
||||
// Add a method to the schema
|
||||
manager.schema.Methods = append(manager.schema.Methods, MethodObject{
|
||||
Name: "test.method",
|
||||
Params: []ContentDescriptorObject{},
|
||||
Result: &ContentDescriptorObject{
|
||||
Name: "result",
|
||||
Schema: SchemaObject{"type": "string"},
|
||||
},
|
||||
})
|
||||
|
||||
// Register the handler
|
||||
err := manager.RegisterHandler("test.method", mockHandler)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to register handler: %v", err)
|
||||
}
|
||||
|
||||
// Check if handler was registered
|
||||
if _, exists := manager.handlers["test.method"]; !exists {
|
||||
t.Error("Handler was not registered")
|
||||
}
|
||||
|
||||
// Try to register the same handler again, should fail
|
||||
err = manager.RegisterHandler("test.method", mockHandler)
|
||||
if err == nil {
|
||||
t.Error("Expected error when registering duplicate handler, but got nil")
|
||||
}
|
||||
|
||||
// Try to register a handler for a method not in the schema
|
||||
err = manager.RegisterHandler("not.in.schema", mockHandler)
|
||||
if err == nil {
|
||||
t.Error("Expected error when registering handler for method not in schema, but got nil")
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandleRequest tests handling an RPC request
|
||||
func TestHandleRequest(t *testing.T) {
|
||||
schema := createTestSchema()
|
||||
handlers := createTestHandlers()
|
||||
manager, err := NewOpenRPCManager(schema, handlers, "test-secret")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create OpenRPCManager: %v", err)
|
||||
}
|
||||
|
||||
// Test the echo handler
|
||||
testParams := json.RawMessage(`{"message":"hello world"}`)
|
||||
result, err := manager.HandleRequest("echo", testParams)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to handle request: %v", err)
|
||||
}
|
||||
|
||||
// Convert result to map for comparison
|
||||
resultMap, ok := result.(map[string]interface{})
|
||||
if !ok {
|
||||
t.Fatalf("Expected map result, got: %T", result)
|
||||
}
|
||||
|
||||
if resultMap["message"] != "hello world" {
|
||||
t.Errorf("Expected 'hello world', got: %v", resultMap["message"])
|
||||
}
|
||||
|
||||
// Test the add handler
|
||||
addParams := json.RawMessage(`{"a":5,"b":7}`)
|
||||
addResult, err := manager.HandleRequest("add", addParams)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to handle add request: %v", err)
|
||||
}
|
||||
|
||||
// Check the result type and value
|
||||
resultValue, ok := addResult.(float64)
|
||||
if !ok {
|
||||
t.Fatalf("Expected result type float64, got: %T", addResult)
|
||||
}
|
||||
if resultValue != float64(12) {
|
||||
t.Errorf("Expected 12, got: %v", resultValue)
|
||||
}
|
||||
|
||||
// Test with non-existent method
|
||||
_, err = manager.HandleRequest("nonexistent", testParams)
|
||||
if err == nil {
|
||||
t.Error("Expected error for non-existent method, but got nil")
|
||||
}
|
||||
|
||||
// Test the discovery method
|
||||
discoveryResult, err := manager.HandleRequest("rpc.discover", json.RawMessage(`{}`))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to handle discovery request: %v", err)
|
||||
}
|
||||
|
||||
// Verify the discovery result is the schema
|
||||
discoverySchema, ok := discoveryResult.(OpenRPCSchema)
|
||||
if !ok {
|
||||
t.Fatalf("Expected OpenRPCSchema result, got: %T", discoveryResult)
|
||||
}
|
||||
|
||||
if discoverySchema.OpenRPC != schema.OpenRPC {
|
||||
t.Errorf("Expected OpenRPC version %s, got: %s", schema.OpenRPC, discoverySchema.OpenRPC)
|
||||
}
|
||||
|
||||
if len(discoverySchema.Methods) != len(schema.Methods) {
|
||||
t.Errorf("Expected %d methods, got: %d", len(schema.Methods), len(discoverySchema.Methods))
|
||||
}
|
||||
}
|
||||
|
||||
// TestHandleRequestWithAuthentication tests handling a request with authentication
|
||||
func TestHandleRequestWithAuthentication(t *testing.T) {
|
||||
secret := "test-secret"
|
||||
schema := createTestSchema()
|
||||
handlers := createTestHandlers()
|
||||
manager, err := NewOpenRPCManager(schema, handlers, secret)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create OpenRPCManager: %v", err)
|
||||
}
|
||||
|
||||
// Test with correct secret
|
||||
result, err := manager.HandleRequestWithAuthentication("secure.method", json.RawMessage(`{}`), secret)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to handle authenticated request: %v", err)
|
||||
}
|
||||
|
||||
if result != "secure data" {
|
||||
t.Errorf("Expected 'secure data', got: %v", result)
|
||||
}
|
||||
|
||||
// Test with incorrect secret
|
||||
_, err = manager.HandleRequestWithAuthentication("secure.method", json.RawMessage(`{}`), "wrong-secret")
|
||||
if err == nil {
|
||||
t.Error("Expected authentication error, but got nil")
|
||||
}
|
||||
}
|
||||
|
||||
// TestUnregisterHandler tests removing a handler from the OpenRPC manager
|
||||
func TestUnregisterHandler(t *testing.T) {
|
||||
manager := NewDefaultOpenRPCManager("test-secret")
|
||||
|
||||
// Define a mock handler
|
||||
mockHandler := func(params json.RawMessage) (interface{}, error) {
|
||||
return "mock response", nil
|
||||
}
|
||||
|
||||
// Add a method to the schema
|
||||
manager.schema.Methods = append(manager.schema.Methods, MethodObject{
|
||||
Name: "test.method",
|
||||
Params: []ContentDescriptorObject{},
|
||||
Result: &ContentDescriptorObject{
|
||||
Name: "result",
|
||||
Schema: SchemaObject{"type": "string"},
|
||||
},
|
||||
})
|
||||
|
||||
// Register the handler
|
||||
manager.RegisterHandler("test.method", mockHandler)
|
||||
|
||||
// Unregister the handler
|
||||
err := manager.UnregisterHandler("test.method")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to unregister handler: %v", err)
|
||||
}
|
||||
|
||||
// Check if handler was unregistered
|
||||
if _, exists := manager.handlers["test.method"]; exists {
|
||||
t.Error("Handler was not unregistered")
|
||||
}
|
||||
|
||||
// Try to unregister non-existent handler
|
||||
err = manager.UnregisterHandler("nonexistent")
|
||||
if err == nil {
|
||||
t.Error("Expected error when unregistering non-existent handler, but got nil")
|
||||
}
|
||||
|
||||
// Try to unregister the discovery method
|
||||
err = manager.UnregisterHandler("rpc.discover")
|
||||
if err == nil {
|
||||
t.Error("Expected error when unregistering discovery method, but got nil")
|
||||
}
|
||||
}
|
||||
|
||||
// TestIntrospection tests the introspection functionality
|
||||
func TestIntrospection(t *testing.T) {
|
||||
// Create a test manager
|
||||
schema := createTestSchema()
|
||||
handlers := createTestHandlers()
|
||||
manager, err := NewOpenRPCManager(schema, handlers, "test-secret")
|
||||
assert.NoError(t, err)
|
||||
|
||||
// The introspection handler is already registered in NewOpenRPCManager
|
||||
|
||||
// Make some test calls to generate logs
|
||||
_, err = manager.HandleRequest("echo", json.RawMessage(`{"message":"hello"}`))
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = manager.HandleRequestWithAuthentication("echo", json.RawMessage(`{"message":"authenticated"}`), "test-secret")
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = manager.HandleRequestWithAuthentication("echo", json.RawMessage(`{"message":"auth-fail"}`), "wrong-secret")
|
||||
assert.Error(t, err)
|
||||
|
||||
// Wait a moment to ensure timestamps are different
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
// Call the introspection handler
|
||||
result, err := manager.handleIntrospection(json.RawMessage(`{"limit":10}`))
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Verify the result
|
||||
response, ok := result.(struct {
|
||||
Logs []CallLog `json:"logs"`
|
||||
Total int `json:"total"`
|
||||
Filtered int `json:"filtered"`
|
||||
})
|
||||
assert.True(t, ok)
|
||||
|
||||
// Should have 3 logs (2 successful calls, 1 auth failure)
|
||||
assert.Equal(t, 3, response.Total)
|
||||
assert.Equal(t, 3, response.Filtered)
|
||||
assert.Len(t, response.Logs, 3)
|
||||
|
||||
// Test filtering by method
|
||||
result, err = manager.handleIntrospection(json.RawMessage(`{"method":"echo"}`))
|
||||
assert.NoError(t, err)
|
||||
response, ok = result.(struct {
|
||||
Logs []CallLog `json:"logs"`
|
||||
Total int `json:"total"`
|
||||
Filtered int `json:"filtered"`
|
||||
})
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 3, response.Total) // Total is still 3
|
||||
assert.Equal(t, 3, response.Filtered) // All 3 match the method filter
|
||||
|
||||
// Test filtering by status
|
||||
result, err = manager.handleIntrospection(json.RawMessage(`{"status":"error"}`))
|
||||
assert.NoError(t, err)
|
||||
response, ok = result.(struct {
|
||||
Logs []CallLog `json:"logs"`
|
||||
Total int `json:"total"`
|
||||
Filtered int `json:"filtered"`
|
||||
})
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, 3, response.Total) // Total is still 3
|
||||
assert.Equal(t, 1, response.Filtered) // Only 1 error
|
||||
assert.Len(t, response.Logs, 1)
|
||||
assert.Equal(t, "error", response.Logs[0].Status)
|
||||
}
|
||||
|
||||
// TestListMethods tests listing all registered methods
|
||||
func TestListMethods(t *testing.T) {
|
||||
schema := createTestSchema()
|
||||
handlers := createTestHandlers()
|
||||
manager, err := NewOpenRPCManager(schema, handlers, "test-secret")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create OpenRPCManager: %v", err)
|
||||
}
|
||||
|
||||
// List all methods
|
||||
registeredMethods := manager.ListMethods()
|
||||
|
||||
// Check if all methods plus discovery and introspection methods are listed
|
||||
expectedCount := len(schema.Methods) + 2 // +2 for rpc.discover and rpc.introspect
|
||||
if len(registeredMethods) != expectedCount {
|
||||
t.Errorf("Expected %d methods, got %d", expectedCount, len(registeredMethods))
|
||||
}
|
||||
|
||||
// Check if all schema methods are in the list
|
||||
for _, methodObj := range schema.Methods {
|
||||
found := false
|
||||
for _, registeredMethod := range registeredMethods {
|
||||
if registeredMethod == methodObj.Name {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Errorf("Method %s not found in list", methodObj.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if discovery method is in the list
|
||||
found := false
|
||||
for _, registeredMethod := range registeredMethods {
|
||||
if registeredMethod == "rpc.discover" {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Error("Discovery method 'rpc.discover' not found in list")
|
||||
}
|
||||
}
|
||||
|
||||
// TestSchemaValidation tests that the schema validation works correctly
|
||||
func TestSchemaValidation(t *testing.T) {
|
||||
secret := "test-secret"
|
||||
schema := createTestSchema()
|
||||
|
||||
// Test with missing handler
|
||||
incompleteHandlers := map[string]RPCHandler{
|
||||
"echo": func(params json.RawMessage) (interface{}, error) {
|
||||
return nil, nil
|
||||
},
|
||||
// Missing "add" handler
|
||||
"secure.method": func(params json.RawMessage) (interface{}, error) {
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
|
||||
_, err := NewOpenRPCManager(schema, incompleteHandlers, secret)
|
||||
if err == nil {
|
||||
t.Error("Expected error when missing handler for schema method, but got nil")
|
||||
}
|
||||
|
||||
// Test with extra handler not in schema
|
||||
extraHandlers := createTestHandlers()
|
||||
extraHandlers["not.in.schema"] = func(params json.RawMessage) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
_, err = NewOpenRPCManager(schema, extraHandlers, secret)
|
||||
if err == nil {
|
||||
t.Error("Expected error when handler has no corresponding method in schema, but got nil")
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
package openrpcmanager
|
||||
|
||||
// OpenRPCSchema represents the OpenRPC specification document
|
||||
// Based on OpenRPC Specification 1.2.6: https://spec.open-rpc.org/
|
||||
type OpenRPCSchema struct {
|
||||
OpenRPC string `json:"openrpc"` // Required: Version of the OpenRPC specification
|
||||
Info InfoObject `json:"info"` // Required: Information about the API
|
||||
Methods []MethodObject `json:"methods"` // Required: List of method objects
|
||||
ExternalDocs *ExternalDocsObject `json:"externalDocs,omitempty"` // Optional: External documentation
|
||||
Servers []ServerObject `json:"servers,omitempty"` // Optional: List of servers
|
||||
Components *ComponentsObject `json:"components,omitempty"` // Optional: Reusable components
|
||||
}
|
||||
|
||||
// InfoObject provides metadata about the API
|
||||
type InfoObject struct {
|
||||
Title string `json:"title"` // Required: Title of the API
|
||||
Description string `json:"description,omitempty"` // Optional: Description of the API
|
||||
Version string `json:"version"` // Required: Version of the API
|
||||
TermsOfService string `json:"termsOfService,omitempty"` // Optional: Terms of service URL
|
||||
Contact *ContactObject `json:"contact,omitempty"` // Optional: Contact information
|
||||
License *LicenseObject `json:"license,omitempty"` // Optional: License information
|
||||
}
|
||||
|
||||
// ContactObject provides contact information for the API
|
||||
type ContactObject struct {
|
||||
Name string `json:"name,omitempty"` // Optional: Name of the contact
|
||||
URL string `json:"url,omitempty"` // Optional: URL of the contact
|
||||
Email string `json:"email,omitempty"` // Optional: Email of the contact
|
||||
}
|
||||
|
||||
// LicenseObject provides license information for the API
|
||||
type LicenseObject struct {
|
||||
Name string `json:"name"` // Required: Name of the license
|
||||
URL string `json:"url,omitempty"` // Optional: URL of the license
|
||||
}
|
||||
|
||||
// ExternalDocsObject provides a URL to external documentation
|
||||
type ExternalDocsObject struct {
|
||||
Description string `json:"description,omitempty"` // Optional: Description of the external docs
|
||||
URL string `json:"url"` // Required: URL of the external docs
|
||||
}
|
||||
|
||||
// ServerObject provides connection information to a server
|
||||
type ServerObject struct {
|
||||
Name string `json:"name,omitempty"` // Optional: Name of the server
|
||||
Description string `json:"description,omitempty"` // Optional: Description of the server
|
||||
URL string `json:"url"` // Required: URL of the server
|
||||
Variables map[string]ServerVariable `json:"variables,omitempty"` // Optional: Server variables
|
||||
}
|
||||
|
||||
// ServerVariable is a variable for server URL template substitution
|
||||
type ServerVariable struct {
|
||||
Default string `json:"default"` // Required: Default value of the variable
|
||||
Description string `json:"description,omitempty"` // Optional: Description of the variable
|
||||
Enum []string `json:"enum,omitempty"` // Optional: Enumeration of possible values
|
||||
}
|
||||
|
||||
// MethodObject describes an RPC method
|
||||
type MethodObject struct {
|
||||
Name string `json:"name"` // Required: Name of the method
|
||||
Description string `json:"description,omitempty"` // Optional: Description of the method
|
||||
Summary string `json:"summary,omitempty"` // Optional: Summary of the method
|
||||
Params []ContentDescriptorObject `json:"params"` // Required: List of parameters
|
||||
Result *ContentDescriptorObject `json:"result"` // Required: Description of the result
|
||||
Deprecated bool `json:"deprecated,omitempty"` // Optional: Whether the method is deprecated
|
||||
Errors []ErrorObject `json:"errors,omitempty"` // Optional: List of possible errors
|
||||
Tags []TagObject `json:"tags,omitempty"` // Optional: List of tags
|
||||
ExternalDocs *ExternalDocsObject `json:"externalDocs,omitempty"` // Optional: External documentation
|
||||
ParamStructure string `json:"paramStructure,omitempty"` // Optional: Structure of the parameters
|
||||
}
|
||||
|
||||
// ContentDescriptorObject describes the content of a parameter or result
|
||||
type ContentDescriptorObject struct {
|
||||
Name string `json:"name"` // Required: Name of the parameter
|
||||
Description string `json:"description,omitempty"` // Optional: Description of the parameter
|
||||
Summary string `json:"summary,omitempty"` // Optional: Summary of the parameter
|
||||
Required bool `json:"required,omitempty"` // Optional: Whether the parameter is required
|
||||
Deprecated bool `json:"deprecated,omitempty"` // Optional: Whether the parameter is deprecated
|
||||
Schema SchemaObject `json:"schema"` // Required: JSON Schema of the parameter
|
||||
}
|
||||
|
||||
// SchemaObject is a JSON Schema definition
|
||||
// This is a simplified version, in a real implementation you would use a full JSON Schema library
|
||||
type SchemaObject map[string]interface{}
|
||||
|
||||
// ErrorObject describes an error that may be returned
|
||||
type ErrorObject struct {
|
||||
Code int `json:"code"` // Required: Error code
|
||||
Message string `json:"message"` // Required: Error message
|
||||
Data interface{} `json:"data,omitempty"` // Optional: Additional error data
|
||||
}
|
||||
|
||||
// TagObject describes a tag for documentation purposes
|
||||
type TagObject struct {
|
||||
Name string `json:"name"` // Required: Name of the tag
|
||||
Description string `json:"description,omitempty"` // Optional: Description of the tag
|
||||
ExternalDocs *ExternalDocsObject `json:"externalDocs,omitempty"` // Optional: External documentation
|
||||
}
|
||||
|
||||
// ComponentsObject holds reusable objects for different aspects of the OpenRPC spec
|
||||
type ComponentsObject struct {
|
||||
Schemas map[string]SchemaObject `json:"schemas,omitempty"` // Optional: Reusable schemas
|
||||
ContentDescriptors map[string]ContentDescriptorObject `json:"contentDescriptors,omitempty"` // Optional: Reusable content descriptors
|
||||
Examples map[string]interface{} `json:"examples,omitempty"` // Optional: Reusable examples
|
||||
Links map[string]LinkObject `json:"links,omitempty"` // Optional: Reusable links
|
||||
Errors map[string]ErrorObject `json:"errors,omitempty"` // Optional: Reusable errors
|
||||
}
|
||||
|
||||
// LinkObject describes a link between operations
|
||||
type LinkObject struct {
|
||||
Name string `json:"name,omitempty"` // Optional: Name of the link
|
||||
Description string `json:"description,omitempty"` // Optional: Description of the link
|
||||
Summary string `json:"summary,omitempty"` // Optional: Summary of the link
|
||||
Method string `json:"method"` // Required: Method name
|
||||
Params map[string]interface{} `json:"params,omitempty"` // Optional: Parameters for the method
|
||||
Server *ServerObject `json:"server,omitempty"` // Optional: Server for the method
|
||||
}
|
@ -1,241 +0,0 @@
|
||||
package openrpcmanager
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// RPCRequest represents an incoming RPC request
|
||||
type RPCRequest struct {
|
||||
Method string `json:"method"`
|
||||
Params json.RawMessage `json:"params"`
|
||||
ID interface{} `json:"id,omitempty"`
|
||||
Secret string `json:"secret,omitempty"`
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
}
|
||||
|
||||
// RPCResponse represents an outgoing RPC response
|
||||
type RPCResponse struct {
|
||||
Result interface{} `json:"result,omitempty"`
|
||||
Error *RPCError `json:"error,omitempty"`
|
||||
ID interface{} `json:"id,omitempty"`
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
}
|
||||
|
||||
// RPCError represents an RPC error
|
||||
type RPCError struct {
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// UnixServer represents a Unix socket server for the OpenRPC manager
|
||||
type UnixServer struct {
|
||||
manager *OpenRPCManager
|
||||
socketPath string
|
||||
listener net.Listener
|
||||
connections map[net.Conn]bool
|
||||
mutex sync.Mutex
|
||||
wg sync.WaitGroup
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
// NewUnixServer creates a new Unix socket server for the OpenRPC manager
|
||||
func NewUnixServer(manager *OpenRPCManager, socketPath string) (*UnixServer, error) {
|
||||
// Create directory if it doesn't exist
|
||||
dir := filepath.Dir(socketPath)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return nil, fmt.Errorf("failed to create socket directory: %w", err)
|
||||
}
|
||||
|
||||
// Remove socket if it already exists
|
||||
if _, err := os.Stat(socketPath); err == nil {
|
||||
if err := os.Remove(socketPath); err != nil {
|
||||
return nil, fmt.Errorf("failed to remove existing socket: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &UnixServer{
|
||||
manager: manager,
|
||||
socketPath: socketPath,
|
||||
connections: make(map[net.Conn]bool),
|
||||
done: make(chan struct{}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Start starts the Unix socket server
|
||||
func (s *UnixServer) Start() error {
|
||||
listener, err := net.Listen("unix", s.socketPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to listen on unix socket: %w", err)
|
||||
}
|
||||
s.listener = listener
|
||||
|
||||
// Set socket permissions
|
||||
if err := os.Chmod(s.socketPath, 0660); err != nil {
|
||||
s.listener.Close()
|
||||
return fmt.Errorf("failed to set socket permissions: %w", err)
|
||||
}
|
||||
|
||||
s.wg.Add(1)
|
||||
go s.acceptConnections()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stop stops the Unix socket server
|
||||
func (s *UnixServer) Stop() error {
|
||||
close(s.done)
|
||||
|
||||
// Close the listener
|
||||
if s.listener != nil {
|
||||
s.listener.Close()
|
||||
}
|
||||
|
||||
// Close all connections
|
||||
s.mutex.Lock()
|
||||
for conn := range s.connections {
|
||||
conn.Close()
|
||||
}
|
||||
s.mutex.Unlock()
|
||||
|
||||
// Wait for all goroutines to finish
|
||||
s.wg.Wait()
|
||||
|
||||
// Remove the socket file
|
||||
os.Remove(s.socketPath)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// acceptConnections accepts incoming connections
|
||||
func (s *UnixServer) acceptConnections() {
|
||||
defer s.wg.Done()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-s.done:
|
||||
return
|
||||
default:
|
||||
conn, err := s.listener.Accept()
|
||||
if err != nil {
|
||||
select {
|
||||
case <-s.done:
|
||||
return
|
||||
default:
|
||||
fmt.Printf("Error accepting connection: %v\n", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
s.mutex.Lock()
|
||||
s.connections[conn] = true
|
||||
s.mutex.Unlock()
|
||||
|
||||
s.wg.Add(1)
|
||||
go s.handleConnection(conn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handleConnection handles a client connection
|
||||
func (s *UnixServer) handleConnection(conn net.Conn) {
|
||||
defer func() {
|
||||
s.mutex.Lock()
|
||||
delete(s.connections, conn)
|
||||
s.mutex.Unlock()
|
||||
conn.Close()
|
||||
s.wg.Done()
|
||||
}()
|
||||
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
select {
|
||||
case <-s.done:
|
||||
return
|
||||
default:
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
fmt.Printf("Error reading from connection: %v\n", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if n > 0 {
|
||||
go s.handleRequest(conn, buf[:n])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handleRequest processes an RPC request
|
||||
func (s *UnixServer) handleRequest(conn net.Conn, data []byte) {
|
||||
var req RPCRequest
|
||||
if err := json.Unmarshal(data, &req); err != nil {
|
||||
s.sendErrorResponse(conn, nil, -32700, "Parse error", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Validate JSON-RPC version
|
||||
if req.JSONRPC != "2.0" {
|
||||
s.sendErrorResponse(conn, req.ID, -32600, "Invalid Request", "Invalid JSON-RPC version")
|
||||
return
|
||||
}
|
||||
|
||||
var result interface{}
|
||||
var err error
|
||||
|
||||
// Check if authentication is required
|
||||
if req.Secret != "" {
|
||||
result, err = s.manager.HandleRequestWithAuthentication(req.Method, req.Params, req.Secret)
|
||||
} else {
|
||||
result, err = s.manager.HandleRequest(req.Method, req.Params)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
s.sendErrorResponse(conn, req.ID, -32603, "Internal error", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Send success response
|
||||
response := RPCResponse{
|
||||
Result: result,
|
||||
ID: req.ID,
|
||||
JSONRPC: "2.0",
|
||||
}
|
||||
|
||||
responseData, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
s.sendErrorResponse(conn, req.ID, -32603, "Internal error", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
conn.Write(responseData)
|
||||
}
|
||||
|
||||
// sendErrorResponse sends an error response
|
||||
func (s *UnixServer) sendErrorResponse(conn net.Conn, id interface{}, code int, message string, data interface{}) {
|
||||
response := RPCResponse{
|
||||
Error: &RPCError{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Data: data,
|
||||
},
|
||||
ID: id,
|
||||
JSONRPC: "2.0",
|
||||
}
|
||||
|
||||
responseData, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
fmt.Printf("Error marshaling error response: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
conn.Write(responseData)
|
||||
}
|
@ -1,362 +0,0 @@
|
||||
package openrpcmanager
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestUnixServer(t *testing.T) {
|
||||
// Create a temporary socket path
|
||||
tempDir, err := os.MkdirTemp("", "openrpc-test")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
socketPath := filepath.Join(tempDir, "openrpc.sock")
|
||||
|
||||
// Create OpenRPC manager
|
||||
schema := createTestSchema()
|
||||
handlers := createTestHandlers()
|
||||
manager, err := NewOpenRPCManager(schema, handlers, "test-secret")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create OpenRPCManager: %v", err)
|
||||
}
|
||||
|
||||
// Create and start Unix server
|
||||
server, err := NewUnixServer(manager, socketPath)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create UnixServer: %v", err)
|
||||
}
|
||||
|
||||
if err := server.Start(); err != nil {
|
||||
t.Fatalf("Failed to start UnixServer: %v", err)
|
||||
}
|
||||
defer server.Stop()
|
||||
|
||||
// Wait for server to start
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
// Test connection
|
||||
conn, err := net.Dial("unix", socketPath)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to connect to Unix socket: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// Test echo method
|
||||
t.Run("Echo method", func(t *testing.T) {
|
||||
request := RPCRequest{
|
||||
Method: "echo",
|
||||
Params: json.RawMessage(`{"message":"hello world"}`),
|
||||
ID: 1,
|
||||
JSONRPC: "2.0",
|
||||
}
|
||||
|
||||
requestData, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal request: %v", err)
|
||||
}
|
||||
|
||||
_, err = conn.Write(requestData)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to send request: %v", err)
|
||||
}
|
||||
|
||||
// Read response
|
||||
buf := make([]byte, 4096)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read response: %v", err)
|
||||
}
|
||||
|
||||
var response RPCResponse
|
||||
if err := json.Unmarshal(buf[:n], &response); err != nil {
|
||||
t.Fatalf("Failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
// Check response
|
||||
if response.Error != nil {
|
||||
t.Fatalf("Received error response: %v", response.Error)
|
||||
}
|
||||
|
||||
// Note: JSON unmarshaling may convert numbers to float64, so we need to check the value not exact type
|
||||
if fmt.Sprintf("%v", response.ID) != fmt.Sprintf("%v", request.ID) {
|
||||
t.Errorf("Response ID mismatch. Expected: %v, Got: %v", request.ID, response.ID)
|
||||
}
|
||||
|
||||
// Check result
|
||||
resultMap, ok := response.Result.(map[string]interface{})
|
||||
if !ok {
|
||||
t.Fatalf("Expected map result, got: %T", response.Result)
|
||||
}
|
||||
|
||||
if resultMap["message"] != "hello world" {
|
||||
t.Errorf("Expected 'hello world', got: %v", resultMap["message"])
|
||||
}
|
||||
})
|
||||
|
||||
// Test add method
|
||||
t.Run("Add method", func(t *testing.T) {
|
||||
request := RPCRequest{
|
||||
Method: "add",
|
||||
Params: json.RawMessage(`{"a":5,"b":7}`),
|
||||
ID: 2,
|
||||
JSONRPC: "2.0",
|
||||
}
|
||||
|
||||
requestData, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal request: %v", err)
|
||||
}
|
||||
|
||||
_, err = conn.Write(requestData)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to send request: %v", err)
|
||||
}
|
||||
|
||||
// Read response
|
||||
buf := make([]byte, 4096)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read response: %v", err)
|
||||
}
|
||||
|
||||
var response RPCResponse
|
||||
if err := json.Unmarshal(buf[:n], &response); err != nil {
|
||||
t.Fatalf("Failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
// Check response
|
||||
if response.Error != nil {
|
||||
t.Fatalf("Received error response: %v", response.Error)
|
||||
}
|
||||
|
||||
// Note: JSON unmarshaling may convert numbers to float64, so we need to check the value not exact type
|
||||
if fmt.Sprintf("%v", response.ID) != fmt.Sprintf("%v", request.ID) {
|
||||
t.Errorf("Response ID mismatch. Expected: %v, Got: %v", request.ID, response.ID)
|
||||
}
|
||||
|
||||
// Check result
|
||||
resultValue, ok := response.Result.(float64)
|
||||
if !ok {
|
||||
t.Fatalf("Expected float64 result, got: %T", response.Result)
|
||||
}
|
||||
|
||||
if resultValue != float64(12) {
|
||||
t.Errorf("Expected 12, got: %v", resultValue)
|
||||
}
|
||||
})
|
||||
|
||||
// Test authenticated method
|
||||
t.Run("Authenticated method", func(t *testing.T) {
|
||||
request := RPCRequest{
|
||||
Method: "secure.method",
|
||||
Params: json.RawMessage(`{}`),
|
||||
ID: 3,
|
||||
Secret: "test-secret",
|
||||
JSONRPC: "2.0",
|
||||
}
|
||||
|
||||
requestData, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal request: %v", err)
|
||||
}
|
||||
|
||||
_, err = conn.Write(requestData)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to send request: %v", err)
|
||||
}
|
||||
|
||||
// Read response
|
||||
buf := make([]byte, 4096)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read response: %v", err)
|
||||
}
|
||||
|
||||
var response RPCResponse
|
||||
if err := json.Unmarshal(buf[:n], &response); err != nil {
|
||||
t.Fatalf("Failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
// Check response
|
||||
if response.Error != nil {
|
||||
t.Fatalf("Received error response: %v", response.Error)
|
||||
}
|
||||
|
||||
// Note: JSON unmarshaling may convert numbers to float64, so we need to check the value not exact type
|
||||
if fmt.Sprintf("%v", response.ID) != fmt.Sprintf("%v", request.ID) {
|
||||
t.Errorf("Response ID mismatch. Expected: %v, Got: %v", request.ID, response.ID)
|
||||
}
|
||||
|
||||
// Check result
|
||||
resultValue, ok := response.Result.(string)
|
||||
if !ok {
|
||||
t.Fatalf("Expected string result, got: %T", response.Result)
|
||||
}
|
||||
|
||||
if resultValue != "secure data" {
|
||||
t.Errorf("Expected 'secure data', got: %v", resultValue)
|
||||
}
|
||||
})
|
||||
|
||||
// Test authentication failure
|
||||
t.Run("Authentication failure", func(t *testing.T) {
|
||||
request := RPCRequest{
|
||||
Method: "secure.method",
|
||||
Params: json.RawMessage(`{}`),
|
||||
ID: 4,
|
||||
Secret: "wrong-secret",
|
||||
JSONRPC: "2.0",
|
||||
}
|
||||
|
||||
requestData, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal request: %v", err)
|
||||
}
|
||||
|
||||
_, err = conn.Write(requestData)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to send request: %v", err)
|
||||
}
|
||||
|
||||
// Read response
|
||||
buf := make([]byte, 4096)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read response: %v", err)
|
||||
}
|
||||
|
||||
var response RPCResponse
|
||||
if err := json.Unmarshal(buf[:n], &response); err != nil {
|
||||
t.Fatalf("Failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
// Check response
|
||||
if response.Error == nil {
|
||||
t.Fatal("Expected error response, but got nil")
|
||||
}
|
||||
|
||||
// Note: JSON unmarshaling may convert numbers to float64, so we need to check the value not exact type
|
||||
if fmt.Sprintf("%v", response.ID) != fmt.Sprintf("%v", request.ID) {
|
||||
t.Errorf("Response ID mismatch. Expected: %v, Got: %v", request.ID, response.ID)
|
||||
}
|
||||
|
||||
if response.Error.Code != -32603 {
|
||||
t.Errorf("Expected error code -32603, got: %v", response.Error.Code)
|
||||
}
|
||||
})
|
||||
|
||||
// Test non-existent method
|
||||
t.Run("Non-existent method", func(t *testing.T) {
|
||||
request := RPCRequest{
|
||||
Method: "nonexistent",
|
||||
Params: json.RawMessage(`{}`),
|
||||
ID: 5,
|
||||
JSONRPC: "2.0",
|
||||
}
|
||||
|
||||
requestData, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal request: %v", err)
|
||||
}
|
||||
|
||||
_, err = conn.Write(requestData)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to send request: %v", err)
|
||||
}
|
||||
|
||||
// Read response
|
||||
buf := make([]byte, 4096)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read response: %v", err)
|
||||
}
|
||||
|
||||
var response RPCResponse
|
||||
if err := json.Unmarshal(buf[:n], &response); err != nil {
|
||||
t.Fatalf("Failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
// Check response
|
||||
if response.Error == nil {
|
||||
t.Fatal("Expected error response, but got nil")
|
||||
}
|
||||
|
||||
// Note: JSON unmarshaling may convert numbers to float64, so we need to check the value not exact type
|
||||
if fmt.Sprintf("%v", response.ID) != fmt.Sprintf("%v", request.ID) {
|
||||
t.Errorf("Response ID mismatch. Expected: %v, Got: %v", request.ID, response.ID)
|
||||
}
|
||||
|
||||
if response.Error.Code != -32603 {
|
||||
t.Errorf("Expected error code -32603, got: %v", response.Error.Code)
|
||||
}
|
||||
})
|
||||
|
||||
// Test discovery method
|
||||
t.Run("Discovery method", func(t *testing.T) {
|
||||
request := RPCRequest{
|
||||
Method: "rpc.discover",
|
||||
Params: json.RawMessage(`{}`),
|
||||
ID: 6,
|
||||
JSONRPC: "2.0",
|
||||
}
|
||||
|
||||
requestData, err := json.Marshal(request)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to marshal request: %v", err)
|
||||
}
|
||||
|
||||
_, err = conn.Write(requestData)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to send request: %v", err)
|
||||
}
|
||||
|
||||
// Read response
|
||||
buf := make([]byte, 4096)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read response: %v", err)
|
||||
}
|
||||
|
||||
var response RPCResponse
|
||||
if err := json.Unmarshal(buf[:n], &response); err != nil {
|
||||
t.Fatalf("Failed to unmarshal response: %v", err)
|
||||
}
|
||||
|
||||
// Check response
|
||||
if response.Error != nil {
|
||||
t.Fatalf("Received error response: %v", response.Error)
|
||||
}
|
||||
|
||||
// Note: JSON unmarshaling may convert numbers to float64, so we need to check the value not exact type
|
||||
if fmt.Sprintf("%v", response.ID) != fmt.Sprintf("%v", request.ID) {
|
||||
t.Errorf("Response ID mismatch. Expected: %v, Got: %v", request.ID, response.ID)
|
||||
}
|
||||
|
||||
// Check that we got a valid schema
|
||||
resultMap, ok := response.Result.(map[string]interface{})
|
||||
if !ok {
|
||||
t.Fatalf("Expected map result, got: %T", response.Result)
|
||||
}
|
||||
|
||||
if resultMap["openrpc"] != "1.2.6" {
|
||||
t.Errorf("Expected OpenRPC version 1.2.6, got: %v", resultMap["openrpc"])
|
||||
}
|
||||
|
||||
methods, ok := resultMap["methods"].([]interface{})
|
||||
if !ok {
|
||||
t.Fatalf("Expected methods array, got: %T", resultMap["methods"])
|
||||
}
|
||||
|
||||
if len(methods) < 3 {
|
||||
t.Errorf("Expected at least 3 methods, got: %d", len(methods))
|
||||
}
|
||||
})
|
||||
}
|
@ -5,8 +5,8 @@ import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||
)
|
||||
|
||||
// RunClientExample runs a complete example of using the process manager OpenRPC client
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces/openrpc"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -6,8 +6,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces"
|
||||
)
|
||||
|
||||
// MockProcessManager implements the interfaces.ProcessManagerInterface for testing purposes
|
||||
|
@ -4,8 +4,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/openrpcmanager/client"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/openrpcmanager/client"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces"
|
||||
)
|
||||
|
||||
// Client provides a client for interacting with process manager operations via RPC
|
||||
|
@ -4,9 +4,9 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/openrpcmanager"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/openrpcmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces"
|
||||
)
|
||||
|
||||
// Handler implements the OpenRPC handlers for process manager operations
|
||||
|
@ -6,8 +6,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/openrpcmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/openrpcmanager"
|
||||
)
|
||||
|
||||
// LoadSchema loads the OpenRPC schema from the embedded JSON file
|
||||
|
@ -6,8 +6,8 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/openrpcmanager"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager/interfaces"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/openrpcmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager/interfaces"
|
||||
)
|
||||
|
||||
// Server represents the Process Manager OpenRPC server
|
||||
|
@ -3,7 +3,7 @@ package interfaces
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/processmanager"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/processmanager"
|
||||
)
|
||||
|
||||
// ProcessManagerInterface defines the interface for process management operations
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/logger"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/logger"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
)
|
||||
|
||||
|
@ -24,7 +24,7 @@ The server implements the following Redis commands:
|
||||
### Basic Usage
|
||||
|
||||
```go
|
||||
import "github.com/freeflowuniverse/heroagent/pkg/redisserver"
|
||||
import "git.ourworld.tf/herocode/heroagent/pkg/redisserver"
|
||||
|
||||
// Create a new server with default configuration
|
||||
server := redisserver.NewServer(redisserver.ServerConfig{
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/servers/redisserver"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/redisserver"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/servers/redisserver"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/servers/redisserver"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/builders/hetznerinstall"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/hetznerinstall"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -6,10 +6,10 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/builders/postgresql/dependencies"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/builders/postgresql/gosp"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/builders/postgresql/postgres"
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/builders/postgresql/verification"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/dependencies"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/gosp"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/postgres"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/verification"
|
||||
)
|
||||
|
||||
// Constants for PostgreSQL installation
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/builders/postgresql"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/builders/postgresql/postgres"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/builders/postgresql/postgres"
|
||||
)
|
||||
|
||||
// Constants for Go stored procedure
|
||||
@ -49,7 +49,7 @@ func (b *GoSPBuilder) run(cmd string, args ...string) error {
|
||||
c.Env = append(os.Environ(),
|
||||
"GOROOT=/usr/local/go",
|
||||
"GOPATH=/root/go",
|
||||
"PATH=/usr/local/go/bin:" + os.Getenv("PATH"))
|
||||
"PATH=/usr/local/go/bin:"+os.Getenv("PATH"))
|
||||
c.Stdout = os.Stdout
|
||||
c.Stderr = os.Stderr
|
||||
return c.Run()
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/mholt/archiver/v3"
|
||||
"github.com/mholt/archiver/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/stats"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/stats"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
"github.com/shirou/gopsutil/v3/process"
|
||||
)
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/stats"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/system/stats"
|
||||
"git.ourworld.tf/herocode/heroagent/pkg/system/stats"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
Loading…
Reference in New Issue
Block a user