Merge pull request #1508 from trheyi/main
refactor(tests): rename and consolidate input building functions for clarity
This commit is contained in:
commit
112d307cc2
7 changed files with 287 additions and 177 deletions
|
|
@ -72,7 +72,7 @@ func (r *ClaudeRunner) buildCommand(ctx context.Context, req *types.StreamReques
|
|||
|
||||
env := buildEnv(req, p)
|
||||
args := buildArgs(req, r, p, isContinuation, assistantID, chatID)
|
||||
inputJSONL := buildInput(req.Messages, isContinuation)
|
||||
inputJSONL := buildLastUserMessageJSONL(req.Messages)
|
||||
|
||||
var systemPrompt string
|
||||
envPrompt := buildSandboxEnvPrompt(p, workDir)
|
||||
|
|
@ -236,13 +236,6 @@ func buildArgs(req *types.StreamRequest, r *ClaudeRunner, p platform, isContinua
|
|||
return args
|
||||
}
|
||||
|
||||
func buildInput(messages []agentContext.Message, isContinuation bool) string {
|
||||
if isContinuation {
|
||||
return buildLastUserMessageJSONL(messages)
|
||||
}
|
||||
return buildFirstRequestJSONL(messages)
|
||||
}
|
||||
|
||||
func buildSandboxEnvPrompt(p platform, workDir string) string {
|
||||
osName := p.OS()
|
||||
if osName == "" {
|
||||
|
|
@ -323,32 +316,6 @@ func buildMCPAllowedTools(servers []types.MCPServer) string {
|
|||
return strings.Join(patterns, ",")
|
||||
}
|
||||
|
||||
// buildFirstRequestJSONL builds the input JSONL for a new (non-continuation)
|
||||
// Claude CLI session. Per the stream-json input protocol, only user messages
|
||||
// should be sent; Claude CLI manages its own assistant history internally.
|
||||
func buildFirstRequestJSONL(messages []agentContext.Message) string {
|
||||
var lines []string
|
||||
for _, msg := range messages {
|
||||
if msg.Role != "user" {
|
||||
continue
|
||||
}
|
||||
content := msg.Content
|
||||
if content == nil {
|
||||
content = ""
|
||||
}
|
||||
streamMsg := map[string]any{
|
||||
"type": "user",
|
||||
"message": map[string]any{
|
||||
"role": "user",
|
||||
"content": content,
|
||||
},
|
||||
}
|
||||
data, _ := json.Marshal(streamMsg)
|
||||
lines = append(lines, string(data))
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
func buildLastUserMessageJSONL(messages []agentContext.Message) string {
|
||||
for i := len(messages) - 1; i >= 0; i-- {
|
||||
if messages[i].Role == "user" {
|
||||
|
|
|
|||
|
|
@ -170,86 +170,43 @@ func TestBuildArgs_WhitelistOptions(t *testing.T) {
|
|||
assert.Contains(t, args, "--max-turns")
|
||||
}
|
||||
|
||||
// --- buildInput ---
|
||||
// --- buildLastUserMessageJSONL (was buildInput / buildFirstRequestJSONL) ---
|
||||
|
||||
func TestBuildInput_FirstRequest(t *testing.T) {
|
||||
msgs := []agentContext.Message{
|
||||
{Role: "user", Content: "hello"},
|
||||
{Role: "assistant", Content: "hi"},
|
||||
}
|
||||
result := buildInput(msgs, false)
|
||||
lines := strings.Split(strings.TrimSpace(result), "\n")
|
||||
assert.Len(t, lines, 1, "first request only includes user messages")
|
||||
assert.Contains(t, lines[0], "hello")
|
||||
assert.NotContains(t, result, "hi")
|
||||
}
|
||||
|
||||
func TestBuildInput_Continuation(t *testing.T) {
|
||||
msgs := []agentContext.Message{
|
||||
{Role: "user", Content: "first question"},
|
||||
{Role: "assistant", Content: "first answer"},
|
||||
{Role: "user", Content: "follow up"},
|
||||
}
|
||||
result := buildInput(msgs, true)
|
||||
var parsed map[string]any
|
||||
err := json.Unmarshal([]byte(result), &parsed)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "user", parsed["type"])
|
||||
msg, _ := parsed["message"].(map[string]any)
|
||||
assert.Equal(t, "follow up", msg["content"])
|
||||
}
|
||||
|
||||
// --- buildFirstRequestJSONL ---
|
||||
|
||||
func TestBuildFirstRequestJSONL_SkipsSystem(t *testing.T) {
|
||||
func TestBuildLastUserMessageJSONL_SkipsSystem(t *testing.T) {
|
||||
msgs := []agentContext.Message{
|
||||
{Role: "system", Content: "system prompt"},
|
||||
{Role: "user", Content: "hello"},
|
||||
}
|
||||
result := buildFirstRequestJSONL(msgs)
|
||||
lines := strings.Split(strings.TrimSpace(result), "\n")
|
||||
assert.Len(t, lines, 1, "system messages should be skipped")
|
||||
assert.Contains(t, lines[0], "hello")
|
||||
result := buildLastUserMessageJSONL(msgs)
|
||||
var parsed map[string]any
|
||||
err := json.Unmarshal([]byte(strings.TrimSpace(result)), &parsed)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "user", parsed["type"])
|
||||
msg, _ := parsed["message"].(map[string]any)
|
||||
assert.Equal(t, "hello", msg["content"])
|
||||
}
|
||||
|
||||
func TestBuildFirstRequestJSONL_OnlyUserMessages(t *testing.T) {
|
||||
func TestBuildLastUserMessageJSONL_OnlyLastUser(t *testing.T) {
|
||||
msgs := []agentContext.Message{
|
||||
{Role: "user", Content: "q1"},
|
||||
{Role: "assistant", Content: "a1"},
|
||||
{Role: "user", Content: "q2"},
|
||||
}
|
||||
result := buildFirstRequestJSONL(msgs)
|
||||
lines := strings.Split(strings.TrimSpace(result), "\n")
|
||||
assert.Len(t, lines, 2, "only user messages should be included")
|
||||
for _, line := range lines {
|
||||
var parsed map[string]any
|
||||
err := json.Unmarshal([]byte(line), &parsed)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "user", parsed["type"])
|
||||
msg, _ := parsed["message"].(map[string]any)
|
||||
assert.Equal(t, "user", msg["role"])
|
||||
}
|
||||
result := buildLastUserMessageJSONL(msgs)
|
||||
var parsed map[string]any
|
||||
err := json.Unmarshal([]byte(strings.TrimSpace(result)), &parsed)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "user", parsed["type"])
|
||||
msg, _ := parsed["message"].(map[string]any)
|
||||
assert.Equal(t, "q2", msg["content"])
|
||||
assert.NotContains(t, result, "q1")
|
||||
}
|
||||
|
||||
func TestBuildFirstRequestJSONL_AssistantOnlyMessages(t *testing.T) {
|
||||
msgs := []agentContext.Message{
|
||||
{Role: "assistant", Content: "a1"},
|
||||
{Role: "assistant", Content: "a2"},
|
||||
{Role: "assistant", Content: "a3"},
|
||||
{Role: "user", Content: "q1"},
|
||||
}
|
||||
result := buildFirstRequestJSONL(msgs)
|
||||
lines := strings.Split(strings.TrimSpace(result), "\n")
|
||||
assert.Len(t, lines, 1, "only the user message should be included")
|
||||
assert.Contains(t, lines[0], "q1")
|
||||
assert.NotContains(t, result, "a1")
|
||||
}
|
||||
|
||||
func TestBuildFirstRequestJSONL_NilContent(t *testing.T) {
|
||||
func TestBuildLastUserMessageJSONL_NilContent(t *testing.T) {
|
||||
msgs := []agentContext.Message{
|
||||
{Role: "user", Content: nil},
|
||||
}
|
||||
result := buildFirstRequestJSONL(msgs)
|
||||
result := buildLastUserMessageJSONL(msgs)
|
||||
var parsed map[string]any
|
||||
err := json.Unmarshal([]byte(strings.TrimSpace(result)), &parsed)
|
||||
require.NoError(t, err)
|
||||
|
|
|
|||
|
|
@ -58,10 +58,16 @@ var langs = map[string]string{
|
|||
"Force migrate": "强制更新数据表结构",
|
||||
"Migrate is not allowed on production mode.": "Migrate 不能再生产环境下使用",
|
||||
"Upgrade yao to latest version": "升级 yao 到最新版本",
|
||||
"Current version:": "当前版本:",
|
||||
"Latest version: ": "最新版本: ",
|
||||
"Checking latest version...": "正在检查最新版本...",
|
||||
"🎉Current version is the latest🎉": "🎉当前版本是最新的🎉",
|
||||
"Do you want to update to %s ? (y/n): ": "是否更新到 %s ? (y/n): ",
|
||||
"Invalid input": "输入错误",
|
||||
"Canceled upgrade": "已取消更新",
|
||||
"Downloading...": "正在下载...",
|
||||
"Progress:": "进度:",
|
||||
"Available assets:": "可用的制品:",
|
||||
"Error occurred while updating binary: %s": "更新二进制文件时出错: %s",
|
||||
"🎉Successfully updated to version: %s🎉": "🎉成功更新到版本: %s🎉",
|
||||
"Print all version information": "显示详细版本信息",
|
||||
|
|
@ -201,7 +207,7 @@ func init() {
|
|||
agentCmd,
|
||||
mcpCmd,
|
||||
robotCmd,
|
||||
// upgradeCmd,
|
||||
upgradeCmd,
|
||||
)
|
||||
// rootCmd.SetHelpCommand(helpCmd)
|
||||
rootCmd.PersistentFlags().StringVarP(&appPath, "app", "a", "", L("Application directory"))
|
||||
|
|
|
|||
240
cmd/upgrade.go
240
cmd/upgrade.go
|
|
@ -2,57 +2,257 @@ package cmd
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/fatih/color"
|
||||
"github.com/rhysd/go-github-selfupdate/selfupdate"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
const githubReleasesAPI = "https://api.github.com/repos/YaoApp/yao/releases/latest"
|
||||
|
||||
// githubRelease represents a GitHub release response
|
||||
type githubRelease struct {
|
||||
TagName string `json:"tag_name"`
|
||||
Name string `json:"name"`
|
||||
Prerelease bool `json:"prerelease"`
|
||||
Assets []githubAsset `json:"assets"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
// githubAsset represents a single release asset
|
||||
type githubAsset struct {
|
||||
Name string `json:"name"`
|
||||
BrowserDownloadURL string `json:"browser_download_url"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
var upgradeCmd = &cobra.Command{
|
||||
Use: "upgrade",
|
||||
Short: L("Upgrade yao app to latest version"),
|
||||
Long: L("Upgrade yao app to latest version"),
|
||||
Short: L("Upgrade yao to latest version"),
|
||||
Long: L("Upgrade yao to latest version"),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
Boot()
|
||||
latest, found, err := selfupdate.DetectLatest("yaoapp/yao")
|
||||
fmt.Printf("%s %s\n", color.WhiteString(L("Current version:")), color.CyanString(share.VERSION))
|
||||
fmt.Println(color.WhiteString(L("Checking latest version...")))
|
||||
|
||||
release, err := fetchLatestRelease()
|
||||
if err != nil {
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
currentVersion := semver.MustParse(share.VERSION)
|
||||
if !found || latest.Version.LTE(currentVersion) {
|
||||
|
||||
latestVersion := strings.TrimPrefix(release.TagName, "v")
|
||||
fmt.Printf("%s %s\n", color.WhiteString(L("Latest version: ")), color.GreenString(latestVersion))
|
||||
|
||||
if latestVersion == share.VERSION {
|
||||
fmt.Println(color.GreenString(L("🎉Current version is the latest🎉")))
|
||||
os.Exit(0)
|
||||
}
|
||||
fmt.Println(color.WhiteString(L("Do you want to update to %s ? (y/n): "), latest.Version))
|
||||
|
||||
assetName := buildAssetName(latestVersion)
|
||||
asset := findAsset(release.Assets, assetName)
|
||||
if asset == nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), fmt.Sprintf("asset not found: %s", assetName)))
|
||||
fmt.Printf("%s %s\n", color.WhiteString(L("Available assets:")), "")
|
||||
for _, a := range release.Assets {
|
||||
if !strings.HasSuffix(a.Name, ".sha256") && !strings.HasSuffix(a.Name, ".zip") && !strings.HasSuffix(a.Name, ".tar.gz") {
|
||||
fmt.Printf(" - %s\n", color.YellowString(a.Name))
|
||||
}
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("%s %s\n", color.WhiteString(L("Do you want to update to %s ? (y/n): "), latestVersion), "")
|
||||
fmt.Print("> ")
|
||||
input, err := bufio.NewReader(os.Stdin).ReadString('\n')
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
if input != "y\n" && input != "Y\n" && input != "n\n" && input != "N\n" {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), L("Invalid input")))
|
||||
os.Exit(1)
|
||||
}
|
||||
if input == "n\n" || input == "N\n" {
|
||||
|
||||
input = strings.TrimSpace(input)
|
||||
if input != "y" && input != "Y" {
|
||||
fmt.Println(color.YellowString(L("Canceled upgrade")))
|
||||
return
|
||||
}
|
||||
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := selfupdate.UpdateTo(latest.AssetURL, exe); err != nil {
|
||||
exe, err = filepath.EvalSymlinks(exe)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("%s %s\n", color.WhiteString(L("Downloading...")), color.CyanString(asset.BrowserDownloadURL))
|
||||
if err := downloadAndReplace(asset.BrowserDownloadURL, exe); err != nil {
|
||||
fmt.Println(color.RedString(L("Error occurred while updating binary: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(color.GreenString(L("🎉Successfully updated to version: %s🎉"), latest.Version))
|
||||
|
||||
fmt.Println(color.GreenString(L("🎉Successfully updated to version: %s🎉"), latestVersion))
|
||||
},
|
||||
}
|
||||
|
||||
// fetchLatestRelease fetches the latest release from GitHub API
|
||||
func fetchLatestRelease() (*githubRelease, error) {
|
||||
client := &http.Client{Timeout: 30 * time.Second}
|
||||
req, err := http.NewRequest("GET", githubReleasesAPI, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Accept", "application/vnd.github.v3+json")
|
||||
req.Header.Set("User-Agent", fmt.Sprintf("yao/%s", share.VERSION))
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("GitHub API returned status %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var release githubRelease
|
||||
if err := json.NewDecoder(resp.Body).Decode(&release); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse release info: %w", err)
|
||||
}
|
||||
return &release, nil
|
||||
}
|
||||
|
||||
// buildAssetName constructs the expected asset filename for the current platform
|
||||
func buildAssetName(version string) string {
|
||||
goos := runtime.GOOS
|
||||
goarch := runtime.GOARCH
|
||||
|
||||
// normalize arch names
|
||||
if goarch == "amd64" {
|
||||
goarch = "amd64"
|
||||
} else if goarch == "arm64" {
|
||||
goarch = "arm64"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("yao-%s-%s-%s", version, goos, goarch)
|
||||
}
|
||||
|
||||
// findAsset finds the matching asset by name prefix
|
||||
func findAsset(assets []githubAsset, name string) *githubAsset {
|
||||
for i, a := range assets {
|
||||
if a.Name == name {
|
||||
return &assets[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// downloadAndReplace downloads the new binary and replaces the current executable
|
||||
func downloadAndReplace(url, exePath string) error {
|
||||
client := &http.Client{Timeout: 10 * time.Minute}
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
return fmt.Errorf("download failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("download failed with status %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// write to a temp file in the same directory as the executable
|
||||
dir := filepath.Dir(exePath)
|
||||
tmpFile, err := os.CreateTemp(dir, ".yao-upgrade-*")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create temp file: %w", err)
|
||||
}
|
||||
tmpPath := tmpFile.Name()
|
||||
defer func() {
|
||||
tmpFile.Close()
|
||||
os.Remove(tmpPath)
|
||||
}()
|
||||
|
||||
total := resp.ContentLength
|
||||
var downloaded int64
|
||||
buf := make([]byte, 32*1024)
|
||||
lastPrint := time.Now()
|
||||
|
||||
for {
|
||||
n, err := resp.Body.Read(buf)
|
||||
if n > 0 {
|
||||
if _, werr := tmpFile.Write(buf[:n]); werr != nil {
|
||||
return fmt.Errorf("write failed: %w", werr)
|
||||
}
|
||||
downloaded += int64(n)
|
||||
if time.Since(lastPrint) > 500*time.Millisecond || err == io.EOF {
|
||||
if total > 0 {
|
||||
pct := float64(downloaded) / float64(total) * 100
|
||||
fmt.Printf("\r %s %.1f%% (%d / %d MB)",
|
||||
color.CyanString(L("Progress:")),
|
||||
pct,
|
||||
downloaded/1024/1024,
|
||||
total/1024/1024,
|
||||
)
|
||||
} else {
|
||||
fmt.Printf("\r %s %d MB downloaded", color.CyanString(L("Progress:")), downloaded/1024/1024)
|
||||
}
|
||||
lastPrint = time.Now()
|
||||
}
|
||||
}
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("download interrupted: %w", err)
|
||||
}
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
return fmt.Errorf("failed to close temp file: %w", err)
|
||||
}
|
||||
|
||||
// make executable
|
||||
if err := os.Chmod(tmpPath, 0755); err != nil {
|
||||
return fmt.Errorf("failed to chmod: %w", err)
|
||||
}
|
||||
|
||||
// atomically replace the executable
|
||||
if err := os.Rename(tmpPath, exePath); err != nil {
|
||||
// on some systems (cross-device) rename fails, fall back to copy
|
||||
if err2 := copyFile(tmpPath, exePath); err2 != nil {
|
||||
return fmt.Errorf("replace failed: %w (copy fallback: %v)", err, err2)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// copyFile copies src to dst, used as fallback when rename fails cross-device
|
||||
func copyFile(src, dst string) error {
|
||||
in, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
|
||||
out, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
_, err = io.Copy(out, in)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
7
go.mod
7
go.mod
|
|
@ -7,7 +7,6 @@ require (
|
|||
github.com/aws/aws-sdk-go-v2 v1.36.3
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3
|
||||
github.com/blang/semver v3.5.1+incompatible
|
||||
github.com/bwmarrin/discordgo v0.29.0
|
||||
github.com/caarlos0/env/v6 v6.10.1
|
||||
github.com/dchest/captcha v1.1.0
|
||||
|
|
@ -37,7 +36,6 @@ require (
|
|||
github.com/pierrec/lz4/v4 v4.1.25
|
||||
github.com/pkoukk/tiktoken-go v0.1.7
|
||||
github.com/pquerna/otp v1.5.0
|
||||
github.com/rhysd/go-github-selfupdate v1.2.3
|
||||
github.com/spf13/cast v1.9.2
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/stretchr/testify v1.11.1
|
||||
|
|
@ -121,8 +119,6 @@ require (
|
|||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v1.0.0 // indirect
|
||||
github.com/google/gnostic-models v0.7.0 // indirect
|
||||
github.com/google/go-github/v30 v30.1.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/gotd/ige v0.2.2 // indirect
|
||||
github.com/gotd/neo v0.1.5 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
|
|
@ -133,7 +129,6 @@ require (
|
|||
github.com/hhrutter/lzw v1.0.0 // indirect
|
||||
github.com/hhrutter/pkcs7 v0.2.0 // indirect
|
||||
github.com/hhrutter/tiff v1.0.2 // indirect
|
||||
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jmoiron/sqlx v1.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
|
|
@ -181,7 +176,6 @@ require (
|
|||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.4 // indirect
|
||||
github.com/spf13/pflag v1.0.9 // indirect
|
||||
github.com/tcnksm/go-gitconfig v0.1.2 // indirect
|
||||
github.com/tidwall/btree v1.7.0 // indirect
|
||||
github.com/tidwall/buntdb v1.3.2 // indirect
|
||||
github.com/tidwall/gjson v1.18.0 // indirect
|
||||
|
|
@ -193,7 +187,6 @@ require (
|
|||
github.com/tiendc/go-deepcopy v1.6.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/ulikunitz/xz v0.5.14 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
|
|
|
|||
39
go.sum
39
go.sum
|
|
@ -43,8 +43,6 @@ github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3 h1:BRXS0U76Z8wfF+bnkilA2QwpIch6U
|
|||
github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3/go.mod h1:bNXKFFyaiVvWuR6O16h/I1724+aXe/tAkA9/QS01t5k=
|
||||
github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k=
|
||||
github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||
|
|
@ -120,7 +118,6 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
|
|||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||
|
|
@ -186,23 +183,15 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
|||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
|
||||
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
|
||||
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-github/v30 v30.1.0 h1:VLDx+UolQICEOKu2m4uAoMti1SxuEBAl7RSEG16L+Oo=
|
||||
github.com/google/go-github/v30 v30.1.0/go.mod h1:n8jBpHl45a/rlBUtRJMOG4GhNADUQFEufcolZ95JfU8=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
|
|
@ -241,9 +230,6 @@ github.com/hhrutter/tiff v1.0.2 h1:7H3FQQpKu/i5WaSChoD1nnJbGx4MxU5TlNqqpxw55z8=
|
|||
github.com/hhrutter/tiff v1.0.2/go.mod h1:pcOeuK5loFUE7Y/WnzGw20YxUdnqjY1P0Jlcieb/cCw=
|
||||
github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519 h1:nqAlWFEdqI0ClbTDrhDvE/8LeQ4pftrqKUX9w5k0j3s=
|
||||
github.com/hokaccha/go-prettyjson v0.0.0-20210113012101-fb4e108d2519/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8=
|
||||
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
|
||||
|
|
@ -343,12 +329,10 @@ github.com/ogen-go/ogen v1.19.0 h1:YvdNpeQJ8A8dLLpS6Vs4WxXL53BT6tBPxH0VSjfALhA=
|
|||
github.com/ogen-go/ogen v1.19.0/go.mod h1:DeShwO+TEpLYXNCuZliSAedphphXsJaTGGbmSomWUjE=
|
||||
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
|
||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.25.1 h1:Fwp6crTREKM+oA6Cz4MsO8RhKQzs2/gOIVOUscMAfZY=
|
||||
github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk=
|
||||
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
|
||||
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
|
||||
github.com/open-dingtalk/dingtalk-stream-sdk-go v0.9.1 h1:Lb/Uzkiw2Ugt2Xf03J5wmv81PdkYOiWbI8CNBi1boC8=
|
||||
|
|
@ -375,8 +359,6 @@ github.com/qdrant/go-client v1.14.0 h1:cyz9OOooAexudw5w69LRe9vKCQFYJvaFvt9icOciI
|
|||
github.com/qdrant/go-client v1.14.0/go.mod h1:iO8ts78jL4x6LDHFOViyYWELVtIBDTjOykBmiOTHLnQ=
|
||||
github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4ViluI=
|
||||
github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=
|
||||
github.com/rhysd/go-github-selfupdate v1.2.3 h1:iaa+J202f+Nc+A8zi75uccC8Wg3omaM7HDeimXA22Ag=
|
||||
github.com/rhysd/go-github-selfupdate v1.2.3/go.mod h1:mp/N8zj6jFfBQy/XMYoWsmfzxazpPAODuqarmPDe2Rg=
|
||||
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
||||
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
|
|
@ -421,8 +403,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
|||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
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/tcnksm/go-gitconfig v0.1.2 h1:iiDhRitByXAEyjgBqsKi9QU4o2TNtv9kPP3RgPgXBPw=
|
||||
github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE=
|
||||
github.com/tidwall/assert v0.1.0 h1:aWcKyRBUAdLoVebxo95N7+YZVTFF/ASTr7BN4sLP6XI=
|
||||
github.com/tidwall/assert v0.1.0/go.mod h1:QLYtGyeqse53vuELQheYl9dngGCJQ+mTtlxcktb+Kj8=
|
||||
github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI=
|
||||
|
|
@ -451,9 +431,6 @@ 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.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.14 h1:uv/0Bq533iFdnMHZdRBTOlaNMdb1+ZxXIlHDZHIHcvg=
|
||||
github.com/ulikunitz/xz v0.5.14/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
|
|
@ -518,7 +495,6 @@ golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
|
|
@ -540,9 +516,6 @@ golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
|||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
||||
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
|
@ -557,11 +530,8 @@ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
|||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
|
||||
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
@ -574,10 +544,8 @@ golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -599,7 +567,6 @@ golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
|
|
@ -612,7 +579,6 @@ golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
|||
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
|
|
@ -642,8 +608,6 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
|
|||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 h1:tu/dtnW1o3wfaxCOjSLn5IRX4YDcJrtlpzYkhHhGaC4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171/go.mod h1:M5krXqk4GhBKvB596udGL3UyjL4I1+cTbK0orROM9ng=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
|
||||
|
|
@ -653,20 +617,17 @@ google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhH
|
|||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/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-20180628173108-788fd7840127/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=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
|
|
|
|||
|
|
@ -34,14 +34,53 @@ func (w *sandboxWatcher) Check(ctx context.Context) []monitor.Alert {
|
|||
Target: "box:" + b.id,
|
||||
Message: fmt.Sprintf("status %s → %s", old, status),
|
||||
})
|
||||
if status == "running" && old != "running" {
|
||||
b.touch()
|
||||
alerts = append(alerts, monitor.Alert{
|
||||
Level: monitor.Trace,
|
||||
Target: "box:" + b.id,
|
||||
Message: fmt.Sprintf("touch on resume, lastCall reset to %s",
|
||||
time.UnixMilli(b.lastCall.Load()).Format(time.RFC3339)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if status != "running" {
|
||||
return true
|
||||
}
|
||||
|
||||
// maxLifetime: independent of idle — prevents indefinitely running containers
|
||||
if b.policy == LongRunning {
|
||||
if lifetime := b.maxLifetime(); lifetime > 0 {
|
||||
age := time.Since(b.createdAt)
|
||||
if age > lifetime {
|
||||
alerts = append(alerts, monitor.Alert{
|
||||
Level: monitor.Warn,
|
||||
Target: "box:" + b.id,
|
||||
Message: fmt.Sprintf("lifetime expired (%s), removing", lifetime),
|
||||
Action: func(ctx context.Context) { mgr.Remove(ctx, b.id) },
|
||||
})
|
||||
} else {
|
||||
alerts = append(alerts, monitor.Alert{
|
||||
Level: monitor.Trace,
|
||||
Target: "box:" + b.id,
|
||||
Message: fmt.Sprintf("lifetime remaining %s (max=%s)",
|
||||
(lifetime - age).Round(time.Second), lifetime),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
idle := time.Since(b.idleSince())
|
||||
timeout := b.idleTimeout()
|
||||
|
||||
alerts = append(alerts, monitor.Alert{
|
||||
Level: monitor.Trace,
|
||||
Target: "box:" + b.id,
|
||||
Message: fmt.Sprintf("heartbeat status=%s policy=%s idle=%s timeout=%s",
|
||||
status, b.policy, idle.Round(time.Second), timeout),
|
||||
})
|
||||
|
||||
if timeout <= 0 || idle <= timeout {
|
||||
return true
|
||||
}
|
||||
|
|
@ -68,19 +107,6 @@ func (w *sandboxWatcher) Check(ctx context.Context) []monitor.Alert {
|
|||
})
|
||||
}
|
||||
|
||||
if b.policy == LongRunning {
|
||||
if lifetime := b.maxLifetime(); lifetime > 0 && time.Since(b.createdAt) > lifetime {
|
||||
alerts = append(alerts, monitor.Alert{
|
||||
Level: monitor.Warn,
|
||||
Target: "box:" + b.id,
|
||||
Message: fmt.Sprintf("lifetime expired (%s), removing", lifetime),
|
||||
Action: func(ctx context.Context) {
|
||||
mgr.Remove(ctx, b.id)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
return alerts
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue