From 423b7a0f2855836d34e68fdf21a04faa7625d95e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 17 Feb 2026 00:10:26 +0000 Subject: [PATCH] refactor(auto-reply): reuse embedded run context helpers --- .../reply/agent-runner-execution.ts | 42 ++++++--------- src/auto-reply/reply/agent-runner-memory.ts | 42 ++++++--------- src/auto-reply/reply/agent-runner-utils.ts | 54 +++++++++++++++++++ src/auto-reply/reply/followup-runner.ts | 7 ++- 4 files changed, 89 insertions(+), 56 deletions(-) diff --git a/src/auto-reply/reply/agent-runner-execution.ts b/src/auto-reply/reply/agent-runner-execution.ts index 1218c113e22..5d3b2351f83 100644 --- a/src/auto-reply/reply/agent-runner-execution.ts +++ b/src/auto-reply/reply/agent-runner-execution.ts @@ -34,7 +34,12 @@ import { } from "../../utils/message-channel.js"; import { stripHeartbeatToken } from "../heartbeat.js"; import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../tokens.js"; -import { buildThreadingToolContext, resolveEnforceFinalTag } from "./agent-runner-utils.js"; +import { + buildEmbeddedContextFromTemplate, + buildTemplateSenderContext, + resolveEnforceFinalTag, + resolveRunAuthProfile, +} from "./agent-runner-utils.js"; import { type BlockReplyPipeline } from "./block-reply-pipeline.js"; import { createBlockReplyDeliveryHandler } from "./reply-delivery.js"; @@ -257,32 +262,20 @@ export async function runAgentTurnWithFallback(params: { } })(); } - const authProfileId = - provider === params.followupRun.run.provider - ? params.followupRun.run.authProfileId - : undefined; + const authProfile = resolveRunAuthProfile(params.followupRun.run, provider); + const embeddedContext = buildEmbeddedContextFromTemplate({ + run: params.followupRun.run, + sessionCtx: params.sessionCtx, + hasRepliedRef: params.opts?.hasRepliedRef, + }); + const senderContext = buildTemplateSenderContext(params.sessionCtx); return runEmbeddedPiAgent({ - sessionId: params.followupRun.run.sessionId, - sessionKey: params.sessionKey, - agentId: params.followupRun.run.agentId, - messageProvider: params.sessionCtx.Provider?.trim().toLowerCase() || undefined, - agentAccountId: params.sessionCtx.AccountId, - messageTo: params.sessionCtx.OriginatingTo ?? params.sessionCtx.To, - messageThreadId: params.sessionCtx.MessageThreadId ?? undefined, + ...embeddedContext, groupId: resolveGroupSessionKey(params.sessionCtx)?.id, groupChannel: params.sessionCtx.GroupChannel?.trim() ?? params.sessionCtx.GroupSubject?.trim(), groupSpace: params.sessionCtx.GroupSpace?.trim() ?? undefined, - senderId: params.sessionCtx.SenderId?.trim() || undefined, - senderName: params.sessionCtx.SenderName?.trim() || undefined, - senderUsername: params.sessionCtx.SenderUsername?.trim() || undefined, - senderE164: params.sessionCtx.SenderE164?.trim() || undefined, - // Provider threading context for tool auto-injection - ...buildThreadingToolContext({ - sessionCtx: params.sessionCtx, - config: params.followupRun.run.config, - hasRepliedRef: params.opts?.hasRepliedRef, - }), + ...senderContext, sessionFile: params.followupRun.run.sessionFile, workspaceDir: params.followupRun.run.workspaceDir, agentDir: params.followupRun.run.agentDir, @@ -294,10 +287,7 @@ export async function runAgentTurnWithFallback(params: { enforceFinalTag: resolveEnforceFinalTag(params.followupRun.run, provider), provider, model, - authProfileId, - authProfileIdSource: authProfileId - ? params.followupRun.run.authProfileIdSource - : undefined, + ...authProfile, thinkLevel: params.followupRun.run.thinkLevel, verboseLevel: params.followupRun.run.verboseLevel, reasoningLevel: params.followupRun.run.reasoningLevel, diff --git a/src/auto-reply/reply/agent-runner-memory.ts b/src/auto-reply/reply/agent-runner-memory.ts index de81ffec664..e2514865885 100644 --- a/src/auto-reply/reply/agent-runner-memory.ts +++ b/src/auto-reply/reply/agent-runner-memory.ts @@ -16,7 +16,12 @@ import { } from "../../config/sessions.js"; import { logVerbose } from "../../globals.js"; import { registerAgentRunContext } from "../../infra/agent-events.js"; -import { buildThreadingToolContext, resolveEnforceFinalTag } from "./agent-runner-utils.js"; +import { + buildEmbeddedContextFromTemplate, + buildTemplateSenderContext, + resolveEnforceFinalTag, + resolveRunAuthProfile, +} from "./agent-runner-utils.js"; import { resolveMemoryFlushContextWindowTokens, resolveMemoryFlushPromptForRun, @@ -107,28 +112,16 @@ export async function runMemoryFlushIfNeeded(params: { resolveAgentIdFromSessionKey(params.followupRun.run.sessionKey), ), run: (provider, model) => { - const authProfileId = - provider === params.followupRun.run.provider - ? params.followupRun.run.authProfileId - : undefined; + const authProfile = resolveRunAuthProfile(params.followupRun.run, provider); + const embeddedContext = buildEmbeddedContextFromTemplate({ + run: params.followupRun.run, + sessionCtx: params.sessionCtx, + hasRepliedRef: params.opts?.hasRepliedRef, + }); + const senderContext = buildTemplateSenderContext(params.sessionCtx); return runEmbeddedPiAgent({ - sessionId: params.followupRun.run.sessionId, - sessionKey: params.sessionKey, - agentId: params.followupRun.run.agentId, - messageProvider: params.sessionCtx.Provider?.trim().toLowerCase() || undefined, - agentAccountId: params.sessionCtx.AccountId, - messageTo: params.sessionCtx.OriginatingTo ?? params.sessionCtx.To, - messageThreadId: params.sessionCtx.MessageThreadId ?? undefined, - // Provider threading context for tool auto-injection - ...buildThreadingToolContext({ - sessionCtx: params.sessionCtx, - config: params.followupRun.run.config, - hasRepliedRef: params.opts?.hasRepliedRef, - }), - senderId: params.sessionCtx.SenderId?.trim() || undefined, - senderName: params.sessionCtx.SenderName?.trim() || undefined, - senderUsername: params.sessionCtx.SenderUsername?.trim() || undefined, - senderE164: params.sessionCtx.SenderE164?.trim() || undefined, + ...embeddedContext, + ...senderContext, sessionFile: params.followupRun.run.sessionFile, workspaceDir: params.followupRun.run.workspaceDir, agentDir: params.followupRun.run.agentDir, @@ -143,10 +136,7 @@ export async function runMemoryFlushIfNeeded(params: { enforceFinalTag: resolveEnforceFinalTag(params.followupRun.run, provider), provider, model, - authProfileId, - authProfileIdSource: authProfileId - ? params.followupRun.run.authProfileIdSource - : undefined, + ...authProfile, thinkLevel: params.followupRun.run.thinkLevel, verboseLevel: params.followupRun.run.verboseLevel, reasoningLevel: params.followupRun.run.reasoningLevel, diff --git a/src/auto-reply/reply/agent-runner-utils.ts b/src/auto-reply/reply/agent-runner-utils.ts index b7c7153c70a..288a9ac6a29 100644 --- a/src/auto-reply/reply/agent-runner-utils.ts +++ b/src/auto-reply/reply/agent-runner-utils.ts @@ -134,3 +134,57 @@ export const appendUsageLine = (payloads: ReplyPayload[], line: string): ReplyPa export const resolveEnforceFinalTag = (run: FollowupRun["run"], provider: string) => Boolean(run.enforceFinalTag || isReasoningTagProvider(provider)); + +export function buildEmbeddedContextFromTemplate(params: { + run: FollowupRun["run"]; + sessionCtx: TemplateContext; + hasRepliedRef: { value: boolean } | undefined; +}) { + return { + sessionId: params.run.sessionId, + sessionKey: params.run.sessionKey, + agentId: params.run.agentId, + messageProvider: params.sessionCtx.Provider?.trim().toLowerCase() || undefined, + agentAccountId: params.sessionCtx.AccountId, + messageTo: params.sessionCtx.OriginatingTo ?? params.sessionCtx.To, + messageThreadId: params.sessionCtx.MessageThreadId ?? undefined, + // Provider threading context for tool auto-injection + ...buildThreadingToolContext({ + sessionCtx: params.sessionCtx, + config: params.run.config, + hasRepliedRef: params.hasRepliedRef, + }), + }; +} + +export function buildTemplateSenderContext(sessionCtx: TemplateContext) { + return { + senderId: sessionCtx.SenderId?.trim() || undefined, + senderName: sessionCtx.SenderName?.trim() || undefined, + senderUsername: sessionCtx.SenderUsername?.trim() || undefined, + senderE164: sessionCtx.SenderE164?.trim() || undefined, + }; +} + +export function resolveRunAuthProfile(run: FollowupRun["run"], provider: string) { + return resolveProviderScopedAuthProfile({ + provider, + primaryProvider: run.provider, + authProfileId: run.authProfileId, + authProfileIdSource: run.authProfileIdSource, + }); +} + +export function resolveProviderScopedAuthProfile(params: { + provider: string; + primaryProvider: string; + authProfileId?: string; + authProfileIdSource?: "auto" | "user"; +}): { authProfileId?: string; authProfileIdSource?: "auto" | "user" } { + const authProfileId = + params.provider === params.primaryProvider ? params.authProfileId : undefined; + return { + authProfileId, + authProfileIdSource: authProfileId ? params.authProfileIdSource : undefined, + }; +} diff --git a/src/auto-reply/reply/followup-runner.ts b/src/auto-reply/reply/followup-runner.ts index cefb8cd21b1..1ef7734e8d4 100644 --- a/src/auto-reply/reply/followup-runner.ts +++ b/src/auto-reply/reply/followup-runner.ts @@ -15,6 +15,7 @@ import { registerAgentRunContext } from "../../infra/agent-events.js"; import { defaultRuntime } from "../../runtime.js"; import { stripHeartbeatToken } from "../heartbeat.js"; import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../tokens.js"; +import { resolveRunAuthProfile } from "./agent-runner-utils.js"; import { applyReplyThreading, filterMessagingToolDuplicates, @@ -135,8 +136,7 @@ export function createFollowupRunner(params: { resolveAgentIdFromSessionKey(queued.run.sessionKey), ), run: (provider, model) => { - const authProfileId = - provider === queued.run.provider ? queued.run.authProfileId : undefined; + const authProfile = resolveRunAuthProfile(queued.run, provider); return runEmbeddedPiAgent({ sessionId: queued.run.sessionId, sessionKey: queued.run.sessionKey, @@ -162,8 +162,7 @@ export function createFollowupRunner(params: { enforceFinalTag: queued.run.enforceFinalTag, provider, model, - authProfileId, - authProfileIdSource: authProfileId ? queued.run.authProfileIdSource : undefined, + ...authProfile, thinkLevel: queued.run.thinkLevel, verboseLevel: queued.run.verboseLevel, reasoningLevel: queued.run.reasoningLevel,