fix: inject pending assistant reply into inbound turns and fill ReplyToMessageID
Gap 1: regular inbound turns now see the previous assistant reply in LLM context even when OnDelivered hasn't fired yet (fast follow-up scenario). Achieved by loading from pendingDeliveries sync.Map after captureRestorePoint and appending to history before BuildMessages. Gap 2: HandleMessage in BaseChannel now fills ReplyToMessageID from metadata so the first-class struct field is populated for all channels that set the key in metadata (e.g. Telegram).
This commit is contained in:
parent
9880cb343b
commit
942c3d3f6e
2 changed files with 43 additions and 22 deletions
|
|
@ -58,6 +58,7 @@ type AgentLoop struct {
|
||||||
hookRuntime hookRuntime
|
hookRuntime hookRuntime
|
||||||
steering *steeringQueue
|
steering *steeringQueue
|
||||||
pendingSkills sync.Map
|
pendingSkills sync.Map
|
||||||
|
pendingDeliveries sync.Map // sessionKey -> string: last undelivered assistant content
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
|
|
||||||
// Concurrent turn management (from HEAD)
|
// Concurrent turn management (from HEAD)
|
||||||
|
|
@ -1697,9 +1698,14 @@ func (al *AgentLoop) runAgentLoop(
|
||||||
}
|
}
|
||||||
|
|
||||||
if !opts.NoHistory && result.finalContent != "" {
|
if !opts.NoHistory && result.finalContent != "" {
|
||||||
|
// Register the pending content so that fast follow-up inbound turns can
|
||||||
|
// inject it into their LLM context before OnDelivered persists it.
|
||||||
|
al.pendingDeliveries.Store(opts.SessionKey, result.finalContent)
|
||||||
|
|
||||||
var once sync.Once
|
var once sync.Once
|
||||||
response.OnDelivered = func(msgIDs []string) {
|
response.OnDelivered = func(msgIDs []string) {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
|
al.pendingDeliveries.Delete(opts.SessionKey)
|
||||||
assistantMsg := providers.Message{
|
assistantMsg := providers.Message{
|
||||||
Role: "assistant",
|
Role: "assistant",
|
||||||
Content: result.finalContent,
|
Content: result.finalContent,
|
||||||
|
|
@ -1843,6 +1849,20 @@ func (al *AgentLoop) runTurn(ctx context.Context, ts *turnState) (turnResult, er
|
||||||
}
|
}
|
||||||
ts.captureRestorePoint(history, summary)
|
ts.captureRestorePoint(history, summary)
|
||||||
|
|
||||||
|
// Inject pending undelivered assistant reply into history so regular inbound turns
|
||||||
|
// see it in LLM context even before OnDelivered persists it to session storage.
|
||||||
|
// Only inject if history doesn't already end with an assistant message (avoids duplication
|
||||||
|
// when OnDelivered fires before the next turn starts).
|
||||||
|
if !ts.opts.NoHistory {
|
||||||
|
if pendingRaw, ok := al.pendingDeliveries.Load(ts.sessionKey); ok {
|
||||||
|
if pendingContent, _ := pendingRaw.(string); pendingContent != "" {
|
||||||
|
if len(history) == 0 || history[len(history)-1].Role != "assistant" {
|
||||||
|
history = append(history, providers.Message{Role: "assistant", Content: pendingContent})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
messages := ts.agent.ContextBuilder.BuildMessages(
|
messages := ts.agent.ContextBuilder.BuildMessages(
|
||||||
history,
|
history,
|
||||||
summary,
|
summary,
|
||||||
|
|
|
||||||
|
|
@ -286,6 +286,7 @@ func (c *BaseChannel) HandleMessage(
|
||||||
MessageID: messageID,
|
MessageID: messageID,
|
||||||
MediaScope: scope,
|
MediaScope: scope,
|
||||||
Metadata: metadata,
|
Metadata: metadata,
|
||||||
|
ReplyToMessageID: metadata["reply_to_message_id"],
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto-trigger typing indicator, message reaction, and placeholder before publishing.
|
// Auto-trigger typing indicator, message reaction, and placeholder before publishing.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue