mirror of
https://github.com/danielmiessler/fabric.git
synced 2026-09-10 07:36:44 -04:00
Merge branch 'main' into add-synthorai-provider
This commit is contained in:
commit
cd54c1a82f
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -1,5 +1,15 @@
|
|||
# Changelog
|
||||
|
||||
## v1.4.471 (2026-08-28)
|
||||
|
||||
### PR [#2200](https://github.com/danielmiessler/Fabric/pull/2200) by [ksylvan](https://github.com/ksylvan): fix: persist Codex OAuth tokens after refresh
|
||||
|
||||
- Persist refreshed Codex OAuth tokens securely across processes, writing rotated credentials atomically with cross-process locks.
|
||||
- Reload stored tokens before refresh and return valid in-memory tokens first, preventing stale disk values from overwriting fresh credentials.
|
||||
- Reuse valid refresh tokens before launching interactive authentication, requiring account identifiers and unexpired tokens for fast-path reuse.
|
||||
- Preserve existing environment values, save environment files atomically while holding locks, and enforce secret-only permissions.
|
||||
- Reactivate configured vendors and surface configuration and provider failures immediately, with localized Codex prompts and persistence errors.
|
||||
|
||||
## v1.4.470 (2026-08-04)
|
||||
|
||||
### PR [#2186](https://github.com/danielmiessler/Fabric/pull/2186) by [giodamelio](https://github.com/giodamelio): Update Nixpkgs version for newer Go version
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
package main
|
||||
|
||||
var version = "v1.4.470"
|
||||
var version = "v1.4.471"
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ Create a `.env` file next to the `generate_changelog` binary:
|
|||
|
||||
```bash
|
||||
GITHUB_TOKEN=your_github_token_here
|
||||
FABRIC_CHANGELOG_SUMMARIZE_MODEL=claude-sonnet-4-20250514
|
||||
FABRIC_CHANGELOG_SUMMARIZE_MODEL=gpt-5.6-sol
|
||||
```
|
||||
|
||||
The tool automatically loads `.env` files for convenient configuration management.
|
||||
|
|
@ -226,8 +226,8 @@ The tool can generate AI-powered summaries using Fabric for more polished, profe
|
|||
# Enable AI summarization
|
||||
generate_changelog --ai-summarize
|
||||
|
||||
# Custom model (default: claude-sonnet-4-20250514)
|
||||
FABRIC_CHANGELOG_SUMMARIZE_MODEL=claude-opus-4 generate_changelog --ai-summarize
|
||||
# Custom model (default: claude-opus-5)
|
||||
FABRIC_CHANGELOG_SUMMARIZE_MODEL=gpt-5.6-sol generate_changelog --ai-summarize
|
||||
```
|
||||
|
||||
### AI Summary Features
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -7,7 +7,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
const DefaultSummarizeModel = "claude-sonnet-4-5"
|
||||
const DefaultSummarizeModel = "claude-opus-5"
|
||||
const MinContentLength = 256 // Minimum content length to consider for summarization
|
||||
|
||||
const prompt = `# ROLE
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ Use parameterized queries instead of string concatenation...
|
|||
- Store secrets in environment variables or secure configuration
|
||||
- Use the built-in setup process for key management
|
||||
- Regularly rotate API keys
|
||||
- `~/.config/fabric/.env` holds API keys and Codex OAuth tokens. Fabric writes it with mode `0600`. Treat the file as secret material. Comments and key order are not preserved when Codex tokens are updated in place.
|
||||
|
||||
### Input Validation
|
||||
|
||||
|
|
|
|||
120
go.mod
120
go.mod
|
|
@ -4,61 +4,62 @@ go 1.26.0
|
|||
|
||||
require (
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.14.0
|
||||
github.com/anthropics/anthropic-sdk-go v1.61.0
|
||||
github.com/anthropics/anthropic-sdk-go v1.67.0
|
||||
github.com/atotto/clipboard v0.1.4
|
||||
github.com/aws/aws-sdk-go-v2 v1.43.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.31
|
||||
github.com/aws/aws-sdk-go-v2/service/bedrock v1.66.0
|
||||
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.56.0
|
||||
github.com/aws/aws-sdk-go-v2 v1.44.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.40
|
||||
github.com/aws/aws-sdk-go-v2/service/bedrock v1.68.0
|
||||
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.58.0
|
||||
github.com/gabriel-vasile/mimetype v1.4.15
|
||||
github.com/gin-gonic/gin v1.12.0
|
||||
github.com/go-git/go-git/v5 v5.19.1
|
||||
github.com/go-git/go-git/v5 v5.19.2
|
||||
github.com/go-shiori/go-readability v0.0.0-20251205110129-5db1dc9836f0
|
||||
github.com/google/go-github/v66 v66.0.0
|
||||
github.com/hasura/go-graphql-client v0.16.0
|
||||
github.com/jessevdk/go-flags v1.6.1
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/mattn/go-sqlite3 v1.14.48
|
||||
github.com/mattn/go-sqlite3 v1.14.50
|
||||
github.com/nicksnyder/go-i18n/v2 v2.6.1
|
||||
github.com/ollama/ollama v0.32.3
|
||||
github.com/ollama/ollama v0.33.1
|
||||
github.com/openai/openai-go v1.12.0
|
||||
github.com/otiai10/copy v1.14.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/samber/lo v1.53.0
|
||||
github.com/sgaunet/perplexity-go/v2 v2.16.1
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/stretchr/testify v1.12.1
|
||||
github.com/swaggo/files v1.0.1
|
||||
github.com/swaggo/gin-swagger v1.6.1
|
||||
github.com/swaggo/swag v1.16.6
|
||||
golang.org/x/oauth2 v0.36.0
|
||||
golang.org/x/text v0.40.0
|
||||
google.golang.org/api v0.290.0
|
||||
golang.org/x/sys v0.47.0
|
||||
golang.org/x/text v0.41.0
|
||||
google.golang.org/api v0.294.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.22.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.12.0 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.7.2 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.9.0 // indirect
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.32 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.5.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.41 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.6.0 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/buger/jsonparser v1.2.0 // indirect
|
||||
github.com/buger/jsonparser v1.6.1 // indirect
|
||||
github.com/bytedance/gopkg v0.1.4 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v1.0.0 // indirect
|
||||
github.com/go-openapi/jsonreference v1.0.0 // indirect
|
||||
github.com/go-openapi/spec v0.22.9 // indirect
|
||||
github.com/go-openapi/swag/conv v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/jsonutils v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/loading v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/pools v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/stringutils v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/typeutils v0.27.3 // indirect
|
||||
github.com/go-openapi/swag/yamlutils v0.27.3 // indirect
|
||||
github.com/go-openapi/jsonreference v1.0.1 // indirect
|
||||
github.com/go-openapi/spec v0.22.11 // indirect
|
||||
github.com/go-openapi/swag/conv v0.29.1 // indirect
|
||||
github.com/go-openapi/swag/jsonutils v0.29.1 // indirect
|
||||
github.com/go-openapi/swag/loading v0.29.1 // indirect
|
||||
github.com/go-openapi/swag/pools v0.29.1 // indirect
|
||||
github.com/go-openapi/swag/stringutils v0.29.1 // indirect
|
||||
github.com/go-openapi/swag/typeutils v0.29.1 // indirect
|
||||
github.com/go-openapi/swag/yamlutils v0.29.1 // indirect
|
||||
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
|
|
@ -72,18 +73,18 @@ require (
|
|||
github.com/quic-go/quic-go v0.61.0 // indirect
|
||||
github.com/standard-webhooks/standard-webhooks/libraries v0.0.1 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
go.mongodb.org/mongo-driver/v2 v2.8.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
go.mongodb.org/mongo-driver/v2 v2.8.2 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.5 // indirect
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.6 // indirect
|
||||
golang.org/x/mod v0.38.0 // indirect
|
||||
golang.org/x/mod v0.40.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
golang.org/x/tools v0.48.0 // indirect
|
||||
golang.org/x/tools v0.49.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.123.0 // indirect
|
||||
cloud.google.com/go/auth v0.22.0 // indirect
|
||||
cloud.google.com/go/auth v0.23.2 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||
dario.cat/mergo v1.0.2 // indirect
|
||||
|
|
@ -91,20 +92,20 @@ require (
|
|||
github.com/ProtonMail/go-crypto v1.4.1 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.4 // indirect
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.14 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.30
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.31 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.31 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.31 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.13 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.31 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.33.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.45.0 // indirect
|
||||
github.com/aws/smithy-go v1.27.4 // indirect
|
||||
github.com/bytedance/sonic v1.15.2 // indirect
|
||||
github.com/bytedance/sonic/loader v0.5.1 // indirect
|
||||
github.com/cloudflare/circl v1.6.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.20 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.39
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.40 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.40 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.40 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.19 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.40 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.34.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.39.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.46.0 // indirect
|
||||
github.com/aws/smithy-go v1.28.1 // indirect
|
||||
github.com/bytedance/sonic v1.15.3 // indirect
|
||||
github.com/bytedance/sonic/loader v0.5.2 // indirect
|
||||
github.com/cloudflare/circl v1.6.5 // indirect
|
||||
github.com/cloudwego/base64x v0.1.7 // indirect
|
||||
github.com/coder/websocket v1.8.15 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.7.0 // indirect
|
||||
|
|
@ -126,8 +127,8 @@ require (
|
|||
github.com/google/go-querystring v1.2.0 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.19 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.23.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.21 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.24.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
|
|
@ -149,21 +150,20 @@ require (
|
|||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||
github.com/ugorji/go/codec v1.3.2 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 // indirect
|
||||
go.opentelemetry.io/otel v1.44.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.44.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.44.0 // indirect
|
||||
golang.org/x/arch v0.29.0 // indirect
|
||||
golang.org/x/crypto v0.54.0 // indirect
|
||||
golang.org/x/net v0.57.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 // indirect
|
||||
go.opentelemetry.io/otel v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.46.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.46.0 // indirect
|
||||
golang.org/x/arch v0.30.0 // indirect
|
||||
golang.org/x/crypto v0.55.0 // indirect
|
||||
golang.org/x/net v0.58.0 // indirect
|
||||
golang.org/x/sync v0.22.0 // indirect
|
||||
golang.org/x/sys v0.47.0 // indirect
|
||||
google.golang.org/genai v1.65.0
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260724162435-b2f20204f0df // indirect
|
||||
google.golang.org/grpc v1.82.1 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
google.golang.org/genai v1.70.0
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
|
||||
google.golang.org/grpc v1.83.2 // indirect
|
||||
google.golang.org/protobuf v1.36.12 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
)
|
||||
|
|
|
|||
125
go.sum
125
go.sum
|
|
@ -2,6 +2,8 @@ cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
|
|||
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
|
||||
cloud.google.com/go/auth v0.22.0 h1:Xp9wAKkLoeaYb5pYZZoQGz4E9sdPxIbzS3gywZE3ciQ=
|
||||
cloud.google.com/go/auth v0.22.0/go.mod h1:M9o2Oz+YI2jAfxewJgb1vyI3vceHF+eohmxyzmrl+9s=
|
||||
cloud.google.com/go/auth v0.23.2 h1:pxSCpfiji41hpzpPdMCftEUCezpgpqmmDdYiAjCKXxo=
|
||||
cloud.google.com/go/auth v0.23.2/go.mod h1:4DhBRcqvtljQN3dJ57qtqbib5ZGCYE5f2crfiiC2EM0=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
||||
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=
|
||||
|
|
@ -10,6 +12,8 @@ dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
|||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.22.0 h1:aokoqcHvaGjiM3VpjKDfMMnF/8epJ+Q1HLJ7CudztqE=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.22.0/go.mod h1:/WYEx9pcM9Y+Dd/APJaNlSvVSvzl54rrMdZT5+Oi2LM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.0 h1:4gRPBpN1f6xt88yi4WR26m7XaD9OlWtVT6bWPdGUIok=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.0/go.mod h1:G7QVLxw1j1JVyrO1MA95S8m8HStaaleDZYTcfGgjB2o=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.14.0 h1:CU4+EJeJi3TKYWEcYuSdWsjzw0nVsK/H0MSQOiPcymU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.14.0/go.mod h1:q0+UTSRvShwUCrR/s5HtyInYphN7Wvxb7snFM3u+SLA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.4.0 h1:xFaZZ+IubdftrDHnGGwZ6QvQ3KHTtWl2MCK+GMt2vxs=
|
||||
|
|
@ -20,6 +24,8 @@ github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJ
|
|||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.7.2 h1:RHK7bS+HQMslb1sZpAokUt+zTVmue0hKSs2C791hhzU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.7.2/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.9.0 h1:MDT4FxAPve5FnYn6vOL1r7RCRDG+l9cI7a5LlCuHsqA=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.9.0/go.mod h1:Y33QHnf0FfdVewFFISOGe20mkZbxX4H839o955/PoeI=
|
||||
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
|
||||
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
||||
|
|
@ -35,6 +41,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
|
|||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/anthropics/anthropic-sdk-go v1.61.0 h1:JRTnm1tPqn5xo1xd1zfrcFDlcoWXVMvV1K68YmhpZKw=
|
||||
github.com/anthropics/anthropic-sdk-go v1.61.0/go.mod h1:3EfIfmFqxH6rbiLcIP4tPFyXL/IHakx2wDG4OU+TIEI=
|
||||
github.com/anthropics/anthropic-sdk-go v1.67.0 h1:tTsVSR+YD6R+1EPoMyZ9im7YKEjJpYGZk5klcDi9HRg=
|
||||
github.com/anthropics/anthropic-sdk-go v1.67.0/go.mod h1:3EfIfmFqxH6rbiLcIP4tPFyXL/IHakx2wDG4OU+TIEI=
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
|
|
@ -43,52 +51,94 @@ github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z
|
|||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
github.com/aws/aws-sdk-go-v2 v1.43.0 h1:fharf/WhbRAVZ1du0QL7roNFxZ6T/sWr+4Ni617bwSI=
|
||||
github.com/aws/aws-sdk-go-v2 v1.43.0/go.mod h1:5pKeft2eJj+gElQ38Jqg4ibCqh+/AK33/0X3hip7IjM=
|
||||
github.com/aws/aws-sdk-go-v2 v1.44.0 h1:4IbaHhtzy+4h37z4JQyO9a2QsiCml3CNYHtq5hIHigo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.44.0/go.mod h1:bttEH6JqnUL8LepvDVfdrds/fZ5bCIxzpe3abyUrhDU=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.14 h1:3IZY0XAJquT3aHzbkHfPzy4ACPcEjVG0x87KOwtpqGY=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.14/go.mod h1:zwM6veDkhGgQFqkBy+uT28AAYpLu+uFMlPl+rCg/73E=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.20 h1:GPRlPwz40I2B2VrBEASOA3Bi77NyeqejNLkifosX0rs=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.20/go.mod h1:g7PNzKcsOKWb4fkSRBA7BZVAS6Y8IcxzN+nRohhQ1Q8=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.31 h1:n4nY9O3QKoHIkL85EX+V8RcMFtOhlpTFhGArg915PXk=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.31/go.mod h1:PN0NYDCCoOpGGsZ2+elDUidmHfQBPyYzN2GCgl8HEBs=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.40 h1:lAVC9gMmKusmqDRe32dPtgKl/BWvJmMJoWELKHCAObw=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.40/go.mod h1:8xOJLbe/hOj1g4PVsfJYV7O2byq+UGET1onDdUgbwqc=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.30 h1:TTCvvzFU6gXa4iJecNG/0F/B0oYTiazoRECr2XyLHrY=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.30/go.mod h1:jKxAp2AEncnliinzpgOSZDFv6+VjvWhjw/AtbfsWT9U=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.39 h1:XOg8LC3Kgnsa3WiPQjc7Bi8k5IBN92cPYfIV9XMFss0=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.39/go.mod h1:GonTDBQ+mTpCVNwaHjj0PagspfrYYMEqOx7FehoEP/I=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.31 h1:kfVL5wAunCJycL6MOQ6aNh6PlAYEymflcjuKmrWUA0o=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.31/go.mod h1:nWfRNDAppujCQgOUd43lKT4yeLv9z3nJ3bw1G3BgQKo=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.40 h1:r5aGipEVgI9aT/tAGjdrPbDQvIAKdTrS3rUPQtG4Rmo=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.40/go.mod h1:vOD3CnPxAdkL6MWZeROkZsTlskklMFfgVFkHzx/oZpY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.31 h1:Z8F3hfCY33IGpJjFAnv0wvtv1FIKj1GHmRDEYqy64tw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.31/go.mod h1:aVyUoytEyOViR6jhq6jula0xkc5NfBE2hgeF6BvOrao=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.40 h1:UIXlbijuB2XK1Kr57fo8iIxCuaSHJzwZ1uo+2tbEYIk=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.40/go.mod h1:wcEsL6jscjZjVUinb0Q5qD/GXOG1yT3GNfmT9HuDwzU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.31 h1:hyOxUyXdh3AyjE93gBgsfziJag9ACwcs+ZpDBLzi8mw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.31/go.mod h1:OERqI9k0draSLB8O8woxY3q25ZWTELRK4RRoLMuMZFo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.40 h1:xLQVRDs2NddDmK9BEyh5KSlJ1Gpy5/GIJXrV6WcVGAE=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.40/go.mod h1:XRXnpFVFGLaEVK+olDdFIM1vNa04ETW452oFGEPUxAo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.32 h1:0MrUL35H/Y4kdFfItoR5jCgtDQ4Z/8LudAoIHRfA4hE=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.32/go.mod h1:2tNZkuWz54arj8mHVf+8Y7cKkcD8Wr/fBpENgEXpjLc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.41 h1:nv/ILuCY0yXACzMQwvtt/HbqDDjemZiI0AeDbxGQlnU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.41/go.mod h1:dzvOSpxaPqQ3j0xS6Lc1vyVuWW0RBj7s/QqYpzu3Q/0=
|
||||
github.com/aws/aws-sdk-go-v2/service/bedrock v1.66.0 h1:RMRC4k42Bt3wHqWiPyFfiRrOyRhJZW7w6vAw5ZnMrPM=
|
||||
github.com/aws/aws-sdk-go-v2/service/bedrock v1.66.0/go.mod h1:1asCJhndokTo9QEJ68/eZv4yJsRPV9A0ROdDx7QQBkQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/bedrock v1.68.0 h1:2T9SsmNe78eLtmobdnvxk088DVuUfYp9Ml9MxFMWQUQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/bedrock v1.68.0/go.mod h1:ANOxqA/+nqohBqirnFCF8EqJFkjAbTLYfyBl6NEjNug=
|
||||
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.56.0 h1:CWw8zDpnMJLwSvZd41Ncf/eJPeZ5t74UxGAu4HbM3S4=
|
||||
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.56.0/go.mod h1:dGxTgK2ZKWrbZv5o/8oCeO3Uch3n0w2rtSFroeJoLcE=
|
||||
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.58.0 h1:TDwZrhBZTHNxvGiqqDoNjdUuoveRRVfy14VeFHbbWBc=
|
||||
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.58.0/go.mod h1:ZnrFfnjYjXc/PC2a2hwAIS2qf1Yqk15EMLryhca2wps=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.13 h1:mbRIur/BiHK6SKPjoBIXSE/hJ6g6JGRLuxQy1jGjlN4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.13/go.mod h1:ITg9em2KbJx1s0y4aqRX5OYWG6HBZ5TVR//OdpEZ2CQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.19 h1:bAdDl/HkGCcGPoe25ToSHEw23VIxt6CT5fLcg111BKg=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.19/go.mod h1:KaUzbLxv4CeSxh6ZCl9B4m7CuFenS8kUEaDs+f/DQr4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.31 h1:w2SIhW92DZPFrSL4ksVCr8IYff5OZwIcxg8+95tzvAI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.31/go.mod h1:wAhpCQbkov+IcvjozJbd2xRCoZybUEHNkcFunssNACg=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.40 h1:gr3Fw1cxZXNCdeo/lQ7isHEHzvHVM7z75qb2zW9aMjw=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.40/go.mod h1:8z/9CmfnQhiuXD7Ykbcg4a/whSWsniE0ODSx9uwVzfk=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.5.0 h1:OHH5iTQvVGmfHjX/5Q+vFuA/Rf2x6/95aJ/75QCQSm4=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.5.0/go.mod h1:mCF3AK9PpL49oOrhniUXWAfhVBVQ/XbytoE5eccZUIs=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.6.0 h1:agcr0j8YeFEzdXNo17Rg9MbbjLRjrimabwNtji4e+lU=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.6.0/go.mod h1:qU5PxgQ4JiUOOMotzfO3+5oUda5W+8JDVKyLQqlrJik=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.33.0 h1:CaJyYhxBE0M/HJX/YvSaSmQlsI91VHB0lKU8LtLxL3A=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.33.0/go.mod h1:+e6BMRMPjBQoCw/WovYR9GLy2IU0z4Q77smOB1DraSg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.34.0 h1:FxaN8/sn61DTXNI6Gt678tFJUY8iUsCchm6Y/F/RjaA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.34.0/go.mod h1:vu4OY6s8LJtT8BtYG2LD6BGSZMptkYn3o5hvCPB22jc=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.0 h1:tC323YV77QdafeBr6LUhLDTsboyuyHLNRwAyCP44kGU=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.0/go.mod h1:SfLK1sgviHmbI+MozR9iDwDjL4cdCVZtahsjoR+z7wg=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.39.0 h1:crWKPeGYTBTuBxQ3p73kjfJvt4brUIsr+Fuypko8FxY=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.39.0/go.mod h1:HjjZVhaBz0JBR/kbWKThmNDhFKS7y6EURuk493tJk9Y=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.45.0 h1:Pd6PNlp4t8PTXxqzstICl52Wsy78vpjFZ7PRUj44mJc=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.45.0/go.mod h1:rmQ0TnHzuLPmabgjPcsywhsSOmaBDgzR4zvDxSPsGdg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.46.0 h1:IZ63JdogSNNjex/jsODNv7jGDcO/xJYd9FsgyfCsp1g=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.46.0/go.mod h1:I+rwAf3spG5dITBaAo3xXRowk8kiOhtU1kYxfvCTC44=
|
||||
github.com/aws/smithy-go v1.27.4 h1:JQcphmBN4f0q/sPqXqROIItRNV/hy10cgu7CsFy616M=
|
||||
github.com/aws/smithy-go v1.27.4/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
|
||||
github.com/aws/smithy-go v1.28.1 h1:R/nXH00c8qcfCzQVELtRw+eLQWtzv+VAIEFJ1/xxXlQ=
|
||||
github.com/aws/smithy-go v1.28.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
|
||||
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/buger/jsonparser v1.2.0 h1:4EFcvK1kD4jyj6YqNK6skK6w+y7FHHBR+XBCtxwu/6g=
|
||||
github.com/buger/jsonparser v1.2.0/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/buger/jsonparser v1.6.1 h1:I0phFv0PlbLHnM7TZAVjZ2MJ2/eWRTDyuO7GLR98IEs=
|
||||
github.com/buger/jsonparser v1.6.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM=
|
||||
github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4=
|
||||
github.com/bytedance/sonic v1.15.2 h1:90H+rcF/FwLXwfB1cudOLq/je83n683Utf4Cbp0xHCo=
|
||||
github.com/bytedance/sonic v1.15.2/go.mod h1:mT2NbXunuaEbnZ+mRIX/vYqKISmgEuHFDI4UzmKx2SA=
|
||||
github.com/bytedance/sonic v1.15.3 h1:P3akjLPBtV/i6bHC6LbcLjY3KuoOvfiqF8wFHeP5IhY=
|
||||
github.com/bytedance/sonic v1.15.3/go.mod h1:8e51yTPdY8M6t+vvGL1c2Y1xL9i+frEeIAQAEl75NUc=
|
||||
github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI=
|
||||
github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||
github.com/bytedance/sonic/loader v0.5.2 h1:0QtP1gevc1OZ6/H8Lb9BRZiCXd1Ftjd3OKuj1T1lBIo=
|
||||
github.com/bytedance/sonic/loader v0.5.2/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||
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/cloudflare/circl v1.6.4 h1:pOXuDTCEYyzydgUpQ0CQz3LsinKjiSk6nNP5Lt5K64U=
|
||||
github.com/cloudflare/circl v1.6.4/go.mod h1:YxarevkLlbaHuWsxG6vmYNWBEsSp4pnp7j+4VljMavY=
|
||||
github.com/cloudflare/circl v1.6.5 h1:O64F26HEqNhznd/hrC5KZXVKYuKM2rx4deZDTc4ihQA=
|
||||
github.com/cloudflare/circl v1.6.5/go.mod h1:h5LNyxAc5nTue9DS5jT+48en2PSDYt3zdGnz5OstK6c=
|
||||
github.com/cloudwego/base64x v0.1.7 h1:NppS+Fgzg5ovhn4NkUXaDT3x9jldgH5ToMCqzBSi2zI=
|
||||
github.com/cloudwego/base64x v0.1.7/go.mod h1:Cu1PV9zfrSf7ET2tIbWbbEy7jO7HHJ13q4X2SQ8aWYg=
|
||||
github.com/cncf/xds/go v0.0.0-20260202195803-dba9d589def2 h1:aBangftG7EVZoUb69Os8IaYg++6uMOdKK83QtkkvJik=
|
||||
|
|
@ -133,6 +183,8 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj
|
|||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.19.1 h1:nX27AnaU43/K5bKktKwgBmR9lawoYVe1Ckg0rgzzN00=
|
||||
github.com/go-git/go-git/v5 v5.19.1/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ=
|
||||
github.com/go-git/go-git/v5 v5.19.2 h1:wkfn7vOlUBu8ivAWKBWisTiwJK4jYHzTF8Ndv1LyGqY=
|
||||
github.com/go-git/go-git/v5 v5.19.2/go.mod h1:QqCBE1EFN5ddFmrliLQ3/ntRCUjZU3EJuwuB/jWEHjk=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8=
|
||||
github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
|
|
@ -142,29 +194,50 @@ github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxg
|
|||
github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y=
|
||||
github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY=
|
||||
github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0=
|
||||
github.com/go-openapi/jsonreference v1.0.1 h1:4zJ7AmYDKNmD3aSpfPnFNCFA5E80/xMHUNKgydaLh38=
|
||||
github.com/go-openapi/jsonreference v1.0.1/go.mod h1:dYplQXa6p5lXprLcJ8LE2iU7vNpXsAHDQ5ZAgL+Qx3A=
|
||||
github.com/go-openapi/spec v0.22.9 h1:/vKIFDcGKp0ktZWGbym/tJEWbk6/XOEmAVU0kqKMH+w=
|
||||
github.com/go-openapi/spec v0.22.9/go.mod h1:b/mNUYIOQOyIiUzUzXEE8xzyZqf93KvM9hQGP91yfl0=
|
||||
github.com/go-openapi/spec v0.22.11 h1:/ZW28n4PCghbBpwjmvoMeyCeDwd6pIe715Ov8T3kAaQ=
|
||||
github.com/go-openapi/spec v0.22.11/go.mod h1:Ypu+u1KTejey7/QCr3j1ChdjwhGgXuklbH7l8+YP1J4=
|
||||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||
github.com/go-openapi/swag/conv v0.27.3 h1:iqJFmGEjmX3AY0lSszABFqRVqOSt99XS0LzNIMJYuhU=
|
||||
github.com/go-openapi/swag/conv v0.27.3/go.mod h1:nPRmN6jgNme99hpf+nM0auDZGALWIqlwhisKPK/bQhQ=
|
||||
github.com/go-openapi/swag/conv v0.29.1 h1:AC4Eh/5c/eUDOUCzzsRC9ghmFgOSBHeRMGIngY0ZUGA=
|
||||
github.com/go-openapi/swag/conv v0.29.1/go.mod h1:S1X7/ZrBEZOC0Wc8AGxjbcGS92l3WEjA7aPtpl+RaqM=
|
||||
github.com/go-openapi/swag/jsonutils v0.27.3 h1:1DEz+O82frtSMBcos/7XIn1GnpNTbsD4Bru4Dc/uhRc=
|
||||
github.com/go-openapi/swag/jsonutils v0.27.3/go.mod h1:qiDCoQvzkMxrV3G8FLEdIU5L+EFYc0zcDOHWT3Yofvo=
|
||||
github.com/go-openapi/swag/jsonutils v0.29.1 h1:AFCxs0eQZ24/QyfhVHM2t49rMz7Vv3XCsZQI6yrNy+c=
|
||||
github.com/go-openapi/swag/jsonutils v0.29.1/go.mod h1:u3+sCfJpttDpcmS5kpm0yxL6GK0eWgODsx8Yw8fcqNM=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.3 h1:h/eT9kmGCDdFLJF29lOhzLtF0FmP1AX2MhLJWVebsb8=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.3/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.29.1 h1:BiiXE31Bx9SfpsMmOQj5KYpUhTZBpLVriVhJDuLuY2o=
|
||||
github.com/go-openapi/swag/loading v0.27.3 h1:L9nQkEgzU7QgFQL+pLEMfGUKxeM4pWwGwbET9Z3weW0=
|
||||
github.com/go-openapi/swag/loading v0.27.3/go.mod h1:rJ0NeaKsF4CVPnMGjPQl7JlSHzvD0bc2DKXLss1hiuE=
|
||||
github.com/go-openapi/swag/loading v0.29.1 h1:FCv5fG8UhTdDJa2R7w+5O9Ekpcbw7tt0nFWvmDKGBjc=
|
||||
github.com/go-openapi/swag/loading v0.29.1/go.mod h1:N0ESuem4p2oedKal8EJhciqnJ9Q9Wmt83L1CRB3Fouw=
|
||||
github.com/go-openapi/swag/pools v0.27.3 h1:gXjImP3F6/56wRRcFgEPld084Y6u2gs21ikPBt8NKBk=
|
||||
github.com/go-openapi/swag/pools v0.27.3/go.mod h1:kVQefhSK5RWuRe7BXsL8htgBPAMpN7HDGpGEknqugeE=
|
||||
github.com/go-openapi/swag/pools v0.29.1 h1:NRogYxdEW9SjRM4mkAOji9iefO4MRXq3p/ZJcoQbUKg=
|
||||
github.com/go-openapi/swag/pools v0.29.1/go.mod h1:leDcaghjkRAhCuCRv9NfJU5f0mjoU3cT/XZObhMk3pc=
|
||||
github.com/go-openapi/swag/stringutils v0.27.3 h1:Ru28hnbAvN5wycALQYy8IobHvASq+FUFMlp1QzLM0JI=
|
||||
github.com/go-openapi/swag/stringutils v0.27.3/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM=
|
||||
github.com/go-openapi/swag/stringutils v0.29.1 h1:1ykunK7iJQk1uOO7+oUH1ukbsK85fFCOiCFMOVSY+F0=
|
||||
github.com/go-openapi/swag/stringutils v0.29.1/go.mod h1:7fSqZ+z8Qc0tOfAAK0jVa5qFGrnIlRi6n7NeGGrr1vc=
|
||||
github.com/go-openapi/swag/typeutils v0.27.3 h1:l6SSrx5eR5/WVwrGNzN6bQ9WqL04mrxNBl9YgQ3rcJ4=
|
||||
github.com/go-openapi/swag/typeutils v0.27.3/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ=
|
||||
github.com/go-openapi/swag/typeutils v0.29.1 h1:Nzv9nhnlLCRBPQqfOX+7lB6Guju370or8StT+lIOf6M=
|
||||
github.com/go-openapi/swag/typeutils v0.29.1/go.mod h1:hxpgDZJVBkBsi/d3MIUosafoFdE5exaQRmVp0zwu3YE=
|
||||
github.com/go-openapi/swag/yamlutils v0.27.3 h1:cRFCAoYtslYn9L9T0xWryHy1t7c1MACC+DMj3CLvwvs=
|
||||
github.com/go-openapi/swag/yamlutils v0.27.3/go.mod h1:6JYBGj8sw/NawMllyZY+cTA8Mzk2etS3ZBASdcyPsiU=
|
||||
github.com/go-openapi/swag/yamlutils v0.29.1 h1:69w3tsBajm7MR/fejLy7HD/3J68Ys1SeeZMEzZ3w2sk=
|
||||
github.com/go-openapi/swag/yamlutils v0.29.1/go.mod h1:rgsp3vT/QdWzKwn43CigDwjOGIenPyTZMKnxEM8jZOA=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.6.0 h1:gGHwAJ0R/5jU8BEGDbfRNR3hL68dAVi84WuOApp29B0=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.6.0/go.mod h1:tY+St1SGq4NFl0QIqdTY4aEdbChAHxhyB77XQi9iJCo=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.6.1 h1:Jm+/ze2rMtbD98yen92AhATGLGREDYXG56Xr4gMjEtE=
|
||||
github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug=
|
||||
github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
|
||||
github.com/go-openapi/testify/v2 v2.6.1 h1:6CNJhTjMzgaeaH8WhshcsZNPIvRemiOcFpU7seO/y7Q=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
|
|
@ -203,8 +276,12 @@ 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/googleapis/enterprise-certificate-proxy v0.3.19 h1:mMOE7DN2+p76/EdIrmAy9B9bH+yC4563vmnJ34QR8i4=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.19/go.mod h1:rSEsBUemEBZEexP2y6jPp16LUmUbjmSbcPMQizR0o4k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.21 h1:OFdQ3tnCX/zaQ0Cedur3D3z7kI6HiLX9g3TiAN4/DFU=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.21/go.mod h1:L3D/IQExI6LqEjBdXcZQ1WluSgigQmSwBboFstVPM4w=
|
||||
github.com/googleapis/gax-go/v2 v2.23.0 h1:Tchl7qkvE7Ip3y+ztvNufYFvkfqTe7NfLTYGIdJRLuE=
|
||||
github.com/googleapis/gax-go/v2 v2.23.0/go.mod h1:rBQKOVJCdb8IFEzg+FCwlt1LP/xMDGuqUXhUG+XMXEg=
|
||||
github.com/googleapis/gax-go/v2 v2.24.0 h1:myMaPYyF9MecEmvQqMqomIwn9t/4KCZN9qnwsS76wlg=
|
||||
github.com/googleapis/gax-go/v2 v2.24.0/go.mod h1:IaTHBDd7NHxSCiu0vEs8pQZu4dGZrWwuSoxCnk16OFM=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hasura/go-graphql-client v0.16.0 h1:DQLfp+djj4j5NPdJkGYym8J55hpm5etML1zqgco78Qc=
|
||||
|
|
@ -247,6 +324,8 @@ github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI
|
|||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-sqlite3 v1.14.48 h1:7XHIgl0a8HwOaiK4E47ozLkST78rR9+OtNGx27D/TFs=
|
||||
github.com/mattn/go-sqlite3 v1.14.48/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w=
|
||||
github.com/mattn/go-sqlite3 v1.14.50 h1:dmdFvo1XG4MPzA4IkAmE9upVz/Nj31uRoM5+jC8hYbY=
|
||||
github.com/mattn/go-sqlite3 v1.14.50/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
|
@ -256,6 +335,8 @@ github.com/nicksnyder/go-i18n/v2 v2.6.1 h1:JDEJraFsQE17Dut9HFDHzCoAWGEQJom5s0TRd
|
|||
github.com/nicksnyder/go-i18n/v2 v2.6.1/go.mod h1:Vee0/9RD3Quc/NmwEjzzD7VTZ+Ir7QbXocrkhOzmUKA=
|
||||
github.com/ollama/ollama v0.32.3 h1:hASAqO6McQAgOhLG3Fcgrj//aXK5rMMWxqFM4eAKkGc=
|
||||
github.com/ollama/ollama v0.32.3/go.mod h1:b1ydCt2oVg0VAg22WWDgCbwW0AyOaRKAFzlS91NI4OY=
|
||||
github.com/ollama/ollama v0.33.1 h1:nEeqiZzqlO+RfjJ7AvfUgrYlV/wbrxPl2szRg9mtxPU=
|
||||
github.com/ollama/ollama v0.33.1/go.mod h1:Kekx/+OtFZHmqbkVH/QUUDVcMQS+1pg1dcz4Qy7TGn4=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||
github.com/openai/openai-go v1.12.0 h1:NBQCnXzqOTv5wsgNC36PrFEiskGfO5wccfCWDo9S1U0=
|
||||
|
|
@ -320,6 +401,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
|
|||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE=
|
||||
github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg=
|
||||
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
|
||||
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
|
||||
github.com/swaggo/gin-swagger v1.6.1 h1:Ri06G4gc9N4t4k8hekMigJ9zKTFSlqj/9paAQCQs7cY=
|
||||
|
|
@ -341,6 +424,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
|||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
||||
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
github.com/ugorji/go/codec v1.3.2 h1:zkEASHHyEClGeURfgNT9PJZVfAbs9oEX9QXggwWNJbc=
|
||||
github.com/ugorji/go/codec v1.3.2/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
|
|
@ -348,40 +433,62 @@ github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI
|
|||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.mongodb.org/mongo-driver/v2 v2.8.0 h1:CxWDGQYY8QQwNjAl/aq2sfWakdnWZynnqJ9F4DhHbP8=
|
||||
go.mongodb.org/mongo-driver/v2 v2.8.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
||||
go.mongodb.org/mongo-driver/v2 v2.8.2 h1:b6o2m7zL8g2URuO8urBedAylxojybKXNZTxgkOcl+2w=
|
||||
go.mongodb.org/mongo-driver/v2 v2.8.2/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0 h1:2yEATaop1/a1I4psnSLgWVPLWwCzkqWakgJy7xTDVy0=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0/go.mod h1:D7J12YRapIekYyPWgGPlA/23pRmpSEZC5xJC/TTLI9U=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0 h1:B2h3uqicet1CT2N5TOFhS+Gq++9i0/CLmaxvhmhtP5s=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.71.0/go.mod h1:dylvB+ZiiwMvsDij9O84Uy7SijLgHMX4mbkncds+4Sw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4vSTOOsNrsI4Ljf6C+6UKvpTEH5XY3JMoyPoo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0/go.mod h1:z9+yiacE0IHRqM4qFfkbt/JYlmYXgss8GY/jXoNuPJI=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 h1:3g7B90UzBltIDKq1/5mrTGxTnOFDV0ICOhLoxiZ8jlg=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0/go.mod h1:Ef8SuTh59BT7+ofpDxN9z+yOlc4t2GjLmKDgYNJL/NU=
|
||||
go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=
|
||||
go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=
|
||||
go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc=
|
||||
go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE=
|
||||
go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=
|
||||
go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo=
|
||||
go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8=
|
||||
go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o=
|
||||
go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58=
|
||||
go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0=
|
||||
go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE=
|
||||
go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk=
|
||||
go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE=
|
||||
go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c=
|
||||
go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI=
|
||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
|
||||
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.6 h1:1h7H1ohdUh93/FyE4YaDa1Zh64K6VVbjF4K6WUxMtH4=
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.6/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
|
||||
golang.org/x/arch v0.29.0 h1:8sSET5wB0+exBm0FGmOtdHMqjlRdV2DRD3/IV6OZgho=
|
||||
golang.org/x/arch v0.29.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8=
|
||||
golang.org/x/arch v0.30.0 h1:sB9h+1gRGa2+LauFSV0tm8bK1J2yo1bx6/Uyi/P6DTU=
|
||||
golang.org/x/arch v0.30.0/go.mod h1:0X+GdSIP+kL5wPmpK7sdkEVTt2XoYP0cSjQSbZBwOi8=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
|
||||
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
|
||||
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
|
||||
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
|
||||
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
|
||||
golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs=
|
||||
golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE=
|
||||
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-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
|
|
@ -389,6 +496,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
|||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
|
||||
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
|
||||
golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To=
|
||||
golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU=
|
||||
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.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
@ -420,6 +529,8 @@ 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.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
|
||||
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
|
||||
golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8=
|
||||
golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M=
|
||||
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
@ -427,23 +538,37 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
|||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
|
||||
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
|
||||
golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI=
|
||||
golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/api v0.290.0 h1:eMw0Xo+IfbbMlKmW7aHvpyQRv9RCXuWx/vs8AD+0x9A=
|
||||
google.golang.org/api v0.290.0/go.mod h1:weJZ3lldHFYI0DBFNKpJelUDNnusTt5YaOEgxvt8ci8=
|
||||
google.golang.org/api v0.294.0 h1:8gASjJxdtcIieB3OqbkLcF0FfbXVNqKtU5iozD1ssvA=
|
||||
google.golang.org/api v0.294.0/go.mod h1:02qB8+Ox1ZFzcaKFMguy1nQLJmSIyvV6Ff4txJEXtl4=
|
||||
google.golang.org/genai v1.65.0 h1:6QK3Rjsx0iuJjbDCE1vf1VUr1IEjRDpvexGGnhxoAIk=
|
||||
google.golang.org/genai v1.65.0/go.mod h1:mDdPDFXo1Ats7f1WXVyZgWb/CkMzFWTWJruIMy7hGIU=
|
||||
google.golang.org/genai v1.70.0 h1:V9oYOBvTDYbmeklOHjvxGeeLau71WiS2CWKrktQtDok=
|
||||
google.golang.org/genai v1.70.0/go.mod h1:mDdPDFXo1Ats7f1WXVyZgWb/CkMzFWTWJruIMy7hGIU=
|
||||
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgnawEVsOn6OFsnpyxNPRY9QV01dNB0=
|
||||
google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:L43LFes82YgSonw6iTXTxXUX1OlULt4AQtkik4ULL/I=
|
||||
google.golang.org/genproto v0.0.0-20260715232425-e75dac1f907d h1:C9v1o0/4quuhOAfmRXA2j+we0PqZIp8traLdeogF3Ms=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260630182238-925bb5da69e7 h1:jQ9p21COKWjP3VwuFrNRiiOTMh3mPpN45R7SLrH/HUU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260630182238-925bb5da69e7/go.mod h1:KqHwBx2upmfa1XSi1WuRvC+2VGCLtooKkfmyvRbUmqA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260715232425-e75dac1f907d h1:QwnJwPte4XXAkhPu26LTDIahnsMSUV0kK8HkxbC+Pc4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260724162435-b2f20204f0df h1:O3ig1i5WDDzsVzRp+cCdgelT9vXnlnOFdlEeFtL4HCc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260724162435-b2f20204f0df/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 h1:1VUiZAXyC+zmiFYi+WLtBzr68Cj8wOofHjjrA/kkizc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA=
|
||||
google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
|
||||
google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
|
||||
google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU=
|
||||
google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
|
||||
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/danielmiessler/fabric/internal/i18n"
|
||||
debuglog "github.com/danielmiessler/fabric/internal/log"
|
||||
|
|
@ -73,6 +74,24 @@ func NewPluginRegistry(db *fsdb.Db) (ret *PluginRegistry, err error) {
|
|||
vendors := []ai.Vendor{}
|
||||
|
||||
// Add non-OpenAI compatible clients
|
||||
codexClient := codex.NewClient()
|
||||
codexClient.WithStoreLock = func(fn func() error) error {
|
||||
return db.WithEnvLock(func() error {
|
||||
env, err := db.ReadEnvFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
codexClient.LoadEnvSettings(env)
|
||||
return fn()
|
||||
})
|
||||
}
|
||||
codexClient.TokenPersist = func() error {
|
||||
return db.ApplyEnvUpdates(map[string]string{
|
||||
codexClient.AccessToken.EnvVariable: strings.TrimSpace(codexClient.AccessToken.Value),
|
||||
codexClient.RefreshToken.EnvVariable: strings.TrimSpace(codexClient.RefreshToken.Value),
|
||||
codexClient.AccountID.EnvVariable: strings.TrimSpace(codexClient.AccountID.Value),
|
||||
})
|
||||
}
|
||||
vendors = append(vendors,
|
||||
openai.NewClient(),
|
||||
digitalocean.NewClient(),
|
||||
|
|
@ -86,7 +105,7 @@ func NewPluginRegistry(db *fsdb.Db) (ret *PluginRegistry, err error) {
|
|||
lmstudio.NewClient(),
|
||||
exolab.NewClient(),
|
||||
perplexity.NewClient(),
|
||||
codex.NewClient(),
|
||||
codexClient,
|
||||
copilot.NewClient(), // Microsoft 365 Copilot
|
||||
bedrock.NewClient(), // AWS Bedrock - credentials configured via setup or AWS credential chain
|
||||
)
|
||||
|
|
@ -123,6 +142,8 @@ func (o *PluginRegistry) ListVendors(out io.Writer) error {
|
|||
type PluginRegistry struct {
|
||||
Db *fsdb.Db
|
||||
|
||||
vendorMu sync.Mutex
|
||||
|
||||
VendorManager *ai.VendorsManager
|
||||
VendorsAll *ai.VendorsManager
|
||||
Defaults *tools.Defaults
|
||||
|
|
@ -288,16 +309,12 @@ func (o *PluginRegistry) runVendorSetup() (err error) {
|
|||
return pluginSetupErr
|
||||
}
|
||||
|
||||
o.registerVendor(plugin)
|
||||
|
||||
if err = o.SaveEnvFile(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if o.VendorManager.FindByName(plugin.GetName()) == nil {
|
||||
if vendor, ok := plugin.(ai.Vendor); ok {
|
||||
o.VendorManager.AddVendors(vendor)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -349,16 +366,11 @@ func (o *PluginRegistry) runInteractiveSetup() (err error) {
|
|||
if pluginSetupErr := plugin.Setup(); pluginSetupErr != nil {
|
||||
println(pluginSetupErr.Error())
|
||||
} else {
|
||||
o.registerVendor(plugin)
|
||||
if err = o.SaveEnvFile(); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if o.VendorManager.FindByName(plugin.GetName()) == nil {
|
||||
if vendor, ok := plugin.(ai.Vendor); ok {
|
||||
o.VendorManager.AddVendors(vendor)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
|
|
@ -425,11 +437,32 @@ func (o *PluginRegistry) SetupVendor(vendorName string) (err error) {
|
|||
if err = o.VendorsAll.SetupVendor(vendorName, o.VendorManager.VendorsByName); err != nil {
|
||||
return
|
||||
}
|
||||
if vendor := o.VendorsAll.FindByName(vendorName); vendor != nil {
|
||||
o.registerVendor(vendor)
|
||||
}
|
||||
err = o.SaveEnvFile()
|
||||
return
|
||||
}
|
||||
|
||||
func (o *PluginRegistry) registerVendor(plugin plugins.Plugin) {
|
||||
vendor, ok := plugin.(ai.Vendor)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
o.vendorMu.Lock()
|
||||
defer o.vendorMu.Unlock()
|
||||
name := vendor.GetName()
|
||||
for _, existing := range o.VendorManager.Vendors {
|
||||
if strings.EqualFold(existing.GetName(), name) {
|
||||
return
|
||||
}
|
||||
}
|
||||
o.VendorManager.AddVendors(vendor)
|
||||
}
|
||||
|
||||
func (o *PluginRegistry) ConfigureVendors() {
|
||||
o.vendorMu.Lock()
|
||||
defer o.vendorMu.Unlock()
|
||||
o.VendorManager.Clear()
|
||||
for _, vendor := range o.VendorsAll.Vendors {
|
||||
if vendorErr := vendor.Configure(); vendorErr == nil && vendor.IsConfigured() {
|
||||
|
|
@ -438,6 +471,34 @@ func (o *PluginRegistry) ConfigureVendors() {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *PluginRegistry) activateVendor(name string) (ai.Vendor, error) {
|
||||
if strings.TrimSpace(name) == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
o.vendorMu.Lock()
|
||||
defer o.vendorMu.Unlock()
|
||||
|
||||
if v := o.VendorManager.FindByName(name); v != nil {
|
||||
return v, nil
|
||||
}
|
||||
if o.VendorsAll == nil {
|
||||
return nil, nil
|
||||
}
|
||||
v := o.VendorsAll.FindByName(name)
|
||||
if v == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if err := v.Configure(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !v.IsConfigured() {
|
||||
return nil, nil
|
||||
}
|
||||
o.VendorManager.AddVendors(v)
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func (o *PluginRegistry) GetModels() (ret *ai.VendorsModels, err error) {
|
||||
o.ConfigureVendors()
|
||||
ret, err = o.VendorManager.GetModels()
|
||||
|
|
@ -503,13 +564,25 @@ func (o *PluginRegistry) GetChatter(model string, modelContextLength int, vendor
|
|||
ret.model = defaultModel
|
||||
}
|
||||
} else if model == "" {
|
||||
if vendorName != "" {
|
||||
ret.vendor = vendorManager.FindByName(vendorName)
|
||||
} else {
|
||||
ret.vendor = vendorManager.FindByName(defaultVendor)
|
||||
name := vendorName
|
||||
if name == "" {
|
||||
name = defaultVendor
|
||||
}
|
||||
if ret.vendor, err = o.activateVendor(name); err != nil {
|
||||
return
|
||||
}
|
||||
ret.model = defaultModel
|
||||
} else {
|
||||
if vendorName != "" {
|
||||
if ret.vendor, err = o.activateVendor(vendorName); err != nil {
|
||||
return
|
||||
}
|
||||
} else if !vendorManager.HasVendors() {
|
||||
if _, err = o.activateVendor(defaultVendor); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var models *ai.VendorsModels
|
||||
if models, err = vendorManager.GetModels(); err != nil {
|
||||
return
|
||||
|
|
@ -567,6 +640,16 @@ func (o *PluginRegistry) GetChatter(model string, modelContextLength int, vendor
|
|||
ret.model = model
|
||||
}
|
||||
|
||||
if ret.vendor == nil {
|
||||
name := vendorName
|
||||
if name == "" {
|
||||
name = defaultVendor
|
||||
}
|
||||
if ret.vendor, err = o.activateVendor(name); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if ret.vendor == nil {
|
||||
var errMsg string
|
||||
if defaultModel == "" || defaultVendor == "" {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package core
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
|
@ -10,11 +11,14 @@ import (
|
|||
|
||||
"github.com/danielmiessler/fabric/internal/chat"
|
||||
"github.com/danielmiessler/fabric/internal/domain"
|
||||
"github.com/danielmiessler/fabric/internal/i18n"
|
||||
debuglog "github.com/danielmiessler/fabric/internal/log"
|
||||
"github.com/danielmiessler/fabric/internal/plugins"
|
||||
"github.com/danielmiessler/fabric/internal/plugins/ai"
|
||||
"github.com/danielmiessler/fabric/internal/plugins/ai/codex"
|
||||
"github.com/danielmiessler/fabric/internal/plugins/db/fsdb"
|
||||
"github.com/danielmiessler/fabric/internal/tools"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func TestSaveEnvFile(t *testing.T) {
|
||||
|
|
@ -32,14 +36,15 @@ func TestSaveEnvFile(t *testing.T) {
|
|||
|
||||
// testVendor implements ai.Vendor for testing purposes
|
||||
type testVendor struct {
|
||||
name string
|
||||
models []string
|
||||
name string
|
||||
models []string
|
||||
configureErr error
|
||||
}
|
||||
|
||||
func (m *testVendor) GetName() string { return m.name }
|
||||
func (m *testVendor) GetSetupDescription() string { return m.name }
|
||||
func (m *testVendor) IsConfigured() bool { return true }
|
||||
func (m *testVendor) Configure() error { return nil }
|
||||
func (m *testVendor) Configure() error { return m.configureErr }
|
||||
func (m *testVendor) Setup() error { return nil }
|
||||
func (m *testVendor) SetupFillEnvFileContent(*bytes.Buffer) {}
|
||||
func (m *testVendor) ListModels(context.Context) ([]string, error) { return m.models, nil }
|
||||
|
|
@ -210,3 +215,116 @@ func TestGetChatter_VendorPrefixIgnoredWhenNotAVendor(t *testing.T) {
|
|||
t.Fatalf("expected model 'notavendor/model', got %s", chatter.model)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetChatter_ReportsConfigureError(t *testing.T) {
|
||||
if _, err := i18n.Init("en"); err != nil {
|
||||
t.Fatalf("i18n.Init() error = %v", err)
|
||||
}
|
||||
for _, tt := range []struct {
|
||||
name, model, vendor string
|
||||
}{
|
||||
{"empty model", "", ""},
|
||||
{"model", "gpt-5.6-sol", ""},
|
||||
{"named vendor", "gpt-5.6-sol", "Codex"},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
configureErr := errors.New(i18n.T("codex_login_refresh_failed"))
|
||||
registry := newInactiveVendorRegistry(t, "Codex", "gpt-5.6-sol", &testVendor{
|
||||
name: "Codex", models: []string{"gpt-5.6-sol"}, configureErr: configureErr,
|
||||
})
|
||||
_, err := registry.GetChatter(tt.model, 0, tt.vendor, false, false)
|
||||
if !errors.Is(err, configureErr) {
|
||||
t.Fatalf("GetChatter() error = %v, want %v", err, configureErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetChatter_ActivatesInactiveVendor(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
name, model, vendor string
|
||||
}{
|
||||
{"named", "gpt-5.6-sol", "Codex"},
|
||||
{"default for model", "gpt-5.6-sol", ""},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
codexVendor := &testVendor{name: "Codex", models: []string{"gpt-5.6-sol"}}
|
||||
registry := newInactiveVendorRegistry(t, "Codex", "gpt-5.6-sol", codexVendor)
|
||||
chatter, err := registry.GetChatter(tt.model, 0, tt.vendor, false, false)
|
||||
if err != nil {
|
||||
t.Fatalf("GetChatter() error = %v", err)
|
||||
}
|
||||
if chatter.vendor.GetName() != "Codex" {
|
||||
t.Fatalf("vendor = %s, want Codex", chatter.vendor.GetName())
|
||||
}
|
||||
if chatter.model != "gpt-5.6-sol" {
|
||||
t.Fatalf("model = %s, want gpt-5.6-sol", chatter.model)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewPluginRegistry_CodexTokenPersist(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
db := fsdb.NewDb(dir)
|
||||
if err := db.SaveEnv("KEEP=old\n"); err != nil {
|
||||
t.Fatalf("SaveEnv() error = %v", err)
|
||||
}
|
||||
|
||||
registry, err := NewPluginRegistry(db)
|
||||
if err != nil {
|
||||
t.Fatalf("NewPluginRegistry() error = %v", err)
|
||||
}
|
||||
|
||||
vendor := registry.VendorsAll.FindByName("Codex")
|
||||
client, ok := vendor.(*codex.Client)
|
||||
if !ok || client == nil {
|
||||
t.Fatal("expected Codex client in VendorsAll")
|
||||
}
|
||||
if client.TokenPersist == nil {
|
||||
t.Fatal("TokenPersist is nil")
|
||||
}
|
||||
|
||||
client.AccessToken.Value = "access-live"
|
||||
client.RefreshToken.Value = "refresh-live"
|
||||
client.AccountID.Value = "acct-live"
|
||||
if err := client.TokenPersist(); err != nil {
|
||||
t.Fatalf("TokenPersist() error = %v", err)
|
||||
}
|
||||
|
||||
parsed, err := godotenv.Read(db.EnvFilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("godotenv.Read() error = %v", err)
|
||||
}
|
||||
if parsed["KEEP"] != "old" {
|
||||
t.Fatalf("KEEP = %q, want old", parsed["KEEP"])
|
||||
}
|
||||
if parsed[client.AccessToken.EnvVariable] != "access-live" {
|
||||
t.Fatalf("access = %q, want access-live", parsed[client.AccessToken.EnvVariable])
|
||||
}
|
||||
if parsed[client.RefreshToken.EnvVariable] != "refresh-live" {
|
||||
t.Fatalf("refresh = %q, want refresh-live", parsed[client.RefreshToken.EnvVariable])
|
||||
}
|
||||
if parsed[client.AccountID.EnvVariable] != "acct-live" {
|
||||
t.Fatalf("account = %q, want acct-live", parsed[client.AccountID.EnvVariable])
|
||||
}
|
||||
}
|
||||
|
||||
func newInactiveVendorRegistry(t *testing.T, defaultVendor, defaultModel string, vendor *testVendor) *PluginRegistry {
|
||||
t.Helper()
|
||||
db := fsdb.NewDb(t.TempDir())
|
||||
all := ai.NewVendorsManager()
|
||||
all.AddVendors(vendor)
|
||||
defaults := &tools.Defaults{
|
||||
PluginBase: &plugins.PluginBase{},
|
||||
Vendor: &plugins.Setting{Value: defaultVendor},
|
||||
Model: &plugins.SetupQuestion{Setting: &plugins.Setting{Value: defaultModel}},
|
||||
ModelContextLength: &plugins.SetupQuestion{Setting: &plugins.Setting{Value: "0"}},
|
||||
}
|
||||
return &PluginRegistry{
|
||||
Db: db,
|
||||
VendorManager: ai.NewVendorsManager(),
|
||||
VendorsAll: all,
|
||||
Defaults: defaults,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@
|
|||
"choose_pattern_from_available": "Wähle ein Muster aus den verfügbaren Mustern",
|
||||
"choose_session_from_available": "Wähle eine Sitzung aus den verfügbaren Sitzungen",
|
||||
"choose_strategy_from_available": "Strategie aus den verfügbaren Strategien wählen",
|
||||
"codex_api_base_url_question": "Geben Sie Ihre Codex-API-Basis-URL ein",
|
||||
"codex_auth_base_url_invalid": "Ungültige Codex-Authentifizierungs-Basis-URL: %w",
|
||||
"codex_auth_base_url_question": "Geben Sie Ihre Codex-OAuth-Basis-URL ein",
|
||||
"codex_browser_open_fallback": "Falls Ihr Browser sich nicht geöffnet hat, navigieren Sie zu dieser URL zur Authentifizierung:",
|
||||
"codex_decode_models_response_failed": "Codex-Modell-Antwort konnte nicht dekodiert werden: %w",
|
||||
"codex_decode_refresh_response_failed": "Aktualisierte Codex-Token-Antwort konnte nicht dekodiert werden: %w",
|
||||
|
|
@ -133,13 +135,16 @@
|
|||
"codex_oauth_random_state_failed": "Sicherer zufälliger OAuth-Status konnte nicht generiert werden: %w",
|
||||
"codex_oauth_server_start_failed": "Lokaler OAuth-Callback-Server konnte nicht gestartet werden: %w",
|
||||
"codex_oauth_state_mismatch": "Status stimmt nicht überein",
|
||||
"codex_provider_error": "Codex-Anbieterfehler (Status %d): %s",
|
||||
"codex_refresh_failed_status": "Codex-Anmeldung konnte nicht aktualisiert werden (Status %d)",
|
||||
"codex_refresh_login_failed": "Codex-Anmeldung konnte nicht aktualisiert werden: %w",
|
||||
"codex_refresh_token_required": "Codex-Aktualisierungstoken ist erforderlich. Bitte führen Sie 'fabric --setup' erneut aus.",
|
||||
"codex_replay_body_unavailable": "Anfragekörper kann für Codex-Reauthentifizierungswiederholung nicht wiedergegeben werden",
|
||||
"codex_request_failed": "Codex-Anfrage fehlgeschlagen: %w",
|
||||
"codex_request_failed_status": "Codex-Anfrage fehlgeschlagen mit Status %d",
|
||||
"codex_starting_browser_login": "Starte browserbasierte OpenAI-Anmeldung für Codex.",
|
||||
"codex_token_exchange_failed": "Codex-Token-Austausch fehlgeschlagen: %w",
|
||||
"codex_token_persist_failed": "Codex-Anmeldung konnte nicht gespeichert werden: %w",
|
||||
"codex_token_refresh_missing_access_token": "Die Codex-Token-Aktualisierung hat kein Zugriffstoken zurückgegeben.",
|
||||
"codex_usage_limit_reached": "Codex-Nutzungslimit erreicht",
|
||||
"command_completed_successfully": "Befehl erfolgreich abgeschlossen",
|
||||
|
|
@ -168,6 +173,7 @@
|
|||
"custom_patterns_setup_description": "Benutzerdefinierte Patterns - Verzeichnis für Ihre benutzerdefinierten Patterns festlegen",
|
||||
"custom_patterns_warning_create_directory": "Warnung: Benutzerdefiniertes Musterverzeichnis %s konnte nicht erstellt werden: %v\n",
|
||||
"db_error_loading_env_file": "fehler beim Laden der .env-Datei: %w",
|
||||
"db_error_updating_env_file": "fehler beim Aktualisieren der .env-Datei: %w",
|
||||
"defaults_model_context_length_question": "Geben Sie die Kontextlänge des Modells ein",
|
||||
"defaults_model_question": "Geben Sie den Index oder den Namen Ihres Standardmodells ein",
|
||||
"defaults_setup_description": "Standard-KI-Anbieter und -Modell",
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@
|
|||
"choose_pattern_from_available": "Choose a pattern from the available patterns",
|
||||
"choose_session_from_available": "Choose a session from the available sessions",
|
||||
"choose_strategy_from_available": "Choose a strategy from the available strategies",
|
||||
"codex_api_base_url_question": "Enter your Codex API base URL",
|
||||
"codex_auth_base_url_invalid": "invalid codex auth base url: %w",
|
||||
"codex_auth_base_url_question": "Enter your Codex OAuth base URL",
|
||||
"codex_browser_open_fallback": "If your browser did not open, navigate to this URL to authenticate:",
|
||||
"codex_decode_models_response_failed": "failed to decode codex models response: %w",
|
||||
"codex_decode_refresh_response_failed": "failed to decode refreshed Codex token response: %w",
|
||||
|
|
@ -133,13 +135,16 @@
|
|||
"codex_oauth_random_state_failed": "failed to generate secure random oauth state: %w",
|
||||
"codex_oauth_server_start_failed": "failed to start local oauth callback server: %w",
|
||||
"codex_oauth_state_mismatch": "State mismatch",
|
||||
"codex_provider_error": "codex provider error (status %d): %s",
|
||||
"codex_refresh_failed_status": "failed to refresh codex login (status %d)",
|
||||
"codex_refresh_login_failed": "failed to refresh Codex login: %w",
|
||||
"codex_refresh_token_required": "Codex refresh token is required. Please rerun 'fabric --setup'.",
|
||||
"codex_replay_body_unavailable": "request body cannot be replayed for Codex re-authentication retry",
|
||||
"codex_request_failed": "codex request failed: %w",
|
||||
"codex_request_failed_status": "codex request failed with status %d",
|
||||
"codex_starting_browser_login": "Starting browser-based OpenAI login for Codex.",
|
||||
"codex_token_exchange_failed": "codex token exchange failed: %w",
|
||||
"codex_token_persist_failed": "failed to persist Codex login: %w",
|
||||
"codex_token_refresh_missing_access_token": "Codex token refresh did not return an access token.",
|
||||
"codex_usage_limit_reached": "codex usage limit reached",
|
||||
"command_completed_successfully": "Command completed successfully",
|
||||
|
|
@ -168,6 +173,7 @@
|
|||
"custom_patterns_setup_description": "Custom Patterns - Set directory for your custom patterns",
|
||||
"custom_patterns_warning_create_directory": "Warning: Could not create custom patterns directory %s: %v\n",
|
||||
"db_error_loading_env_file": "error loading .env file: %w",
|
||||
"db_error_updating_env_file": "error updating .env file: %w",
|
||||
"defaults_model_context_length_question": "Enter model context length",
|
||||
"defaults_model_question": "Enter the index or the name of your default model",
|
||||
"defaults_setup_description": "Default AI Vendor and Model",
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@
|
|||
"choose_pattern_from_available": "Elige un patrón de los patrones disponibles",
|
||||
"choose_session_from_available": "Elige una sesión de las sesiones disponibles",
|
||||
"choose_strategy_from_available": "Elegir una estrategia de las estrategias disponibles",
|
||||
"codex_api_base_url_question": "Ingrese la URL base de la API de Codex",
|
||||
"codex_auth_base_url_invalid": "URL base de autenticación de Codex no válida: %w",
|
||||
"codex_auth_base_url_question": "Ingrese la URL base de OAuth de Codex",
|
||||
"codex_browser_open_fallback": "Si su navegador no se abrió, navegue a esta URL para autenticarse:",
|
||||
"codex_decode_models_response_failed": "No se pudo decodificar la respuesta de modelos de Codex: %w",
|
||||
"codex_decode_refresh_response_failed": "No se pudo decodificar la respuesta de token actualizado de Codex: %w",
|
||||
|
|
@ -133,13 +135,16 @@
|
|||
"codex_oauth_random_state_failed": "No se pudo generar un estado OAuth aleatorio seguro: %w",
|
||||
"codex_oauth_server_start_failed": "No se pudo iniciar el servidor local de callback OAuth: %w",
|
||||
"codex_oauth_state_mismatch": "El estado no coincide",
|
||||
"codex_provider_error": "error del proveedor de Codex (estado %d): %s",
|
||||
"codex_refresh_failed_status": "No se pudo actualizar el inicio de sesión de Codex (estado %d)",
|
||||
"codex_refresh_login_failed": "No se pudo actualizar el inicio de sesión de Codex: %w",
|
||||
"codex_refresh_token_required": "Se requiere el token de actualización de Codex. Ejecute 'fabric --setup' de nuevo.",
|
||||
"codex_replay_body_unavailable": "El cuerpo de la solicitud no se puede reproducir para el reintento de reautenticación de Codex",
|
||||
"codex_request_failed": "La solicitud de Codex falló: %w",
|
||||
"codex_request_failed_status": "La solicitud de Codex falló con estado %d",
|
||||
"codex_starting_browser_login": "Iniciando inicio de sesión de OpenAI basado en navegador para Codex.",
|
||||
"codex_token_exchange_failed": "El intercambio de token de Codex falló: %w",
|
||||
"codex_token_persist_failed": "no se pudo guardar el inicio de sesión de Codex: %w",
|
||||
"codex_token_refresh_missing_access_token": "La actualización del token de Codex no devolvió un token de acceso.",
|
||||
"codex_usage_limit_reached": "Límite de uso de Codex alcanzado",
|
||||
"command_completed_successfully": "Comando completado exitosamente",
|
||||
|
|
@ -168,6 +173,7 @@
|
|||
"custom_patterns_setup_description": "Patrones personalizados - Establecer directorio para tus patrones personalizados",
|
||||
"custom_patterns_warning_create_directory": "Advertencia: No se pudo crear el directorio de patrones personalizados %s: %v\n",
|
||||
"db_error_loading_env_file": "error al cargar el archivo .env: %w",
|
||||
"db_error_updating_env_file": "error al actualizar el archivo .env: %w",
|
||||
"defaults_model_context_length_question": "Introduce la longitud del contexto del modelo",
|
||||
"defaults_model_question": "Introduce el índice o el nombre de tu modelo predeterminado",
|
||||
"defaults_setup_description": "Proveedor y modelo de IA predeterminados",
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@
|
|||
"choose_pattern_from_available": "الگویی از الگوهای موجود انتخاب کنید",
|
||||
"choose_session_from_available": "جلسهای از جلسات موجود انتخاب کنید",
|
||||
"choose_strategy_from_available": "انتخاب استراتژی از استراتژیهای موجود",
|
||||
"codex_api_base_url_question": "آدرس پایه API Codex را وارد کنید",
|
||||
"codex_auth_base_url_invalid": "آدرس پایه احراز هویت Codex نامعتبر است: %w",
|
||||
"codex_auth_base_url_question": "آدرس پایه OAuth Codex را وارد کنید",
|
||||
"codex_browser_open_fallback": "اگر مرورگر شما باز نشد، برای احراز هویت به این آدرس بروید:",
|
||||
"codex_decode_models_response_failed": "رمزگشایی پاسخ مدلهای Codex ناموفق بود: %w",
|
||||
"codex_decode_refresh_response_failed": "رمزگشایی پاسخ توکن بازنشانیشده Codex ناموفق بود: %w",
|
||||
|
|
@ -133,13 +135,16 @@
|
|||
"codex_oauth_random_state_failed": "تولید وضعیت تصادفی امن OAuth ناموفق بود: %w",
|
||||
"codex_oauth_server_start_failed": "راهاندازی سرور محلی بازگشت OAuth ناموفق بود: %w",
|
||||
"codex_oauth_state_mismatch": "وضعیت مطابقت ندارد",
|
||||
"codex_provider_error": "خطای ارائهدهنده Codex (وضعیت %d): %s",
|
||||
"codex_refresh_failed_status": "بازنشانی ورود Codex ناموفق بود (وضعیت %d)",
|
||||
"codex_refresh_login_failed": "بازنشانی ورود Codex ناموفق بود: %w",
|
||||
"codex_refresh_token_required": "توکن بازنشانی Codex مورد نیاز است. لطفاً 'fabric --setup' را دوباره اجرا کنید.",
|
||||
"codex_replay_body_unavailable": "بدنه درخواست برای تلاش مجدد احراز هویت Codex قابل بازپخش نیست",
|
||||
"codex_request_failed": "درخواست Codex ناموفق بود: %w",
|
||||
"codex_request_failed_status": "درخواست Codex با وضعیت %d ناموفق بود",
|
||||
"codex_starting_browser_login": "شروع ورود مبتنی بر مرورگر OpenAI برای Codex.",
|
||||
"codex_token_exchange_failed": "تبادل توکن Codex ناموفق بود: %w",
|
||||
"codex_token_persist_failed": "ذخیره ورود Codex ناموفق بود: %w",
|
||||
"codex_token_refresh_missing_access_token": "بازنشانی توکن Codex توکن دسترسی را برنگرداند.",
|
||||
"codex_usage_limit_reached": "محدودیت استفاده Codex به حداکثر رسیده است",
|
||||
"command_completed_successfully": "دستور با موفقیت تکمیل شد",
|
||||
|
|
@ -168,6 +173,7 @@
|
|||
"custom_patterns_setup_description": "الگوهای سفارشی - تنظیم دایرکتوری برای الگوهای سفارشی شما",
|
||||
"custom_patterns_warning_create_directory": "هشدار: امکان ایجاد پوشه الگوهای سفارشی %s وجود ندارد: %v\n",
|
||||
"db_error_loading_env_file": "خطا در بارگذاری فایل .env: %w",
|
||||
"db_error_updating_env_file": "خطا در بهروزرسانی فایل .env: %w",
|
||||
"defaults_model_context_length_question": "طول زمینه مدل را وارد کنید",
|
||||
"defaults_model_question": "شاخص یا نام مدل پیشفرض خود را وارد کنید",
|
||||
"defaults_setup_description": "ارائهدهنده و مدل هوش مصنوعی پیشفرض",
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@
|
|||
"choose_pattern_from_available": "Choisissez un motif parmi les motifs disponibles",
|
||||
"choose_session_from_available": "Choisissez une session parmi les sessions disponibles",
|
||||
"choose_strategy_from_available": "Choisir une stratégie parmi les stratégies disponibles",
|
||||
"codex_api_base_url_question": "Entrez l'URL de base de l'API Codex",
|
||||
"codex_auth_base_url_invalid": "URL de base d'authentification Codex invalide : %w",
|
||||
"codex_auth_base_url_question": "Entrez l'URL de base OAuth de Codex",
|
||||
"codex_browser_open_fallback": "Si votre navigateur ne s'est pas ouvert, accédez à cette URL pour vous authentifier :",
|
||||
"codex_decode_models_response_failed": "Échec du décodage de la réponse des modèles Codex : %w",
|
||||
"codex_decode_refresh_response_failed": "Échec du décodage de la réponse du jeton Codex rafraîchi : %w",
|
||||
|
|
@ -133,13 +135,16 @@
|
|||
"codex_oauth_random_state_failed": "Échec de la génération d'un état OAuth aléatoire sécurisé : %w",
|
||||
"codex_oauth_server_start_failed": "Échec du démarrage du serveur local de rappel OAuth : %w",
|
||||
"codex_oauth_state_mismatch": "L'état ne correspond pas",
|
||||
"codex_provider_error": "erreur du fournisseur Codex (statut %d) : %s",
|
||||
"codex_refresh_failed_status": "Échec du rafraîchissement de la connexion Codex (statut %d)",
|
||||
"codex_refresh_login_failed": "Échec du rafraîchissement de la connexion Codex : %w",
|
||||
"codex_refresh_token_required": "Le jeton de rafraîchissement Codex est requis. Veuillez relancer 'fabric --setup'.",
|
||||
"codex_replay_body_unavailable": "Le corps de la requête ne peut pas être rejoué pour la tentative de réauthentification Codex",
|
||||
"codex_request_failed": "La requête Codex a échoué : %w",
|
||||
"codex_request_failed_status": "La requête Codex a échoué avec le statut %d",
|
||||
"codex_starting_browser_login": "Démarrage de la connexion OpenAI par navigateur pour Codex.",
|
||||
"codex_token_exchange_failed": "L'échange de jeton Codex a échoué : %w",
|
||||
"codex_token_persist_failed": "échec de l'enregistrement de la connexion Codex : %w",
|
||||
"codex_token_refresh_missing_access_token": "Le rafraîchissement du jeton Codex n'a pas renvoyé de jeton d'accès.",
|
||||
"codex_usage_limit_reached": "Limite d'utilisation Codex atteinte",
|
||||
"command_completed_successfully": "Commande terminée avec succès",
|
||||
|
|
@ -168,6 +173,7 @@
|
|||
"custom_patterns_setup_description": "Patrons personnalisés - Définir le répertoire pour vos patrons personnalisés",
|
||||
"custom_patterns_warning_create_directory": "Avertissement : Impossible de créer le répertoire de modèles personnalisés %s : %v\n",
|
||||
"db_error_loading_env_file": "erreur lors du chargement du fichier .env : %w",
|
||||
"db_error_updating_env_file": "erreur lors de la mise à jour du fichier .env : %w",
|
||||
"defaults_model_context_length_question": "Saisissez la longueur du contexte du modèle",
|
||||
"defaults_model_question": "Saisissez l'index ou le nom de votre modèle par défaut",
|
||||
"defaults_setup_description": "Fournisseur et modèle d'IA par défaut",
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@
|
|||
"choose_pattern_from_available": "Scegli un pattern dai pattern disponibili",
|
||||
"choose_session_from_available": "Scegli una sessione dalle sessioni disponibili",
|
||||
"choose_strategy_from_available": "Scegli una strategia dalle strategie disponibili",
|
||||
"codex_api_base_url_question": "Inserisci l'URL di base dell'API Codex",
|
||||
"codex_auth_base_url_invalid": "URL base di autenticazione Codex non valido: %w",
|
||||
"codex_auth_base_url_question": "Inserisci l'URL di base OAuth di Codex",
|
||||
"codex_browser_open_fallback": "Se il browser non si è aperto, navigare a questo URL per autenticarsi:",
|
||||
"codex_decode_models_response_failed": "Decodifica della risposta dei modelli Codex non riuscita: %w",
|
||||
"codex_decode_refresh_response_failed": "Decodifica della risposta del token Codex aggiornato non riuscita: %w",
|
||||
|
|
@ -133,13 +135,16 @@
|
|||
"codex_oauth_random_state_failed": "Generazione dello stato OAuth casuale sicuro non riuscita: %w",
|
||||
"codex_oauth_server_start_failed": "Avvio del server locale di callback OAuth non riuscito: %w",
|
||||
"codex_oauth_state_mismatch": "Lo stato non corrisponde",
|
||||
"codex_provider_error": "errore del fornitore Codex (stato %d): %s",
|
||||
"codex_refresh_failed_status": "Aggiornamento dell'accesso Codex non riuscito (stato %d)",
|
||||
"codex_refresh_login_failed": "Aggiornamento dell'accesso Codex non riuscito: %w",
|
||||
"codex_refresh_token_required": "Il token di aggiornamento Codex è richiesto. Eseguire di nuovo 'fabric --setup'.",
|
||||
"codex_replay_body_unavailable": "Il corpo della richiesta non può essere riprodotto per il tentativo di riautenticazione Codex",
|
||||
"codex_request_failed": "La richiesta Codex è fallita: %w",
|
||||
"codex_request_failed_status": "La richiesta Codex è fallita con stato %d",
|
||||
"codex_starting_browser_login": "Avvio dell'accesso OpenAI basato su browser per Codex.",
|
||||
"codex_token_exchange_failed": "Lo scambio di token Codex è fallito: %w",
|
||||
"codex_token_persist_failed": "impossibile salvare l'accesso Codex: %w",
|
||||
"codex_token_refresh_missing_access_token": "L'aggiornamento del token Codex non ha restituito un token di accesso.",
|
||||
"codex_usage_limit_reached": "Limite di utilizzo Codex raggiunto",
|
||||
"command_completed_successfully": "Comando completato con successo",
|
||||
|
|
@ -168,6 +173,7 @@
|
|||
"custom_patterns_setup_description": "Pattern personalizzati - Imposta la directory per i tuoi pattern personalizzati",
|
||||
"custom_patterns_warning_create_directory": "Avviso: Impossibile creare la directory dei modelli personalizzati %s: %v\n",
|
||||
"db_error_loading_env_file": "errore nel caricamento del file .env: %w",
|
||||
"db_error_updating_env_file": "errore nell'aggiornamento del file .env: %w",
|
||||
"defaults_model_context_length_question": "Inserisci la lunghezza del contesto del modello",
|
||||
"defaults_model_question": "Inserisci l'indice o il nome del tuo modello predefinito",
|
||||
"defaults_setup_description": "Fornitore e modello AI predefiniti",
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@
|
|||
"choose_pattern_from_available": "利用可能なパターンからパターンを選択",
|
||||
"choose_session_from_available": "利用可能なセッションからセッションを選択",
|
||||
"choose_strategy_from_available": "利用可能な戦略から戦略を選択",
|
||||
"codex_api_base_url_question": "Codex APIベースURLを入力してください",
|
||||
"codex_auth_base_url_invalid": "Codex認証ベースURLが無効です: %w",
|
||||
"codex_auth_base_url_question": "Codex OAuthベースURLを入力してください",
|
||||
"codex_browser_open_fallback": "ブラウザが開かなかった場合は、このURLに移動して認証してください:",
|
||||
"codex_decode_models_response_failed": "Codexモデルレスポンスのデコードに失敗しました: %w",
|
||||
"codex_decode_refresh_response_failed": "更新されたCodexトークンレスポンスのデコードに失敗しました: %w",
|
||||
|
|
@ -133,13 +135,16 @@
|
|||
"codex_oauth_random_state_failed": "安全なランダムOAuthステートの生成に失敗しました: %w",
|
||||
"codex_oauth_server_start_failed": "ローカルOAuthコールバックサーバーの起動に失敗しました: %w",
|
||||
"codex_oauth_state_mismatch": "ステートが一致しません",
|
||||
"codex_provider_error": "Codexベンダーエラー(ステータス %d): %s",
|
||||
"codex_refresh_failed_status": "Codexログインの更新に失敗しました(ステータス %d)",
|
||||
"codex_refresh_login_failed": "Codexログインの更新に失敗しました: %w",
|
||||
"codex_refresh_token_required": "Codexリフレッシュトークンが必要です。'fabric --setup'を再実行してください。",
|
||||
"codex_replay_body_unavailable": "Codex再認証リトライのためにリクエストボディを再送できません",
|
||||
"codex_request_failed": "Codexリクエストに失敗しました: %w",
|
||||
"codex_request_failed_status": "Codexリクエストがステータス %d で失敗しました",
|
||||
"codex_starting_browser_login": "Codex用のブラウザベースOpenAIログインを開始しています。",
|
||||
"codex_token_exchange_failed": "Codexトークン交換に失敗しました: %w",
|
||||
"codex_token_persist_failed": "Codexログインの保存に失敗しました: %w",
|
||||
"codex_token_refresh_missing_access_token": "Codexトークンの更新がアクセストークンを返しませんでした。",
|
||||
"codex_usage_limit_reached": "Codex使用量制限に達しました",
|
||||
"command_completed_successfully": "コマンドが正常に完了しました",
|
||||
|
|
@ -168,6 +173,7 @@
|
|||
"custom_patterns_setup_description": "カスタムパターン - カスタムパターン用のディレクトリを設定",
|
||||
"custom_patterns_warning_create_directory": "警告: カスタムパターンディレクトリ%sを作成できませんでした: %v\n",
|
||||
"db_error_loading_env_file": ".envファイルの読み込みエラー: %w",
|
||||
"db_error_updating_env_file": ".envファイルの更新エラー: %w",
|
||||
"defaults_model_context_length_question": "モデルのコンテキスト長を入力してください",
|
||||
"defaults_model_question": "デフォルトモデルのインデックスまたは名前を入力してください",
|
||||
"defaults_setup_description": "デフォルトのAIプロバイダーとモデル",
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@
|
|||
"choose_pattern_from_available": "Wybierz wzorzec spośród dostępnych wzorców",
|
||||
"choose_session_from_available": "Wybierz sesję spośród dostępnych sesji",
|
||||
"choose_strategy_from_available": "Wybierz strategię spośród dostępnych strategii",
|
||||
"codex_api_base_url_question": "Podaj bazowy URL API Codex",
|
||||
"codex_auth_base_url_invalid": "Nieprawidłowy bazowy URL uwierzytelniania Codex: %w",
|
||||
"codex_auth_base_url_question": "Podaj bazowy URL OAuth Codex",
|
||||
"codex_browser_open_fallback": "Jeśli przeglądarka się nie otworzyła, przejdź pod ten URL, aby się uwierzytelnić:",
|
||||
"codex_decode_models_response_failed": "Nie udało się zdekodować odpowiedzi modeli Codex: %w",
|
||||
"codex_decode_refresh_response_failed": "Nie udało się zdekodować odpowiedzi odświeżonego tokenu Codex: %w",
|
||||
|
|
@ -133,13 +135,16 @@
|
|||
"codex_oauth_random_state_failed": "Nie udało się wygenerować bezpiecznego losowego stanu OAuth: %w",
|
||||
"codex_oauth_server_start_failed": "Nie udało się uruchomić lokalnego serwera zwrotnego OAuth: %w",
|
||||
"codex_oauth_state_mismatch": "Stan nie jest zgodny",
|
||||
"codex_provider_error": "błąd dostawcy Codex (status %d): %s",
|
||||
"codex_refresh_failed_status": "Nie udało się odświeżyć logowania Codex (status %d)",
|
||||
"codex_refresh_login_failed": "Nie udało się odświeżyć logowania Codex: %w",
|
||||
"codex_refresh_token_required": "Token odświeżania Codex jest wymagany. Uruchom ponownie 'fabric --setup'.",
|
||||
"codex_replay_body_unavailable": "Treść żądania nie może być odtworzona dla ponownej próby uwierzytelnienia Codex",
|
||||
"codex_request_failed": "Żądanie Codex nie powiodło się: %w",
|
||||
"codex_request_failed_status": "Żądanie Codex nie powiodło się ze statusem %d",
|
||||
"codex_starting_browser_login": "Uruchamianie logowania OpenAI przez przeglądarkę dla Codex.",
|
||||
"codex_token_exchange_failed": "Wymiana tokenu Codex nie powiodła się: %w",
|
||||
"codex_token_persist_failed": "nie udało się zapisać logowania Codex: %w",
|
||||
"codex_token_refresh_missing_access_token": "Odświeżenie tokenu Codex nie zwróciło tokenu dostępu.",
|
||||
"codex_usage_limit_reached": "Osiągnięto limit użycia Codex",
|
||||
"command_completed_successfully": "Polecenie zakończone pomyślnie",
|
||||
|
|
@ -168,6 +173,7 @@
|
|||
"custom_patterns_setup_description": "Niestandardowe wzorce - Ustaw katalog dla swoich niestandardowych wzorców",
|
||||
"custom_patterns_warning_create_directory": "Ostrzeżenie: Nie można utworzyć katalogu niestandardowych wzorców %s: %v\n",
|
||||
"db_error_loading_env_file": "błąd podczas ładowania pliku .env: %w",
|
||||
"db_error_updating_env_file": "błąd podczas aktualizacji pliku .env: %w",
|
||||
"defaults_model_context_length_question": "Podaj długość kontekstu modelu",
|
||||
"defaults_model_question": "Podaj indeks lub nazwę domyślnego modelu",
|
||||
"defaults_setup_description": "Domyślny dostawca AI i model",
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@
|
|||
"choose_pattern_from_available": "Escolha um padrão entre os padrões disponíveis",
|
||||
"choose_session_from_available": "Escolha uma sessão das sessões disponíveis",
|
||||
"choose_strategy_from_available": "Escolher uma estratégia das estratégias disponíveis",
|
||||
"codex_api_base_url_question": "Insira a URL base da API do Codex",
|
||||
"codex_auth_base_url_invalid": "URL base de autenticação do Codex inválida: %w",
|
||||
"codex_auth_base_url_question": "Insira a URL base de OAuth do Codex",
|
||||
"codex_browser_open_fallback": "Se o navegador não abriu, navegue até esta URL para se autenticar:",
|
||||
"codex_decode_models_response_failed": "Falha ao decodificar a resposta de modelos do Codex: %w",
|
||||
"codex_decode_refresh_response_failed": "Falha ao decodificar a resposta do token atualizado do Codex: %w",
|
||||
|
|
@ -133,13 +135,16 @@
|
|||
"codex_oauth_random_state_failed": "Falha ao gerar estado OAuth aleatório seguro: %w",
|
||||
"codex_oauth_server_start_failed": "Falha ao iniciar o servidor local de callback OAuth: %w",
|
||||
"codex_oauth_state_mismatch": "O estado não corresponde",
|
||||
"codex_provider_error": "erro do fornecedor Codex (status %d): %s",
|
||||
"codex_refresh_failed_status": "Falha ao atualizar o login do Codex (status %d)",
|
||||
"codex_refresh_login_failed": "Falha ao atualizar o login do Codex: %w",
|
||||
"codex_refresh_token_required": "O token de atualização do Codex é obrigatório. Execute 'fabric --setup' novamente.",
|
||||
"codex_replay_body_unavailable": "O corpo da requisição não pode ser reproduzido para a tentativa de reautenticação do Codex",
|
||||
"codex_request_failed": "A requisição do Codex falhou: %w",
|
||||
"codex_request_failed_status": "A requisição do Codex falhou com status %d",
|
||||
"codex_starting_browser_login": "Iniciando login OpenAI baseado em navegador para o Codex.",
|
||||
"codex_token_exchange_failed": "A troca de token do Codex falhou: %w",
|
||||
"codex_token_persist_failed": "falha ao persistir o login do Codex: %w",
|
||||
"codex_token_refresh_missing_access_token": "A atualização do token do Codex não retornou um token de acesso.",
|
||||
"codex_usage_limit_reached": "Limite de uso do Codex atingido",
|
||||
"command_completed_successfully": "Comando concluído com sucesso",
|
||||
|
|
@ -168,6 +173,7 @@
|
|||
"custom_patterns_setup_description": "Padrões personalizados - Definir diretório para seus padrões personalizados",
|
||||
"custom_patterns_warning_create_directory": "Aviso: Não foi possível criar o diretório de padrões personalizados %s: %v\n",
|
||||
"db_error_loading_env_file": "erro ao carregar o arquivo .env: %w",
|
||||
"db_error_updating_env_file": "erro ao atualizar o arquivo .env: %w",
|
||||
"defaults_model_context_length_question": "Informe o comprimento do contexto do modelo",
|
||||
"defaults_model_question": "Informe o índice ou o nome do seu modelo padrão",
|
||||
"defaults_setup_description": "Provedor e modelo de IA padrão",
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@
|
|||
"choose_pattern_from_available": "Escolha um padrão dos padrões disponíveis",
|
||||
"choose_session_from_available": "Escolha uma sessão das sessões disponíveis",
|
||||
"choose_strategy_from_available": "Escolher uma estratégia das estratégias disponíveis",
|
||||
"codex_api_base_url_question": "Introduza o URL base da API do Codex",
|
||||
"codex_auth_base_url_invalid": "URL base de autenticação do Codex inválido: %w",
|
||||
"codex_auth_base_url_question": "Introduza o URL base de OAuth do Codex",
|
||||
"codex_browser_open_fallback": "Se o navegador não abriu, navegue até este URL para se autenticar:",
|
||||
"codex_decode_models_response_failed": "Falha ao descodificar a resposta de modelos do Codex: %w",
|
||||
"codex_decode_refresh_response_failed": "Falha ao descodificar a resposta do token atualizado do Codex: %w",
|
||||
|
|
@ -133,13 +135,16 @@
|
|||
"codex_oauth_random_state_failed": "Falha ao gerar estado OAuth aleatório seguro: %w",
|
||||
"codex_oauth_server_start_failed": "Falha ao iniciar o servidor local de retorno OAuth: %w",
|
||||
"codex_oauth_state_mismatch": "O estado não corresponde",
|
||||
"codex_provider_error": "erro do fornecedor Codex (estado %d): %s",
|
||||
"codex_refresh_failed_status": "Falha ao atualizar o início de sessão do Codex (estado %d)",
|
||||
"codex_refresh_login_failed": "Falha ao atualizar o início de sessão do Codex: %w",
|
||||
"codex_refresh_token_required": "O token de atualização do Codex é obrigatório. Execute 'fabric --setup' novamente.",
|
||||
"codex_replay_body_unavailable": "O corpo do pedido não pode ser reproduzido para a tentativa de reautenticação do Codex",
|
||||
"codex_request_failed": "O pedido do Codex falhou: %w",
|
||||
"codex_request_failed_status": "O pedido do Codex falhou com estado %d",
|
||||
"codex_starting_browser_login": "A iniciar início de sessão OpenAI baseado no navegador para o Codex.",
|
||||
"codex_token_exchange_failed": "A troca de token do Codex falhou: %w",
|
||||
"codex_token_persist_failed": "falha ao persistir o início de sessão do Codex: %w",
|
||||
"codex_token_refresh_missing_access_token": "A atualização do token do Codex não devolveu um token de acesso.",
|
||||
"codex_usage_limit_reached": "Limite de utilização do Codex atingido",
|
||||
"command_completed_successfully": "Comando concluído com sucesso",
|
||||
|
|
@ -168,6 +173,7 @@
|
|||
"custom_patterns_setup_description": "Padrões personalizados - Definir diretório para os seus padrões personalizados",
|
||||
"custom_patterns_warning_create_directory": "Aviso: Não foi possível criar o diretório de padrões personalizados %s: %v\n",
|
||||
"db_error_loading_env_file": "erro ao carregar o ficheiro .env: %w",
|
||||
"db_error_updating_env_file": "erro ao atualizar o ficheiro .env: %w",
|
||||
"defaults_model_context_length_question": "Indique o comprimento do contexto do modelo",
|
||||
"defaults_model_question": "Indique o índice ou o nome do seu modelo padrão",
|
||||
"defaults_setup_description": "Fornecedor e modelo de IA padrão",
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@
|
|||
"choose_pattern_from_available": "从可用模式中选择一个模式",
|
||||
"choose_session_from_available": "从可用会话中选择一个会话",
|
||||
"choose_strategy_from_available": "从可用策略中选择一个策略",
|
||||
"codex_api_base_url_question": "请输入您的 Codex API 基础 URL",
|
||||
"codex_auth_base_url_invalid": "Codex 认证基础 URL 无效:%w",
|
||||
"codex_auth_base_url_question": "请输入您的 Codex OAuth 基础 URL",
|
||||
"codex_browser_open_fallback": "如果浏览器未打开,请导航到此 URL 进行身份验证:",
|
||||
"codex_decode_models_response_failed": "解码 Codex 模型响应失败:%w",
|
||||
"codex_decode_refresh_response_failed": "解码刷新的 Codex 令牌响应失败:%w",
|
||||
|
|
@ -133,13 +135,16 @@
|
|||
"codex_oauth_random_state_failed": "生成安全随机 OAuth 状态失败:%w",
|
||||
"codex_oauth_server_start_failed": "启动本地 OAuth 回调服务器失败:%w",
|
||||
"codex_oauth_state_mismatch": "状态不匹配",
|
||||
"codex_provider_error": "Codex 供应商错误(状态 %d):%s",
|
||||
"codex_refresh_failed_status": "刷新 Codex 登录失败(状态 %d)",
|
||||
"codex_refresh_login_failed": "刷新 Codex 登录失败:%w",
|
||||
"codex_refresh_token_required": "需要 Codex 刷新令牌。请重新运行 'fabric --setup'。",
|
||||
"codex_replay_body_unavailable": "请求正文无法重放用于 Codex 重新认证重试",
|
||||
"codex_request_failed": "Codex 请求失败:%w",
|
||||
"codex_request_failed_status": "Codex 请求失败,状态 %d",
|
||||
"codex_starting_browser_login": "正在启动基于浏览器的 OpenAI 登录以连接 Codex。",
|
||||
"codex_token_exchange_failed": "Codex 令牌交换失败:%w",
|
||||
"codex_token_persist_failed": "无法保存 Codex 登录:%w",
|
||||
"codex_token_refresh_missing_access_token": "Codex 令牌刷新未返回访问令牌。",
|
||||
"codex_usage_limit_reached": "已达到 Codex 使用限制",
|
||||
"command_completed_successfully": "命令执行成功",
|
||||
|
|
@ -168,6 +173,7 @@
|
|||
"custom_patterns_setup_description": "自定义模式 - 设置您的自定义模式目录",
|
||||
"custom_patterns_warning_create_directory": "警告:无法创建自定义模式目录 %s:%v\n",
|
||||
"db_error_loading_env_file": "加载 .env 文件错误:%w",
|
||||
"db_error_updating_env_file": "更新 .env 文件错误:%w",
|
||||
"defaults_model_context_length_question": "请输入模型上下文长度",
|
||||
"defaults_model_question": "请输入您的默认模型的索引或名称",
|
||||
"defaults_setup_description": "默认 AI 提供商和模型",
|
||||
|
|
|
|||
|
|
@ -24,6 +24,45 @@ type authTransport struct {
|
|||
}
|
||||
|
||||
func (c *Client) ensureAccessToken(ctx context.Context, forceRefresh bool) (string, string, error) {
|
||||
// Fast path: a valid in-memory token needs no refresh, so avoid the store
|
||||
// lock and disk reload. This also keeps Setup's fresh OAuth tokens from
|
||||
// being overwritten by the stale values still on disk before SaveEnvFile.
|
||||
if !forceRefresh {
|
||||
if access, account, ok := c.currentToken(); ok {
|
||||
return access, account, nil
|
||||
}
|
||||
}
|
||||
if c.WithStoreLock == nil {
|
||||
return c.ensureAccessTokenLocked(ctx, forceRefresh)
|
||||
}
|
||||
var access, account string
|
||||
err := c.WithStoreLock(func() error {
|
||||
var inner error
|
||||
access, account, inner = c.ensureAccessTokenLocked(ctx, forceRefresh)
|
||||
return inner
|
||||
})
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return access, account, nil
|
||||
}
|
||||
|
||||
// currentToken returns the in-memory token when it is present and unexpired.
|
||||
// A missing account ID falls through to the locked path, which parses it from
|
||||
// the JWT.
|
||||
func (c *Client) currentToken() (access string, account string, ok bool) {
|
||||
c.tokenMu.Lock()
|
||||
defer c.tokenMu.Unlock()
|
||||
|
||||
access = strings.TrimSpace(c.AccessToken.Value)
|
||||
account = strings.TrimSpace(c.AccountID.Value)
|
||||
if access == "" || account == "" || tokenNeedsRefresh(access, time.Now()) {
|
||||
return "", "", false
|
||||
}
|
||||
return access, account, true
|
||||
}
|
||||
|
||||
func (c *Client) ensureAccessTokenLocked(ctx context.Context, forceRefresh bool) (string, string, error) {
|
||||
c.tokenMu.Lock()
|
||||
defer c.tokenMu.Unlock()
|
||||
|
||||
|
|
@ -61,7 +100,13 @@ func (c *Client) ensureAccessToken(ctx context.Context, forceRefresh bool) (stri
|
|||
c.setSettingValue(c.RefreshToken, refreshed.RefreshToken)
|
||||
}
|
||||
c.setSettingValue(c.AccountID, refreshedAccountID)
|
||||
debuglog.Debug(debuglog.Detailed, "Codex access token refreshed for account=%s\n", refreshedAccountID)
|
||||
if c.TokenPersist != nil {
|
||||
if err := c.TokenPersist(); err != nil {
|
||||
debuglog.Log("Codex token persist failed: %v\n", err)
|
||||
return "", "", fmt.Errorf(i18n.T("codex_token_persist_failed"), err)
|
||||
}
|
||||
}
|
||||
debuglog.Debug(debuglog.Detailed, "Codex access token refreshed account_present=%t\n", refreshedAccountID != "")
|
||||
|
||||
return c.AccessToken.Value, c.AccountID.Value, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,10 @@ type Client struct {
|
|||
apiHTTPClient *http.Client
|
||||
|
||||
tokenMu sync.Mutex
|
||||
// TokenPersist writes current tokens after refresh. Nil skips. Error fails the refresh.
|
||||
TokenPersist func() error
|
||||
// WithStoreLock, when set, wraps refresh+persist (reload tokens inside the lock).
|
||||
WithStoreLock func(func() error) error
|
||||
}
|
||||
|
||||
type modelInfo struct {
|
||||
|
|
@ -81,11 +85,11 @@ func NewClient() *Client {
|
|||
client.AccountID = client.AddSetting("Account ID", true)
|
||||
|
||||
client.ApiBaseURL = client.AddSetupQuestionWithEnvName("Base URL", false,
|
||||
"Enter your Codex API base URL")
|
||||
i18n.T("codex_api_base_url_question"))
|
||||
client.ApiBaseURL.Value = defaultBaseURL
|
||||
|
||||
client.AuthBaseURL = client.AddSetupQuestionWithEnvName("Auth Base URL", false,
|
||||
"Enter your Codex OAuth base URL")
|
||||
i18n.T("codex_auth_base_url_question"))
|
||||
client.AuthBaseURL.Value = defaultAuthBaseURL
|
||||
|
||||
client.authHTTPClient = &http.Client{Timeout: modelsRequestTimeout}
|
||||
|
|
@ -101,6 +105,14 @@ func (c *Client) Setup() error {
|
|||
return err
|
||||
}
|
||||
|
||||
if strings.TrimSpace(c.RefreshToken.Value) != "" {
|
||||
if err := c.configure(); err == nil {
|
||||
return nil
|
||||
} else {
|
||||
debuglog.Log("Codex configure failed; starting browser login: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), oauthTimeout)
|
||||
defer cancel()
|
||||
|
||||
|
|
@ -153,11 +165,26 @@ func (c *Client) configure() error {
|
|||
option.WithHTTPClient(c.apiHTTPClient),
|
||||
)
|
||||
c.ApiClient = &apiClient
|
||||
debuglog.Debug(debuglog.Detailed, "Codex configure: authenticated account=%s base_url=%s\n", c.AccountID.Value, c.ApiBaseURL.Value)
|
||||
debuglog.Debug(debuglog.Detailed, "Codex configure: authenticated account_present=%t base_url=%s\n", strings.TrimSpace(c.AccountID.Value) != "", c.ApiBaseURL.Value)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadEnvSettings copies non-empty Codex token values from env.
|
||||
func (c *Client) LoadEnvSettings(env map[string]string) {
|
||||
apply := func(setting *plugins.Setting) {
|
||||
if setting == nil || setting.EnvVariable == "" {
|
||||
return
|
||||
}
|
||||
if value := strings.TrimSpace(env[setting.EnvVariable]); value != "" {
|
||||
c.setSettingValue(setting, value)
|
||||
}
|
||||
}
|
||||
apply(c.AccessToken)
|
||||
apply(c.RefreshToken)
|
||||
apply(c.AccountID)
|
||||
}
|
||||
|
||||
// ListModels returns the Codex models available to the configured account.
|
||||
func (c *Client) ListModels(ctx context.Context) ([]string, error) {
|
||||
if c.apiHTTPClient == nil {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import (
|
|||
|
||||
"github.com/danielmiessler/fabric/internal/chat"
|
||||
"github.com/danielmiessler/fabric/internal/domain"
|
||||
"github.com/danielmiessler/fabric/internal/i18n"
|
||||
openaiapi "github.com/openai/openai-go"
|
||||
"github.com/openai/openai-go/shared/constant"
|
||||
)
|
||||
|
|
@ -211,6 +212,10 @@ func TestNormalizeSemverLikeVersion(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMapRequestErrorPreservesCodexAPIErrorMessage(t *testing.T) {
|
||||
if _, err := i18n.Init("en"); err != nil {
|
||||
t.Fatalf("i18n.Init() error = %v", err)
|
||||
}
|
||||
|
||||
client := NewClient()
|
||||
apiErr := &openaiapi.Error{StatusCode: http.StatusBadRequest}
|
||||
if err := apiErr.UnmarshalJSON([]byte(`{"message":"The requested model is not supported.","type":"invalid_request_error","param":"model","code":"invalid_value"}`)); err != nil {
|
||||
|
|
@ -221,8 +226,9 @@ func TestMapRequestErrorPreservesCodexAPIErrorMessage(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Fatal("mapRequestError() returned nil")
|
||||
}
|
||||
if got := err.Error(); got != "codex request failed with status 400" {
|
||||
t.Fatalf("mapRequestError() = %q, want %q", got, "codex request failed with status 400")
|
||||
want := fmt.Sprintf(i18n.T("codex_request_failed_status"), http.StatusBadRequest)
|
||||
if got := err.Error(); got != want {
|
||||
t.Fatalf("mapRequestError() = %q, want %q", got, want)
|
||||
}
|
||||
if unwrapped := errors.Unwrap(err); unwrapped == nil || !strings.Contains(unwrapped.Error(), "The requested model is not supported.") {
|
||||
t.Fatalf("wrapped error = %v, want provider detail", unwrapped)
|
||||
|
|
@ -230,6 +236,10 @@ func TestMapRequestErrorPreservesCodexAPIErrorMessage(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestMapRequestErrorReadsAPIErrorResponseBodyWhenRawJSONMissing(t *testing.T) {
|
||||
if _, err := i18n.Init("en"); err != nil {
|
||||
t.Fatalf("i18n.Init() error = %v", err)
|
||||
}
|
||||
|
||||
client := NewClient()
|
||||
apiErr := &openaiapi.Error{
|
||||
StatusCode: http.StatusBadRequest,
|
||||
|
|
@ -242,8 +252,9 @@ func TestMapRequestErrorReadsAPIErrorResponseBodyWhenRawJSONMissing(t *testing.T
|
|||
if err == nil {
|
||||
t.Fatal("mapRequestError() returned nil")
|
||||
}
|
||||
if got := err.Error(); got != "codex request failed with status 400" {
|
||||
t.Fatalf("mapRequestError() = %q, want %q", got, "codex request failed with status 400")
|
||||
want := fmt.Sprintf(i18n.T("codex_request_failed_status"), http.StatusBadRequest)
|
||||
if got := err.Error(); got != want {
|
||||
t.Fatalf("mapRequestError() = %q, want %q", got, want)
|
||||
}
|
||||
if unwrapped := errors.Unwrap(err); unwrapped == nil || !strings.Contains(unwrapped.Error(), "The requested model is not supported for Codex.") {
|
||||
t.Fatalf("wrapped error = %v, want provider detail", unwrapped)
|
||||
|
|
@ -575,8 +586,8 @@ func TestSendStreamClosesChannelAndMapsHTTPError(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Fatal("SendStream() error = nil, want mapped HTTP error")
|
||||
}
|
||||
if got := err.Error(); got != "codex usage limit reached" {
|
||||
t.Fatalf("SendStream() error = %q, want %q", got, "codex usage limit reached")
|
||||
if got := err.Error(); got != i18n.T("codex_usage_limit_reached") {
|
||||
t.Fatalf("SendStream() error = %q, want %q", got, i18n.T("codex_usage_limit_reached"))
|
||||
}
|
||||
|
||||
update, ok := <-updates
|
||||
|
|
@ -585,6 +596,159 @@ func TestSendStreamClosesChannelAndMapsHTTPError(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestEnsureAccessTokenPersistsRotatedRefreshToken(t *testing.T) {
|
||||
authServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/oauth/token" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(refreshResponse{
|
||||
IDToken: testJWT("acct_persist", time.Now().Add(2*time.Hour)),
|
||||
AccessToken: testJWT("acct_persist", time.Now().Add(2*time.Hour)),
|
||||
RefreshToken: "refresh-rotated",
|
||||
})
|
||||
}))
|
||||
defer authServer.Close()
|
||||
|
||||
var persisted map[string]string
|
||||
client := NewClient()
|
||||
client.ApiBaseURL.Value = "https://example.invalid"
|
||||
client.AuthBaseURL.Value = authServer.URL
|
||||
client.RefreshToken.Value = "refresh-old"
|
||||
client.AccessToken.Value = testJWT("acct_persist", time.Now().Add(-time.Hour))
|
||||
client.AccountID.Value = "acct_persist"
|
||||
client.TokenPersist = func() error {
|
||||
persisted = map[string]string{
|
||||
"access": client.AccessToken.Value,
|
||||
"refresh": client.RefreshToken.Value,
|
||||
"account": client.AccountID.Value,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
access, account, err := client.ensureAccessToken(context.Background(), false)
|
||||
if err != nil {
|
||||
t.Fatalf("ensureAccessToken() error = %v", err)
|
||||
}
|
||||
if access == "" {
|
||||
t.Fatal("ensureAccessToken() returned empty access token")
|
||||
}
|
||||
if account != "acct_persist" {
|
||||
t.Fatalf("account = %q, want acct_persist", account)
|
||||
}
|
||||
if persisted["refresh"] != "refresh-rotated" {
|
||||
t.Fatalf("persisted refresh = %q, want refresh-rotated", persisted["refresh"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureAccessTokenPersistError(t *testing.T) {
|
||||
if _, err := i18n.Init("en"); err != nil {
|
||||
t.Fatalf("i18n.Init() error = %v", err)
|
||||
}
|
||||
|
||||
authServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/oauth/token" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(refreshResponse{
|
||||
IDToken: testJWT("acct_persist", time.Now().Add(2*time.Hour)),
|
||||
AccessToken: testJWT("acct_persist", time.Now().Add(2*time.Hour)),
|
||||
RefreshToken: "refresh-rotated",
|
||||
})
|
||||
}))
|
||||
defer authServer.Close()
|
||||
|
||||
persistErr := errors.New("disk full")
|
||||
client := NewClient()
|
||||
client.ApiBaseURL.Value = "https://example.invalid"
|
||||
client.AuthBaseURL.Value = authServer.URL
|
||||
client.RefreshToken.Value = "refresh-old"
|
||||
client.AccessToken.Value = testJWT("acct_persist", time.Now().Add(-time.Hour))
|
||||
client.AccountID.Value = "acct_persist"
|
||||
client.TokenPersist = func() error {
|
||||
return persistErr
|
||||
}
|
||||
|
||||
_, _, err := client.ensureAccessToken(context.Background(), false)
|
||||
if err == nil {
|
||||
t.Fatal("ensureAccessToken() error = nil, want persist error")
|
||||
}
|
||||
if !errors.Is(err, persistErr) {
|
||||
t.Fatalf("ensureAccessToken() error = %v, want persist error %v", err, persistErr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureAccessTokenReloadsStoreBeforeRefresh(t *testing.T) {
|
||||
authHits := 0
|
||||
authServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
authHits++
|
||||
http.Error(w, "unexpected refresh", http.StatusInternalServerError)
|
||||
}))
|
||||
defer authServer.Close()
|
||||
|
||||
fresh := testJWT("acct_reload", time.Now().Add(2*time.Hour))
|
||||
client := NewClient()
|
||||
client.ApiBaseURL.Value = "https://example.invalid"
|
||||
client.AuthBaseURL.Value = authServer.URL
|
||||
client.RefreshToken.Value = "refresh-old"
|
||||
client.AccessToken.Value = testJWT("acct_reload", time.Now().Add(-time.Hour))
|
||||
client.AccountID.Value = "acct_reload"
|
||||
client.WithStoreLock = func(fn func() error) error {
|
||||
client.AccessToken.Value = fresh
|
||||
client.AccountID.Value = "acct_reload"
|
||||
return fn()
|
||||
}
|
||||
|
||||
access, account, err := client.ensureAccessToken(context.Background(), false)
|
||||
if err != nil {
|
||||
t.Fatalf("ensureAccessToken() error = %v", err)
|
||||
}
|
||||
if access != fresh {
|
||||
t.Fatal("ensureAccessToken() did not use reloaded access token")
|
||||
}
|
||||
if account != "acct_reload" {
|
||||
t.Fatalf("account = %q, want acct_reload", account)
|
||||
}
|
||||
if authHits != 0 {
|
||||
t.Fatalf("auth server hits = %d, want 0", authHits)
|
||||
}
|
||||
}
|
||||
|
||||
// Regression: a valid in-memory token (e.g. just obtained via Setup's OAuth)
|
||||
// must not be reloaded from the store, which still holds the stale token until
|
||||
// SaveEnvFile runs. The fast path returns before WithStoreLock can clobber it.
|
||||
func TestEnsureAccessTokenKeepsFreshTokenOverStore(t *testing.T) {
|
||||
fresh := testJWT("acct_fresh", time.Now().Add(2*time.Hour))
|
||||
client := NewClient()
|
||||
client.ApiBaseURL.Value = "https://example.invalid"
|
||||
client.AuthBaseURL.Value = "https://auth.invalid"
|
||||
client.RefreshToken.Value = "refresh-new"
|
||||
client.AccessToken.Value = fresh
|
||||
client.AccountID.Value = "acct_fresh"
|
||||
|
||||
storeLocked := false
|
||||
client.WithStoreLock = func(fn func() error) error {
|
||||
storeLocked = true
|
||||
client.AccessToken.Value = "stale-from-disk"
|
||||
client.AccountID.Value = "acct_stale"
|
||||
return fn()
|
||||
}
|
||||
|
||||
access, account, err := client.ensureAccessToken(context.Background(), false)
|
||||
if err != nil {
|
||||
t.Fatalf("ensureAccessToken() error = %v", err)
|
||||
}
|
||||
if storeLocked {
|
||||
t.Fatal("store lock ran and clobbered a valid in-memory token")
|
||||
}
|
||||
if access != fresh || account != "acct_fresh" {
|
||||
t.Fatalf("got access=%q account=%q, want fresh token for acct_fresh", access, account)
|
||||
}
|
||||
}
|
||||
|
||||
func newConfiguredTestClient(t *testing.T, apiBaseURL string, accountID string, accessToken string) *Client {
|
||||
t.Helper()
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ func (c *Client) mapRequestError(err error) error {
|
|||
case isUsageLimitMessage(message):
|
||||
return &publicError{
|
||||
message: i18n.T("codex_usage_limit_reached"),
|
||||
cause: fmt.Errorf("codex request failed: %w", err),
|
||||
cause: fmt.Errorf(i18n.T("codex_request_failed"), err),
|
||||
}
|
||||
default:
|
||||
return err
|
||||
|
|
@ -91,7 +91,7 @@ func wrapPublicError(message string, statusCode int, providerMessage string) err
|
|||
|
||||
return &publicError{
|
||||
message: message,
|
||||
cause: fmt.Errorf("codex provider error (status %d): %s", statusCode, providerMessage),
|
||||
cause: fmt.Errorf(i18n.T("codex_provider_error"), statusCode, providerMessage),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/danielmiessler/fabric/internal/i18n"
|
||||
|
|
@ -41,6 +42,8 @@ type Db struct {
|
|||
Contexts *ContextsEntity
|
||||
|
||||
EnvFilePath string
|
||||
|
||||
envMu sync.Mutex
|
||||
}
|
||||
|
||||
func (o *Db) Configure() (err error) {
|
||||
|
|
@ -92,9 +95,100 @@ func (o *Db) IsEnvFileExists() (ret bool) {
|
|||
return
|
||||
}
|
||||
|
||||
func (o *Db) SaveEnv(content string) (err error) {
|
||||
err = os.WriteFile(o.EnvFilePath, []byte(content), 0644)
|
||||
return
|
||||
func (o *Db) SaveEnv(content string) error {
|
||||
return o.WithEnvLock(func() error {
|
||||
if err := writeFileAtomic(o.EnvFilePath, []byte(content)); err != nil {
|
||||
return fmt.Errorf(i18n.T("db_error_updating_env_file"), err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (o *Db) ReadEnvFile() (map[string]string, error) {
|
||||
env, err := godotenv.Read(o.EnvFilePath)
|
||||
if err != nil {
|
||||
if o.IsEnvFileExists() {
|
||||
return nil, fmt.Errorf(i18n.T("db_error_loading_env_file"), err)
|
||||
}
|
||||
return map[string]string{}, nil
|
||||
}
|
||||
return env, nil
|
||||
}
|
||||
|
||||
func (o *Db) WithEnvLock(fn func() error) error {
|
||||
o.envMu.Lock()
|
||||
defer o.envMu.Unlock()
|
||||
|
||||
lockFile, err := os.OpenFile(o.EnvFilePath+".lock", os.O_CREATE|os.O_RDWR, 0600)
|
||||
if err != nil {
|
||||
return fmt.Errorf(i18n.T("db_error_updating_env_file"), err)
|
||||
}
|
||||
defer lockFile.Close()
|
||||
if err := lockExclusive(lockFile); err != nil {
|
||||
return fmt.Errorf(i18n.T("db_error_updating_env_file"), err)
|
||||
}
|
||||
defer unlockExclusive(lockFile)
|
||||
|
||||
return fn()
|
||||
}
|
||||
|
||||
// UpdateEnvVars merges non-empty values into .env under a file lock.
|
||||
// Comments and key order are not preserved.
|
||||
func (o *Db) UpdateEnvVars(updates map[string]string) error {
|
||||
return o.WithEnvLock(func() error {
|
||||
return o.ApplyEnvUpdates(updates)
|
||||
})
|
||||
}
|
||||
|
||||
// ApplyEnvUpdates writes non-empty updates atomically. Callers holding WithEnvLock use this.
|
||||
func (o *Db) ApplyEnvUpdates(updates map[string]string) error {
|
||||
env, err := o.ReadEnvFile()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for key, value := range updates {
|
||||
if strings.TrimSpace(value) == "" {
|
||||
continue
|
||||
}
|
||||
env[key] = value
|
||||
}
|
||||
if err := writeEnvFileAtomic(o.EnvFilePath, env); err != nil {
|
||||
return fmt.Errorf(i18n.T("db_error_updating_env_file"), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeEnvFileAtomic(path string, env map[string]string) error {
|
||||
content, err := godotenv.Marshal(env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return writeFileAtomic(path, []byte(content+"\n"))
|
||||
}
|
||||
|
||||
func writeFileAtomic(path string, content []byte) error {
|
||||
tmp, err := os.CreateTemp(filepath.Dir(path), ".env.tmp-")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmpName := tmp.Name()
|
||||
defer os.Remove(tmpName)
|
||||
|
||||
if err := tmp.Chmod(0600); err != nil {
|
||||
_ = tmp.Close()
|
||||
return err
|
||||
}
|
||||
_, err = tmp.Write(content)
|
||||
if err == nil {
|
||||
err = tmp.Sync()
|
||||
}
|
||||
if cerr := tmp.Close(); err == nil {
|
||||
err = cerr
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmpName, path)
|
||||
}
|
||||
|
||||
func (o *Db) FilePath(fileName string) (ret string) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,12 @@ package fsdb
|
|||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func TestDb_Configure(t *testing.T) {
|
||||
|
|
@ -52,4 +57,150 @@ func TestDb_SaveEnv(t *testing.T) {
|
|||
if _, err := os.Stat(db.EnvFilePath); os.IsNotExist(err) {
|
||||
t.Errorf("expected .env file to be saved")
|
||||
}
|
||||
assertEnvMode(t, db.EnvFilePath)
|
||||
}
|
||||
|
||||
func TestDb_UpdateEnvVars(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
db := NewDb(dir)
|
||||
if err := db.SaveEnv("KEEP=old\nCODEX_REFRESH_TOKEN=stale\n"); err != nil {
|
||||
t.Fatalf("SaveEnv() error = %v", err)
|
||||
}
|
||||
|
||||
if err := db.UpdateEnvVars(map[string]string{
|
||||
"CODEX_REFRESH_TOKEN": "rotated",
|
||||
"CODEX_ACCESS_TOKEN": "fresh",
|
||||
}); err != nil {
|
||||
t.Fatalf("UpdateEnvVars() error = %v", err)
|
||||
}
|
||||
|
||||
parsed, err := godotenv.Read(db.EnvFilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("godotenv.Read() error = %v", err)
|
||||
}
|
||||
if parsed["KEEP"] != "old" {
|
||||
t.Fatalf("KEEP = %q, want old", parsed["KEEP"])
|
||||
}
|
||||
if parsed["CODEX_REFRESH_TOKEN"] != "rotated" {
|
||||
t.Fatalf("CODEX_REFRESH_TOKEN = %q, want rotated", parsed["CODEX_REFRESH_TOKEN"])
|
||||
}
|
||||
if parsed["CODEX_ACCESS_TOKEN"] != "fresh" {
|
||||
t.Fatalf("CODEX_ACCESS_TOKEN = %q, want fresh", parsed["CODEX_ACCESS_TOKEN"])
|
||||
}
|
||||
assertEnvMode(t, db.EnvFilePath)
|
||||
}
|
||||
|
||||
func TestDb_UpdateEnvVars_MissingFile(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
db := NewDb(dir)
|
||||
|
||||
if err := db.UpdateEnvVars(map[string]string{"CODEX_ACCESS_TOKEN": "fresh"}); err != nil {
|
||||
t.Fatalf("UpdateEnvVars() error = %v", err)
|
||||
}
|
||||
|
||||
parsed, err := godotenv.Read(db.EnvFilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("godotenv.Read() error = %v", err)
|
||||
}
|
||||
if parsed["CODEX_ACCESS_TOKEN"] != "fresh" {
|
||||
t.Fatalf("CODEX_ACCESS_TOKEN = %q, want fresh", parsed["CODEX_ACCESS_TOKEN"])
|
||||
}
|
||||
assertEnvMode(t, db.EnvFilePath)
|
||||
}
|
||||
|
||||
func TestDb_UpdateEnvVars_CorruptFile(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
db := NewDb(dir)
|
||||
if err := os.Mkdir(db.EnvFilePath, 0700); err != nil {
|
||||
t.Fatalf("Mkdir() error = %v", err)
|
||||
}
|
||||
|
||||
err := db.UpdateEnvVars(map[string]string{"CODEX_ACCESS_TOKEN": "fresh"})
|
||||
if err == nil {
|
||||
t.Fatal("UpdateEnvVars() error = nil, want corrupt-file error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDb_UpdateEnvVars_SkipEmpty(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
db := NewDb(dir)
|
||||
if err := db.SaveEnv("CODEX_REFRESH_TOKEN=live\nKEEP=old\n"); err != nil {
|
||||
t.Fatalf("SaveEnv() error = %v", err)
|
||||
}
|
||||
|
||||
if err := db.UpdateEnvVars(map[string]string{
|
||||
"CODEX_REFRESH_TOKEN": "",
|
||||
"CODEX_ACCESS_TOKEN": "fresh",
|
||||
}); err != nil {
|
||||
t.Fatalf("UpdateEnvVars() error = %v", err)
|
||||
}
|
||||
|
||||
parsed, err := godotenv.Read(db.EnvFilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("godotenv.Read() error = %v", err)
|
||||
}
|
||||
if parsed["CODEX_REFRESH_TOKEN"] != "live" {
|
||||
t.Fatalf("CODEX_REFRESH_TOKEN = %q, want live", parsed["CODEX_REFRESH_TOKEN"])
|
||||
}
|
||||
if parsed["CODEX_ACCESS_TOKEN"] != "fresh" {
|
||||
t.Fatalf("CODEX_ACCESS_TOKEN = %q, want fresh", parsed["CODEX_ACCESS_TOKEN"])
|
||||
}
|
||||
if parsed["KEEP"] != "old" {
|
||||
t.Fatalf("KEEP = %q, want old", parsed["KEEP"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestDb_UpdateEnvVars_Concurrent(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
db := NewDb(dir)
|
||||
if err := db.SaveEnv("KEEP=old\n"); err != nil {
|
||||
t.Fatalf("SaveEnv() error = %v", err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
errs := make(chan error, 2)
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
errs <- db.UpdateEnvVars(map[string]string{"CODEX_ACCESS_TOKEN": "one"})
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
errs <- db.UpdateEnvVars(map[string]string{"CODEX_REFRESH_TOKEN": "two"})
|
||||
}()
|
||||
wg.Wait()
|
||||
close(errs)
|
||||
for err := range errs {
|
||||
if err != nil {
|
||||
t.Fatalf("UpdateEnvVars() error = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
parsed, err := godotenv.Read(db.EnvFilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("godotenv.Read() error = %v", err)
|
||||
}
|
||||
if parsed["KEEP"] != "old" {
|
||||
t.Fatalf("KEEP = %q, want old", parsed["KEEP"])
|
||||
}
|
||||
if parsed["CODEX_ACCESS_TOKEN"] != "one" {
|
||||
t.Fatalf("CODEX_ACCESS_TOKEN = %q, want one", parsed["CODEX_ACCESS_TOKEN"])
|
||||
}
|
||||
if parsed["CODEX_REFRESH_TOKEN"] != "two" {
|
||||
t.Fatalf("CODEX_REFRESH_TOKEN = %q, want two", parsed["CODEX_REFRESH_TOKEN"])
|
||||
}
|
||||
}
|
||||
|
||||
func assertEnvMode(t *testing.T, path string) {
|
||||
t.Helper()
|
||||
if runtime.GOOS == "windows" {
|
||||
return
|
||||
}
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
t.Fatalf("Stat(%s) error = %v", path, err)
|
||||
}
|
||||
if perm := info.Mode().Perm(); perm != 0600 {
|
||||
t.Fatalf("%s mode = %o, want 0600", filepath.Base(path), perm)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
22
internal/plugins/db/fsdb/env_lock_unix.go
Normal file
22
internal/plugins/db/fsdb/env_lock_unix.go
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//go:build unix
|
||||
|
||||
package fsdb
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func lockExclusive(f *os.File) error {
|
||||
err := unix.Flock(int(f.Fd()), unix.LOCK_EX)
|
||||
runtime.KeepAlive(f)
|
||||
return err
|
||||
}
|
||||
|
||||
func unlockExclusive(f *os.File) error {
|
||||
err := unix.Flock(int(f.Fd()), unix.LOCK_UN)
|
||||
runtime.KeepAlive(f)
|
||||
return err
|
||||
}
|
||||
19
internal/plugins/db/fsdb/env_lock_windows.go
Normal file
19
internal/plugins/db/fsdb/env_lock_windows.go
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
//go:build windows
|
||||
|
||||
package fsdb
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func lockExclusive(f *os.File) error {
|
||||
var overlapped windows.Overlapped
|
||||
return windows.LockFileEx(windows.Handle(f.Fd()), windows.LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &overlapped)
|
||||
}
|
||||
|
||||
func unlockExclusive(f *os.File) error {
|
||||
var overlapped windows.Overlapped
|
||||
return windows.UnlockFileEx(windows.Handle(f.Fd()), 0, 1, 0, &overlapped)
|
||||
}
|
||||
|
|
@ -5,8 +5,8 @@ schema = 3
|
|||
version = "v0.123.0"
|
||||
hash = "sha256-OjuvlqYrGvoUiXO/5ALbMxHvXRlrhDjLby1BN/nuhAw="
|
||||
[mod."cloud.google.com/go/auth"]
|
||||
version = "v0.22.0"
|
||||
hash = "sha256-EZmoz4OvycM9aIS1M3qexFo6ThMk0tESjdtq9mQytNQ="
|
||||
version = "v0.23.2"
|
||||
hash = "sha256-D28j2x5WFAg56/zTI9jGTH9MDUhteBo/RP1OKRKjB3s="
|
||||
[mod."cloud.google.com/go/auth/oauth2adapt"]
|
||||
version = "v0.2.8"
|
||||
hash = "sha256-GoXFqAbp1WO1tDj07PF5EyxDYvCBP0l0qwxY2oV2hfc="
|
||||
|
|
@ -17,8 +17,8 @@ schema = 3
|
|||
version = "v1.0.2"
|
||||
hash = "sha256-p6jdiHlLEfZES8vJnDywG4aVzIe16p0CU6iglglIweA="
|
||||
[mod."github.com/Azure/azure-sdk-for-go/sdk/azcore"]
|
||||
version = "v1.22.0"
|
||||
hash = "sha256-JhJgAeC3G0l+th1Xdu0Vf+FzWXTALHyb5FSIsKYTgBo="
|
||||
version = "v1.23.0"
|
||||
hash = "sha256-eOzqLjG50rNk/gZ264KPMNq0BaSuzH4saQBbvaWJpOQ="
|
||||
[mod."github.com/Azure/azure-sdk-for-go/sdk/azidentity"]
|
||||
version = "v1.14.0"
|
||||
hash = "sha256-oUoSbjql472sT24daGzICuBMEQLjpHXooGT83KtnUfc="
|
||||
|
|
@ -26,8 +26,8 @@ schema = 3
|
|||
version = "v1.12.0"
|
||||
hash = "sha256-jX/JR3WToz0vEWowfDBVjpul9EE2V2xGF1EfckrhDus="
|
||||
[mod."github.com/AzureAD/microsoft-authentication-library-for-go"]
|
||||
version = "v1.7.2"
|
||||
hash = "sha256-zB4M5bgMGDcjvF4GKu2t+NHTIHm9xQbsw9CUGT0tkk8="
|
||||
version = "v1.9.0"
|
||||
hash = "sha256-K29z7ruv8vG4PIz6O4DiXBenh/NAfySIrjb8ywl037A="
|
||||
[mod."github.com/KyleBanks/depth"]
|
||||
version = "v1.2.1"
|
||||
hash = "sha256-czR52MfeKA2FdStXCebTMQRKT8jaWQcbV214O3j49qU="
|
||||
|
|
@ -41,8 +41,8 @@ schema = 3
|
|||
version = "v1.3.4"
|
||||
hash = "sha256-CpXE/C+gW7V8MXREZguszzAQumizrCXGTdDRPBaflCs="
|
||||
[mod."github.com/anthropics/anthropic-sdk-go"]
|
||||
version = "v1.61.0"
|
||||
hash = "sha256-xAnuyZes72nZoanCzjjIbC22bcApU4mfVHGh3C1VhNg="
|
||||
version = "v1.67.0"
|
||||
hash = "sha256-mdEVuL2R8bhhrNAfAiHrvyew/cS0FTBtnsV/LFhC/LY="
|
||||
[mod."github.com/araddon/dateparse"]
|
||||
version = "v0.0.0-20210429162001-6b43995a97de"
|
||||
hash = "sha256-UuX84naeRGMsFOgIgRoBHG5sNy1CzBkWPKmd6VbLwFw="
|
||||
|
|
@ -50,77 +50,77 @@ schema = 3
|
|||
version = "v0.1.4"
|
||||
hash = "sha256-ZZ7U5X0gWOu8zcjZcWbcpzGOGdycwq0TjTFh/eZHjXk="
|
||||
[mod."github.com/aws/aws-sdk-go-v2"]
|
||||
version = "v1.43.0"
|
||||
hash = "sha256-4aQxyJbnh6Swz+VDlsdtnX2yup5ou56OwS8EYHddmJE="
|
||||
version = "v1.44.0"
|
||||
hash = "sha256-0GXyEXecrEAKw1FxElG7rTPyXns5MpgvtEJFO8PSh+0="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream"]
|
||||
version = "v1.7.14"
|
||||
hash = "sha256-EJ3UrrMG10cTJLL8hIZ1SFR8O6J9rpdicL7x4RSk5CY="
|
||||
version = "v1.7.20"
|
||||
hash = "sha256-ICB2yD83Gl628LRkg3HhYlDtsL4xgGhOmphZ5D0bJXI="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/config"]
|
||||
version = "v1.32.31"
|
||||
hash = "sha256-D2jpMMLn5AgkXpZbbpab3+thofD6xCScixtRF2K32LU="
|
||||
version = "v1.32.40"
|
||||
hash = "sha256-aCTxFSDt/1hSgFSAAwHQzjSrOcSDg0lAt1ely0Eb6X4="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/credentials"]
|
||||
version = "v1.19.30"
|
||||
hash = "sha256-SoO465t2X7w3o7hGy88N1Zy6AEcG/LiFZ7xnPUmt7Jw="
|
||||
version = "v1.19.39"
|
||||
hash = "sha256-zPAy8z+s46o9En+df+FhYQCNNP58S+VLGAWyBIMHx5k="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/feature/ec2/imds"]
|
||||
version = "v1.18.31"
|
||||
hash = "sha256-6X1A4Cz7j40SaSUzS3u+QRbBzmHHZmValGBJeSHMQUo="
|
||||
version = "v1.18.40"
|
||||
hash = "sha256-LXOaz48PXTgjwbFYQ9cUc1Y9cmPODypl6SpZz9GLHZg="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/internal/configsources"]
|
||||
version = "v1.4.31"
|
||||
hash = "sha256-xv5BgkSZbTJwgDN8mtUCg3Q6Ac0S/IdPZW1tTrEsGgY="
|
||||
version = "v1.4.40"
|
||||
hash = "sha256-1EmqriwNg/7JCqpj7vnGB2oHgMrm/EgkLlGMhBTNh3k="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/internal/endpoints/v2"]
|
||||
version = "v2.7.31"
|
||||
hash = "sha256-dvD/UE5fVVxOb668bZNg5hM6H9F4foclI5HbD+b7Dks="
|
||||
version = "v2.7.40"
|
||||
hash = "sha256-XnMvLK1GmJcPNLov91EBKh+xpwIRk6DqlzXiI+epyd8="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/internal/v4a"]
|
||||
version = "v1.4.32"
|
||||
hash = "sha256-EovofAvyGZoaQsNwXl2F6Uc0+jNwRYV8At6if3Ki/z8="
|
||||
version = "v1.4.41"
|
||||
hash = "sha256-tgerq8bZzDemsJsVdBzHCEm/S2TyPpdSmG+uwCd9XJ0="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/service/bedrock"]
|
||||
version = "v1.66.0"
|
||||
hash = "sha256-xlv9OA8FmWK8Y1NuL9sarAvRQWP6iK0Vr/CsCkOCe2E="
|
||||
version = "v1.68.0"
|
||||
hash = "sha256-NKNT8mKBH3TDrCzH4WD1ukHEp+9tzojxrxpLXajiZ/8="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/service/bedrockruntime"]
|
||||
version = "v1.56.0"
|
||||
hash = "sha256-fNMQSKKnVasKUyEybcBlkP7/vCDM+cvyAgYhFwZ6Dyw="
|
||||
version = "v1.58.0"
|
||||
hash = "sha256-1vapY7IXJvcsWEn4rDaI8nSIfPCmuDHZPD9gP0DYHYA="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding"]
|
||||
version = "v1.13.13"
|
||||
hash = "sha256-C0L0B5qRP8IhX02Wz/wttNtOkI6xrI9VHQr/FiTCUsc="
|
||||
version = "v1.13.19"
|
||||
hash = "sha256-LfifyqFh49PPH0asF1TJz3QJYHTwxQttthUD5p4z2YM="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/service/internal/presigned-url"]
|
||||
version = "v1.13.31"
|
||||
hash = "sha256-43rStuRFoLjAAz/arhzCNsyxkX1DAlnQiKFbGv6AXSA="
|
||||
version = "v1.13.40"
|
||||
hash = "sha256-l88t3s/MssSelRkyukz4fYSs7mZCOvfCeNrsfzdyKuI="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/service/signin"]
|
||||
version = "v1.5.0"
|
||||
hash = "sha256-zty6NW++dIHGZiy4rBCkDLZVfDf9FSc1ouMeaUI42sc="
|
||||
version = "v1.6.0"
|
||||
hash = "sha256-NxIbOpqkwWKLSlZJx/dRoNMQ0QDh6jolC8xKJTxxo9A="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/service/sso"]
|
||||
version = "v1.33.0"
|
||||
hash = "sha256-1IpQJTXInKuQUXIX6pwxiMgwzJx9tO/n9ZEHn5vrkP0="
|
||||
version = "v1.34.0"
|
||||
hash = "sha256-yRdflsmsXNXki2xJLEtQur6Dpbb9N3beLdXD5Vu2Ss0="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/service/ssooidc"]
|
||||
version = "v1.38.0"
|
||||
hash = "sha256-FYqk0nJsW9FEMSjq9Rl9lOKtXvJ9AHAvsH0AZSohKbY="
|
||||
version = "v1.39.0"
|
||||
hash = "sha256-XGRs+nBRUfxyuCbDJ7QnV738UPMm2nSbxbLtK19hqY0="
|
||||
[mod."github.com/aws/aws-sdk-go-v2/service/sts"]
|
||||
version = "v1.45.0"
|
||||
hash = "sha256-5CuJRPHxwORAl/YYeLFW9JSlT4J1AqDUaOSfqxG6vgE="
|
||||
version = "v1.46.0"
|
||||
hash = "sha256-7j2UmV1FHIcJ/K+iUhGGO2Q+dhuoHlOxR1TuCf4M68Y="
|
||||
[mod."github.com/aws/smithy-go"]
|
||||
version = "v1.27.4"
|
||||
hash = "sha256-V4BvRCkpbkBbFRKyxV+hGDPDKUd1nZYcr+WQ09GqC/k="
|
||||
version = "v1.28.1"
|
||||
hash = "sha256-52wJGnuZVxhZtqgp4Gf7mgYrK6DOL8hFgtjo8e1NlCA="
|
||||
[mod."github.com/bahlo/generic-list-go"]
|
||||
version = "v0.2.0"
|
||||
hash = "sha256-BIzqwG61hnMDknZOn/5+VX09yemzFzMjhPF48XoALto="
|
||||
[mod."github.com/buger/jsonparser"]
|
||||
version = "v1.2.0"
|
||||
hash = "sha256-CiwV8UFYw2PnnyUoRojiVLq+MlKJ/aviufLcRi1GLbw="
|
||||
version = "v1.6.1"
|
||||
hash = "sha256-barqoLEuh2FBMNG4kIjK3oRs8Izq4eVotpbzHPliqXc="
|
||||
[mod."github.com/bytedance/gopkg"]
|
||||
version = "v0.1.4"
|
||||
hash = "sha256-GpfG8K5YTWAt5MRg7RvpcemU7jfPV0A+mMbxSfA+2ws="
|
||||
[mod."github.com/bytedance/sonic"]
|
||||
version = "v1.15.2"
|
||||
hash = "sha256-FVhsfwSb5q7MzdVuPtElecrz8E62DJVfG2YI4mScuzk="
|
||||
version = "v1.15.3"
|
||||
hash = "sha256-/LTRsTbgpQPLEMX7CRIMxi/Unh9VAyys6QuALGWwgMc="
|
||||
[mod."github.com/bytedance/sonic/loader"]
|
||||
version = "v0.5.1"
|
||||
hash = "sha256-fbUguA0wNj+aggu3oHaEzkduQVO4oawcvjohfgUmha8="
|
||||
version = "v0.5.2"
|
||||
hash = "sha256-tsrtIbjYXZadwLzlL3ZmC4DEytwmT1tvPDQT/nwNb20="
|
||||
[mod."github.com/cespare/xxhash/v2"]
|
||||
version = "v2.3.0"
|
||||
hash = "sha256-7hRlwSR+fos1kx4VZmJ/7snR7zHh8ZFKX+qqqqGcQpY="
|
||||
[mod."github.com/cloudflare/circl"]
|
||||
version = "v1.6.4"
|
||||
hash = "sha256-HfbrlhDNcQ7shn2dBzUrXJRtRPMShjo+HiqquEwzByI="
|
||||
version = "v1.6.5"
|
||||
hash = "sha256-nrD+9cNt6xEohb0EA2bZCuSM03GXYPg/YMD0Y+HF8WU="
|
||||
[mod."github.com/cloudwego/base64x"]
|
||||
version = "v0.1.7"
|
||||
hash = "sha256-zhZGPCTM8HiLALQfaE/L7B0IwbXZxClDVLCFt5zbusE="
|
||||
|
|
@ -155,8 +155,8 @@ schema = 3
|
|||
version = "v5.9.1"
|
||||
hash = "sha256-VW8mfdLjvAuiooR2WV7P0IoOosAvtDZvFWcGQJJVSSY="
|
||||
[mod."github.com/go-git/go-git/v5"]
|
||||
version = "v5.19.1"
|
||||
hash = "sha256-C0e3oOXYRgLUhm1TQk9mBwRwwj6iusxFAt5U9vqWz8A="
|
||||
version = "v5.19.2"
|
||||
hash = "sha256-2du2hn5JDTEEYTWuGX+heSftkmd7HoaJXyWJG4bZeSM="
|
||||
[mod."github.com/go-logr/logr"]
|
||||
version = "v1.4.4"
|
||||
hash = "sha256-q9HX9aelONTLsywyLY4Wc5UYCK+wG0FbSzFWisCYiIA="
|
||||
|
|
@ -167,32 +167,32 @@ schema = 3
|
|||
version = "v1.0.0"
|
||||
hash = "sha256-he4+Ue27HuNS0imS55XaS4g54v2OrKFJppdhz8cO94s="
|
||||
[mod."github.com/go-openapi/jsonreference"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-+UaHDX6kNBxmhH6N2BE22KyXISiEvxPyTpJF5i6l+GE="
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-UMGGlJPWjL7SoeLd51PLyYnUuQMz1Jx41MuULCwQUp4="
|
||||
[mod."github.com/go-openapi/spec"]
|
||||
version = "v0.22.9"
|
||||
hash = "sha256-TJBuxXaAct9XElR6juOEa5jNSuiLNoMrWNscr3ygsEk="
|
||||
version = "v0.22.11"
|
||||
hash = "sha256-QmZOssbAZDUKdk/hZUmOxDYIa4u2VCIGm6E8/gY1y4Y="
|
||||
[mod."github.com/go-openapi/swag/conv"]
|
||||
version = "v0.27.3"
|
||||
hash = "sha256-8IoLDL3UsjWefUgvndFTevdeJhKhN1Qi8cm3j8NpH9U="
|
||||
version = "v0.29.1"
|
||||
hash = "sha256-hOh54OqE1yVfy5O2FRuHZZKejpUk26eM8qzB0ndoJhM="
|
||||
[mod."github.com/go-openapi/swag/jsonutils"]
|
||||
version = "v0.27.3"
|
||||
hash = "sha256-kksIySYFFusCXd+Iua+G2IjEfb+I1xCXlv7YH4E1/8o="
|
||||
version = "v0.29.1"
|
||||
hash = "sha256-Yj1UfqLEwJA5PWQTs3EbcohqxlknhFFwkYJXoO/Y6c0="
|
||||
[mod."github.com/go-openapi/swag/loading"]
|
||||
version = "v0.27.3"
|
||||
hash = "sha256-HPIc1YHoh06K1OExI6NnqsOKx5L+CzArTfXanTSYABk="
|
||||
version = "v0.29.1"
|
||||
hash = "sha256-ig2w4q11AOWerFTVN6a2MdZ4mKiFXWkeiTCDuWFwUxY="
|
||||
[mod."github.com/go-openapi/swag/pools"]
|
||||
version = "v0.27.3"
|
||||
hash = "sha256-v6e+U41LGxzT1aT4KV6PQvowY3N0Y6Z2zCItIpAuoG0="
|
||||
version = "v0.29.1"
|
||||
hash = "sha256-NhaFtD29d759M/H5AiYiHAxn6s4bkfYW63B7xFpkGvA="
|
||||
[mod."github.com/go-openapi/swag/stringutils"]
|
||||
version = "v0.27.3"
|
||||
hash = "sha256-QnCMIHYGwrMMzZBRFz3zvOoQWPgzToMIMRCfujww8Vw="
|
||||
version = "v0.29.1"
|
||||
hash = "sha256-VLkfHTvfO+yU6VMNdzSp3rb2v/A4OqpScBHq77GoOA8="
|
||||
[mod."github.com/go-openapi/swag/typeutils"]
|
||||
version = "v0.27.3"
|
||||
hash = "sha256-7DkJz+zFA2Zu6iIkoExf2H3gKKRg47KfzGE2aSXiehs="
|
||||
version = "v0.29.1"
|
||||
hash = "sha256-xsKC/xVt7LdZIHOv+h5KwJEULyebSFPTghUj1LC04uQ="
|
||||
[mod."github.com/go-openapi/swag/yamlutils"]
|
||||
version = "v0.27.3"
|
||||
hash = "sha256-dDH3tA5gTeifnUgq595ERiwWxyaoOpLpXsziXNxmC9U="
|
||||
version = "v0.29.1"
|
||||
hash = "sha256-nrru5csGEKnr+ff28sVdkJNubhjbLwY8cPp9JqSl1DE="
|
||||
[mod."github.com/go-playground/locales"]
|
||||
version = "v0.14.1"
|
||||
hash = "sha256-BMJGAexq96waZn60DJXZfByRHb8zA/JP/i6f/YrW9oQ="
|
||||
|
|
@ -239,11 +239,11 @@ schema = 3
|
|||
version = "v1.6.0"
|
||||
hash = "sha256-VWl9sqUzdOuhW0KzQlv0gwwUQClYkmZwSydHG2sALYw="
|
||||
[mod."github.com/googleapis/enterprise-certificate-proxy"]
|
||||
version = "v0.3.19"
|
||||
hash = "sha256-I9lw9E0WvndUTWiwOlBQv6ySF6/+SS/cXeGLJnPlri4="
|
||||
version = "v0.3.21"
|
||||
hash = "sha256-h8t4jzU7hRY/KaSI51xAkxX2934i5k6XVvpuNPef4iE="
|
||||
[mod."github.com/googleapis/gax-go/v2"]
|
||||
version = "v2.23.0"
|
||||
hash = "sha256-aIJepJZI5PCsc9eteAP9x+n4RSSyOWi4kPnI5mmrBXk="
|
||||
version = "v2.24.0"
|
||||
hash = "sha256-uDcY93yvQS3wDkhM85bAxSo67Z+cWlwR1Vnv9hZRa5o="
|
||||
[mod."github.com/gorilla/websocket"]
|
||||
version = "v1.5.3"
|
||||
hash = "sha256-vTIGEFMEi+30ZdO6ffMNJ/kId6pZs5bbyqov8xe9BM0="
|
||||
|
|
@ -290,8 +290,8 @@ schema = 3
|
|||
version = "v0.0.24"
|
||||
hash = "sha256-pmq8KKIb2+qMF3E1cR2B7NAj5joF2tZduyXjIfIlkTk="
|
||||
[mod."github.com/mattn/go-sqlite3"]
|
||||
version = "v1.14.48"
|
||||
hash = "sha256-a2Cs9fotWnjY+9WaOnrHk6LbbP4idOHo//tAAlc6naI="
|
||||
version = "v1.14.50"
|
||||
hash = "sha256-olsWcNOIhMP67ZfuYvxxe3AHvyynAUmJ6WbDXfc1VbE="
|
||||
[mod."github.com/modern-go/concurrent"]
|
||||
version = "v0.0.0-20180306012644-bacd9c7ef1dd"
|
||||
hash = "sha256-OTySieAgPWR4oJnlohaFTeK1tRaVp/b0d1rYY8xKMzo="
|
||||
|
|
@ -302,8 +302,8 @@ schema = 3
|
|||
version = "v2.6.1"
|
||||
hash = "sha256-ag/8GBAwqkOyIVrdlaFYLxy9dgPOq7VbactrLmzxK7E="
|
||||
[mod."github.com/ollama/ollama"]
|
||||
version = "v0.32.3"
|
||||
hash = "sha256-giQRZODIilkGdEtyrzTMkBI1cUXMpVSZorv06U9aVA4="
|
||||
version = "v0.33.1"
|
||||
hash = "sha256-E297N5FElu4OEDM75FHekPr/fyxMpu+7M3GS3Robals="
|
||||
[mod."github.com/openai/openai-go"]
|
||||
version = "v1.12.0"
|
||||
hash = "sha256-JHLlKvDwERPf728GUXBsKU58ODgCxcxEe9TKJTGAG1w="
|
||||
|
|
@ -359,8 +359,8 @@ schema = 3
|
|||
version = "v0.0.1"
|
||||
hash = "sha256-ORbb8w6VS4Yw0vsPhVzAqCCUYyaMOPcQyyP4DBZgLzM="
|
||||
[mod."github.com/stretchr/testify"]
|
||||
version = "v1.11.1"
|
||||
hash = "sha256-sWfjkuKJyDllDEtnM8sb/pdLzPQmUYWYtmeWz/5suUc="
|
||||
version = "v1.12.1"
|
||||
hash = "sha256-9MTDdVjZMh1MJ5EH3HmAFrm24YqZayeMBgKwtaURZCc="
|
||||
[mod."github.com/swaggo/files"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-bNBmpJaM7g1BNwd7VxNIRSdY35NKSXhYHGfnZsSEUZ8="
|
||||
|
|
@ -386,8 +386,8 @@ schema = 3
|
|||
version = "v0.15.1"
|
||||
hash = "sha256-HLk6oUe7EoITrNvP0y8D6BtIgIcmDZYtb/xl/dufIoY="
|
||||
[mod."github.com/ugorji/go/codec"]
|
||||
version = "v1.3.1"
|
||||
hash = "sha256-VQtXVaKxXjm5Q60hCgVKZxNywl6SJFPqju6JNjADp4w="
|
||||
version = "v1.3.2"
|
||||
hash = "sha256-/W4sowusGHO1Fb4mlqNQlfqgl278E0BqgMUzexkzWVw="
|
||||
[mod."github.com/wk8/go-ordered-map/v2"]
|
||||
version = "v2.1.8"
|
||||
hash = "sha256-v7/5+7lAypZfgClXgWxhxtA1skQq9o+1yrI+V0o1j2o="
|
||||
|
|
@ -395,44 +395,44 @@ schema = 3
|
|||
version = "v0.3.3"
|
||||
hash = "sha256-l3pGB6IdzcPA/HLk93sSN6NM2pKPy+bVOoacR5RC2+c="
|
||||
[mod."go.mongodb.org/mongo-driver/v2"]
|
||||
version = "v2.8.0"
|
||||
hash = "sha256-VaSRntfFY0SBfIPmhFVY0jPNlv0pYp8ivwdOoeLTeIs="
|
||||
version = "v2.8.2"
|
||||
hash = "sha256-1syL133Npfw250xMeOfEhExvEYFU7GTnWsdHCOOmNuA="
|
||||
[mod."go.opentelemetry.io/auto/sdk"]
|
||||
version = "v1.2.1"
|
||||
hash = "sha256-73bFYhnxNf4SfeQ52ebnwOWywdQbqc9lWawCcSgofvE="
|
||||
[mod."go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"]
|
||||
version = "v0.69.0"
|
||||
hash = "sha256-37oe5RsiBWxaOs7lZXJWEUN4P49jkr2ej+64FQ4ybT8="
|
||||
version = "v0.71.0"
|
||||
hash = "sha256-2vwtDspRM7jZyvxclBmKTCDZ31qw/TiG+HHI6Z8ub2s="
|
||||
[mod."go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"]
|
||||
version = "v0.69.0"
|
||||
hash = "sha256-ypZB41ebghWCNZmuoDgdGbWyTjCglBEirLZ+s7jqCgc="
|
||||
version = "v0.71.0"
|
||||
hash = "sha256-E5YtRLrs1/LqpvPt6LzC+sDpmxSROgpNmgca5s6iyCg="
|
||||
[mod."go.opentelemetry.io/otel"]
|
||||
version = "v1.44.0"
|
||||
hash = "sha256-XTGV9RjOIKyWrrgXJ32IA59lovxXqSeRrpcpC1FAFZA="
|
||||
version = "v1.46.0"
|
||||
hash = "sha256-2+xTacXn22hsJuMGGgXwazMbP/ZW5gkPRnf+rNUZgvQ="
|
||||
[mod."go.opentelemetry.io/otel/metric"]
|
||||
version = "v1.44.0"
|
||||
hash = "sha256-e8dVyRoavby/YG7aH2T05IhWHlLvwnMHyPhelAS1mCQ="
|
||||
version = "v1.46.0"
|
||||
hash = "sha256-cY1DXXzRfcP0kKh7oBzowbu6kbFr3jANiEVyMlD5Bt8="
|
||||
[mod."go.opentelemetry.io/otel/trace"]
|
||||
version = "v1.44.0"
|
||||
hash = "sha256-69HorWRTLLzAHRgLe4nPp13qJthb3qp7RU7c0Y9qV/c="
|
||||
version = "v1.46.0"
|
||||
hash = "sha256-zfj85gCR5Z3v1N+8nlOO+6+FVShaL/7Vb/3lXjdXnnw="
|
||||
[mod."go.yaml.in/yaml/v3"]
|
||||
version = "v3.0.4"
|
||||
hash = "sha256-NkGFiDPoCxbr3LFsI6OCygjjkY0rdmg5ggvVVwpyDQ4="
|
||||
version = "v3.0.5"
|
||||
hash = "sha256-ygho+GU5kE7vPMx+dZYyNfCaeMjNxj66XmrcVf3afFE="
|
||||
[mod."go.yaml.in/yaml/v4"]
|
||||
version = "v4.0.0-rc.6"
|
||||
hash = "sha256-9aOIQpQ53KLv/Hb14104qYKLVrZUcCGLwzYp6UGLP90="
|
||||
[mod."golang.org/x/arch"]
|
||||
version = "v0.29.0"
|
||||
hash = "sha256-CqC8aNJdS0Qtr31j2ao9hTQJk8KRfcHDL7/HL3mbD4g="
|
||||
version = "v0.30.0"
|
||||
hash = "sha256-od8lOmP+IOtiO7s1VaFVMBCQfRmtXT8jqe7Yo077xDs="
|
||||
[mod."golang.org/x/crypto"]
|
||||
version = "v0.54.0"
|
||||
hash = "sha256-m8jsqlPuoPxGDjClzcAVbXf1aiU07L+9j7vYcqJu/0Q="
|
||||
version = "v0.55.0"
|
||||
hash = "sha256-99uV/ESeqhaDEwqbXxDpePuwzO0JoEHGhqZXZVHq/H4="
|
||||
[mod."golang.org/x/mod"]
|
||||
version = "v0.38.0"
|
||||
hash = "sha256-BpKfvsmb7ecEDvTBKx9ZHauxoWRkOAZCqg4BrHM2/S0="
|
||||
version = "v0.40.0"
|
||||
hash = "sha256-gmuKtxidzYWVlQYNB/8BREmajyfockaQ5/6Xk4IR32A="
|
||||
[mod."golang.org/x/net"]
|
||||
version = "v0.57.0"
|
||||
hash = "sha256-gKo8UMw4hfETBHm8N5GOfuNadse9TWEQXJo2YWq5bY4="
|
||||
version = "v0.58.0"
|
||||
hash = "sha256-fDOkQJXURrbq2dBGa91bCUsXknCZlo3ru2JIofSOGRo="
|
||||
[mod."golang.org/x/oauth2"]
|
||||
version = "v0.36.0"
|
||||
hash = "sha256-evS7WkMrpgonmTcqtWFpC5rSKZN8O+vnAhNUs1MS9kw="
|
||||
|
|
@ -443,29 +443,29 @@ schema = 3
|
|||
version = "v0.47.0"
|
||||
hash = "sha256-TpbRyWWqHjddP6QzUgAbaLd2EE0S+GYNRUIDJd18r98="
|
||||
[mod."golang.org/x/text"]
|
||||
version = "v0.40.0"
|
||||
hash = "sha256-LJfnki46XEreGbSgjl+DeqgcTsINTOu2owyXNvijMcA="
|
||||
version = "v0.41.0"
|
||||
hash = "sha256-22nHcolG87qSPahT2Ey8S5iGlCLAglE9ObYXO6XZ3ZY="
|
||||
[mod."golang.org/x/time"]
|
||||
version = "v0.15.0"
|
||||
hash = "sha256-5D24A65wn7k93Jj3+918UKjB9ccmGHPBEqjD2XDB92E="
|
||||
[mod."golang.org/x/tools"]
|
||||
version = "v0.48.0"
|
||||
hash = "sha256-9cRNUaup6fexA5S1zc+Ic3aaoxAgKWntyMJ2xaOdiP8="
|
||||
version = "v0.49.0"
|
||||
hash = "sha256-3oaXp2PlfuIn6/UTarnYD279YqJKTyaCWT/KD7ABjD4="
|
||||
[mod."google.golang.org/api"]
|
||||
version = "v0.290.0"
|
||||
hash = "sha256-qqNG4ExSaHNa9iRHq/F4JXqdnegRrWFx8oMKEEMgApA="
|
||||
version = "v0.294.0"
|
||||
hash = "sha256-fSc8hIUo3a92Rf7CmI3D+gL5Vk33e5alr8EIIR613bc="
|
||||
[mod."google.golang.org/genai"]
|
||||
version = "v1.65.0"
|
||||
hash = "sha256-PtEwnslN9VBUur0fNwXLBryOzvw2zkHfHSlb0v/z+DQ="
|
||||
version = "v1.70.0"
|
||||
hash = "sha256-T0jXx52Hc3aOROPpX66RGhZs0FrRg5Bhqm3WyR1zjkM="
|
||||
[mod."google.golang.org/genproto/googleapis/rpc"]
|
||||
version = "v0.0.0-20260724162435-b2f20204f0df"
|
||||
hash = "sha256-ldJTTb7hhj1mdmzTn9IEkQVwCoj3KRlENZtUSEKHABU="
|
||||
version = "v0.0.0-20260825221802-da73d73af1c5"
|
||||
hash = "sha256-CQdjYGIrgAnEDfWW3DIJF9Orf7oJdhx3G9rGg6fow88="
|
||||
[mod."google.golang.org/grpc"]
|
||||
version = "v1.82.1"
|
||||
hash = "sha256-5Q85pZWiKulJSGRAjYcVrlBe7y4tfa9gsjCqYiBhLUU="
|
||||
version = "v1.83.2"
|
||||
hash = "sha256-q5VtdeJvWM7kbIvui8ncNV/+Rm+d0y/b6XkNN0/u1is="
|
||||
[mod."google.golang.org/protobuf"]
|
||||
version = "v1.36.11"
|
||||
hash = "sha256-7W+6jntfI/awWL3JP6yQedxqP5S9o3XvPgJ2XxxsIeE="
|
||||
version = "v1.36.12"
|
||||
hash = "sha256-MKd0AdkWEe2A79mGPzOY5I76nMqTsGJKQNPJOKyOwkQ="
|
||||
[mod."gopkg.in/warnings.v0"]
|
||||
version = "v0.1.2"
|
||||
hash = "sha256-ATVL9yEmgYbkJ1DkltDGRn/auGAjqGOfjQyBYyUo8s8="
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
"1.4.470"
|
||||
"1.4.471"
|
||||
|
|
|
|||
Loading…
Reference in a new issue