Skip to content

Commit a642a54

Browse files
committed
fix:Prepare 阶段的 workdir 持久化从“整包回写会话头”改成“只更新 workdir + updated_at
1 parent 9bb0ba4 commit a642a54

10 files changed

Lines changed: 320 additions & 21 deletions

internal/runtime/input_prepare_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@ func newPrepareTestService(t *testing.T, workdir string, withPreparer bool) (*Se
160160
}
161161

162162
store := agentsession.NewStore(t.TempDir(), workdir)
163+
t.Cleanup(func() {
164+
_ = store.Close()
165+
})
163166
svc := NewWithFactory(manager, nil, store, nil, nil)
164167
svc.SetSessionAssetStore(store)
165168
if withPreparer {

internal/runtime/runtime_internal_helpers_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ func (s *lockProbeStore) ListSummaries(ctx context.Context) ([]agentsession.Summ
4444
return nil, errors.New("not implemented")
4545
}
4646

47+
// UpdateSessionWorkdir 仅为接口占位,当前测试不会走到该分支。
48+
func (s *lockProbeStore) UpdateSessionWorkdir(ctx context.Context, input agentsession.UpdateSessionWorkdirInput) error {
49+
return errors.New("not implemented")
50+
}
51+
4752
func (s *lockProbeStore) UpdateSessionState(ctx context.Context, input agentsession.UpdateSessionStateInput) error {
4853
return errors.New("not implemented")
4954
}

internal/runtime/runtime_remaining_branches_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ func (s *saveHookStore) AppendMessages(ctx context.Context, input agentsession.A
100100
return s.base.AppendMessages(ctx, input)
101101
}
102102

103+
// UpdateSessionWorkdir 在写前注入回调,再转发给底层内存 store。
104+
func (s *saveHookStore) UpdateSessionWorkdir(ctx context.Context, input agentsession.UpdateSessionWorkdirInput) error {
105+
if err := s.beforeSave(ctx); err != nil {
106+
return err
107+
}
108+
return s.base.UpdateSessionWorkdir(ctx, input)
109+
}
110+
103111
func (s *saveHookStore) UpdateSessionState(ctx context.Context, input agentsession.UpdateSessionStateInput) error {
104112
if err := s.beforeSave(ctx); err != nil {
105113
return err
@@ -131,6 +139,11 @@ func (s *postSaveHookStore) AppendMessages(ctx context.Context, input agentsessi
131139
return s.afterSave(s.base.AppendMessages(ctx, input))
132140
}
133141

142+
// UpdateSessionWorkdir 在底层写入完成后执行一次 post-save 钩子。
143+
func (s *postSaveHookStore) UpdateSessionWorkdir(ctx context.Context, input agentsession.UpdateSessionWorkdirInput) error {
144+
return s.afterSave(s.base.UpdateSessionWorkdir(ctx, input))
145+
}
146+
134147
func (s *postSaveHookStore) UpdateSessionState(ctx context.Context, input agentsession.UpdateSessionStateInput) error {
135148
return s.afterSave(s.base.UpdateSessionState(ctx, input))
136149
}

internal/runtime/runtime_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,27 @@ func (s *memoryStore) AppendMessages(ctx context.Context, input agentsession.App
161161
}
162162

163163
// UpdateSessionState 只覆写会话头字段,不改消息正文。
164+
// UpdateSessionWorkdir 仅更新会话 workdir 与时间,避免输入归一化覆盖其他会话头字段。
165+
func (s *memoryStore) UpdateSessionWorkdir(ctx context.Context, input agentsession.UpdateSessionWorkdirInput) error {
166+
if err := ctx.Err(); err != nil {
167+
return err
168+
}
169+
s.mu.Lock()
170+
defer s.mu.Unlock()
171+
172+
session, ok := s.sessions[input.SessionID]
173+
if !ok {
174+
return errors.New("not found")
175+
}
176+
if !input.UpdatedAt.IsZero() {
177+
session.UpdatedAt = input.UpdatedAt
178+
}
179+
session.Workdir = input.Workdir
180+
s.saves++
181+
s.sessions[input.SessionID] = cloneSession(session)
182+
return nil
183+
}
184+
164185
func (s *memoryStore) UpdateSessionState(ctx context.Context, input agentsession.UpdateSessionStateInput) error {
165186
if err := ctx.Err(); err != nil {
166187
return err
@@ -257,6 +278,17 @@ func (s *failingStore) AppendMessages(ctx context.Context, input agentsession.Ap
257278
}
258279

259280
// UpdateSessionState 转发到底层 Store,并按写入次数注入失败。
281+
// UpdateSessionWorkdir 杞彂鍒板簳灞?Store锛屽苟鎸夊啓鍏ユ鏁版敞鍏ュけ璐ャ€?
282+
func (s *failingStore) UpdateSessionWorkdir(ctx context.Context, input agentsession.UpdateSessionWorkdirInput) error {
283+
if err := s.nextSaveError(ctx); err != nil {
284+
return err
285+
}
286+
if s.Store == nil {
287+
return nil
288+
}
289+
return s.Store.UpdateSessionWorkdir(ctx, input)
290+
}
291+
260292
func (s *failingStore) UpdateSessionState(ctx context.Context, input agentsession.UpdateSessionStateInput) error {
261293
if err := s.nextSaveError(ctx); err != nil {
262294
return err
@@ -376,6 +408,25 @@ func (s *blockingLoadStore) AppendMessages(ctx context.Context, input agentsessi
376408
}
377409

378410
// UpdateSessionState 在阻塞加载测试桩中更新会话头。
411+
// UpdateSessionWorkdir 鍦ㄩ樆濉炲姞杞芥祴璇曟々涓粎鏇存柊 workdir 涓庢椂闂淬€?
412+
func (s *blockingLoadStore) UpdateSessionWorkdir(ctx context.Context, input agentsession.UpdateSessionWorkdirInput) error {
413+
if err := ctx.Err(); err != nil {
414+
return err
415+
}
416+
s.mu.Lock()
417+
defer s.mu.Unlock()
418+
session, ok := s.sessions[input.SessionID]
419+
if !ok {
420+
return errors.New("not found")
421+
}
422+
if !input.UpdatedAt.IsZero() {
423+
session.UpdatedAt = input.UpdatedAt
424+
}
425+
session.Workdir = input.Workdir
426+
s.sessions[input.SessionID] = cloneSession(session)
427+
return nil
428+
}
429+
379430
func (s *blockingLoadStore) UpdateSessionState(ctx context.Context, input agentsession.UpdateSessionStateInput) error {
380431
if err := ctx.Err(); err != nil {
381432
return err

internal/runtime/todo_mutator_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,23 @@ func (s *mutatorStore) AppendMessages(ctx context.Context, input agentsession.Ap
6666
return nil
6767
}
6868

69+
// UpdateSessionWorkdir 仅更新 workdir 与更新时间,模拟最小粒度持久化。
70+
func (s *mutatorStore) UpdateSessionWorkdir(ctx context.Context, input agentsession.UpdateSessionWorkdirInput) error {
71+
if err := ctx.Err(); err != nil {
72+
return err
73+
}
74+
if s.err != nil {
75+
return s.err
76+
}
77+
if s.last.ID != "" && s.last.ID != input.SessionID {
78+
return errors.New("not found")
79+
}
80+
s.last.ID = input.SessionID
81+
s.last.UpdatedAt = input.UpdatedAt
82+
s.last.Workdir = input.Workdir
83+
return nil
84+
}
85+
6986
func (s *mutatorStore) UpdateSessionState(ctx context.Context, input agentsession.UpdateSessionStateInput) error {
7087
if err := ctx.Err(); err != nil {
7188
return err

internal/session/asset_store_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ func TestSQLiteStoreSaveAssetRejectsInvalidInput(t *testing.T) {
7171
}
7272
if _, err := store.SaveAsset(ctx, "missing", strings.NewReader("x"), "image/png"); err == nil {
7373
t.Fatalf("expected missing session error")
74+
} else if !errors.Is(err, os.ErrNotExist) {
75+
t.Fatalf("expected os.ErrNotExist, got %v", err)
7476
}
7577
if _, _, err := store.Open(ctx, "bad/session", "asset_ok"); err == nil {
7678
t.Fatalf("expected invalid session id error")

internal/session/input_preparer.go

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -401,18 +401,10 @@ func (p *InputPreparer) persistSessionWorkdirUpdate(ctx context.Context, pending
401401
if !pending.dirty {
402402
return nil
403403
}
404-
if err := p.store.UpdateSessionState(ctx, UpdateSessionStateInput{
405-
SessionID: pending.session.ID,
406-
Title: pending.session.Title,
407-
UpdatedAt: pending.session.UpdatedAt,
408-
Provider: pending.session.Provider,
409-
Model: pending.session.Model,
410-
Workdir: pending.session.Workdir,
411-
TaskState: pending.session.TaskState,
412-
ActivatedSkills: pending.session.ActivatedSkills,
413-
Todos: pending.session.Todos,
414-
TokenInputTotal: pending.session.TokenInputTotal,
415-
TokenOutputTotal: pending.session.TokenOutputTotal,
404+
if err := p.store.UpdateSessionWorkdir(ctx, UpdateSessionWorkdirInput{
405+
SessionID: pending.session.ID,
406+
UpdatedAt: pending.session.UpdatedAt,
407+
Workdir: pending.session.Workdir,
416408
}); err != nil {
417409
return err
418410
}

0 commit comments

Comments
 (0)