openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
154 lines (153 loc) • 6.72 kB
JavaScript
import { n as AgentHarnessSessionSupersededError, t as AgentHarnessPreflightError } from "./errors-Bd6GQRkh.mjs";
import { t as abortAndDrainEmbeddedAgentRun } from "./runs-D3elciTh.mjs";
import { m as toolPolicy } from "./agent-harness-runtime-CfbNr0AL.mjs";
import { n as prepareNativeSessionGenerationAuthority } from "./agent-harness-session-runtime-DFZWNbRI.mjs";
import { t as requireAgentsApiSessionTarget } from "./agentsapi-target-ClP2ww2I.mjs";
import { t as runAgentsApiAttempt } from "./agentsapi-attempt-DsyfsjYz.mjs";
import { t as createAgentsApiBindings } from "./agentsapi-bindings-BvrW3YcT.mjs";
import { t as runAgentsApiIsolatedCompletion } from "./agentsapi-isolated-completion-BjNPeL8H.mjs";
//#region extensions/agentsapi/agentsapi-harness.ts
const AGENTS_API_NATIVE_TOOL_REQUIREMENTS = [
"exec",
"process",
"read",
"write",
"edit",
"apply_patch",
"web_search"
];
/** Agents API owns native protocol; the host harness runtime owns coordination. */
function createAgentsApiHarness(runtime) {
let disposed = false;
let closing = false;
const runningSessions = /* @__PURE__ */ new Map();
const isolatedRuns = /* @__PURE__ */ new Map();
const promptHistories = /* @__PURE__ */ new WeakMap();
let bindings;
const getBindings = () => bindings ??= createAgentsApiBindings(runtime);
const assertCurrent = () => {
if (disposed) throw new Error("Agents API harness is disposed");
};
return {
id: "agentsapi",
label: "OpenAI Agents API (MVP)",
autoSelection: { providerIds: [] },
deliveryDefaults: { visibleReplies: "automatic" },
conversationToolPolicySupport: "exact",
conversationToolPolicyNativeTools: AGENTS_API_NATIVE_TOOL_REQUIREMENTS,
conversationToolPolicySafeDenyTools: [
"gateway",
"agents_list",
"openclaw",
"session_status",
"progress_card",
"automations",
"message",
"sessions_send",
"conversations_list",
"conversations_send",
"conversations_turn",
"subagents",
"sessions_list",
"sessions_history",
"sessions_search",
"sessions_spawn"
],
supports: (ctx) => {
if (ctx.provider !== "openai") return {
supported: false,
reason: "Agents API requires the OpenAI provider"
};
if (ctx.modelProvider?.preparedAuth?.requirement === "subscription" || ctx.modelProvider?.api && ctx.modelProvider.api !== "openai-responses" || ctx.modelProvider?.requestTransportOverrides === "present" || ctx.modelProvider?.baseUrl && ctx.modelProvider.baseUrl !== "https://api.openai.com/v1") return {
supported: false,
reason: "Agents API MVP requires the official API-key route"
};
return { supported: true };
},
runIsolatedCompletionV2: (params) => {
assertCurrent();
if (closing) throw new Error("Agents API harness is closing");
const controller = new AbortController();
const pending = runAgentsApiIsolatedCompletion({
...params,
abortSignal: params.abortSignal ? AbortSignal.any([params.abortSignal, controller.signal]) : controller.signal
}, assertCurrent);
isolatedRuns.set(controller, pending);
return pending.finally(() => isolatedRuns.delete(controller));
},
runAttempt: async (params) => {
assertCurrent();
if (closing) throw new Error("Agents API harness is closing");
const target = validateAgentsApiInput(params);
const authority = (await prepareNativeSessionGenerationAuthority({
target,
config: params.config,
storePath: target.storePath,
assertCurrent: () => {
assertCurrent();
params.hostCapabilities.assertActive();
},
createSupersededError: (sessionId) => new AgentHarnessSessionSupersededError(`Agents API session generation is no longer current: ${sessionId}`)
})).authority;
authority.assertLegacyCurrent();
runningSessions.set(params.sessionId, (runningSessions.get(params.sessionId) ?? 0) + 1);
try {
return await getBindings().withSession(params.sessionId, () => authority.assertLegacyCurrent(), (binding, bind, assertLeaseCurrent) => {
if (closing) throw new Error("Agents API harness is closing");
return runAgentsApiAttempt(params, binding, bind, () => {
authority.assertLegacyCurrent();
assertLeaseCurrent();
}, () => {
assertCurrent();
assertLeaseCurrent();
}, target, () => runtime.config.current().plugins?.entries?.agentsapi?.config, promptHistories);
});
} finally {
const count = runningSessions.get(params.sessionId) - 1;
if (count > 0) runningSessions.set(params.sessionId, count);
else runningSessions.delete(params.sessionId);
}
},
reset: async (params) => {
assertCurrent();
if (params.sessionId) await getBindings().reset(params.sessionId, assertCurrent);
},
withSessionDeletion: (params, run) => getBindings().withSessionDeletion({
...params,
assertCurrent: () => {
params.assertCurrent();
assertCurrent();
}
}, run),
dispose: async () => {
closing = true;
for (const controller of isolatedRuns.keys()) controller.abort();
await Promise.allSettled(isolatedRuns.values());
await Promise.all([...runningSessions.keys()].map((sessionId) => abortAndDrainEmbeddedAgentRun({
sessionId,
settleMs: 95e3
})));
if (bindings) await bindings.withExclusiveMutationFence(async () => {
disposed = true;
});
else disposed = true;
}
};
}
function validateAgentsApiInput(params) {
const runtimeToolAllowed = toolPolicy.createToolPolicyMatcher({ allow: params.toolsAllow });
if (params.disableTools || params.pluginHarnessToolPolicyRestricted || params.toolExecutionAllow !== void 0 || params.toolsAllow?.length === 0 || AGENTS_API_NATIVE_TOOL_REQUIREMENTS.some((name) => !runtimeToolAllowed(name))) throw new AgentHarnessPreflightError("Agents API cannot enforce this run's restrictions on native shell, file, or web-search tools.", {
scope: "harness",
userMessage: "Agents API cannot run with this chat's tool restrictions because it cannot enforce them on native tools. Choose a harness that supports these restrictions or update the tool settings."
});
const target = requireAgentsApiSessionTarget(params);
if (!params.resolvedApiKey) throw new Error("Agents API MVP requires an OpenAI API key");
if (params.sandbox) throw new AgentHarnessPreflightError("Agents API does not support Gateway sandbox placement.", {
scope: "harness",
userMessage: "Agents API cannot run in the configured Gateway sandbox. Choose a harness that supports Gateway sandbox placement before retrying."
});
if (params.contextEngine && params.contextEngine.info.id !== "legacy") throw new Error("Agents API MVP currently supports only the default legacy context engine");
return target;
}
//#endregion
export { createAgentsApiHarness as t };