openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
233 lines (232 loc) • 8.28 kB
JavaScript
import { n as validateAgentParams, r as validateAgentWaitParams } from "./src-BiL5aQto.js";
import { d as throwIfGatewayDispatchAborted, f as unwrapGatewayMethodDispatchResponse, p as waitForGatewayDispatch } from "./server-plugin-in-process-dispatch-DYlW9gzA.js";
import { t as abortChatRunById } from "./chat-abort-qLn3eFOg.js";
import { r as validateGatewayMethodParams } from "./validation-pzrlzFvo.js";
import { i as runWithGatewayRequestEnvelope, n as createRequestGatewayMethodRegistry, t as authorizeGatewayRequestPreDispatch } from "./server-methods-D5bRlIc3.js";
import { i as prepareAgentRequestPreflight, n as resolveAgentTurnRunObserver, r as createAgentTurnService, t as captureAgentTurnPrincipal } from "./principal-CyvMFpus.js";
//#region src/gateway/agent-turn/internal-facade.ts
function throwEnvelopeRejection(method, error) {
return unwrapGatewayMethodDispatchResponse(method, {
ok: false,
error
});
}
/** Typed, frame-free access to agent turns owned by the running Gateway instance. */
function createInternalAgentTurnFacade(options) {
const isWebchatConnect = options.isWebchatConnect ?? (() => false);
const getMethodRegistry = options.getMethodRegistry ?? createRequestGatewayMethodRegistry;
const dispatchRaw = async (request, dispatchOptions = {}) => {
const method = "agent";
throwIfGatewayDispatchAborted(method, dispatchOptions.signal);
dispatchOptions.assertAdmissionCurrent?.();
options.assertContextCurrent?.();
const context = options.getContext();
const entry = context.requestEntryLifetime?.enter({
req: {
method,
params: request
},
client: options.client,
context
});
try {
const methodRegistry = getMethodRegistry();
const authorization = await authorizeGatewayRequestPreDispatch({
method,
requestParams: request,
client: options.client,
context,
methodRegistry
});
entry?.assertOpen();
if (authorization.error) return {
ok: false,
error: authorization.error
};
const validationError = validateGatewayMethodParams(request, validateAgentParams, method);
if (validationError) return {
ok: false,
error: validationError
};
options.assertContextCurrent?.();
dispatchOptions.assertAdmissionCurrent?.();
let acceptance;
let final;
let resolveAcceptance;
let rejectAcceptance;
let resolveFinal;
let rejectFinal;
let postAcceptanceError;
let acceptedAbortOwner;
let pendingCancelReason;
const cancelAcceptedRun = (reason) => {
pendingCancelReason ??= reason;
const owner = acceptedAbortOwner;
if (!owner || context.chatAbortControllers.get(owner.runId) !== owner.entry) return;
abortChatRunById(context, {
runId: owner.runId,
sessionKey: owner.entry.sessionKey,
stopReason: pendingCancelReason
});
};
const acceptancePromise = new Promise((resolve, reject) => {
resolveAcceptance = resolve;
rejectAcceptance = reject;
});
const createFinalPromise = () => new Promise((resolve, reject) => {
resolveFinal = resolve;
rejectFinal = reject;
if (final) resolve(final);
});
const io = {
emitAcceptance: (frame, meta) => {
if (!acceptance) {
acceptance = {
ok: frame[0],
payload: frame[1],
error: frame[2],
...meta ? { meta } : {}
};
resolveAcceptance?.(acceptance);
const acceptedRunId = typeof meta?.runId === "string" && meta.runId.trim() ? meta.runId.trim() : void 0;
const acceptedEntry = acceptedRunId ? context.chatAbortControllers.get(acceptedRunId) : void 0;
if (acceptedRunId && acceptedEntry) {
acceptedAbortOwner = {
entry: acceptedEntry,
runId: acceptedRunId
};
if (pendingCancelReason) cancelAcceptedRun(pendingCancelReason);
}
if (meta?.cached === true && acceptedRunId && context.chatAbortControllers.get(acceptedRunId)?.executionStarted === true) dispatchOptions.onExecutionStarted?.();
}
},
emitFinal: (frame, meta) => {
if (!final) {
final = {
ok: frame[0],
payload: frame[1],
error: frame[2],
...meta ? { meta } : {}
};
resolveFinal?.(final);
}
},
...dispatchOptions.onExecutionStarted ? { emitExecutionStarted: dispatchOptions.onExecutionStarted } : {}
};
context.trackExecution(() => runWithGatewayRequestEnvelope(method, options.client, async () => {
entry?.assertOpen();
dispatchOptions.assertAdmissionCurrent?.();
entry?.release();
const principal = captureAgentTurnPrincipal(options.client);
const preflight = prepareAgentRequestPreflight({
request,
context,
client: principal,
io
});
if (!preflight) return;
const onRunObserved = resolveAgentTurnRunObserver({
principal,
registerToolEventRecipient: context.registerToolEventRecipient
});
await createAgentTurnService({
context,
isWebchatConnect
}, options.assertContextCurrent).startTurn({
preflight,
principal,
io,
onRunObserved,
assertAdmissionCurrent: dispatchOptions.assertAdmissionCurrent
});
}, {
context,
isWebchatConnect,
methodRegistry,
reject: (error) => io.emitAcceptance([
false,
void 0,
error
])
})).then(() => {
if (!acceptance) rejectAcceptance?.(/* @__PURE__ */ new Error(`Gateway method "${method}" completed without a response.`));
}, (error) => {
const dispatchError = error instanceof Error ? error : new Error(String(error));
if (acceptance) {
postAcceptanceError = dispatchError;
rejectFinal?.(dispatchError);
return;
}
rejectAcceptance?.(dispatchError);
});
const response = (async () => {
const first = acceptance ?? await acceptancePromise;
if (dispatchOptions.expectFinal !== true || first.payload?.status !== "accepted") return first;
dispatchOptions.onAccepted?.(first.payload);
if (postAcceptanceError) throw postAcceptanceError;
return final ?? await createFinalPromise();
})();
return await waitForGatewayDispatch(method, response, dispatchOptions.timeoutMs, dispatchOptions.signal, dispatchOptions.cancelOnDeadline || dispatchOptions.onSignalAbort ? async () => {
if (dispatchOptions.cancelOnDeadline) cancelAcceptedRun("rpc");
await dispatchOptions.onSignalAbort?.();
} : void 0, dispatchOptions.cancelOnDeadline ? () => cancelAcceptedRun("timeout") : void 0);
} finally {
entry?.release();
}
};
const dispatch = async (request, dispatchOptions = {}) => {
return unwrapGatewayMethodDispatchResponse("agent", await dispatchRaw(request, typeof dispatchOptions === "number" ? { timeoutMs: dispatchOptions } : dispatchOptions));
};
const wait = async (params, timeoutMs, signal, onSignalAbort) => {
const method = "agent.wait";
throwIfGatewayDispatchAborted(method, signal);
options.assertContextCurrent?.();
const context = options.getContext();
const entry = context.requestEntryLifetime?.enter({
req: {
method,
params
},
client: options.client,
context
});
try {
const methodRegistry = getMethodRegistry();
const authorization = await authorizeGatewayRequestPreDispatch({
method,
requestParams: params,
client: options.client,
context,
methodRegistry
});
entry?.assertOpen();
if (authorization.error) return throwEnvelopeRejection(method, authorization.error);
const validationError = validateGatewayMethodParams(params, validateAgentWaitParams, method);
if (validationError) return throwEnvelopeRejection(method, validationError);
options.assertContextCurrent?.();
const result = context.trackExecution(() => runWithGatewayRequestEnvelope(method, options.client, () => {
entry?.assertOpen();
entry?.release();
return createAgentTurnService({
context,
isWebchatConnect
}).waitForTurn(params);
}, {
context,
isWebchatConnect,
methodRegistry,
reject: (error) => throwEnvelopeRejection(method, error)
}));
return await waitForGatewayDispatch(method, result, timeoutMs, signal, onSignalAbort);
} finally {
entry?.release();
}
};
return {
dispatch,
dispatchRaw,
wait
};
}
//#endregion
export { createInternalAgentTurnFacade as t };