UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

229 lines (228 loc) 11.7 kB
import { r as defaultRuntime } from "./runtime-CF2WjnNZ.js"; import { i as appendSystemAgentAuditEntry } from "./audit-D3_LINzS.js"; import { stat } from "node:fs/promises"; //#region src/system-agent/hosted-setup.runtime.ts let setupSharedPromise; function loadSetupShared() { return setupSharedPromise ??= import("./setup.shared-mTYEiwX9.js"); } const GATEWAY_WRITE_POLICY = { mode: "none", reason: "Gateway setup defers runtime apply until explicit restart" }; function requireLocalGateway(config) { if (config.gateway?.mode === "local") return; throw new Error("Hosted Gateway setup manages only a local Gateway. Use `openclaw onboard` for fresh setup or `openclaw configure` for the mode question, then retry after selecting local mode."); } function createHostedWizardRuntime(runtime) { return { ...runtime, exit: (code) => { throw new Error(`hosted wizard exited with code ${String(code)}`); } }; } async function runHostedSetup(params) { const { readSetupConfigFileSnapshot, writeWizardConfigFile } = await loadSetupShared(); const snapshot = await readSetupConfigFileSnapshot(); if (!snapshot.exists || !snapshot.valid || !snapshot.hash) throw new Error(`${params.label} requires a valid saved config snapshot. On the machine running OpenClaw, run \`openclaw doctor --fix\` and resolve any remaining validation errors; then retry.`); const baseConfig = snapshot.sourceConfig ?? snapshot.config; const runtime = params.runtime ?? createHostedWizardRuntime(defaultRuntime); const result = await params.run({ baseConfig, runtime }); if ("keptCurrent" in result) return "kept-current"; await params.beforePersistentApply(runtime); const committedConfig = await writeWizardConfigFile(result.nextConfig, { allowConfigSizeDrop: false, baseHash: snapshot.hash, ...params.afterWrite ? { afterWrite: params.afterWrite } : {} }); await result.afterWrite?.(committedConfig); return "applied"; } async function runHostedChannelSetup(channel, prompter, beforePersistentApply, runtime) { const { createChannelSetupTransaction, setupChannels } = await import("./onboard-channels-wf3-q-wO.js"); let channelSetup; return await runHostedSetup({ label: "Channel setup", runtime, beforePersistentApply, run: async ({ baseConfig, runtime: setupRuntime }) => { channelSetup = createChannelSetupTransaction({ runtime: setupRuntime, beforePersistentEffect: async () => await beforePersistentApply(setupRuntime) }); return { nextConfig: await setupChannels(baseConfig, setupRuntime, prompter, { initialSelection: [channel], forceAllowFromChannels: [channel], allowIMessageInstall: true, allowSignalInstall: true, deferStatusUntilSelection: true, quickstartDefaults: true, skipDmPolicyPrompt: true, skipConfirm: true, beforePersistentEffect: async () => await beforePersistentApply(setupRuntime), onPostWriteHook: (hook) => channelSetup.onPostWriteHook(hook) }), afterWrite: async (committedConfig) => { await channelSetup.runPostWriteHooks(committedConfig); } }; } }); } async function runHostedSkillsSetup(prompter, beforePersistentApply, runtime) { const [{ setupSkills }, { resolveSystemAgentOnboardingTarget }] = await Promise.all([import("./onboard-skills-CxRLAPZC.js"), import("./onboard-agent-target-QRPwWluC.js")]); return await runHostedSetup({ label: "Skills setup", runtime, beforePersistentApply, run: async ({ baseConfig, runtime: setupRuntime }) => ({ nextConfig: await setupSkills(baseConfig, resolveSystemAgentOnboardingTarget(baseConfig).workspaceDir, setupRuntime, prompter, { beforePersistentEffect: async () => await beforePersistentApply(setupRuntime) }) }) }); } async function runHostedSearchSetup(prompter, beforePersistentApply, runtime) { const { runSearchSetupFlow } = await import("./search-setup-3CsvMo3b.js"); return await runHostedSetup({ label: "Web search setup", runtime, beforePersistentApply, run: async ({ baseConfig, runtime: setupRuntime }) => { const result = await runSearchSetupFlow(baseConfig, setupRuntime, prompter, { preserveDisabledSearchState: false, beforePersistentEffect: async () => await beforePersistentApply(setupRuntime) }); if (result.outcome === "install-failed") { const failure = result.reason === "timed-out" ? "timed out" : "failed"; throw new Error(`web search provider ${result.providerId} installation ${failure}`); } if (result.outcome === "kept-current") { if (result.reason === "user-skipped" || result.reason === "provider-install-skipped") return { keptCurrent: true }; const reason = result.reason === "no-providers" ? "no web search providers are available under the current plugin policy" : "the selected web search provider is no longer available"; throw new Error(reason); } return { nextConfig: result.config }; } }); } async function runHostedGatewaySetup(prompter, beforePersistentApply, runtime) { const [{ resolveGatewayPort }, { configureGatewayForSetup }, { resolveQuickstartGatewayDefaults }] = await Promise.all([ import("./config/config.js"), import("./setup.gateway-config-DiwA0U0H.js"), loadSetupShared() ]); return await runHostedSetup({ label: "Gateway setup", runtime, beforePersistentApply, afterWrite: GATEWAY_WRITE_POLICY, run: async ({ baseConfig, runtime: setupRuntime }) => { requireLocalGateway(baseConfig); return { nextConfig: (await configureGatewayForSetup({ flow: "advanced", baseConfig, nextConfig: baseConfig, localPort: resolveGatewayPort(baseConfig), quickstartGateway: resolveQuickstartGatewayDefaults(baseConfig), prompter, runtime: setupRuntime })).nextConfig }; } }); } async function runHostedMemoryImport(prompter, beforePersistentApply, onProviderOutcome) { const [{ readSetupConfigFileSnapshot }, { resolveSystemAgentOnboardingTarget }] = await Promise.all([loadSetupShared(), import("./onboard-agent-target-QRPwWluC.js")]); const snapshot = await readSetupConfigFileSnapshot(); if (!snapshot.exists || !snapshot.valid || !snapshot.hash) throw new Error("Memory import requires a valid saved config. Run `openclaw doctor --fix`, then retry."); const baseHash = snapshot.hash; const config = snapshot.config; const { agentId, workspaceDir: workspace } = resolveSystemAgentOnboardingTarget(config); try { if (!(await stat(workspace)).isDirectory()) return { status: "workspace-missing", providers: [], workspace }; } catch (error) { const code = error.code; if (code === "ENOENT" || code === "ENOTDIR") return { status: "workspace-missing", providers: [], workspace }; throw error; } const { runSetupMemoryImportStep } = await import("./setup.memory-import-Dft2AxH2.js"); const runtime = createHostedWizardRuntime(defaultRuntime); return await runSetupMemoryImportStep({ config, agentId, prompter, runtime, beforeApply: async () => { await beforePersistentApply(runtime); const currentSnapshot = await readSetupConfigFileSnapshot(); if (!currentSnapshot.exists || !currentSnapshot.valid || currentSnapshot.hash !== baseHash) throw new Error("configuration changed during memory import; nothing further was copied — retry to import against the current setup"); }, onProviderOutcome }); } function hasConfirmedMemoryImportCount(provider) { return provider.copiesIndeterminate !== true; } function formatItemCount(count) { return `${count} ${count === 1 ? "item" : "items"}`; } function formatMemoryImportProviders(providers) { return providers.map((provider) => `${provider.label} (${formatItemCount(provider.migrated)})`).join(", "); } async function auditMemoryImport(providers, appendAuditEntry = appendSystemAgentAuditEntry) { const importedProviders = providers.filter(hasConfirmedMemoryImportCount).filter((provider) => provider.migrated > 0); const indeterminateProviders = providers.filter((provider) => provider.copiesIndeterminate === true); const importedItems = importedProviders.reduce((total, provider) => total + provider.migrated, 0); if (importedItems === 0 && indeterminateProviders.length === 0) return; const providerSummary = formatMemoryImportProviders(importedProviders); const indeterminateSummary = indeterminateProviders.map((provider) => `${provider.label} (copy count indeterminate)`).join(", "); await appendAuditEntry({ operation: "memory.import", summary: indeterminateProviders.length > 0 ? `Memory import failed partway via chat: ${[providerSummary ? `confirmed ${providerSummary}` : "", indeterminateSummary].filter(Boolean).join("; ")}` : `Imported memory via chat: ${providerSummary}`, details: { ...indeterminateProviders.length > 0 ? { confirmedItems: importedItems, copiesIndeterminate: true } : { totalItems: importedItems }, providers: providers.map((provider) => provider.copiesIndeterminate === true ? { providerId: provider.providerId, copiesIndeterminate: true } : { providerId: provider.providerId, items: provider.migrated, ...provider.failure ? { partial: true } : {} }) } }); } async function renderMemoryImport(outcome, appendAuditEntry = appendSystemAgentAuditEntry) { if (!outcome) return "Memory import did not complete. No outcome was reported, and no success was assumed."; if (outcome.status === "workspace-missing") return [`Memory import is unavailable because the default agent workspace does not exist at ${outcome.workspace}.`, "Finish onboarding first with `openclaw onboard`, then retry."].join("\n"); if (outcome.status === "nothing-to-import") return "Nothing to import — no new memory files were detected in supported local agent homes."; if (outcome.status === "skipped") return "Memory import skipped. Nothing was copied."; const confirmedProviders = outcome.providers.filter(hasConfirmedMemoryImportCount); const importedProviders = confirmedProviders.filter((provider) => provider.migrated > 0); const failedProviders = confirmedProviders.filter((provider) => provider.failure); const indeterminateProviders = outcome.providers.filter((provider) => provider.copiesIndeterminate === true); const importedItems = importedProviders.reduce((total, provider) => total + provider.migrated, 0); const providerSummary = formatMemoryImportProviders(importedProviders); await auditMemoryImport(outcome.providers, appendAuditEntry); if (importedItems === 0) { if (indeterminateProviders.length > 0) return ["Memory import failed partway. Some files may have been copied before the failure.", `Copy counts are indeterminate for: ${indeterminateProviders.map((provider) => provider.label).join(", ")}.`].join("\n"); if (failedProviders.length > 0) return ["Memory import did not complete. No files were copied.", `Failed providers: ${failedProviders.map((provider) => provider.label).join(", ")}.`].join("\n"); return "Nothing was imported. No files were copied."; } const sourceSummary = importedProviders.length === 1 ? importedProviders[0].label : providerSummary; return [`Imported ${formatItemCount(importedItems)} from ${sourceSummary}.`, indeterminateProviders.length > 0 ? `Memory import failed partway for ${indeterminateProviders.map((provider) => provider.label).join(", ")}; some additional files may have been copied before the failure.` : failedProviders.length > 0 ? `Some providers did not complete: ${failedProviders.map((provider) => provider.label).join(", ")}.` : ""].filter(Boolean).join("\n"); } //#endregion export { GATEWAY_WRITE_POLICY, auditMemoryImport, renderMemoryImport, requireLocalGateway, runHostedChannelSetup, runHostedGatewaySetup, runHostedMemoryImport, runHostedSearchSetup, runHostedSetup, runHostedSkillsSetup };