UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

224 lines (223 loc) 10.1 kB
import { r as resolveRuntimeWorkerUrl } from "./runtime-worker-url-CpdriB1D.js"; import { n as resolveInstalledManifestRegistryIndexFingerprint } from "./manifest-registry-installed-DdhpzefH.js"; import { f as serializeConfigResolutionFacts, o as getConfigResolutionFacts } from "./resolution-facts-Dks1tbik.js"; import { t as projectConfigOntoRuntimeSourceSnapshot } from "./runtime-source-projection-DOHmC11j.js"; import { k as cloneAuthProfileStore } from "./persisted-B_qhhBlh.js"; import { n as withPluginRuntimeGenerationScope } from "./generation-scope-Cf83d_iq.js"; import { o as setPreparedModelFullCatalogAuth } from "./prepared-model-runtime-auth-CnrySjUa.js"; import { o as captureProviderSyntheticAuthFacts } from "./provider-runtime-BRJDPNgk.js"; import { t as listManifestSyntheticAuthProviderRefs } from "./synthetic-auth.runtime.js"; import { n as WorkerTaskPool, t as WorkerTaskError } from "./worker-task-pool-BNbf5LmH.js"; import { n as markPreparedModelCatalogFull } from "./prepared-model-runtime.full-catalog-CFj7JJlS.js"; import { n as PreparedModelRuntimePublicationSupersededError } from "./prepared-model-runtime.errors-DeG6Ut3_.js"; import { t as fingerprintPreparedRuntimeFacts } from "./prepared-model-runtime.facts-vxXJKbiM.js"; //#region src/agents/prepared-model-catalog-worker.ts /** Runs complete model-catalog discovery outside the Gateway event loop. */ const PREPARED_MODEL_CATALOG_WORKER_TIMEOUT_MS = 18e4; const PREPARED_MODEL_CATALOG_WORKER_GENERATION_POLL_MS = 25; var PreparedModelCatalogGenerationMismatchError = class extends Error { constructor(agentDir, generationFingerprint, reconstructedFingerprint) { super(`prepared model catalog worker reconstructed a different runtime generation for ${agentDir} (owner=${generationFingerprint} worker=${reconstructedFingerprint})`); this.agentDir = agentDir; this.generationFingerprint = generationFingerprint; this.reconstructedFingerprint = reconstructedFingerprint; this.name = "PreparedModelCatalogGenerationMismatchError"; } }; function fingerprintPreparedModelWorkerRequest(input, request) { return fingerprintPreparedRuntimeFacts([input.generationFingerprint, request]); } function fingerprintPreparedModelCatalogPlugins(snapshot) { return fingerprintPreparedRuntimeFacts({ config: snapshot.configFingerprint ?? null, index: resolveInstalledManifestRegistryIndexFingerprint(snapshot.index), pluginIds: snapshot.pluginIds ?? null, policy: snapshot.policyHash, workspaceDir: snapshot.workspaceDir ?? null }); } function fingerprintPreparedModelCatalogGeneration(params) { return fingerprintPreparedRuntimeFacts({ input: params.input, sourceConfigForSecrets: params.sourceConfigForSecrets, configResolutionFacts: params.configResolutionFacts, sourceConfigResolutionFacts: params.sourceConfigResolutionFacts, authStore: params.authStore, providerIds: params.providerIds, preferBuiltPluginArtifacts: params.preferBuiltPluginArtifacts === true, pluginFingerprint: fingerprintPreparedModelCatalogPlugins(params.pluginMetadataSnapshot) }); } function createPreparedModelCatalogWorkerInput(params) { const source = params.agentFacts.input; const input = { ...source.agentId ? { agentId: source.agentId } : {}, agentDir: source.agentDir, ...source.inheritedAuthDir ? { inheritedAuthDir: source.inheritedAuthDir } : {}, ...source.workspaceDir ? { workspaceDir: source.workspaceDir } : {}, ...source.readOnly ? { readOnly: true } : {}, skipCredentials: true, env: { ...params.agentFacts.env }, ...source.allowGatewaySubagentBinding ? { allowGatewaySubagentBinding: true } : {}, ...source.runtimePluginSelections ? { runtimePluginSelections: source.runtimePluginSelections } : {}, config: source.config }; const sourceConfigForSecrets = projectConfigOntoRuntimeSourceSnapshot(source.config); const configResolutionFacts = serializeConfigResolutionFacts(source.config); const sourceConfigResolutionFacts = getConfigResolutionFacts(source.config) === getConfigResolutionFacts(sourceConfigForSecrets) ? configResolutionFacts : serializeConfigResolutionFacts(sourceConfigForSecrets); const authStore = cloneAuthProfileStore(params.agentFacts.authStore); const providerIds = [...params.agentFacts.providerIds]; const { normalizePluginId: _normalizePluginId, ...pluginMetadataSnapshot } = params.pluginMetadataSnapshot; return { kind: "catalog", generationFingerprint: fingerprintPreparedModelCatalogGeneration({ input, sourceConfigForSecrets, configResolutionFacts, sourceConfigResolutionFacts, authStore, providerIds, preferBuiltPluginArtifacts: params.preferBuiltPluginArtifacts, pluginMetadataSnapshot: params.pluginMetadataSnapshot }), input, sourceConfigForSecrets, configResolutionFacts, sourceConfigResolutionFacts, authStore, providerIds, preferBuiltPluginArtifacts: params.preferBuiltPluginArtifacts === true, pluginMetadataSnapshot }; } function createPreparedModelCatalogWorker(params) { const workerInput = createPreparedModelCatalogWorkerInput(params); const metadataSnapshot = params.pluginMetadataSnapshot; const superseded = () => new PreparedModelRuntimePublicationSupersededError(`prepared model runtime catalog generation was superseded for ${workerInput.input.agentDir}`); let generationPoll; let stoppedError; let expectedFingerprint; const captures = /* @__PURE__ */ new Map(); const assertCurrent = () => { if (stoppedError) throw stoppedError; if (!params.isCurrent()) throw superseded(); }; let pool; const mismatch = (message) => new PreparedModelCatalogGenerationMismatchError(workerInput.input.agentDir, message.generationFingerprint, message.reconstructedFingerprint); const createPool = () => new WorkerTaskPool({ workerUrl: resolveRuntimeWorkerUrl({ currentModuleUrl: import.meta.url, sourceWorkerName: "prepared-model-catalog.worker", distWorkerPath: "agents/prepared-model-catalog.worker.js" }), maxWorkers: 1, idleTimeoutMs: 0, restartOnError: false, workerOptions: { workerData: workerInput, env: workerInput.input.env }, validateResult: (message) => { assertCurrent(); if (message.status === "generation-mismatch") throw mismatch(message); if (message.status === "ok" && message.generationFingerprint !== expectedFingerprint) throw new Error("prepared model catalog worker returned a stale generation"); } }); const stop = async (error) => { stoppedError ??= error; clearInterval(generationPoll); generationPoll = void 0; for (const controller of captures.keys()) controller.abort(stoppedError); await Promise.allSettled(captures.values()); await pool?.close(stoppedError); }; const request = async (command) => { let message; let requestPool; const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(new WorkerTaskError("worker task timed out", "timeout")), PREPARED_MODEL_CATALOG_WORKER_TIMEOUT_MS); try { assertCurrent(); generationPoll ??= setInterval(() => { if (!params.isCurrent()) stop(superseded()); }, PREPARED_MODEL_CATALOG_WORKER_GENERATION_POLL_MS); generationPoll.unref(); const { input } = workerInput; const capture = withPluginRuntimeGenerationScope({ metadataSnapshot, pluginRegistry: params.pluginRegistry }, () => captureProviderSyntheticAuthFacts({ config: input.config, env: input.env, workspaceDir: input.workspaceDir, providerRefs: command.kind === "catalog" ? [...listManifestSyntheticAuthProviderRefs(metadataSnapshot.index), ...workerInput.providerIds] : [...workerInput.providerIds, ...command.providerIds], signal: controller.signal })); captures.set(controller, capture); let syntheticAuth; try { syntheticAuth = await capture; } finally { captures.delete(controller); } controller.signal.throwIfAborted(); const value = { ...command, syntheticAuth }; requestPool = pool ??= createPool(); message = await requestPool.run(() => { assertCurrent(); expectedFingerprint = fingerprintPreparedModelWorkerRequest(workerInput, value); return value; }, { timeoutMs: PREPARED_MODEL_CATALOG_WORKER_TIMEOUT_MS, signal: controller.signal }); assertCurrent(); } catch (error) { const failure = error instanceof Error ? error : new Error(String(error)); if (failure instanceof PreparedModelCatalogGenerationMismatchError) { if (pool === requestPool) pool = void 0; await requestPool?.close(failure); throw failure; } controller.abort(error); await stop(failure); throw error; } finally { clearTimeout(timeout); } if (message.status === "failed") throw new Error(message.error); if (message.status === "generation-mismatch") throw mismatch(message); return message; }; return { loadCatalog: async () => { const message = await request({ kind: "catalog" }); if (message.kind !== "catalog") throw new Error("prepared model catalog worker returned an auth refresh result"); const modelCatalog = markPreparedModelCatalogFull(message.snapshot); setPreparedModelFullCatalogAuth(modelCatalog, { authStore: message.authStore, authModes: message.authModes }); return modelCatalog; }, loadAuth: async ({ providerIds, profileIds }) => { const normalizedProviderIds = [...new Set(providerIds)].toSorted((left, right) => left.localeCompare(right)); const normalizedProfileIds = profileIds ? [...new Set(profileIds)].toSorted((left, right) => left.localeCompare(right)) : void 0; const message = await request({ kind: "auth-refresh", providerIds: normalizedProviderIds, ...normalizedProfileIds ? { profileIds: normalizedProfileIds } : {} }); if (message.kind !== "auth-refresh") throw new Error("prepared model auth refresh worker returned a catalog result"); return { authStore: message.authStore, authModes: message.authModes }; } }; } //#endregion export { fingerprintPreparedModelCatalogGeneration as n, fingerprintPreparedModelWorkerRequest as r, createPreparedModelCatalogWorker as t };