feat(auggie): enable native session resume with ACP session/load (#380)
This commit is contained in:
@@ -17,7 +17,7 @@ var auggieLogoLight []byte
|
||||
//go:embed logos/auggie_dark.svg
|
||||
var auggieLogoDark []byte
|
||||
|
||||
const auggiePkg = "@augmentcode/auggie@0.16.2"
|
||||
const auggiePkg = "@augmentcode/auggie@0.18.1"
|
||||
|
||||
var (
|
||||
_ Agent = (*Auggie)(nil)
|
||||
@@ -74,7 +74,7 @@ func (a *Auggie) IsInstalled(ctx context.Context) (*DiscoveryResult, error) {
|
||||
result.SupportsMCP = true
|
||||
result.InstallationPaths = []string{expandHomePath("~/.augment/.auggie.json")}
|
||||
result.Capabilities = DiscoveryCapabilities{
|
||||
SupportsSessionResume: false,
|
||||
SupportsSessionResume: true,
|
||||
SupportsShell: false,
|
||||
SupportsWorkspaceOnly: false,
|
||||
}
|
||||
@@ -92,16 +92,16 @@ func (a *Auggie) ListModels(ctx context.Context) (*ModelList, error) {
|
||||
}
|
||||
|
||||
func (a *Auggie) BuildCommand(opts CommandOptions) Command {
|
||||
// Session resume is handled via ACP session/load, not CLI flags (NativeSessionResume: true)
|
||||
return Cmd("npx", "-y", auggiePkg, "--acp").
|
||||
Model(NewParam("--model", "{model}"), opts.Model).
|
||||
Resume(NewParam("--resume"), opts.SessionID, false).
|
||||
Permissions("--permission", auggiePermTools, opts).
|
||||
Settings(auggiePermSettings, opts.PermissionValues).
|
||||
Build()
|
||||
}
|
||||
|
||||
func (a *Auggie) Runtime() *RuntimeConfig {
|
||||
canRecover := false
|
||||
canRecover := true
|
||||
return &RuntimeConfig{
|
||||
Image: "kandev/multi-agent",
|
||||
Tag: "latest",
|
||||
@@ -117,11 +117,8 @@ func (a *Auggie) Runtime() *RuntimeConfig {
|
||||
ModelFlag: NewParam("--model", "{model}"),
|
||||
WorkspaceFlag: "--workspace-root",
|
||||
SessionConfig: SessionConfig{
|
||||
ResumeFlag: NewParam("--resume"),
|
||||
CanRecover: &canRecover,
|
||||
HistoryContextInjection: true,
|
||||
SessionDirTemplate: "{home}/.augment/sessions",
|
||||
SessionDirTarget: "/root/.augment/sessions",
|
||||
NativeSessionResume: true,
|
||||
CanRecover: &canRecover,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,11 @@ type Adapter struct {
|
||||
// When set, this context will be prepended to the first prompt sent to the session.
|
||||
pendingContext string
|
||||
|
||||
// isLoadingSession is true during LoadSession() to suppress history replay notifications.
|
||||
// ACP agents stream the entire conversation history during session/load which should
|
||||
// not be emitted as new message events.
|
||||
isLoadingSession bool
|
||||
|
||||
// Tool call tracking for result normalization
|
||||
// Maps toolCallId -> NormalizedPayload so we can update with results
|
||||
activeToolCalls map[string]*streams.NormalizedPayload
|
||||
@@ -291,11 +296,23 @@ func (a *Adapter) LoadSession(ctx context.Context, sessionID string) error {
|
||||
ctx, span := shared.TraceProtocolRequest(ctx, shared.ProtocolACP, a.agentID, "session.load")
|
||||
defer span.End()
|
||||
|
||||
// Suppress history replay notifications during load.
|
||||
// ACP agents stream the entire conversation history during session/load.
|
||||
a.mu.Lock()
|
||||
a.isLoadingSession = true
|
||||
a.mu.Unlock()
|
||||
|
||||
resp, err := conn.LoadSession(ctx, acp.LoadSessionRequest{
|
||||
SessionId: acp.SessionId(sessionID),
|
||||
Cwd: a.cfg.WorkDir,
|
||||
McpServers: []acp.McpServer{}, // MCPs configured via CLI args; empty satisfies the required field
|
||||
})
|
||||
|
||||
// Clear the loading flag (even on error) before processing response
|
||||
a.mu.Lock()
|
||||
a.isLoadingSession = false
|
||||
a.mu.Unlock()
|
||||
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
return fmt.Errorf("failed to load session: %w", err)
|
||||
@@ -581,6 +598,22 @@ func (a *Adapter) handleACPUpdate(n acp.SessionNotification) {
|
||||
shared.LogRawEvent(shared.ProtocolACP, a.agentID, "session_notification", rawData)
|
||||
}
|
||||
|
||||
// During session/load, suppress history replay notifications.
|
||||
// ACP agents stream the entire conversation history during load, which should not
|
||||
// be emitted as new message events to avoid duplicating messages in the UI.
|
||||
a.mu.RLock()
|
||||
isLoading := a.isLoadingSession
|
||||
a.mu.RUnlock()
|
||||
|
||||
if isLoading {
|
||||
u := n.Update
|
||||
if u.AgentMessageChunk != nil || u.UserMessageChunk != nil || u.AgentThoughtChunk != nil {
|
||||
a.logger.Debug("suppressing history replay notification during session load",
|
||||
zap.String("session_id", string(n.SessionId)))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
event := a.convertNotification(n)
|
||||
if event != nil {
|
||||
shared.LogNormalizedEvent(shared.ProtocolACP, a.agentID, event)
|
||||
|
||||
@@ -308,7 +308,7 @@ The session is NOT marked as failed -- the user can send a new message to start
|
||||
| Claude Code | - | - | Uses `--resume` CLI flag with stored resume token |
|
||||
| Codex | yes | - | ACP `session/load` restores context |
|
||||
| Copilot | yes | - | ACP `session/load` restores context |
|
||||
| Auggie | - | yes | Fresh start + history injection on first prompt |
|
||||
| Auggie | yes | - | ACP `session/load` restores context (v0.18.1+) |
|
||||
| Gemini | - | - | Boots idle, no context restoration |
|
||||
| Amp | - | - | Uses `ForkSessionCmd` / `ContinueSessionCmd` |
|
||||
| OpenCode | yes | - | ACP `session/load` restores context |
|
||||
|
||||
Reference in New Issue
Block a user