UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

282 lines (281 loc) • 13.1 kB
import { r as truncateUtf16Safe } from "./utf16-slice-D_ngcYKd.mjs"; import { r as captureOpenClawStateWorkerContext } from "./openclaw-state-worker-context-epCM4Gdh.mjs"; import { r as isIncognitoSessionKey } from "./session-key-DDIJxXfQ.mjs"; import "./session-key-BC4m_Ly5.mjs"; import { a as clearAgentRunContext, y as registerAgentRunContext } from "./agent-run-registry-RDoBEeyg.mjs"; import { r as getRuntimeConfig } from "./io.runtime-FunTy0y1.mjs"; import "./config-B-SAEPyK.mjs"; import { b as runWithGatewayDetachedWorkAdmission, s as getGatewayRestartDrainSignal } from "./gateway-work-admission-G8XukyHo.mjs"; import { d as prepareSystemAgentRunAdmission, s as createOperationalRunInstanceRef, u as prepareAgentRunAdmission } from "./admitted-run-context-CbCp9bj_.mjs"; import { n as resolveInternalSessionEffectsIdentity } from "./internal-session-key-BOMXCQVf.mjs"; import { c as loadSessionEntryReadOnly } from "./session-accessor.sqlite-entry-BuCmtpuj.mjs"; import "./session-accessor-BM3Wa1Bx.mjs"; import { i as validateSessionTranscriptContextAnchor } from "./session-accessor.sqlite-model-context-CDYsnQhq.mjs"; import { n as resolveAgentTimeoutMs } from "./timeout-ilZESygE.mjs"; import { t as resolveSkillWorkshopConfig } from "./config-C8iJzbV2.mjs"; import { o as resolveToolDisplay } from "./tool-display-DLY_VyQb.mjs"; import { f as runWithCronCreatorAuthorityCapability, u as createCronCreatorAuthorityCapability } from "./cron-creator-authority-context-C3oD224u.mjs"; import { t as createBackgroundWorkOwner } from "./background-work-e4eP0NpZ.mjs"; import { t as bumpSkillsSnapshotVersion } from "./refresh-state-Cazo5oir.mjs"; import { t as resolveWorkshopSkillsDir } from "./skills-root-BZ-eiihY.mjs"; import { r as recordSkillExperienceReviewOutcome } from "./collection-review-state-K1aUTSi7.mjs"; import { t as SessionManager } from "./session-manager-fQvjf7cC.mjs"; import { n as SKILL_WORKSHOP_MAINTENANCE_TOOLS } from "./maintenance-prompt-zOCiE9ju.mjs"; import { t as buildSkillExperienceReviewPrompt } from "./experience-review-prompt-DuXikY_S.mjs"; import { n as rootedAgentRunParams } from "./rooted-run-params-RwbFgtCU.mjs"; import fs from "node:fs/promises"; import { randomUUID } from "node:crypto"; //#region src/skills/workshop/review-outcome.ts function assertSkillReviewRunSucceeded(result) { const errorPayload = result.payloads?.find((payload) => payload.isError); const unresolvedError = result.meta.toolSummary?.unresolvedError; const message = result.meta.error?.message.trim() || result.meta.failureSignal?.message.trim() || (result.meta.aborted ? "Skill review model run aborted." : void 0) || errorPayload?.text?.trim() || (unresolvedError ? `${resolveToolDisplay({ name: unresolvedError.toolName }).label} failed.` : void 0); if (message || errorPayload) throw new Error(message || "Skill review model run failed."); } //#endregion //#region src/skills/workshop/review-run.ts const reviews = createBackgroundWorkOwner({ owner: "core:skill-workshop", maxConcurrent: 1 }); /** Experience reviews retain admission, model locking, and background capacity. */ async function runSkillWorkshopReview(params) { const restartSignal = getGatewayRestartDrainSignal(); const abortSignal = params.abortSignal ? AbortSignal.any([restartSignal, params.abortSignal]) : restartSignal; abortSignal.throwIfAborted(); const preparedRunAdmission = params.preparedRunAdmission ?? prepareSystemAgentRunAdmission(params.config, params.runId, params.agentId, "skill-workshop.experience"); try { const { runEmbeddedAgent } = await import("./embedded-agent-TxLiyYQ5.mjs"); return await runEmbeddedAgent({ ...params, preparedRunAdmission, abortSignal, lane: reviews.lane, agentHarnessId: "openclaw", agentHarnessRuntimeOverride: "openclaw", modelSelectionLocked: true, modelFallbacksOverride: [], requestedRouteResolution: "resolved", disableTrajectory: true, skillWorkshopProposalOnly: params.skillWorkshopProposalOnly ?? true, cleanupBundleMcpOnRunEnd: true, verboseLevel: "off" }); } finally { preparedRunAdmission.close(); } } //#endregion //#region src/skills/workshop/experience-review.ts async function prepareSkillExperienceReviewCandidate(candidate, config) { if (isIncognitoSessionKey(candidate.source.sessionKey) || resolveSkillWorkshopConfig(config).autonomous.mode === "off") return; const { resolveConversationCapabilityProfile } = await import("./agents/conversation-capability-profile.js"); const { resolveSandboxRuntimeStatus } = await import("./sandbox-BMFqDKul.mjs"); const { isToolAllowedByPolicies } = await import("./tool-policy-match-CUjWTbS4.mjs"); const { mergeAlsoAllowPolicy } = await import("./tool-policy-WAMgDI9G.mjs"); const foreground = candidate.ctx.foregroundPromptContext; const sessionKey = candidate.source.sessionKey; if (resolveSkillWorkshopConfig(config).autonomous.mode === "propose" && resolveSandboxRuntimeStatus({ cfg: config, sessionKey, agentId: foreground.agentId }).sandboxed) return; const capabilityProfile = resolveConversationCapabilityProfile({ config, sessionKey, sandboxSessionKey: sessionKey, agentId: foreground.agentId, agentAccountId: foreground.agentAccountId, messageProvider: foreground.messageProvider, messageChannel: foreground.messageChannel, chatType: foreground.chatType, groupId: foreground.groupId, groupChannel: foreground.groupChannel, groupSpace: foreground.groupSpace, memberRoleIds: foreground.memberRoleIds, spawnedBy: foreground.spawnedBy, senderId: foreground.senderId, senderName: foreground.senderName, senderUsername: foreground.senderUsername, senderE164: foreground.senderE164, senderIsOwner: foreground.senderIsOwner, modelProvider: candidate.ctx.modelProviderId, modelId: candidate.ctx.modelId, workspaceDir: candidate.ctx.workspaceDir }); if (!isToolAllowedByPolicies("skill_workshop", [ mergeAlsoAllowPolicy(capabilityProfile.policy.profilePolicy, capabilityProfile.policy.profileAlsoAllow), mergeAlsoAllowPolicy(capabilityProfile.policy.providerProfilePolicy, capabilityProfile.policy.providerProfileAlsoAllow), capabilityProfile.policy.globalPolicy, capabilityProfile.policy.globalProviderPolicy, capabilityProfile.policy.agentPolicy, capabilityProfile.policy.agentProviderPolicy, capabilityProfile.policy.groupPolicy, capabilityProfile.policy.senderPolicy, capabilityProfile.policy.subagentPolicy, capabilityProfile.policy.inheritedToolPolicy ])) return; return { ...candidate, config }; } async function runSkillExperienceReview(candidate) { await runWithGatewayDetachedWorkAdmission(() => runSkillExperienceReviewInner(candidate), "skills:experience-review"); } async function runSkillExperienceReviewInner(candidate) { const abortSignal = getGatewayRestartDrainSignal(); const { foregroundPromptContext, workspaceDir } = candidate.ctx; const { sessionKey } = candidate.source; const config = candidate.config; const mode = resolveSkillWorkshopConfig(config).autonomous.mode; if (mode === "off") return; const outcomeStore = { context: captureOpenClawStateWorkerContext() }; const executionRoot = mode === "auto" ? resolveWorkshopSkillsDir(config, foregroundPromptContext.agentId) : void 0; const runId = `skill-workshop-review:${randomUUID()}`; const reviewSession = resolveInternalSessionEffectsIdentity({ agentId: foregroundPromptContext.agentId, runId }); const origin = foregroundPromptContext.cronCreatorCallerOrigin; const capability = origin ? createCronCreatorAuthorityCapability(runId, origin) : void 0; const proposalMutationBudget = mode === "propose" ? { remaining: 1, readSkillHashes: /* @__PURE__ */ new Map() } : void 0; const attemptedAtMs = Date.now(); let outcome; let proposalId; let usage; registerAgentRunContext(runId, { agentId: foregroundPromptContext.agentId, sessionId: reviewSession.sessionId, sessionKey: reviewSession.sessionKey, isControlUiVisible: false, projectSessionActive: false, projectSessionLifecycle: false, projectSessionMessages: false }); try { abortSignal.throwIfAborted(); if (executionRoot) await fs.mkdir(executionRoot, { recursive: true }); const sessionManager = await SessionManager.openModelContextAsync(candidate.source, { cwd: executionRoot ?? workspaceDir, through: candidate.source, signal: abortSignal }); abortSignal.throwIfAborted(); const { listWritableWorkshopSkillSummaries } = await import("./workspace-skill-read-eu4ZUk1W.mjs"); abortSignal.throwIfAborted(); const sourceEntry = loadSessionEntryReadOnly({ ...candidate.source, hydrateSkillPromptRefs: false, readConsistency: "latest" }); if (sourceEntry?.sessionId !== candidate.source.sessionId) throw new Error("Skill experience review source session was deleted or replaced."); const existingSkills = mode === "propose" ? listWritableWorkshopSkillSummaries({ config, agentId: foregroundPromptContext.agentId }) : void 0; validateSessionTranscriptContextAnchor(candidate.source, candidate.source); const assertSourceCurrent = () => { abortSignal.throwIfAborted(); if (mode === "auto" && resolveSkillWorkshopConfig(getRuntimeConfig()).autonomous.mode !== "auto") throw new Error("Automatic Skill Workshop maintenance was disabled during review."); const current = loadSessionEntryReadOnly({ ...candidate.source, hydrateSkillPromptRefs: false, readConsistency: "latest" }); if (current?.sessionId !== candidate.source.sessionId || current?.permissionMode !== sourceEntry.permissionMode) throw new Error("Skill experience review source session was deleted, replaced, or changed permissions."); validateSessionTranscriptContextAnchor(candidate.source, candidate.source); }; const preparedRunAdmission = prepareAgentRunAdmission({ cfg: config, operationalRunInstance: createOperationalRunInstanceRef(runId), facts: { runId, agentId: foregroundPromptContext.agentId, ingress: { kind: "system", boundary: "skill-workshop.experience", state: "present" } }, assertSourceCurrent }); const run = () => runSkillWorkshopReview({ ...foregroundPromptContext, preparedRunAdmission, sessionId: reviewSession.sessionId, sessionKey: reviewSession.sessionKey, messageActionTurnCapability: void 0, sessionManager, sessionPersistence: "detached", workspaceDir, ...executionRoot ? rootedAgentRunParams(workspaceDir, executionRoot) : {}, permissionMode: sourceEntry.permissionMode ?? foregroundPromptContext.permissionMode, ...executionRoot ? { skillsSnapshot: { prompt: "", skills: [] } } : {}, config, abortSignal, prompt: buildSkillExperienceReviewPrompt({ ...candidate, existingSkills }, mode), provider: candidate.ctx.modelProviderId, model: candidate.ctx.modelId, ...candidate.ctx.authProfileId ? { authProfileId: candidate.ctx.authProfileId, authProfileIdSource: "user" } : {}, timeoutMs: resolveAgentTimeoutMs({ cfg: config }), runId, silentExpected: true, allowEmptyAssistantReplyAsSilent: true, terminalReplyExpectation: "optional", toolExecutionAllow: mode === "auto" ? [...SKILL_WORKSHOP_MAINTENANCE_TOOLS] : ["skill_workshop"], skillWorkshopProposalOnly: mode === "propose", skillWorkshopUpdateProposals: mode === "propose", skillWorkshopAutonomousCapture: mode === "propose", skillWorkshopProposalMutationBudget: proposalMutationBudget, skillWorkshopOrigin: { agentId: foregroundPromptContext.agentId, sessionKey, ...candidate.ctx.runId ? { runId: candidate.ctx.runId } : {} }, ...capability ? { cronCreatorAuthorityCapability: capability } : {} }); const embeddedResult = capability ? await runWithCronCreatorAuthorityCapability(capability, run) : await run(); preparedRunAdmission.assertSourceCurrent(); assertSkillReviewRunSucceeded(embeddedResult); const proposalIds = [...proposalMutationBudget?.mutatedProposalIds ?? []]; proposalId = proposalIds[0]; outcome = mode === "auto" ? "completed" : proposalIds.length === 0 ? "nothing" : "proposed"; const agentUsage = embeddedResult.meta?.agentMeta?.usage; usage = agentUsage ? { inputTokens: (agentUsage.input ?? 0) + (agentUsage.cacheRead ?? 0) + (agentUsage.cacheWrite ?? 0), cachedInputTokens: agentUsage.cacheRead ?? 0, outputTokens: agentUsage.output ?? 0 } : void 0; } catch (error) { await recordSkillExperienceReviewOutcome(foregroundPromptContext.agentId, workspaceDir, { attemptedAtMs, outcome: "failed", error: truncateUtf16Safe(String(error), 300) }, outcomeStore); throw error; } finally { if (executionRoot) bumpSkillsSnapshotVersion({ reason: "workshop" }); clearAgentRunContext(runId); } await recordSkillExperienceReviewOutcome(foregroundPromptContext.agentId, workspaceDir, { attemptedAtMs, outcome, ...proposalId ? { proposalId } : {}, ...usage ? { usage } : {} }, outcomeStore); } //#endregion export { prepareSkillExperienceReviewCandidate, runSkillExperienceReview };