UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

479 lines (478 loc) 18.6 kB
import { n as getRuntimeConfig } from "./io.runtime-B9iJRs3w.js"; import { m as resolveAgentWorkspaceDir, u as resolveAgentDir, y as resolveDefaultAgentId } from "./agent-scope-config-DcbEhP0R.js"; import { n as resolvePreferredOpenClawTmpDir } from "./tmp-openclaw-dir-DnyL0lW9.js"; import { r as withTempWorkspace } from "./private-temp-workspace-Dh7teFP0.js"; import "./agent-scope-DbtJyKUL.js"; import "./config-Cs0XXL3x.js"; import { n as withPluginRuntimeGenerationScope } from "./generation-scope-Cf83d_iq.js"; import { r as ensureAuthProfileStore } from "./store-F1B2duCT.js"; import { n as getRegisteredAgentHarness } from "./registry-D1_C7waJ.js"; import { a as unwrapSecretSentinelsForProviderEgress, i as unwrapModelHeaderSentinelsForProviderEgress } from "./provider-secret-egress-C-JiHB7J.js"; import { a as resolveCliRuntimeCanonicalProvider, i as resolveCliBackendConfig } from "./cli-backends-Bs_a4MW0.js"; import { i as isCliRuntimeAliasForProvider, s as resolveCliRuntimeExecutionProvider } from "./model-runtime-aliases-BJ2qM8I_.js"; import { o as resolveEffectiveAgentRuntime } from "./thinking-runtime-BiFbTVdI.js"; import { t as acquireAgentRunPreparedModelRuntime } from "./prepared-model-runtime-DgNj94yb.js"; import "./model-auth-C48_DZ-I.js"; import { o as prepareSystemAgentRunAdmission } from "./admitted-run-context-CHY5SdVF.js"; import { i as preparedAgentRuntimeProfileAttemptHasCandidate, n as canRunPreparedAgentRuntimeAuthAttempt, r as prepareAgentRuntimeAuth } from "./prepare-auth-Ci9igqt8.js"; import { r as resolveModelWithRegistry } from "./model-qCT5QXYI.js"; import { n as prepareSimpleCompletionModel } from "./simple-completion-runtime-Dgdi_92D.js"; import { t as resolveEmbeddedCliBackendDispatchEligibility } from "./cli-backend-dispatch-eligibility-42vj_OnX.js"; import { r as scopeAuthProfileStoreToPreparedPlan } from "./resolve-auth-DN46qixj.js"; import { t as ensureSelectedAgentHarnessPlugin } from "./runtime-plugin-D91_vuOE.js"; import { a as normalizeCliModel } from "./helpers-D0iW2O3m.js"; import path from "node:path"; import { randomUUID } from "node:crypto"; //#region src/agents/isolated-completion.ts /** * Fresh, prompt-only inference with an exact zero-tool execution contract. * * This operation deliberately bypasses the ordinary agent attempt, retry, * transcript, hook, and delivery lifecycle. Execution owners either prove a * literal empty native tool surface or fail before inference starts. */ var IsolatedCompletionError = class extends Error { constructor(code, message, options) { super(message, options); this.name = "IsolatedCompletionError"; this.code = code; } }; function clampIsolatedStreamParams(streamParams, modelMaxTokens) { if (streamParams?.maxTokens === void 0 || modelMaxTokens === void 0) return streamParams; return { ...streamParams, maxTokens: Math.min(streamParams.maxTokens, modelMaxTokens) }; } function selectIsolatedHarnessAuthPlan(attempt) { if (attempt.kind !== "profile") return attempt.plan; return { ...attempt.plan, forwardedAuthProfileId: attempt.profileId, forwardedAuthProfileCandidateIds: [attempt.profileId] }; } function requireIsolatedAssistantText(assistant) { if (assistant.stopReason !== "stop" && assistant.stopReason !== "length") throw new IsolatedCompletionError("output-rejected", `Isolated completion failed with stop reason ${assistant.stopReason}.`); const textParts = []; for (const block of assistant.content) { if (block.type === "text") { textParts.push(block.text); continue; } if (block.type === "thinking") continue; throw new IsolatedCompletionError("output-rejected", "Isolated completion returned a tool call; the result was rejected."); } return textParts.join("").trim(); } function hasCliSideEffectEvidence(result) { return Boolean(result.didSendViaMessagingTool || result.didDeliverSourceReplyViaMessageTool || result.messagingToolSentTexts?.length || result.messagingToolSentMediaUrls?.length || result.messagingToolSentTargets?.length || result.messagingToolSourceReplyPayloads?.length || result.acceptedSessionSpawns?.length || result.successfulCronAdds); } async function runCliIsolatedCompletion(params) { return await withTempWorkspace({ rootDir: resolvePreferredOpenClawTmpDir(), prefix: "openclaw-isolated-completion-" }, async ({ dir }) => { const { runCliAgent } = await import("./cli-runner.runtime.js"); params.request.assertCurrent?.(); const sessionId = `isolated-completion-${randomUUID()}`; const config = params.request.config ?? getRuntimeConfig(); const preparedRunAdmission = prepareSystemAgentRunAdmission(config, sessionId, params.agentId, "isolated-completion"); try { params.request.assertCurrent?.(); const result = await runCliAgent({ preparedRunAdmission, sessionId, sessionFile: path.join(dir, "session.json"), workspaceDir: params.workspaceDir, cwd: dir, agentDir: params.agentDir, agentId: params.agentId, config, prompt: params.request.prompt, extraSystemPrompt: params.request.systemPrompt, timeoutMs: params.request.timeoutMs, runId: sessionId, provider: params.provider, modelProvider: params.modelProvider, model: params.request.model, authProfileId: params.request.authProfileId, thinkLevel: params.request.thinkLevel, streamParams: params.request.streamParams, abortSignal: params.request.abortSignal, assertCurrent: params.request.assertCurrent, executionMode: "side-question", cliToolAvailability: { native: [], openClaw: [] }, disableTools: true, disableCliLiveSession: true, cleanupCliLiveSessionOnRunEnd: true, cleanupBundleMcpOnRunEnd: true, requireExplicitMessageTarget: true, isolatedCompletion: true, outputTextPolicy: params.request.outputTextPolicy }); if (hasCliSideEffectEvidence(result)) throw new IsolatedCompletionError("output-rejected", "Isolated CLI completion returned side-effect evidence; result rejected."); const payloads = result.payloads ?? []; if (payloads.some((payload) => payload.isError || payload.mediaUrl || payload.mediaUrls?.length || payload.audioAsVoice || payload.channelData)) throw new IsolatedCompletionError("output-rejected", "Isolated CLI completion returned non-text output; result rejected."); const text = payloads.filter((payload) => !payload.isReasoning && typeof payload.text === "string").map((payload) => payload.text ?? "").join("\n").trim(); const backend = resolveCliBackendConfig(params.provider, params.request.config, { agentId: params.agentId }); if (!backend) throw new IsolatedCompletionError("runtime-unavailable", `CLI backend ${params.provider} became unavailable after execution.`); const usage = result.meta?.agentMeta?.usage; return { text, model: normalizeCliModel(params.request.model, backend.config), ...usage ? { usage } : {} }; } finally { preparedRunAdmission.close(); } }); } function resolveCliOwner(params) { if (isCliRuntimeAliasForProvider({ runtime: params.runtime, provider: params.provider, cfg: params.request.config })) return params.runtime; if (params.request.agentHarnessRuntimeOverride) return; return resolveCliRuntimeExecutionProvider({ provider: params.provider, cfg: params.request.config, agentId: params.agentId, modelId: params.request.model, authProfileId: params.request.authProfileId }) ?? resolveEmbeddedCliBackendDispatchEligibility({ provider: params.provider, model: params.request.model, agentId: params.agentId, authProfileId: params.request.authProfileId, config: params.request.config, agentDir: params.agentDir, workspaceDir: params.workspaceDir })?.provider; } async function resolveHarness(runtime) { if (runtime === "openclaw") { const { createOpenClawAgentHarness } = await import("./builtin-openclaw-BrAbeZ2n.js"); return createOpenClawAgentHarness(); } const harness = getRegisteredAgentHarness(runtime)?.harness; if (!harness) throw new IsolatedCompletionError("runtime-unavailable", `Agent harness ${runtime} is unavailable for isolated completion.`); return harness; } function prepareIsolatedHarnessParams(harness, params) { if (harness.id === "openclaw") return params; const boundary = "plugin harness isolated completion handoff"; const apiKey = params.auth.apiKey ? unwrapSecretSentinelsForProviderEgress(params.auth.apiKey, boundary) : params.auth.apiKey; const model = unwrapModelHeaderSentinelsForProviderEgress(params.model, boundary); if (apiKey === params.auth.apiKey && model === params.model) return params; return { ...params, model, auth: { ...params.auth, apiKey } }; } function prepareIsolatedHarnessParamsV2(harness, params) { if (harness.id === "openclaw" || params.authorization.owner === "harness") return params; const boundary = "plugin harness isolated completion handoff"; const apiKey = params.authorization.auth.apiKey ? unwrapSecretSentinelsForProviderEgress(params.authorization.auth.apiKey, boundary) : params.authorization.auth.apiKey; const model = unwrapModelHeaderSentinelsForProviderEgress(params.authorization.model, boundary); if (apiKey === params.authorization.auth.apiKey && model === params.authorization.model) return params; return { ...params, authorization: { ...params.authorization, model, auth: { ...params.authorization.auth, apiKey } } }; } async function prepareHostAuthorization(params) { const prepared = await prepareSimpleCompletionModel({ cfg: params.config, agentId: params.agentId, provider: params.provider, modelId: params.modelId, agentDir: params.agentDir, profileId: params.authProfileId, allowMissingApiKeyModes: ["aws-sdk"], allowBundledStaticCatalogFallback: true, skipAgentDiscovery: true, bindAuthOwner: true, workspaceDir: params.workspaceDir, preparedModelRuntime: params.preparedModelRuntime }); if ("error" in prepared) throw new Error(`Isolated completion preparation failed: ${prepared.error}`); return { owner: "host", model: prepared.model, auth: prepared.auth, ...prepared.sourceAuthFingerprint ? { sourceAuthFingerprint: prepared.sourceAuthFingerprint } : {} }; } /** Run one fresh, zero-tool completion through its selected runtime. */ async function runIsolatedCompletion(request) { let closed = false; const assertCurrent = () => { if (closed) throw new IsolatedCompletionError("runtime-unavailable", "Isolated completion has ended."); request.assertCurrent?.(); request.abortSignal?.throwIfAborted(); }; assertCurrent(); const config = request.config ?? {}; const agentId = request.agentId ?? resolveDefaultAgentId(config); const agentDir = request.agentDir ?? resolveAgentDir(config, agentId); const workspaceDir = request.workspaceDir ?? resolveAgentWorkspaceDir(config, agentId); const canonicalProvider = resolveCliRuntimeCanonicalProvider({ runtime: request.provider, config, includeSetupRegistry: true }); const provider = canonicalProvider ?? request.provider; const runtimeOverride = request.agentHarnessRuntimeOverride ?? (canonicalProvider ? request.provider : void 0); const lease = await acquireAgentRunPreparedModelRuntime({ config, agentId, agentDir, workspaceDir, runtimePluginSelections: [{ provider, modelId: request.model, ...runtimeOverride ? { runtime: runtimeOverride } : {}, agentId }] }, { catalogMode: "static", abortSignal: request.abortSignal }); const pluginRegistry = lease.snapshot.pluginRegistry; try { assertCurrent(); const run = async () => { await ensureSelectedAgentHarnessPlugin({ provider, modelId: request.model, config, agentId, agentHarnessId: runtimeOverride, agentHarnessRuntimeOverride: runtimeOverride, workspaceDir, pluginRegistry }); assertCurrent(); const runtime = runtimeOverride ?? resolveEffectiveAgentRuntime({ cfg: config, provider, modelId: request.model, agentId }); const cliOwner = resolveCliOwner({ request, provider, runtime, agentId, agentDir, workspaceDir }); if (cliOwner) { const completion = await runCliIsolatedCompletion({ request: { ...request, assertCurrent }, provider: cliOwner, modelProvider: provider, agentId, agentDir, workspaceDir }); return { text: completion.text, provider, model: completion.model, owner: { kind: "cli", id: cliOwner }, ...completion.usage ? { usage: completion.usage } : {} }; } const harness = await resolveHarness(runtime); assertCurrent(); if (!harness.runIsolatedCompletionV2 && !harness.runIsolatedCompletion) throw new IsolatedCompletionError("unsupported", `Agent harness ${harness.id} does not support isolated completion.`); const commonParams = { provider, modelId: request.model, config, agentId, agentDir, workspaceDir, systemPrompt: request.systemPrompt, prompt: request.prompt, timeoutMs: request.timeoutMs, abortSignal: request.abortSignal, assertCurrent, thinkLevel: request.thinkLevel, outputTextPolicy: request.outputTextPolicy }; let result; if (harness.runIsolatedCompletionV2) { let modelMaxTokens; let authProfileStore; let authAttempts; if (harness.authBootstrap === "harness") { const { modelRegistry } = lease.snapshot.createStores(); const runtimeModel = resolveModelWithRegistry({ provider, modelId: request.model, modelRegistry, cfg: config }); if (!runtimeModel) throw new IsolatedCompletionError("runtime-unavailable", `Unknown isolated completion model ${provider}/${request.model}.`); modelMaxTokens = runtimeModel.maxTokens; authProfileStore = ensureAuthProfileStore(agentDir, { profileId: request.authProfileId, readOnly: true, allowKeychainPrompt: false, config }); authAttempts = prepareAgentRuntimeAuth({ provider: runtimeModel.provider, modelId: runtimeModel.id, modelApi: runtimeModel.api, modelBaseUrl: runtimeModel.baseUrl, config, env: process.env, agentDir, workspaceDir, authProfileStore, sessionAuthProfileId: request.authProfileId, sessionAuthProfileSource: request.authProfileId ? "user" : void 0, harnessId: harness.id, harnessRuntime: harness.id, harnessAuthBootstrap: harness.authBootstrap }).attempts; } let firstError; let priorProfileAttempted = false; for (const preparedAttempt of authAttempts?.length ? authAttempts : [void 0]) { assertCurrent(); const attempt = preparedAttempt?.kind === "profile" ? { ...preparedAttempt, plan: selectIsolatedHarnessAuthPlan(preparedAttempt) } : preparedAttempt; if (attempt && !canRunPreparedAgentRuntimeAuthAttempt({ attempt, priorProfileAttempted })) { firstError ??= /* @__PURE__ */ new Error("Prepared direct auth requires a prior profile attempt."); continue; } if (attempt?.kind === "profile" && authProfileStore && !preparedAgentRuntimeProfileAttemptHasCandidate({ attempt, store: authProfileStore, modelId: request.model })) { firstError ??= /* @__PURE__ */ new Error("Prepared runtime auth candidates are temporarily unavailable."); continue; } try { let authorization; if (attempt?.plan.harnessAuthProvider && attempt.plan.modelRoute?.authRequirement !== "api-key" && authProfileStore) { const plan = attempt.plan; authorization = { owner: "harness", plan, authProfileStore: scopeAuthProfileStoreToPreparedPlan(authProfileStore, plan) }; } else { authorization = await prepareHostAuthorization({ config, agentId, agentDir, provider, modelId: request.model, authProfileId: attempt?.kind === "profile" ? attempt.profileId : request.authProfileId, workspaceDir, preparedModelRuntime: lease.snapshot }); modelMaxTokens = authorization.model.maxTokens; } if (attempt?.kind === "profile" && authProfileStore && !preparedAgentRuntimeProfileAttemptHasCandidate({ attempt, store: authProfileStore, modelId: request.model })) throw new Error("Prepared runtime auth candidates are temporarily unavailable."); assertCurrent(); const pending = harness.runIsolatedCompletionV2(prepareIsolatedHarnessParamsV2(harness, { ...commonParams, authorization, streamParams: clampIsolatedStreamParams(request.streamParams, modelMaxTokens) })); priorProfileAttempted ||= attempt?.kind === "profile"; result = await pending; break; } catch (error) { assertCurrent(); firstError ??= error; } } if (!result) { if (firstError instanceof Error) throw firstError; throw new Error("No prepared auth attempt succeeded.", { cause: firstError }); } } else { const authorization = await prepareHostAuthorization({ config, agentId, agentDir, provider, modelId: request.model, authProfileId: request.authProfileId, workspaceDir, preparedModelRuntime: lease.snapshot }); assertCurrent(); const harnessParams = { ...commonParams, streamParams: clampIsolatedStreamParams(request.streamParams, authorization.model.maxTokens), model: authorization.model, auth: authorization.auth, ...authorization.sourceAuthFingerprint ? { sourceAuthFingerprint: authorization.sourceAuthFingerprint } : {} }; assertCurrent(); result = await harness.runIsolatedCompletion(prepareIsolatedHarnessParams(harness, harnessParams)); } if (!result) throw new IsolatedCompletionError("runtime-unavailable", "Isolated completion failed."); return { text: requireIsolatedAssistantText(result.assistant), provider: result.assistant.provider, model: result.assistant.model, owner: { kind: "harness", id: harness.id }, usage: result.assistant.usage }; }; const result = await withPluginRuntimeGenerationScope(lease.snapshot, run); assertCurrent(); if (!result.text && request.outputTextPolicy !== "strict-visible") throw new IsolatedCompletionError("output-rejected", "Isolated completion returned empty output."); return result; } finally { closed = true; lease.release(); } } //#endregion export { runIsolatedCompletion as t };