diff --git a/examples/agent-go/go.mod b/examples/agent-go/go.mod index 351c147..e0e23a0 100644 --- a/examples/agent-go/go.mod +++ b/examples/agent-go/go.mod @@ -1,6 +1,6 @@ module github.com/coder/portabledesktop/examples/agent-go -go 1.26.0 +go 1.26.1 require charm.land/fantasy v0.0.0-20260310103256-242e3d156af6 @@ -8,26 +8,26 @@ require ( cloud.google.com/go/auth v0.18.2 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect - github.com/aws/aws-sdk-go-v2 v1.41.1 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect - github.com/aws/aws-sdk-go-v2/config v1.32.9 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.19.9 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 // indirect - github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.30.10 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect - github.com/aws/smithy-go v1.24.1 // indirect + github.com/aws/aws-sdk-go-v2 v1.41.3 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.5 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.11 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.11 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.19 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.16 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.41.8 // indirect + github.com/aws/smithy-go v1.24.2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charmbracelet/anthropic-sdk-go v0.0.0-20260223140439-63879b0b8dab // indirect github.com/charmbracelet/x/exp/slice v0.0.0-20250904123553-b4e2667e5ad5 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e // indirect + github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-viper/mapstructure/v2 v2.5.0 // indirect @@ -35,9 +35,9 @@ require ( github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.12 // indirect github.com/googleapis/gax-go/v2 v2.17.0 // indirect - github.com/kaptinlin/go-i18n v0.2.11 // indirect - github.com/kaptinlin/jsonpointer v0.4.16 // indirect - github.com/kaptinlin/jsonschema v0.7.3 // indirect + github.com/kaptinlin/go-i18n v0.2.12 // indirect + github.com/kaptinlin/jsonpointer v0.4.17 // indirect + github.com/kaptinlin/jsonschema v0.7.5 // indirect github.com/kaptinlin/messageformat-go v0.4.18 // indirect github.com/tidwall/gjson v1.18.0 // indirect github.com/tidwall/match v1.1.1 // indirect @@ -50,16 +50,16 @@ require ( go.opentelemetry.io/otel/metric v1.40.0 // indirect go.opentelemetry.io/otel/trace v1.40.0 // indirect golang.org/x/crypto v0.48.0 // indirect - golang.org/x/net v0.50.0 // indirect - golang.org/x/oauth2 v0.35.0 // indirect + golang.org/x/net v0.51.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.41.0 // indirect golang.org/x/text v0.34.0 // indirect golang.org/x/time v0.14.0 // indirect - google.golang.org/api v0.267.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d // indirect + google.golang.org/api v0.269.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect google.golang.org/grpc v1.79.1 // indirect google.golang.org/protobuf v1.36.11 // indirect ) -replace charm.land/fantasy => github.com/hugodutka/fantasy v0.0.0-20260310103256-242e3d156af6 +replace charm.land/fantasy => github.com/hugodutka/fantasy v0.0.0-20260312150824-7d96450e2412 diff --git a/examples/agent-go/go.sum b/examples/agent-go/go.sum index c76b592..dcbeea1 100644 --- a/examples/agent-go/go.sum +++ b/examples/agent-go/go.sum @@ -4,36 +4,36 @@ cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIi cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= -github.com/aws/aws-sdk-go-v2 v1.41.1 h1:ABlyEARCDLN034NhxlRUSZr4l71mh+T5KAeGh6cerhU= -github.com/aws/aws-sdk-go-v2 v1.41.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 h1:489krEF9xIGkOaaX3CE/Be2uWjiXrkCH6gUX+bZA/BU= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4/go.mod h1:IOAPF6oT9KCsceNTvvYMNHy0+kMF8akOjeDvPENWxp4= -github.com/aws/aws-sdk-go-v2/config v1.32.9 h1:ktda/mtAydeObvJXlHzyGpK1xcsLaP16zfUPDGoW90A= -github.com/aws/aws-sdk-go-v2/config v1.32.9/go.mod h1:U+fCQ+9QKsLW786BCfEjYRj34VVTbPdsLP3CHSYXMOI= -github.com/aws/aws-sdk-go-v2/credentials v1.19.9 h1:sWvTKsyrMlJGEuj/WgrwilpoJ6Xa1+KhIpGdzw7mMU8= -github.com/aws/aws-sdk-go-v2/credentials v1.19.9/go.mod h1:+J44MBhmfVY/lETFiKI+klz0Vym2aCmIjqgClMmW82w= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 h1:I0GyV8wiYrP8XpA70g1HBcQO1JlQxCMTW9npl5UbDHY= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17/go.mod h1:tyw7BOl5bBe/oqvoIeECFJjMdzXoa/dfVz3QQ5lgHGA= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 h1:xOLELNKGp2vsiteLsvLPwxC+mYmO6OZ8PYgiuPJzF8U= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17/go.mod h1:5M5CI3D12dNOtH3/mk6minaRwI2/37ifCURZISxA/IQ= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 h1:WWLqlh79iO48yLkj1v3ISRNiv+3KdQoZ6JWyfcsyQik= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17/go.mod h1:EhG22vHRrvF8oXSTYStZhJc1aUgKtnJe+aOiFEV90cM= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 h1:RuNSMoozM8oXlgLG/n6WLaFGoea7/CddrCfIiSA+xdY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17/go.mod h1:F2xxQ9TZz5gDWsclCtPQscGpP0VUOc8RqgFM3vDENmU= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 h1:VrhDvQib/i0lxvr3zqlUwLwJP4fpmpyD9wYG1vfSu+Y= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.5/go.mod h1:k029+U8SY30/3/ras4G/Fnv/b88N4mAfliNn08Dem4M= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.10 h1:+VTRawC4iVY58pS/lzpo0lnoa/SYNGF4/B/3/U5ro8Y= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.10/go.mod h1:yifAsgBxgJWn3ggx70A3urX2AN49Y5sJTD1UQFlfqBw= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14 h1:0jbJeuEHlwKJ9PfXtpSFc4MF+WIWORdhN1n30ITZGFM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.14/go.mod h1:sTGThjphYE4Ohw8vJiRStAcu3rbjtXRsdNB0TvZ5wwo= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/pJ1jOWYlFDJTjRQ= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ= -github.com/aws/smithy-go v1.24.1 h1:VbyeNfmYkWoxMVpGUAbQumkODcYmfMRfZ8yQiH30SK0= -github.com/aws/smithy-go v1.24.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= +github.com/aws/aws-sdk-go-v2 v1.41.3 h1:4kQ/fa22KjDt13QCy1+bYADvdgcxpfH18f0zP542kZA= +github.com/aws/aws-sdk-go-v2 v1.41.3/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.5 h1:zWFmPmgw4sveAYi1mRqG+E/g0461cJ5M4bJ8/nc6d3Q= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.5/go.mod h1:nVUlMLVV8ycXSb7mSkcNu9e3v/1TJq2RTlrPwhYWr5c= +github.com/aws/aws-sdk-go-v2/config v1.32.11 h1:ftxI5sgz8jZkckuUHXfC/wMUc8u3fG1vQS0plr2F2Zs= +github.com/aws/aws-sdk-go-v2/config v1.32.11/go.mod h1:twF11+6ps9aNRKEDimksp923o44w/Thk9+8YIlzWMmo= +github.com/aws/aws-sdk-go-v2/credentials v1.19.11 h1:NdV8cwCcAXrCWyxArt58BrvZJ9pZ9Fhf9w6Uh5W3Uyc= +github.com/aws/aws-sdk-go-v2/credentials v1.19.11/go.mod h1:30yY2zqkMPdrvxBqzI9xQCM+WrlrZKSOpSJEsylVU+8= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.19 h1:INUvJxmhdEbVulJYHI061k4TVuS3jzzthNvjqvVvTKM= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.19/go.mod h1:FpZN2QISLdEBWkayloda+sZjVJL+e9Gl0k1SyTgcswU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19 h1:/sECfyq2JTifMI2JPyZ4bdRN77zJmr6SrS1eL3augIA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19/go.mod h1:dMf8A5oAqr9/oxOfLkC/c2LU/uMcALP0Rgn2BD5LWn0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 h1:AWeJMk33GTBf6J20XJe6qZoRSJo0WfUhsMdUKhoODXE= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19/go.mod h1:+GWrYoaAsV7/4pNHpwh1kiNLXkKaSoppxQq9lbH8Ejw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 h1:clHU5fm//kWS1C2HgtgWxfQbFbx4b6rx+5jzhgX9HrI= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 h1:XAq62tBTJP/85lFD5oqOOe7YYgWxY9LvWq8plyDvDVg= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 h1:X1Tow7suZk9UCJHE1Iw9GMZJJl0dAnKXXP1NaSDHwmw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row= +github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 h1:iSsvB9EtQ09YrsmIc44Heqlx5ByGErqhPK1ZQLppias= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.12/go.mod h1:fEWYKTRGoZNl8tZ77i61/ccwOMJdGxwOhWCkp6TXAr0= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.16 h1:EnUdUqRP1CNzt2DkV67tJx6XDN4xlfBFm+bzeNOQVb0= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.16/go.mod h1:Jic/xv0Rq/pFNCh3WwpH4BEqdbSAl+IyHro8LbibHD8= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.8 h1:XQTQTF75vnug2TXS8m7CVJfC2nniYPZnO1D4Np761Oo= +github.com/aws/aws-sdk-go-v2/service/sts v1.41.8/go.mod h1:Xgx+PR1NUOjNmQY+tRMnouRp83JRM8pRMw/vCaVhPkI= +github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= +github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= 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/charmbracelet/anthropic-sdk-go v0.0.0-20260223140439-63879b0b8dab h1:J7XQLgl9sefgTnTGrmX3xqvp5o6MCiBzEjGv5igAlc4= @@ -53,8 +53,8 @@ github.com/envoyproxy/protoc-gen-validate v1.3.3 h1:MVQghNeW+LZcmXe7SY1V36Z+WFMD github.com/envoyproxy/protoc-gen-validate v1.3.3/go.mod h1:TsndJ/ngyIdQRhMcVVGDDHINPLWB7C82oDArY51KfB0= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= +github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 h1:vymEbVwYFP/L05h5TKQxvkXoKxNvTpjxYKdF1Nlwuao= +github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433/go.mod h1:tphK2c80bpPhMOI4v6bIc2xWywPfbqi1Z06+RcrMkDg= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -76,14 +76,14 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.12 h1:Fg+zsqzYEs1Znvmczt github.com/googleapis/enterprise-certificate-proxy v0.3.12/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc= github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY= -github.com/hugodutka/fantasy v0.0.0-20260310103256-242e3d156af6 h1:bFV3LXw6nN97y1aSpQ4rBygqnFTFt1afIevClVUZ7uQ= -github.com/hugodutka/fantasy v0.0.0-20260310103256-242e3d156af6/go.mod h1:KIeNQUpJTswwpY0P6HJsr3LBFgfTDb8FDpOdVQMsKqY= -github.com/kaptinlin/go-i18n v0.2.11 h1:OayNt8mWt8nDaqAOp09/C1VG9Y5u8LpQnnxbyGARDV4= -github.com/kaptinlin/go-i18n v0.2.11/go.mod h1:pVcu9qsW5pOIOoZFJXesRYmLos1vMQrby70JPAoWmJU= -github.com/kaptinlin/jsonpointer v0.4.16 h1:Ux4w4FY+uLv+K+TxaCJtM/TpPv+1+eS6gH4Z9/uhOuA= -github.com/kaptinlin/jsonpointer v0.4.16/go.mod h1:SsfsjqnHG5zuKo1DTBzk1VknaHlL4osHw+X9kZKukpU= -github.com/kaptinlin/jsonschema v0.7.3 h1:kyIydij76ORiSxmfy0xFYy0cOx8MwG6pyyaSoQshsK4= -github.com/kaptinlin/jsonschema v0.7.3/go.mod h1:Ys6zr+W6/1330FzZEouFrAYImK+AmYt5HQVTHQQXQo8= +github.com/hugodutka/fantasy v0.0.0-20260312150824-7d96450e2412 h1:jN/I3o2aUWakyiEAZ7A01rVftM9eSY++2LNtleu1sqw= +github.com/hugodutka/fantasy v0.0.0-20260312150824-7d96450e2412/go.mod h1:QeRVUeG1XNTWBszRAbhUtPyX1VWs6zjkCxwfcwnICdc= +github.com/kaptinlin/go-i18n v0.2.12 h1:ywDsvb4KDFddMC2dpI/rrIzGU2mWUSvHmWUm9BMsdl4= +github.com/kaptinlin/go-i18n v0.2.12/go.mod h1:pVcu9qsW5pOIOoZFJXesRYmLos1vMQrby70JPAoWmJU= +github.com/kaptinlin/jsonpointer v0.4.17 h1:mY9k8ciWncxbsECyaxKnR0MdmxamNdp2tLQkAKVrtSk= +github.com/kaptinlin/jsonpointer v0.4.17/go.mod h1:SsfsjqnHG5zuKo1DTBzk1VknaHlL4osHw+X9kZKukpU= +github.com/kaptinlin/jsonschema v0.7.5 h1:jkK4a3NyzNoGlvu12CsL3IcqNMVa5sL51HPVa0nWcPY= +github.com/kaptinlin/jsonschema v0.7.5/go.mod h1:3gIWnptl+SWMyfMR2r4TXXd0xsQZ1m50AKrwmcUONSg= github.com/kaptinlin/messageformat-go v0.4.18 h1:RBlHVWgZyoxTcUgGWBsl2AcyScq/urqbLZvzgryTmSI= github.com/kaptinlin/messageformat-go v0.4.18/go.mod h1:ntI3154RnqJgr7GaC+vZBnIExl2V3sv9selvRNNEM24= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= @@ -122,10 +122,10 @@ go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZY go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= -golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= -golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= -golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= -golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= +golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= @@ -136,10 +136,10 @@ golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/api v0.267.0 h1:w+vfWPMPYeRs8qH1aYYsFX68jMls5acWl/jocfLomwE= -google.golang.org/api v0.267.0/go.mod h1:Jzc0+ZfLnyvXma3UtaTl023TdhZu6OMBP9tJ+0EmFD0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d h1:t/LOSXPJ9R0B6fnZNyALBRfZBH0Uy0gT+uR+SJ6syqQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/api v0.269.0 h1:qDrTOxKUQ/P0MveH6a7vZ+DNHxJQjtGm/uvdbdGXCQg= +google.golang.org/api v0.269.0/go.mod h1:N8Wpcu23Tlccl0zSHEkcAZQKDLdquxK+l9r2LkwAauE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY= google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/examples/agent-go/main.go b/examples/agent-go/main.go index 2322d5f..6b4c50a 100644 --- a/examples/agent-go/main.go +++ b/examples/agent-go/main.go @@ -37,7 +37,7 @@ import ( // --------------------------------------------------------------------------- const ( - defaultPrompt = "Navigate to news.ycombinator.com and tell me what the top story is." + defaultPrompt = "Navigate to news.ycombinator.com and tell me what the top comments on the top 3 stories are. Never wait for a page to load more than 1 second." defaultWidth = 1280 defaultHeight = 800 defaultViewerPort = 6080 @@ -285,11 +285,10 @@ func resolveDesktopBrowser() string { return "" } -func launchDesktopBrowser(url string) { +func launchDesktopBrowser(url string) error { browser := resolveDesktopBrowser() if browser == "" { - fmt.Fprintln(os.Stderr, "warning: no browser found inside the desktop") - return + return fmt.Errorf("no browser found inside the desktop") } args := []string{browser, "--no-first-run", "--disable-session-crashed-bubble"} @@ -306,7 +305,7 @@ func launchDesktopBrowser(url string) { } allArgs := append([]string{"open", "--"}, args...) - _ = pdExecVoid(allArgs...) + return pdExecVoid(allArgs...) } // --------------------------------------------------------------------------- @@ -332,17 +331,6 @@ func computeScaledSize(w, h int) (int, int) { // Computer action types (matching Anthropic computer_20251124) // --------------------------------------------------------------------------- -type computerAction struct { - Action string `json:"action"` - Coordinate *[2]int `json:"coordinate,omitempty"` - StartCoordinate *[2]int `json:"start_coordinate,omitempty"` - Text string `json:"text,omitempty"` - ScrollDirection string `json:"scroll_direction,omitempty"` - ScrollAmount *int `json:"scroll_amount,omitempty"` - Duration *float64 `json:"duration,omitempty"` - Region *[4]int `json:"region,omitempty"` -} - // --------------------------------------------------------------------------- // Computer tool execution // --------------------------------------------------------------------------- @@ -353,18 +341,18 @@ func clampCoord(x, y int) (int, int) { // executeComputerAction runs a single computer action and returns a tool // result that can be fed back into the conversation. -func executeComputerAction(input computerAction) ([]fantasy.ToolResultOutputContent, error) { +func executeComputerAction(input anthropic.ComputerUseInput) ([]fantasy.ToolResultOutputContent, error) { switch input.Action { - case "key": + case anthropic.ActionKey: if input.Text == "" { return textResult("text is required for key action"), nil } if err := pdExecVoid("keyboard", "key", input.Text); err != nil { return errorResult(err.Error()), nil } - return textResult(fmt.Sprintf("pressed key combo: %s", input.Text)), nil + return captureScreenshotResult(nil) - case "hold_key": + case anthropic.ActionHoldKey: if input.Text == "" { return errorResult("text is required for hold_key action"), nil } @@ -384,8 +372,8 @@ func executeComputerAction(input computerAction) ([]fantasy.ToolResultOutputCont pressed = append(pressed, k) } dur := 250 * time.Millisecond - if input.Duration != nil { - dur = time.Duration(*input.Duration * float64(time.Second)) + if input.Duration > 0 { + dur = time.Duration(input.Duration) * time.Second if dur < 10*time.Millisecond { dur = 10 * time.Millisecond } @@ -394,127 +382,92 @@ func executeComputerAction(input computerAction) ([]fantasy.ToolResultOutputCont for i := len(pressed) - 1; i >= 0; i-- { _ = pdExecVoid("keyboard", "up", pressed[i]) } - return textResult(fmt.Sprintf("held keys for %dms: %s", dur.Milliseconds(), input.Text)), nil + return captureScreenshotResult(nil) - case "type": + case anthropic.ActionType: if input.Text == "" { return errorResult("text is required for type action"), nil } if err := pdExecVoid("keyboard", "type", input.Text); err != nil { return errorResult(err.Error()), nil } - return textResult(fmt.Sprintf("typed %d characters", len(input.Text))), nil + return captureScreenshotResult(nil) - case "cursor_position": - out, err := pdExec("cursor", "--json") - if err != nil { - return errorResult(err.Error()), nil - } - var pos struct { - X int `json:"x"` - Y int `json:"y"` - } - if err := json.Unmarshal([]byte(strings.TrimSpace(out)), &pos); err != nil { + case anthropic.ActionMouseMove: + x, y := clampCoord(int(input.Coordinate[0]), int(input.Coordinate[1])) + if err := pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)); err != nil { return errorResult(err.Error()), nil } - return textResult(fmt.Sprintf("cursor at %d,%d", pos.X, pos.Y)), nil + return captureScreenshotResult(nil) - case "mouse_move": - if input.Coordinate == nil { - return errorResult("coordinate is required for mouse_move"), nil - } - x, y := clampCoord(input.Coordinate[0], input.Coordinate[1]) + case anthropic.ActionLeftClick: + x, y := clampCoord(int(input.Coordinate[0]), int(input.Coordinate[1])) if err := pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)); err != nil { return errorResult(err.Error()), nil } - return textResult(fmt.Sprintf("moved mouse to %d,%d", x, y)), nil - - case "left_click": - if input.Coordinate != nil { - x, y := clampCoord(input.Coordinate[0], input.Coordinate[1]) - if err := pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)); err != nil { - return errorResult(err.Error()), nil - } - } if err := pdExecVoid("mouse", "click", "left"); err != nil { return errorResult(err.Error()), nil } - return textResult("left click"), nil + return captureScreenshotResult(nil) - case "left_click_drag": - if input.StartCoordinate == nil { - return errorResult("start_coordinate is required for left_click_drag"), nil - } - if input.Coordinate == nil { - return errorResult("coordinate is required for left_click_drag"), nil - } - sx, sy := clampCoord(input.StartCoordinate[0], input.StartCoordinate[1]) - ex, ey := clampCoord(input.Coordinate[0], input.Coordinate[1]) + case anthropic.ActionLeftClickDrag: + sx, sy := clampCoord(int(input.StartCoordinate[0]), int(input.StartCoordinate[1])) + ex, ey := clampCoord(int(input.Coordinate[0]), int(input.Coordinate[1])) _ = pdExecVoid("mouse", "move", strconv.Itoa(sx), strconv.Itoa(sy)) _ = pdExecVoid("mouse", "down", "left") _ = pdExecVoid("mouse", "move", strconv.Itoa(ex), strconv.Itoa(ey)) _ = pdExecVoid("mouse", "up", "left") - return textResult(fmt.Sprintf("dragged from %d,%d to %d,%d", sx, sy, ex, ey)), nil + return captureScreenshotResult(nil) - case "left_mouse_down": + case anthropic.ActionLeftMouseDown: if err := pdExecVoid("mouse", "down", "left"); err != nil { return errorResult(err.Error()), nil } - return textResult("left mouse down"), nil + return captureScreenshotResult(nil) - case "left_mouse_up": + case anthropic.ActionLeftMouseUp: if err := pdExecVoid("mouse", "up", "left"); err != nil { return errorResult(err.Error()), nil } - return textResult("left mouse up"), nil + return captureScreenshotResult(nil) - case "right_click": - if input.Coordinate != nil { - x, y := clampCoord(input.Coordinate[0], input.Coordinate[1]) - _ = pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)) - } + case anthropic.ActionRightClick: + x, y := clampCoord(int(input.Coordinate[0]), int(input.Coordinate[1])) + _ = pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)) if err := pdExecVoid("mouse", "click", "right"); err != nil { return errorResult(err.Error()), nil } - return textResult("right click"), nil + return captureScreenshotResult(nil) - case "middle_click": - if input.Coordinate != nil { - x, y := clampCoord(input.Coordinate[0], input.Coordinate[1]) - _ = pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)) - } + case anthropic.ActionMiddleClick: + x, y := clampCoord(int(input.Coordinate[0]), int(input.Coordinate[1])) + _ = pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)) if err := pdExecVoid("mouse", "click", "middle"); err != nil { return errorResult(err.Error()), nil } - return textResult("middle click"), nil + return captureScreenshotResult(nil) - case "double_click": - if input.Coordinate != nil { - x, y := clampCoord(input.Coordinate[0], input.Coordinate[1]) - _ = pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)) - } + case anthropic.ActionDoubleClick: + x, y := clampCoord(int(input.Coordinate[0]), int(input.Coordinate[1])) + _ = pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)) _ = pdExecVoid("mouse", "click", "left") _ = pdExecVoid("mouse", "click", "left") - return textResult("double click"), nil + return captureScreenshotResult(nil) - case "triple_click": - if input.Coordinate != nil { - x, y := clampCoord(input.Coordinate[0], input.Coordinate[1]) - _ = pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)) - } + case anthropic.ActionTripleClick: + x, y := clampCoord(int(input.Coordinate[0]), int(input.Coordinate[1])) + _ = pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)) _ = pdExecVoid("mouse", "click", "left") _ = pdExecVoid("mouse", "click", "left") _ = pdExecVoid("mouse", "click", "left") - return textResult("triple click"), nil + return captureScreenshotResult(nil) - case "scroll": - if input.Coordinate != nil { - x, y := clampCoord(input.Coordinate[0], input.Coordinate[1]) - _ = pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)) - } - amount := 3 - if input.ScrollAmount != nil { - amount = max(1, *input.ScrollAmount) + case anthropic.ActionScroll: + x, y := clampCoord(int(input.Coordinate[0]), int(input.Coordinate[1])) + _ = pdExecVoid("mouse", "move", strconv.Itoa(x), strconv.Itoa(y)) + amount := int(input.ScrollAmount) + if amount < 1 { + amount = 3 } dir := input.ScrollDirection if dir == "" { @@ -534,22 +487,23 @@ func executeComputerAction(input computerAction) ([]fantasy.ToolResultOutputCont if err := pdExecVoid("mouse", "scroll", strconv.Itoa(dx), strconv.Itoa(dy)); err != nil { return errorResult(err.Error()), nil } - return textResult(fmt.Sprintf("scrolled %s by %d", dir, amount)), nil + return captureScreenshotResult(nil) - case "wait": - dur := 1.0 - if input.Duration != nil { - dur = *input.Duration + case anthropic.ActionWait: + durSec := input.Duration + if durSec < 1 { + durSec = 1 } - ms := max(10, int(math.Round(dur*1000))) + ms := max(10, int(durSec)*1000) time.Sleep(time.Duration(ms) * time.Millisecond) - return textResult(fmt.Sprintf("waited %dms", ms)), nil + return captureScreenshotResult(nil) - case "screenshot": + case anthropic.ActionScreenshot: return captureScreenshotResult(nil) - case "zoom": - return captureScreenshotResult(input.Region) + case anthropic.ActionZoom: + region := &[4]int{int(input.Region[0]), int(input.Region[1]), int(input.Region[2]), int(input.Region[3])} + return captureScreenshotResult(region) default: return errorResult(fmt.Sprintf("unsupported action: %s", input.Action)), nil @@ -625,6 +579,16 @@ func captureScreenshotResult(region *[4]int) ([]fantasy.ToolResultOutputContent, }, nil } +// formatAction returns a human-readable summary of the non-empty +// fields in a computerAction, suitable for log output. +func formatAction(a anthropic.ComputerUseInput) string { + marshalled, err := json.Marshal(a) + if err != nil { + return fmt.Sprintf("error marshalling action: %v", err) + } + return string(marshalled) +} + // --------------------------------------------------------------------------- // Agent loop — drives model.Generate with tool results fed back // --------------------------------------------------------------------------- @@ -717,8 +681,8 @@ func runAgentLoop(ctx context.Context, model fantasy.LanguageModel, computerTool for _, tc := range toolCalls { fmt.Fprintf(os.Stderr, " [step %d] tool: %s (id=%s)\n", step, tc.ToolName, tc.ToolCallID) - var action computerAction - if err := json.Unmarshal([]byte(tc.Input), &action); err != nil { + action, err := anthropic.ParseComputerUseInput(tc.Input) + if err != nil { toolResultParts = append(toolResultParts, fantasy.ToolResultPart{ ToolCallID: tc.ToolCallID, Output: fantasy.ToolResultOutputContentText{Text: fmt.Sprintf("invalid input: %v", err)}, @@ -726,9 +690,11 @@ func runAgentLoop(ctx context.Context, model fantasy.LanguageModel, computerTool continue } - fmt.Fprintf(os.Stderr, " [step %d] action: %s\n", step, action.Action) - + fmt.Fprintf(os.Stderr, " [step %d] action: %s\n", step, formatAction(action)) + start := time.Now() results, err := executeComputerAction(action) + elapsed := time.Since(start) + fmt.Fprintf(os.Stderr, " [step %d] action executed in %s\n", step, elapsed) if err != nil { toolResultParts = append(toolResultParts, fantasy.ToolResultPart{ ToolCallID: tc.ToolCallID, @@ -767,13 +733,12 @@ func runAgentLoop(ctx context.Context, model fantasy.LanguageModel, computerTool // Main // --------------------------------------------------------------------------- -func main() { +func entrypoint() error { flag.Parse() loadEnvLocal() if os.Getenv("ANTHROPIC_API_KEY") == "" { - fmt.Fprintln(os.Stderr, "ANTHROPIC_API_KEY is missing. Set it in environment or .env.local at repo root.") - os.Exit(1) + return fmt.Errorf("ANTHROPIC_API_KEY is missing. Set it in environment or .env.local at repo root.") } ctx, cancel := context.WithCancel(context.Background()) @@ -794,8 +759,7 @@ func main() { "#1f252f", ) if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) + return fmt.Errorf("start desktop: %w", err) } defer session.stop() @@ -813,26 +777,31 @@ func main() { // Start the viewer. viewerCmd := startViewer(defaultViewerPort) + defer func() { + if viewerCmd.Process != nil { + _ = viewerCmd.Process.Kill() + } + }() viewerURL := fmt.Sprintf("http://127.0.0.1:%d", defaultViewerPort) fmt.Printf("viewer: %s\n", viewerURL) openHostBrowser(viewerURL) // Let the desktop settle, then launch a browser inside it. time.Sleep(1500 * time.Millisecond) - launchDesktopBrowser("about:blank") + if err := launchDesktopBrowser("about:blank"); err != nil { + return fmt.Errorf("launch desktop browser: %w", err) + } time.Sleep(2000 * time.Millisecond) // Set up the Anthropic provider and model. provider, err := anthropic.New(anthropic.WithAPIKey(os.Getenv("ANTHROPIC_API_KEY"))) if err != nil { - fmt.Fprintf(os.Stderr, "could not create provider: %v\n", err) - os.Exit(1) + return fmt.Errorf("create provider: %w", err) } model, err := provider.LanguageModel(ctx, *flagModel) if err != nil { - fmt.Fprintf(os.Stderr, "could not get language model: %v\n", err) - os.Exit(1) + return fmt.Errorf("get language model: %w", err) } // Create the computer use tool (provider-defined) for the model. @@ -855,17 +824,21 @@ func main() { fmt.Printf("messages: %s\n", messagesPath) if err := runAgentLoop(ctx, model, computerTool, *flagPrompt, *flagMaxSteps, messagesPath); err != nil { - fmt.Fprintf(os.Stderr, "agent loop failed: %v\n", err) + return fmt.Errorf("agent loop: %w", err) } // Finalize. recording.stop() fmt.Printf("\nsaved recording: %s\n", recordingPath) - if viewerCmd.Process != nil { - _ = viewerCmd.Process.Kill() - } - openHostBrowser("file://" + recordingPath) fmt.Printf("opened recording: file://%s\n", recordingPath) + return nil +} + +func main() { + if err := entrypoint(); err != nil { + fmt.Fprintf(os.Stderr, "error: %v\n", err) + os.Exit(1) + } }