From bfe5016f5cef5f8394e73de8429a40d009957e55 Mon Sep 17 00:00:00 2001 From: xgopilot Date: Sun, 3 May 2026 17:01:59 +0000 Subject: [PATCH] fix(app): initialize checkpoint store on cold startup Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: phantom5099 <245659304+phantom5099@users.noreply.github.com> --- internal/app/bootstrap.go | 9 +++++--- internal/app/bootstrap_test.go | 40 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/internal/app/bootstrap.go b/internal/app/bootstrap.go index 94669476..1f1cf644 100644 --- a/internal/app/bootstrap.go +++ b/internal/app/bootstrap.go @@ -231,10 +231,13 @@ func BuildGatewayServerDeps(ctx context.Context, opts BootstrapOptions) (Runtime )) } - // Checkpoint 基础设施:影子仓库 + SQLite checkpoint 存储 - // 复用 sessionStore 的 *sql.DB 连接,避免 Windows 上多连接文件锁定。 + // Checkpoint 基础设施:影子仓库 + SQLite checkpoint 存储。 + // 优先复用 sessionStore 已打开的 *sql.DB;冷启动尚未建连时回退到同一路径的独立 store, + // 避免 sessionStore.DB() 为 nil 时整条 checkpoint 链路被静默跳过。 sessionDB := sessionStore.DB() - var checkpointStore *checkpoint.SQLiteCheckpointStore + checkpointStore := checkpoint.NewSQLiteCheckpointStore( + agentsession.DatabasePath(sharedDeps.ConfigManager.BaseDir(), cfg.Workdir), + ) if sessionDB != nil { checkpointStore = checkpoint.NewSQLiteCheckpointStoreWithDB(sessionDB) } diff --git a/internal/app/bootstrap_test.go b/internal/app/bootstrap_test.go index 17a11d5d..1e270a8d 100644 --- a/internal/app/bootstrap_test.go +++ b/internal/app/bootstrap_test.go @@ -17,6 +17,7 @@ import ( "testing" "time" + "neo-code/internal/checkpoint" "neo-code/internal/config" configstate "neo-code/internal/config/state" "neo-code/internal/gateway/protocol" @@ -918,6 +919,45 @@ func TestBuildRuntimeUsesWorkdirOverride(t *testing.T) { } } +func TestBuildGatewayServerDepsInitializesCheckpointStoreOnFreshStartup(t *testing.T) { + disableBuiltinProviderAPIKeys(t) + + home := t.TempDir() + t.Setenv("HOME", home) + t.Setenv("USERPROFILE", home) + + bundle, err := BuildGatewayServerDeps(context.Background(), BootstrapOptions{}) + if err != nil { + t.Fatalf("BuildGatewayServerDeps() error = %v", err) + } + if bundle.Close != nil { + t.Cleanup(func() { + if err := bundle.Close(); err != nil { + t.Fatalf("bundle.Close() error = %v", err) + } + }) + } + + runtimeWithCheckpoints, ok := bundle.Runtime.(interface { + ListCheckpoints(ctx context.Context, sessionID string, opts checkpoint.ListCheckpointOpts) ([]agentsession.CheckpointRecord, error) + }) + if !ok { + t.Fatalf("expected runtime to expose ListCheckpoints") + } + + records, err := runtimeWithCheckpoints.ListCheckpoints( + context.Background(), + "fresh-startup-session", + checkpoint.ListCheckpointOpts{}, + ) + if err != nil { + t.Fatalf("expected checkpoint store to be available on fresh startup, got %v", err) + } + if len(records) != 0 { + t.Fatalf("expected no checkpoints for fresh session, got %+v", records) + } +} + func TestBuildRuntimeSucceedsWhenSkillsRootMissing(t *testing.T) { disableBuiltinProviderAPIKeys(t)