openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
159 lines (158 loc) • 6.85 kB
JavaScript
import { a as normalizeOptionalAgentRuntimeId } from "./agent-runtime-id-BpfvnoN1.js";
import { t as DEFAULT_CONTEXT_TOKENS } from "./defaults-CdX9UGcX.js";
import { a as isAgentHarnessSessionKey, c as isValidAgentHarnessSessionStoreEntry, d as resolveAgentHarnessSessionStoreEntryError, h as resolveSessionPinnedHarnessId, n as AGENT_HARNESS_SESSION_ID_LOCKED_MESSAGE, r as AGENT_HARNESS_SESSION_KEY_RESERVED_MESSAGE } from "./agent-harness-session-key-BOz3yx0-.js";
import { t as FailoverError } from "./error-Bb_OF8ag.js";
import "./failover-error-BkNxlp8A.js";
import { t as log } from "./logger-C3TD2wdV.js";
import { a as resolveContextWindowInfo, i as formatContextWindowWarningMessage, n as evaluateContextWindowGuard, r as formatContextWindowBlockMessage } from "./context-window-guard-DHDMEGvr.js";
import { t as readAgentModelContextTokens } from "./model-context-tokens-Cy1KpVE9.js";
import { t as resolveModelContextWindowProfile } from "./model-context-window-CoR3Uyg1.js";
//#region src/agents/embedded-agent-runner/run/setup.ts
/** Durable harness sessions run only with their exact persisted identity and runtime lock. */
function resolveAgentHarnessRunAdmissionError(params) {
const sessionKey = params.sessionKey?.trim();
if (!sessionKey) return;
const entry = params.entry;
const reservedKey = isAgentHarnessSessionKey(sessionKey);
if (!entry) return reservedKey ? AGENT_HARNESS_SESSION_KEY_RESERVED_MESSAGE : void 0;
if (entry.modelSelectionLocked !== true) return;
const durableEntryError = resolveAgentHarnessSessionStoreEntryError(sessionKey, entry);
if (durableEntryError) return durableEntryError;
if (!isValidAgentHarnessSessionStoreEntry(sessionKey, entry)) return;
const requestedHarnessId = normalizeOptionalAgentRuntimeId(params.agentHarnessId);
const durableHarnessId = resolveSessionPinnedHarnessId(entry);
const matchesRequestedRuntime = params.modelSelectionLocked === true && requestedHarnessId === durableHarnessId;
const matchesDurableRuntime = entry.sessionId === params.sessionId && durableHarnessId !== void 0;
return matchesRequestedRuntime && matchesDurableRuntime ? void 0 : reservedKey ? AGENT_HARNESS_SESSION_KEY_RESERVED_MESSAGE : AGENT_HARNESS_SESSION_ID_LOCKED_MESSAGE;
}
/**
* Runs model-selection hooks before resolving the runtime model.
*/
async function resolveHookModelSelection(params) {
let provider = params.provider;
let modelId = params.modelId;
if (params.modelSelectionLocked === true) return {
provider,
modelId
};
let modelResolveOverride;
const hookRunner = params.hookRunner;
if (hookRunner?.hasHooks("before_model_resolve")) try {
const event = params.attachments ? {
prompt: params.prompt,
attachments: params.attachments
} : { prompt: params.prompt };
modelResolveOverride = await hookRunner.runBeforeModelResolve(event, params.hookContext);
} catch (hookErr) {
log.warn(`before_model_resolve hook failed: ${String(hookErr)}`);
}
if (modelResolveOverride?.providerOverride) {
provider = modelResolveOverride.providerOverride;
log.info(`[hooks] provider overridden to ${provider}`);
}
if (modelResolveOverride?.modelOverride) {
modelId = modelResolveOverride.modelOverride;
log.info(`[hooks] model overridden to ${modelId}`);
}
return {
provider,
modelId
};
}
/**
* Converts prompt image refs into the minimal attachment shape exposed to
* before-model-resolve hooks. Empty image lists stay undefined so hook payloads
* do not grow a meaningless attachments field.
*/
function buildBeforeModelResolveAttachments(images) {
if (!images?.length) return;
return images.map((img) => ({
kind: "image",
mimeType: img.mimeType
}));
}
/** Builds structural model metadata for a harness that resolves its real model natively. */
function createNativeModelOwnedRuntimeModel(params) {
return {
provider: params.provider,
id: params.modelId,
name: params.modelId,
baseUrl: "",
api: "openai-responses",
reasoning: true,
input: ["text", "image"],
cost: {
input: 0,
output: 0,
cacheRead: 0,
cacheWrite: 0
},
contextWindow: DEFAULT_CONTEXT_TOKENS,
maxTokens: DEFAULT_CONTEXT_TOKENS
};
}
/**
* Resolves context-window policy for the selected runtime model and returns the
* model shape the session runtime should see. Configured context caps are
* reflected in `effectiveModel.contextWindow` so auto-compaction uses the same
* limit as the guard.
*/
function resolveEffectiveRuntimeModel(params) {
const contextWindowProfile = resolveModelContextWindowProfile({
catalogEntry: params.runtimeModel,
selected: params.contextWindow
});
const resolvedCtxInfo = resolveContextWindowInfo({
cfg: params.cfg,
provider: params.contextConfigProvider ?? params.provider,
modelId: params.modelId,
modelContextTokens: readAgentModelContextTokens(params.runtimeModel),
modelContextWindow: contextWindowProfile.contextTokens,
defaultTokens: DEFAULT_CONTEXT_TOKENS
});
const ctxInfo = contextWindowProfile.contextWindow && contextWindowProfile.contextTokens !== void 0 && resolvedCtxInfo.tokens > contextWindowProfile.contextTokens ? {
...resolvedCtxInfo,
tokens: contextWindowProfile.contextTokens,
source: "model"
} : resolvedCtxInfo;
const effectiveModel = ctxInfo.tokens < (params.runtimeModel.contextWindow ?? Infinity) ? {
...params.runtimeModel,
contextWindow: ctxInfo.tokens
} : params.runtimeModel;
const ctxGuard = evaluateContextWindowGuard({ info: ctxInfo });
const runtimeBaseUrl = typeof params.runtimeModel.baseUrl === "string" ? params.runtimeModel.baseUrl : void 0;
if (ctxGuard.shouldWarn) log.warn(formatContextWindowWarningMessage({
provider: params.provider,
modelId: params.modelId,
guard: ctxGuard,
runtimeBaseUrl
}));
if (ctxGuard.shouldBlock) {
const message = formatContextWindowBlockMessage({
guard: ctxGuard,
runtimeBaseUrl
});
log.error(`blocked model (context window too small): ${params.provider}/${params.modelId} ctx=${ctxGuard.tokens} (min=${ctxGuard.hardMinTokens}) source=${ctxGuard.source}; ${message}`);
throw new FailoverError(message, {
reason: "unknown",
provider: params.provider,
model: params.modelId
});
}
return {
ctxInfo,
effectiveModel
};
}
/** Resolves only OpenClaw-owned context policy; native model owners keep that policy private. */
function resolveEmbeddedRuntimeModelPolicy(params) {
if (params.nativeModelOwned) return { effectiveModel: params.runtimeModel };
const resolved = resolveEffectiveRuntimeModel(params);
return {
contextWindowInfo: resolved.ctxInfo,
contextTokenBudget: resolved.ctxInfo.tokens,
effectiveModel: resolved.effectiveModel
};
}
//#endregion
export { resolveHookModelSelection as a, resolveEmbeddedRuntimeModelPolicy as i, createNativeModelOwnedRuntimeModel as n, resolveAgentHarnessRunAdmissionError as r, buildBeforeModelResolveAttachments as t };