Why: a crash after a tool was about to run left the call unpaired, and workspace writes could not be rewound. Evidence: GOWORK=off go test ./runtime/ ./runtime/llm/ ./runtime/checkpoint/ ./runtime/telemetry/ ./runtime/tools/ ./runtime/session/ ./adapters/native/ Impact: pending calls rerun only when both the stored and current replay declarations are safe; otherwise the result is an error. Empty fallback lists and a nil checkpoint log keep the previous behavior. Refs: feature/durable-rewind Co-authored-by: Cursor <cursoragent@cursor.com>
58 lines
1.4 KiB
Go
58 lines
1.4 KiB
Go
package session
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"agent-native/runtime/llm"
|
|
)
|
|
|
|
// ToolIntent 是一次尚未配对结果的工具调用声明。
|
|
type ToolIntent struct {
|
|
CallID string `json:"callId"`
|
|
Name string `json:"name"`
|
|
Arguments string `json:"arguments,omitempty"`
|
|
Replay string `json:"replay"`
|
|
}
|
|
|
|
// AppendToolIntent 先落下「即将执行」。结果另写一条 tool 消息。
|
|
func (s *Store) AppendToolIntent(in ToolIntent) error {
|
|
raw, err := json.Marshal(in)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = s.AppendEntry(Entry{Type: TypeToolIntent, Data: raw})
|
|
return err
|
|
}
|
|
|
|
// PendingIntents 返回活动分支上还没有对应 tool 结果的意图。
|
|
func (s *Store) PendingIntents() ([]ToolIntent, error) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
entries, err := s.readEntriesLocked()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
answered := map[string]bool{}
|
|
var intents []ToolIntent
|
|
for _, e := range pathTo(entries, s.leafLocked(entries)) {
|
|
if e.Type == TypeMessage && e.Message != nil && e.Message.Role == llm.RoleTool && e.Message.ToolCallID != "" {
|
|
answered[e.Message.ToolCallID] = true
|
|
}
|
|
if e.Type != TypeToolIntent {
|
|
continue
|
|
}
|
|
var in ToolIntent
|
|
if err := json.Unmarshal(e.Data, &in); err != nil {
|
|
return nil, err
|
|
}
|
|
intents = append(intents, in)
|
|
}
|
|
var pending []ToolIntent
|
|
for _, in := range intents {
|
|
if !answered[in.CallID] {
|
|
pending = append(pending, in)
|
|
}
|
|
}
|
|
return pending, nil
|
|
}
|