mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 22:11:36 +00:00
refactor(reply): share embedded run fallback/context builders
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
import crypto from "node:crypto";
|
import crypto from "node:crypto";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import { resolveAgentModelFallbacksOverride } from "../../agents/agent-scope.js";
|
|
||||||
import { runCliAgent } from "../../agents/cli-runner.js";
|
import { runCliAgent } from "../../agents/cli-runner.js";
|
||||||
import { getCliSessionId } from "../../agents/cli-session.js";
|
import { getCliSessionId } from "../../agents/cli-session.js";
|
||||||
import { runWithModelFallback } from "../../agents/model-fallback.js";
|
import { runWithModelFallback } from "../../agents/model-fallback.js";
|
||||||
@@ -14,7 +13,6 @@ import {
|
|||||||
} from "../../agents/pi-embedded-helpers.js";
|
} from "../../agents/pi-embedded-helpers.js";
|
||||||
import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
|
import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
|
||||||
import {
|
import {
|
||||||
resolveAgentIdFromSessionKey,
|
|
||||||
resolveGroupSessionKey,
|
resolveGroupSessionKey,
|
||||||
resolveSessionTranscriptPath,
|
resolveSessionTranscriptPath,
|
||||||
type SessionEntry,
|
type SessionEntry,
|
||||||
@@ -33,11 +31,10 @@ import type { VerboseLevel } from "../thinking.js";
|
|||||||
import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../tokens.js";
|
import { isSilentReplyText, SILENT_REPLY_TOKEN } from "../tokens.js";
|
||||||
import type { GetReplyOptions, ReplyPayload } from "../types.js";
|
import type { GetReplyOptions, ReplyPayload } from "../types.js";
|
||||||
import {
|
import {
|
||||||
buildEmbeddedContextFromTemplate,
|
buildEmbeddedRunBaseParams,
|
||||||
buildTemplateSenderContext,
|
buildEmbeddedRunContexts,
|
||||||
resolveRunAuthProfile,
|
resolveModelFallbackOptions,
|
||||||
} from "./agent-runner-utils.js";
|
} from "./agent-runner-utils.js";
|
||||||
import { resolveEnforceFinalTag } from "./agent-runner-utils.js";
|
|
||||||
import { type BlockReplyPipeline } from "./block-reply-pipeline.js";
|
import { type BlockReplyPipeline } from "./block-reply-pipeline.js";
|
||||||
import type { FollowupRun } from "./queue.js";
|
import type { FollowupRun } from "./queue.js";
|
||||||
import { createBlockReplyDeliveryHandler } from "./reply-delivery.js";
|
import { createBlockReplyDeliveryHandler } from "./reply-delivery.js";
|
||||||
@@ -157,14 +154,7 @@ export async function runAgentTurnWithFallback(params: {
|
|||||||
const blockReplyPipeline = params.blockReplyPipeline;
|
const blockReplyPipeline = params.blockReplyPipeline;
|
||||||
const onToolResult = params.opts?.onToolResult;
|
const onToolResult = params.opts?.onToolResult;
|
||||||
const fallbackResult = await runWithModelFallback({
|
const fallbackResult = await runWithModelFallback({
|
||||||
cfg: params.followupRun.run.config,
|
...resolveModelFallbackOptions(params.followupRun.run),
|
||||||
provider: params.followupRun.run.provider,
|
|
||||||
model: params.followupRun.run.model,
|
|
||||||
agentDir: params.followupRun.run.agentDir,
|
|
||||||
fallbacksOverride: resolveAgentModelFallbacksOverride(
|
|
||||||
params.followupRun.run.config,
|
|
||||||
resolveAgentIdFromSessionKey(params.followupRun.run.sessionKey),
|
|
||||||
),
|
|
||||||
run: (provider, model) => {
|
run: (provider, model) => {
|
||||||
// Notify that model selection is complete (including after fallback).
|
// Notify that model selection is complete (including after fallback).
|
||||||
// This allows responsePrefix template interpolation with the actual model.
|
// This allows responsePrefix template interpolation with the actual model.
|
||||||
@@ -262,13 +252,19 @@ export async function runAgentTurnWithFallback(params: {
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
const authProfile = resolveRunAuthProfile(params.followupRun.run, provider);
|
const { authProfile, embeddedContext, senderContext } = buildEmbeddedRunContexts({
|
||||||
const embeddedContext = buildEmbeddedContextFromTemplate({
|
|
||||||
run: params.followupRun.run,
|
run: params.followupRun.run,
|
||||||
sessionCtx: params.sessionCtx,
|
sessionCtx: params.sessionCtx,
|
||||||
hasRepliedRef: params.opts?.hasRepliedRef,
|
hasRepliedRef: params.opts?.hasRepliedRef,
|
||||||
|
provider,
|
||||||
|
});
|
||||||
|
const runBaseParams = buildEmbeddedRunBaseParams({
|
||||||
|
run: params.followupRun.run,
|
||||||
|
provider,
|
||||||
|
model,
|
||||||
|
runId,
|
||||||
|
authProfile,
|
||||||
});
|
});
|
||||||
const senderContext = buildTemplateSenderContext(params.sessionCtx);
|
|
||||||
return runEmbeddedPiAgent({
|
return runEmbeddedPiAgent({
|
||||||
...embeddedContext,
|
...embeddedContext,
|
||||||
groupId: resolveGroupSessionKey(params.sessionCtx)?.id,
|
groupId: resolveGroupSessionKey(params.sessionCtx)?.id,
|
||||||
@@ -276,22 +272,9 @@ export async function runAgentTurnWithFallback(params: {
|
|||||||
params.sessionCtx.GroupChannel?.trim() ?? params.sessionCtx.GroupSubject?.trim(),
|
params.sessionCtx.GroupChannel?.trim() ?? params.sessionCtx.GroupSubject?.trim(),
|
||||||
groupSpace: params.sessionCtx.GroupSpace?.trim() ?? undefined,
|
groupSpace: params.sessionCtx.GroupSpace?.trim() ?? undefined,
|
||||||
...senderContext,
|
...senderContext,
|
||||||
sessionFile: params.followupRun.run.sessionFile,
|
...runBaseParams,
|
||||||
workspaceDir: params.followupRun.run.workspaceDir,
|
|
||||||
agentDir: params.followupRun.run.agentDir,
|
|
||||||
config: params.followupRun.run.config,
|
|
||||||
skillsSnapshot: params.followupRun.run.skillsSnapshot,
|
|
||||||
prompt: params.commandBody,
|
prompt: params.commandBody,
|
||||||
extraSystemPrompt: params.followupRun.run.extraSystemPrompt,
|
extraSystemPrompt: params.followupRun.run.extraSystemPrompt,
|
||||||
ownerNumbers: params.followupRun.run.ownerNumbers,
|
|
||||||
enforceFinalTag: resolveEnforceFinalTag(params.followupRun.run, provider),
|
|
||||||
provider,
|
|
||||||
model,
|
|
||||||
...authProfile,
|
|
||||||
thinkLevel: params.followupRun.run.thinkLevel,
|
|
||||||
verboseLevel: params.followupRun.run.verboseLevel,
|
|
||||||
reasoningLevel: params.followupRun.run.reasoningLevel,
|
|
||||||
execOverrides: params.followupRun.run.execOverrides,
|
|
||||||
toolResultFormat: (() => {
|
toolResultFormat: (() => {
|
||||||
const channel = resolveMessageChannel(
|
const channel = resolveMessageChannel(
|
||||||
params.sessionCtx.Surface,
|
params.sessionCtx.Surface,
|
||||||
@@ -303,9 +286,6 @@ export async function runAgentTurnWithFallback(params: {
|
|||||||
return isMarkdownCapableMessageChannel(channel) ? "markdown" : "plain";
|
return isMarkdownCapableMessageChannel(channel) ? "markdown" : "plain";
|
||||||
})(),
|
})(),
|
||||||
suppressToolErrorWarnings: params.opts?.suppressToolErrorWarnings,
|
suppressToolErrorWarnings: params.opts?.suppressToolErrorWarnings,
|
||||||
bashElevated: params.followupRun.run.bashElevated,
|
|
||||||
timeoutMs: params.followupRun.run.timeoutMs,
|
|
||||||
runId,
|
|
||||||
images: params.opts?.images,
|
images: params.opts?.images,
|
||||||
abortSignal: params.opts?.abortSignal,
|
abortSignal: params.opts?.abortSignal,
|
||||||
blockReplyBreak: params.resolvedBlockStreamingBreak,
|
blockReplyBreak: params.resolvedBlockStreamingBreak,
|
||||||
|
|||||||
@@ -1,26 +1,20 @@
|
|||||||
import crypto from "node:crypto";
|
import crypto from "node:crypto";
|
||||||
import { resolveAgentModelFallbacksOverride } from "../../agents/agent-scope.js";
|
|
||||||
import { runWithModelFallback } from "../../agents/model-fallback.js";
|
import { runWithModelFallback } from "../../agents/model-fallback.js";
|
||||||
import { isCliProvider } from "../../agents/model-selection.js";
|
import { isCliProvider } from "../../agents/model-selection.js";
|
||||||
import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
|
import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
|
||||||
import { resolveSandboxConfigForAgent, resolveSandboxRuntimeStatus } from "../../agents/sandbox.js";
|
import { resolveSandboxConfigForAgent, resolveSandboxRuntimeStatus } from "../../agents/sandbox.js";
|
||||||
import type { OpenClawConfig } from "../../config/config.js";
|
import type { OpenClawConfig } from "../../config/config.js";
|
||||||
import {
|
import { type SessionEntry, updateSessionStoreEntry } from "../../config/sessions.js";
|
||||||
resolveAgentIdFromSessionKey,
|
|
||||||
type SessionEntry,
|
|
||||||
updateSessionStoreEntry,
|
|
||||||
} from "../../config/sessions.js";
|
|
||||||
import { logVerbose } from "../../globals.js";
|
import { logVerbose } from "../../globals.js";
|
||||||
import { registerAgentRunContext } from "../../infra/agent-events.js";
|
import { registerAgentRunContext } from "../../infra/agent-events.js";
|
||||||
import type { TemplateContext } from "../templating.js";
|
import type { TemplateContext } from "../templating.js";
|
||||||
import type { VerboseLevel } from "../thinking.js";
|
import type { VerboseLevel } from "../thinking.js";
|
||||||
import type { GetReplyOptions } from "../types.js";
|
import type { GetReplyOptions } from "../types.js";
|
||||||
import {
|
import {
|
||||||
buildEmbeddedContextFromTemplate,
|
buildEmbeddedRunBaseParams,
|
||||||
buildTemplateSenderContext,
|
buildEmbeddedRunContexts,
|
||||||
resolveRunAuthProfile,
|
resolveModelFallbackOptions,
|
||||||
} from "./agent-runner-utils.js";
|
} from "./agent-runner-utils.js";
|
||||||
import { resolveEnforceFinalTag } from "./agent-runner-utils.js";
|
|
||||||
import {
|
import {
|
||||||
resolveMemoryFlushContextWindowTokens,
|
resolveMemoryFlushContextWindowTokens,
|
||||||
resolveMemoryFlushPromptForRun,
|
resolveMemoryFlushPromptForRun,
|
||||||
@@ -103,47 +97,30 @@ export async function runMemoryFlushIfNeeded(params: {
|
|||||||
.join("\n\n");
|
.join("\n\n");
|
||||||
try {
|
try {
|
||||||
await runWithModelFallback({
|
await runWithModelFallback({
|
||||||
cfg: params.followupRun.run.config,
|
...resolveModelFallbackOptions(params.followupRun.run),
|
||||||
provider: params.followupRun.run.provider,
|
|
||||||
model: params.followupRun.run.model,
|
|
||||||
agentDir: params.followupRun.run.agentDir,
|
|
||||||
fallbacksOverride: resolveAgentModelFallbacksOverride(
|
|
||||||
params.followupRun.run.config,
|
|
||||||
resolveAgentIdFromSessionKey(params.followupRun.run.sessionKey),
|
|
||||||
),
|
|
||||||
run: (provider, model) => {
|
run: (provider, model) => {
|
||||||
const authProfile = resolveRunAuthProfile(params.followupRun.run, provider);
|
const { authProfile, embeddedContext, senderContext } = buildEmbeddedRunContexts({
|
||||||
const embeddedContext = buildEmbeddedContextFromTemplate({
|
|
||||||
run: params.followupRun.run,
|
run: params.followupRun.run,
|
||||||
sessionCtx: params.sessionCtx,
|
sessionCtx: params.sessionCtx,
|
||||||
hasRepliedRef: params.opts?.hasRepliedRef,
|
hasRepliedRef: params.opts?.hasRepliedRef,
|
||||||
|
provider,
|
||||||
|
});
|
||||||
|
const runBaseParams = buildEmbeddedRunBaseParams({
|
||||||
|
run: params.followupRun.run,
|
||||||
|
provider,
|
||||||
|
model,
|
||||||
|
runId: flushRunId,
|
||||||
|
authProfile,
|
||||||
});
|
});
|
||||||
const senderContext = buildTemplateSenderContext(params.sessionCtx);
|
|
||||||
return runEmbeddedPiAgent({
|
return runEmbeddedPiAgent({
|
||||||
...embeddedContext,
|
...embeddedContext,
|
||||||
...senderContext,
|
...senderContext,
|
||||||
sessionFile: params.followupRun.run.sessionFile,
|
...runBaseParams,
|
||||||
workspaceDir: params.followupRun.run.workspaceDir,
|
|
||||||
agentDir: params.followupRun.run.agentDir,
|
|
||||||
config: params.followupRun.run.config,
|
|
||||||
skillsSnapshot: params.followupRun.run.skillsSnapshot,
|
|
||||||
prompt: resolveMemoryFlushPromptForRun({
|
prompt: resolveMemoryFlushPromptForRun({
|
||||||
prompt: memoryFlushSettings.prompt,
|
prompt: memoryFlushSettings.prompt,
|
||||||
cfg: params.cfg,
|
cfg: params.cfg,
|
||||||
}),
|
}),
|
||||||
extraSystemPrompt: flushSystemPrompt,
|
extraSystemPrompt: flushSystemPrompt,
|
||||||
ownerNumbers: params.followupRun.run.ownerNumbers,
|
|
||||||
enforceFinalTag: resolveEnforceFinalTag(params.followupRun.run, provider),
|
|
||||||
provider,
|
|
||||||
model,
|
|
||||||
...authProfile,
|
|
||||||
thinkLevel: params.followupRun.run.thinkLevel,
|
|
||||||
verboseLevel: params.followupRun.run.verboseLevel,
|
|
||||||
reasoningLevel: params.followupRun.run.reasoningLevel,
|
|
||||||
execOverrides: params.followupRun.run.execOverrides,
|
|
||||||
bashElevated: params.followupRun.run.bashElevated,
|
|
||||||
timeoutMs: params.followupRun.run.timeoutMs,
|
|
||||||
runId: flushRunId,
|
|
||||||
onAgentEvent: (evt) => {
|
onAgentEvent: (evt) => {
|
||||||
if (evt.stream === "compaction") {
|
if (evt.stream === "compaction") {
|
||||||
const phase = typeof evt.data.phase === "string" ? evt.data.phase : "";
|
const phase = typeof evt.data.phase === "string" ? evt.data.phase : "";
|
||||||
|
|||||||
152
src/auto-reply/reply/agent-runner-utils.test.ts
Normal file
152
src/auto-reply/reply/agent-runner-utils.test.ts
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import type { FollowupRun } from "./queue.js";
|
||||||
|
|
||||||
|
const hoisted = vi.hoisted(() => {
|
||||||
|
const resolveAgentModelFallbacksOverrideMock = vi.fn();
|
||||||
|
const resolveAgentIdFromSessionKeyMock = vi.fn();
|
||||||
|
return { resolveAgentModelFallbacksOverrideMock, resolveAgentIdFromSessionKeyMock };
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.mock("../../agents/agent-scope.js", () => ({
|
||||||
|
resolveAgentModelFallbacksOverride: (...args: unknown[]) =>
|
||||||
|
hoisted.resolveAgentModelFallbacksOverrideMock(...args),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("../../config/sessions.js", () => ({
|
||||||
|
resolveAgentIdFromSessionKey: (...args: unknown[]) =>
|
||||||
|
hoisted.resolveAgentIdFromSessionKeyMock(...args),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const {
|
||||||
|
buildEmbeddedRunBaseParams,
|
||||||
|
buildEmbeddedRunContexts,
|
||||||
|
resolveModelFallbackOptions,
|
||||||
|
resolveProviderScopedAuthProfile,
|
||||||
|
} = await import("./agent-runner-utils.js");
|
||||||
|
|
||||||
|
function makeRun(overrides: Partial<FollowupRun["run"]> = {}): FollowupRun["run"] {
|
||||||
|
return {
|
||||||
|
sessionId: "session-1",
|
||||||
|
agentId: "agent-1",
|
||||||
|
config: { models: { providers: {} } },
|
||||||
|
provider: "openai",
|
||||||
|
model: "gpt-4.1",
|
||||||
|
agentDir: "/tmp/agent",
|
||||||
|
sessionKey: "agent:test:session",
|
||||||
|
sessionFile: "/tmp/session.json",
|
||||||
|
workspaceDir: "/tmp/workspace",
|
||||||
|
skillsSnapshot: [],
|
||||||
|
ownerNumbers: ["+15550001"],
|
||||||
|
enforceFinalTag: false,
|
||||||
|
thinkLevel: "medium",
|
||||||
|
verboseLevel: "off",
|
||||||
|
reasoningLevel: "none",
|
||||||
|
execOverrides: {},
|
||||||
|
bashElevated: false,
|
||||||
|
timeoutMs: 60_000,
|
||||||
|
...overrides,
|
||||||
|
} as unknown as FollowupRun["run"];
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("agent-runner-utils", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
hoisted.resolveAgentModelFallbacksOverrideMock.mockReset();
|
||||||
|
hoisted.resolveAgentIdFromSessionKeyMock.mockReset();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("resolves model fallback options from run context", () => {
|
||||||
|
hoisted.resolveAgentIdFromSessionKeyMock.mockReturnValue("agent-id");
|
||||||
|
hoisted.resolveAgentModelFallbacksOverrideMock.mockReturnValue(["fallback-model"]);
|
||||||
|
const run = makeRun();
|
||||||
|
|
||||||
|
const resolved = resolveModelFallbackOptions(run);
|
||||||
|
|
||||||
|
expect(hoisted.resolveAgentIdFromSessionKeyMock).toHaveBeenCalledWith(run.sessionKey);
|
||||||
|
expect(hoisted.resolveAgentModelFallbacksOverrideMock).toHaveBeenCalledWith(
|
||||||
|
run.config,
|
||||||
|
"agent-id",
|
||||||
|
);
|
||||||
|
expect(resolved).toEqual({
|
||||||
|
cfg: run.config,
|
||||||
|
provider: run.provider,
|
||||||
|
model: run.model,
|
||||||
|
agentDir: run.agentDir,
|
||||||
|
fallbacksOverride: ["fallback-model"],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("builds embedded run base params with auth profile and run metadata", () => {
|
||||||
|
const run = makeRun({ enforceFinalTag: true });
|
||||||
|
const authProfile = resolveProviderScopedAuthProfile({
|
||||||
|
provider: "openai",
|
||||||
|
primaryProvider: "openai",
|
||||||
|
authProfileId: "profile-openai",
|
||||||
|
authProfileIdSource: "user",
|
||||||
|
});
|
||||||
|
|
||||||
|
const resolved = buildEmbeddedRunBaseParams({
|
||||||
|
run,
|
||||||
|
provider: "openai",
|
||||||
|
model: "gpt-4.1-mini",
|
||||||
|
runId: "run-1",
|
||||||
|
authProfile,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(resolved).toMatchObject({
|
||||||
|
sessionFile: run.sessionFile,
|
||||||
|
workspaceDir: run.workspaceDir,
|
||||||
|
agentDir: run.agentDir,
|
||||||
|
config: run.config,
|
||||||
|
skillsSnapshot: run.skillsSnapshot,
|
||||||
|
ownerNumbers: run.ownerNumbers,
|
||||||
|
enforceFinalTag: true,
|
||||||
|
provider: "openai",
|
||||||
|
model: "gpt-4.1-mini",
|
||||||
|
authProfileId: "profile-openai",
|
||||||
|
authProfileIdSource: "user",
|
||||||
|
thinkLevel: run.thinkLevel,
|
||||||
|
verboseLevel: run.verboseLevel,
|
||||||
|
reasoningLevel: run.reasoningLevel,
|
||||||
|
execOverrides: run.execOverrides,
|
||||||
|
bashElevated: run.bashElevated,
|
||||||
|
timeoutMs: run.timeoutMs,
|
||||||
|
runId: "run-1",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("builds embedded contexts and scopes auth profile by provider", () => {
|
||||||
|
const run = makeRun({
|
||||||
|
authProfileId: "profile-openai",
|
||||||
|
authProfileIdSource: "auto",
|
||||||
|
});
|
||||||
|
|
||||||
|
const resolved = buildEmbeddedRunContexts({
|
||||||
|
run,
|
||||||
|
sessionCtx: {
|
||||||
|
Provider: "OpenAI",
|
||||||
|
To: "channel-1",
|
||||||
|
SenderId: "sender-1",
|
||||||
|
},
|
||||||
|
hasRepliedRef: undefined,
|
||||||
|
provider: "anthropic",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(resolved.authProfile).toEqual({
|
||||||
|
authProfileId: undefined,
|
||||||
|
authProfileIdSource: undefined,
|
||||||
|
});
|
||||||
|
expect(resolved.embeddedContext).toMatchObject({
|
||||||
|
sessionId: run.sessionId,
|
||||||
|
sessionKey: run.sessionKey,
|
||||||
|
agentId: run.agentId,
|
||||||
|
messageProvider: "openai",
|
||||||
|
messageTo: "channel-1",
|
||||||
|
});
|
||||||
|
expect(resolved.senderContext).toEqual({
|
||||||
|
senderId: "sender-1",
|
||||||
|
senderName: undefined,
|
||||||
|
senderUsername: undefined,
|
||||||
|
senderE164: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
|
import { resolveAgentModelFallbacksOverride } from "../../agents/agent-scope.js";
|
||||||
import type { NormalizedUsage } from "../../agents/usage.js";
|
import type { NormalizedUsage } from "../../agents/usage.js";
|
||||||
import { getChannelDock } from "../../channels/dock.js";
|
import { getChannelDock } from "../../channels/dock.js";
|
||||||
import type { ChannelId, ChannelThreadingToolContext } from "../../channels/plugins/types.js";
|
import type { ChannelId, ChannelThreadingToolContext } from "../../channels/plugins/types.js";
|
||||||
import { normalizeAnyChannelId, normalizeChannelId } from "../../channels/registry.js";
|
import { normalizeAnyChannelId, normalizeChannelId } from "../../channels/registry.js";
|
||||||
import type { OpenClawConfig } from "../../config/config.js";
|
import type { OpenClawConfig } from "../../config/config.js";
|
||||||
|
import { resolveAgentIdFromSessionKey } from "../../config/sessions.js";
|
||||||
import { isReasoningTagProvider } from "../../utils/provider-utils.js";
|
import { isReasoningTagProvider } from "../../utils/provider-utils.js";
|
||||||
import { estimateUsageCost, formatTokenCount, formatUsd } from "../../utils/usage-format.js";
|
import { estimateUsageCost, formatTokenCount, formatUsd } from "../../utils/usage-format.js";
|
||||||
import type { TemplateContext } from "../templating.js";
|
import type { TemplateContext } from "../templating.js";
|
||||||
@@ -135,6 +137,47 @@ export const appendUsageLine = (payloads: ReplyPayload[], line: string): ReplyPa
|
|||||||
export const resolveEnforceFinalTag = (run: FollowupRun["run"], provider: string) =>
|
export const resolveEnforceFinalTag = (run: FollowupRun["run"], provider: string) =>
|
||||||
Boolean(run.enforceFinalTag || isReasoningTagProvider(provider));
|
Boolean(run.enforceFinalTag || isReasoningTagProvider(provider));
|
||||||
|
|
||||||
|
export function resolveModelFallbackOptions(run: FollowupRun["run"]) {
|
||||||
|
return {
|
||||||
|
cfg: run.config,
|
||||||
|
provider: run.provider,
|
||||||
|
model: run.model,
|
||||||
|
agentDir: run.agentDir,
|
||||||
|
fallbacksOverride: resolveAgentModelFallbacksOverride(
|
||||||
|
run.config,
|
||||||
|
resolveAgentIdFromSessionKey(run.sessionKey),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildEmbeddedRunBaseParams(params: {
|
||||||
|
run: FollowupRun["run"];
|
||||||
|
provider: string;
|
||||||
|
model: string;
|
||||||
|
runId: string;
|
||||||
|
authProfile: ReturnType<typeof resolveProviderScopedAuthProfile>;
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
sessionFile: params.run.sessionFile,
|
||||||
|
workspaceDir: params.run.workspaceDir,
|
||||||
|
agentDir: params.run.agentDir,
|
||||||
|
config: params.run.config,
|
||||||
|
skillsSnapshot: params.run.skillsSnapshot,
|
||||||
|
ownerNumbers: params.run.ownerNumbers,
|
||||||
|
enforceFinalTag: resolveEnforceFinalTag(params.run, params.provider),
|
||||||
|
provider: params.provider,
|
||||||
|
model: params.model,
|
||||||
|
...params.authProfile,
|
||||||
|
thinkLevel: params.run.thinkLevel,
|
||||||
|
verboseLevel: params.run.verboseLevel,
|
||||||
|
reasoningLevel: params.run.reasoningLevel,
|
||||||
|
execOverrides: params.run.execOverrides,
|
||||||
|
bashElevated: params.run.bashElevated,
|
||||||
|
timeoutMs: params.run.timeoutMs,
|
||||||
|
runId: params.runId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function buildEmbeddedContextFromTemplate(params: {
|
export function buildEmbeddedContextFromTemplate(params: {
|
||||||
run: FollowupRun["run"];
|
run: FollowupRun["run"];
|
||||||
sessionCtx: TemplateContext;
|
sessionCtx: TemplateContext;
|
||||||
@@ -175,6 +218,23 @@ export function resolveRunAuthProfile(run: FollowupRun["run"], provider: string)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildEmbeddedRunContexts(params: {
|
||||||
|
run: FollowupRun["run"];
|
||||||
|
sessionCtx: TemplateContext;
|
||||||
|
hasRepliedRef: { value: boolean } | undefined;
|
||||||
|
provider: string;
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
authProfile: resolveRunAuthProfile(params.run, params.provider),
|
||||||
|
embeddedContext: buildEmbeddedContextFromTemplate({
|
||||||
|
run: params.run,
|
||||||
|
sessionCtx: params.sessionCtx,
|
||||||
|
hasRepliedRef: params.hasRepliedRef,
|
||||||
|
}),
|
||||||
|
senderContext: buildTemplateSenderContext(params.sessionCtx),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function resolveProviderScopedAuthProfile(params: {
|
export function resolveProviderScopedAuthProfile(params: {
|
||||||
provider: string;
|
provider: string;
|
||||||
primaryProvider: string;
|
primaryProvider: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user