UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

584 lines (583 loc) 26.5 kB
import "./src-vebZIeLe.js"; import { t as expectDefined } from "./expect-CyE8FADM.js"; import { t as stableStringify } from "./stable-stringify-C8X7niaI.js"; import { l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js"; import { n as normalizeAgentId } from "./agent-id-CeT3w4ap.js"; import { m as resolveAgentWorkspaceDir } from "./agent-scope-config-DcbEhP0R.js"; import { O as parseAgentSessionKey } from "./session-key-BnWWjqNc.js"; import { t as formatErrorMessage } from "./errors-Db3Ymjlb.js"; import "./agent-scope-DbtJyKUL.js"; import { t as ADMIN_SCOPE } from "./operator-scopes-Dw7Gu2cA.js"; import { t as ErrorCodes } from "./gateway-error-details-w0nAGBBp.js"; import { ei as validateSessionsCreateParams, vm as SESSION_CREATE_IDEMPOTENCY_RETENTION_MS } from "./src-BiL5aQto.js"; import { r as authorizeOperatorScopesForRequiredScope } from "./method-scopes-K6J_UQGL.js"; import { d as errorShape, f as missingScopeErrorShape } from "./error-codes-Bo8q2D1o.js"; import { O as sessionEntryForkedFromParent } from "./session-accessor.sqlite-entry-CWk3jL7s.js"; import "./server-constants-BrVEC7RW.js"; import { r as resolveAgentMainSessionKey } from "./main-session-Br0F9dzh.js"; import { t as assertPreparedSkillLibrarySelection } from "./selection-NYtFFG08.js"; import { f as resolveOperatorSessionCreation } from "./operator-role-policy-wsr1DeJv.js"; import { a as insideGitCheckout } from "./git-BuLvhVpD.js"; import { n as resolveRequestedSessionAgentId } from "./session-request-agent-CCRSEGCB.js"; import { d as resolveGatewaySessionStoreTarget, i as loadGatewaySessionEntryReadOnly } from "./session-utils-store-CInT2loy.js"; import "./session-utils-Cai0_C6U.js"; import { n as resolveWorkspacePathContainment } from "./workspace-path-containment-Sb6Du35U.js"; import { y as ensureSessionGroupRegistered } from "./session-sharing-B7MI8hNo.js"; import { a as normalizeChatSendRequest, c as prepareSessionCreateFilesystemRoot, l as prepareSessionWorktree, o as normalizeSessionProjectGitUrl, s as validateSessionProjectPreparation, u as resolveSpawnParentWorktreeSource } from "./chat-send-handler-Dpw17Gmy.js"; import { t as chatHandlers } from "./chat-IsrqkYID.js"; import { t as ModelAccountConnectAuthorityError } from "./model-account-connect-BqlZBB8r.js"; import { r as prepareSessionModelAccountAccess } from "./users-model-account-access-B9iXjlLs.js"; import { t as assertValidParams } from "./validation-pzrlzFvo.js"; import { t as prepareSkillLibrarySessionCreation } from "./skill-library-session-B_Xf-cjX.js"; import { c as resolveExplicitSessionName, n as generateWorktreeSessionTitle, t as buildDashboardSessionTitleSource } from "./dashboard-session-title-DoHAIULX.js"; import { n as emitSessionsChanged } from "./session-change-event-DzmH4zlz.js"; import { c as resolveProjectDirectory, l as resolveProjectRegistry, s as resolveProjectCheckout, t as ProjectCheckoutError } from "./project-registry-Cm-dqnhv.js"; import { n as createAgentRuntimeAuthorityGuard } from "./agent-runtime-authority-BkcmfdKo.js"; import { t as normalizeRpcAttachmentsToChatAttachments } from "./attachment-normalize-BA7mKleS.js"; import { d as sessionLog } from "./sessions-shared-D_lV07q2.js"; import { t as resolveRegisteredCatalogCreateTarget } from "./session-catalog-D-2VZMkn.js"; import { n as createGatewaySession, t as buildDashboardSessionKey } from "./session-create-service-CM4MxLMO.js"; import path from "node:path"; import { createHash, randomUUID } from "node:crypto"; //#region src/gateway/server-methods/session-create-category.ts function registerCreatedSessionCategory(category, context) { if (!category) return; try { if (ensureSessionGroupRegistered(category)) emitSessionsChanged(context, { reason: "groups" }); } catch (error) { sessionLog.warn(`failed to register created session category: ${formatErrorMessage(error)}`); } } //#endregion //#region src/gateway/server-methods/session-create-idempotency.ts const sessionCreatesByContext = /* @__PURE__ */ new WeakMap(); function idempotentSessionCreate(handler) { return async (request) => { const idempotencyKey = request.params.idempotencyKey; if (typeof idempotencyKey !== "string" || !idempotencyKey) { await handler(request); return; } const principal = request.client?.authenticatedUserProfile?.profileId ?? request.client?.authenticatedUserId; const deviceId = request.client?.connect.device?.id?.trim(); if (!principal && !deviceId) { request.respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "idempotent session creation requires an authenticated principal or device identity")); return; } const owner = principal ? `principal:${principal}` : `device:${deviceId}`; let entriesByOwner = sessionCreatesByContext.get(request.context); if (!entriesByOwner) { entriesByOwner = /* @__PURE__ */ new Map(); sessionCreatesByContext.set(request.context, entriesByOwner); } const now = Date.now(); let retainedEntryCount = 0; for (const [entryOwner, ownerEntries] of entriesByOwner) { for (const [key, entry] of ownerEntries) if (entry.state.kind === "completed" && entry.expiresAt <= now) ownerEntries.delete(key); if (ownerEntries.size === 0) entriesByOwner.delete(entryOwner); else retainedEntryCount += ownerEntries.size; } let entries = entriesByOwner.get(owner); const requestIdentity = createHash("sha256").update(stableStringify(request.params)).digest("hex"); const authorization = { role: request.client?.connect.role ?? null, scopes: request.client?.connect.scopes?.toSorted() ?? [] }; const existing = entries?.get(idempotencyKey); if (existing) { if (existing.requestIdentity !== requestIdentity) { request.respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "session creation idempotency key was reused with different parameters")); return; } if (existing.authorization.role !== authorization.role) { request.respond(false, void 0, errorShape(ErrorCodes.FORBIDDEN, "session creation authorization changed; start again")); return; } const missingScope = existing.authorization.scopes.find((scope) => !authorization.scopes.includes(scope)); if (missingScope) { request.respond(false, void 0, missingScopeErrorShape({ missingScope, requiredScopes: existing.authorization.scopes })); return; } const result = existing.state.kind === "completed" ? existing.state.result : await existing.state.work; request.respond(result.ok, result.payload, result.error, { ...result.meta, cached: true }); return; } if ((entries?.size ?? 0) >= 1e3 || retainedEntryCount >= 2e3) { request.respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, "session creation capacity is full; retry later")); return; } if (!entries) { entries = /* @__PURE__ */ new Map(); entriesByOwner.set(owner, entries); } const releaseEntry = () => { entries.delete(idempotencyKey); if (entries.size === 0) entriesByOwner.delete(owner); }; const work = Promise.resolve().then(async () => { try { let result; await handler({ ...request, respond: (ok, payload, error, meta) => { result = { ok, payload, error, meta }; } }); result ??= { ok: false, error: errorShape(ErrorCodes.UNAVAILABLE, "session creation was interrupted") }; if (result.ok) { entry.expiresAt = Date.now() + SESSION_CREATE_IDEMPOTENCY_RETENTION_MS; entry.state = { kind: "completed", result }; } else releaseEntry(); return result; } catch (error) { releaseEntry(); throw error; } }); const entry = { requestIdentity, authorization, expiresAt: now + SESSION_CREATE_IDEMPOTENCY_RETENTION_MS, state: { kind: "inflight", work } }; entries.set(idempotencyKey, entry); const result = await work; request.respond(result.ok, result.payload, result.error, result.meta); }; } //#endregion //#region src/gateway/server-methods/session-create-initial-turn.ts function resolveOptionalInitialSessionMessage(params) { if (typeof params.task === "string" && params.task.trim()) return params.task; if (typeof params.message === "string" && params.message.trim()) return params.message; } function resolveSessionCreateInitialTurn(params) { const message = resolveOptionalInitialSessionMessage(params); const normalizedAttachments = normalizeRpcAttachmentsToChatAttachments(params.attachments); if (params.attachments?.length && !message && normalizedAttachments.length === 0) return null; const attachments = normalizedAttachments.length ? normalizedAttachments : void 0; return { attachments, hasInitialTurn: message !== void 0 || attachments !== void 0, message }; } function isFreshChatSendStarted(params) { if (params.cached) return false; return (params.payload && typeof params.payload === "object" ? params.payload.status : void 0) === "started"; } //#endregion //#region src/gateway/server-methods/sessions-create.ts const sessionCreateHandlers = { "sessions.create": async ({ req, params, respond, context, client, isWebchatConnect, sessionMutationCommitGuard, sessionMutationAuthorization, signal }) => { if (!assertValidParams(params, validateSessionsCreateParams, "sessions.create", respond)) return; const p = params; const parentSessionKey = normalizeOptionalString(p.parentSessionKey); const sessionCreation = prepareSkillLibrarySessionCreation(client, context.getRuntimeConfig, resolveOperatorSessionCreation(client, { allowTrustedHint: true })); const spawnRequesterSessionKey = sessionCreation.via === "spawn" ? normalizeOptionalString(sessionCreation.requesterSessionKey) : void 0; if (sessionCreation.inheritedToolPolicy && parentSessionKey !== spawnRequesterSessionKey) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "spawn parent must match the trusted agent caller")); return; } const requestedModel = normalizeOptionalString(p.model); let personalAccounts; try { personalAccounts = prepareSessionModelAccountAccess({ client, context, signal }, requestedModel); } catch (error) { if (!(error instanceof ModelAccountConnectAuthorityError)) throw error; respond(false, void 0, errorShape(ErrorCodes.FORBIDDEN, error.message)); return; } const { personalModelSelection, personalAccountDefaults } = personalAccounts; const cfg = context.getRuntimeConfig(); const authority = createAgentRuntimeAuthorityGuard(client, context, respond); let commitGuard = () => { sessionMutationCommitGuard?.(); authority.commitGuard?.(); sessionMutationAuthorization?.assertCurrent(); assertPreparedSkillLibrarySelection(sessionCreation.skillLibrarySelections); personalModelSelection?.assertCurrent(); personalAccountDefaults?.assertCurrent(); }; const catalogId = normalizeOptionalString(p.catalogId); const catalogConflict = p.model ? "model" : p.key ? "key" : void 0; if (catalogId && catalogConflict) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, `sessions.create catalogId cannot include ${catalogConflict}`)); return; } const explicitlyRequestedKey = normalizeOptionalString(p.key); const explicitlyRequestedAgent = resolveRequestedSessionAgentId(cfg, explicitlyRequestedKey ?? (p.agentId === void 0 ? "main" : void 0), p.agentId ?? parseAgentSessionKey(explicitlyRequestedKey)?.agentId); if (!explicitlyRequestedAgent.ok) { respond(false, void 0, explicitlyRequestedAgent.error); return; } const catalogRequestedKey = normalizeOptionalString(p.key) ?? "global"; const catalogAgentId = catalogId ? normalizeAgentId(parseAgentSessionKey(catalogRequestedKey)?.agentId ?? explicitlyRequestedAgent.agentId) : void 0; const catalogTarget = catalogId && catalogAgentId ? resolveRegisteredCatalogCreateTarget(catalogId, catalogAgentId, cfg) : void 0; if (catalogTarget && !catalogTarget.ok) { respond(false, void 0, errorShape(catalogTarget.unknownCatalog ? ErrorCodes.INVALID_REQUEST : ErrorCodes.UNAVAILABLE, catalogTarget.message)); return; } const initialTurn = resolveSessionCreateInitialTurn(p); if (!initialTurn) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "sessions.create attachments require usable content")); return; } const { attachments: initialAttachments, hasInitialTurn, message: initialMessage } = initialTurn; let sessionKey = explicitlyRequestedKey; const initialRunId = randomUUID(); if (p.mentions?.length) { if (catalogId || p.incognito) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "Human mentions are unavailable for this session mode. Remove the selected mentions to continue.")); return; } sessionKey ??= buildDashboardSessionKey(explicitlyRequestedAgent.agentId); const normalized = normalizeChatSendRequest({ params: { sessionKey, message: initialMessage ?? "", mentions: p.mentions, idempotencyKey: initialRunId }, client }); if (!normalized.ok) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, normalized.error)); return; } const eligible = context.mentionInbox?.validateRecipients(client, { agentId: explicitlyRequestedAgent.agentId, ...p.visibility ? { visibility: p.visibility } : {} }, p.mentions.map((mention) => mention.profileId)); if (!eligible?.ok) { respond(false, void 0, eligible?.error ?? errorShape(ErrorCodes.UNAVAILABLE, "Human mentions are unavailable; reconnect and retry.")); return; } } let requestedCwd = normalizeOptionalString(p.cwd); const requestedExecNode = normalizeOptionalString(p.execNode); const requestedProjectId = normalizeOptionalString(p.projectId); const requestedProjectGitUrl = p.projectGitUrl; const projectPreparationError = validateSessionProjectPreparation({ cwd: requestedCwd, execNode: requestedExecNode, gitUrl: requestedProjectGitUrl, hasInitialTurn, projectId: requestedProjectId }); if (projectPreparationError) { respond(false, void 0, projectPreparationError); return; } if (!(!requestedCwd || (requestedExecNode ? path.isAbsolute(requestedCwd) || path.win32.isAbsolute(requestedCwd) : path.isAbsolute(requestedCwd)))) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "sessions.create cwd must be absolute")); return; } const clientScopes = Array.isArray(client?.connect?.scopes) ? client.connect.scopes : []; if (p.permissionMode === "full" && client !== null && !clientScopes.includes("operator.admin")) { respond(false, void 0, missingScopeErrorShape({ missingScope: ADMIN_SCOPE, requiredScopes: [ADMIN_SCOPE] })); return; } if (requestedCwd && !requestedExecNode && !clientScopes.includes("operator.admin")) { const containment = await resolveWorkspacePathContainment(requestedCwd, cfg); if (!containment) { respond(false, void 0, missingScopeErrorShape({ missingScope: ADMIN_SCOPE, requiredScopes: [ADMIN_SCOPE] })); return; } requestedCwd = containment.path; } if (requestedExecNode && p.worktree === true) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "sessions.create worktree cannot target execNode")); return; } const requestedWorktreeBaseRef = normalizeOptionalString(p.worktreeBaseRef); const requestedWorktreeName = normalizeOptionalString(p.worktreeName); if ((requestedWorktreeBaseRef || requestedWorktreeName) && p.worktree !== true) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "sessions.create worktreeBaseRef/worktreeName require worktree=true")); return; } const explicitSessionLabel = normalizeOptionalString(p.label); const preparedDisplayName = normalizeOptionalString(p.displayName); const titleAgentId = explicitlyRequestedAgent.agentId; const existingWorktreeTarget = p.worktree === true && explicitlyRequestedKey ? loadGatewaySessionEntryReadOnly(explicitlyRequestedKey, { agentId: titleAgentId }).entry : void 0; const deferWorktree = p.worktree === true && hasInitialTurn && !existingWorktreeTarget; let projectRoot; if (requestedProjectId) { const project = resolveProjectRegistry(cfg, requestedProjectId); if (!project) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, `unknown project id: ${requestedProjectId}`)); return; } try { const checkout = p.worktree === true ? await resolveProjectCheckout(project.repoRoot) : void 0; projectRoot = checkout?.path ?? await resolveProjectDirectory(project.repoRoot); if (checkout && project.source !== "workspace" && checkout.path !== checkout.repoRoot) throw new ProjectCheckoutError(`project root is no longer a git checkout`); } catch (error) { const detail = error instanceof ProjectCheckoutError ? error.message : formatErrorMessage(error); respond(false, void 0, errorShape(ErrorCodes.UNAVAILABLE, `project ${requestedProjectId} is unavailable (${detail}); update the agent workspace path or re-register the project`)); return; } } let sessionAgentId = catalogAgentId ?? explicitlyRequestedAgent.agentId; let preparedWorktree; let pendingWorktree; const sessionExecCwd = requestedExecNode ? requestedCwd : void 0; let sessionCwd = requestedExecNode ? void 0 : projectRoot ?? requestedCwd; let prepareLifecycle; const preparedRoot = prepareSessionCreateFilesystemRoot({ cfg, enforceSandboxContainment: Boolean(sessionCwd && !requestedExecNode && (requestedProjectId || p.worktree !== true)), requestedExecNode, requestedProjectId, sessionCwd, sessionKey, targetAgentId: sessionAgentId }); if (!preparedRoot.ok) { respond(false, void 0, preparedRoot.error); return; } sessionCwd = preparedRoot.value.sessionCwd; const sessionRoot = preparedRoot.value.sessionRoot; if (p.worktree === true) { const agentId = explicitlyRequestedAgent.agentId; let targetKey = sessionKey; let preservesUnspecifiedKey = false; if (!targetKey && parentSessionKey && p.emitCommandHooks === true && !hasInitialTurn && cfg.session?.dmScope === "main") { const parentRequestedAgent = resolveRequestedSessionAgentId(cfg, parentSessionKey, agentId); if (!parentRequestedAgent.ok) { respond(false, void 0, parentRequestedAgent.error); return; } const parent = loadGatewaySessionEntryReadOnly(parentSessionKey, { agentId: parentRequestedAgent.agentId }); const parentAgentId = parentRequestedAgent.agentId; if (parent.entry?.sessionId && parent.canonicalKey === resolveAgentMainSessionKey({ cfg, agentId: parentAgentId })) { targetKey = parent.canonicalKey; preservesUnspecifiedKey = true; } } targetKey ??= buildDashboardSessionKey(agentId); const target = resolveGatewaySessionStoreTarget({ cfg, key: targetKey, agentId }); sessionKey = preservesUnspecifiedKey ? void 0 : targetKey; sessionAgentId = target.agentId; const inheritedSource = !projectRoot && !requestedCwd && !requestedProjectGitUrl && spawnRequesterSessionKey && spawnRequesterSessionKey === parentSessionKey && sessionCreation.actor?.type === "agent" && normalizeAgentId(sessionCreation.actor.id) === target.agentId ? resolveSpawnParentWorktreeSource(spawnRequesterSessionKey, target.agentId, commitGuard) : void 0; commitGuard = inheritedSource?.assertCurrent ?? commitGuard; const workspace = projectRoot ?? requestedCwd ?? inheritedSource?.workspace ?? resolveAgentWorkspaceDir(cfg, target.agentId); if (!requestedProjectGitUrl && !insideGitCheckout(workspace)) { respond(false, void 0, errorShape(ErrorCodes.INVALID_REQUEST, "agent workspace is not a git checkout")); return; } if (deferWorktree) pendingWorktree = { ...requestedProjectGitUrl ? {} : { workspace }, name: requestedWorktreeName, baseRef: requestedWorktreeBaseRef, titleSource: buildDashboardSessionTitleSource({ message: initialMessage ?? "", attachments: initialAttachments }) }; else prepareLifecycle = async (lifecycleTarget) => { const source = buildDashboardSessionTitleSource({ message: initialMessage ?? "", attachments: initialAttachments }); const title = !requestedWorktreeName && !explicitSessionLabel && !preparedDisplayName && lifecycleTarget.entry && lifecycleTarget.titleModelSelection !== null ? await generateWorktreeSessionTitle({ cfg, agentId: lifecycleTarget.agentId, entry: requestedModel && !personalModelSelection ? { ...lifecycleTarget.entry, ...lifecycleTarget.titleModelSelection } : lifecycleTarget.entry, sessionId: lifecycleTarget.entry.sessionId, sessionKey: lifecycleTarget.key, storePath: lifecycleTarget.storePath, currentUserMessage: initialMessage, userMessage: source, commitGuard, onError: (error) => sessionLog.warn(`worktree title failed: ${formatErrorMessage(error)}`), onPersisted: () => emitSessionsChanged(context, { sessionKey: lifecycleTarget.key, agentId: lifecycleTarget.agentId, reason: "chat.title" }) }) : void 0; const prepared = await prepareSessionWorktree({ target: lifecycleTarget, workspace, name: requestedWorktreeName, baseRef: requestedWorktreeBaseRef, label: explicitSessionLabel ?? preparedDisplayName ?? title ?? resolveExplicitSessionName(lifecycleTarget.entry) ?? source, runSetupScript: clientScopes.includes(ADMIN_SCOPE), commitGuard }); if (prepared.ok) preparedWorktree = prepared.value; return prepared; }; } let runPayload; let runError; let runMeta; const allowExistingModelSelection = authorizeOperatorScopesForRequiredScope(ADMIN_SCOPE, clientScopes).allowed; const modelCatalogAgentId = sessionAgentId; if (!authority.ensureActive()) return; const created = await createGatewaySession({ cfg, key: sessionKey, agentId: sessionAgentId, label: p.label, displayName: preparedDisplayName, category: p.category, ...catalogTarget ? { catalogTarget: catalogTarget.target } : { model: requestedModel }, personalModelSelection, personalAccountDefaults, contextWindow: p.contextWindow, thinkingLevel: p.thinkingLevel, fastMode: p.fastMode, projectId: requestedProjectId, pendingProjectGitUrl: normalizeSessionProjectGitUrl(requestedProjectGitUrl), pendingWorktree, incognito: p.incognito, ...client?.connect ? { requestingOperatorScopes: clientScopes } : {}, ...client?.authenticatedUserProfile ? { requestingOperatorProfileId: client.authenticatedUserProfile.profileId } : {}, ...client?.internal?.operatorRoleActor ? { operatorRoleActor: client.internal.operatorRoleActor } : {}, visibility: p.visibility, allowExistingModelSelection, parentSessionKey, spawnDepth: p.spawnDepth, spawnToolPolicy: sessionCreation.via === "spawn" && sessionCreation.inheritedToolPolicy ? { ...sessionCreation.inheritedToolPolicy, ...sessionCreation.completionOwnerSessionKey ? { completionOwnerSessionKey: sessionCreation.completionOwnerSessionKey } : {} } : void 0, spawnedCwd: p.worktree === true ? void 0 : sessionCwd, sessionRoot: p.worktree === true ? void 0 : sessionRoot, permissionMode: p.permissionMode, ...p.toolOverrides !== void 0 ? { toolOverrides: p.toolOverrides } : {}, prepareLifecycle, onLifecycleCleanupError: (error) => { sessionLog.warn(`failed to finalize session worktree lifecycle: ${formatErrorMessage(error)}`); }, execNode: requestedExecNode, execCwd: sessionExecCwd, clearExecBinding: !requestedExecNode, clearSpawnedCwd: p.worktree !== true && !sessionCwd, fork: p.fork, forkFrom: p.forkFrom, succeedsParent: p.succeedsParent, emitCommandHooks: p.emitCommandHooks, resetMainWhenUnspecified: !hasInitialTurn, commandSource: "webchat", creation: sessionCreation, authorizedPluginId: normalizeOptionalString(client?.internal?.pluginRuntimeOwnerId), armSessionDiffBaselineCapture: true, loadGatewayModelCatalog: () => context.loadGatewayModelCatalog({ agentId: modelCatalogAgentId }), commitGuard, afterCreate: async ({ key, agentId }) => { if (!authority.hasActive()) return; if (hasInitialTurn) await expectDefined(chatHandlers["chat.send"], "chat.send handler")({ req, params: { sessionKey: key, agentId, message: initialMessage ?? "", idempotencyKey: initialRunId, ...p.mentions ? { mentions: p.mentions } : {}, ...initialAttachments ? { attachments: initialAttachments } : {} }, respond: (ok, payload, error, meta) => { if (ok && payload && typeof payload === "object") runPayload = payload; else runError = error; runMeta = meta; }, context, client, isWebchatConnect }); } }).catch((error) => { if (error instanceof ModelAccountConnectAuthorityError) { respond(false, void 0, errorShape(ErrorCodes.FORBIDDEN, error.message)); return; } return authority.handleClosedError(error); }); if (!created) return; if (!created.ok) { respond(false, void 0, created.error); return; } if (created.postCommit.status === "failed") runError = errorShape(ErrorCodes.UNAVAILABLE, formatErrorMessage(created.postCommit.error)); registerCreatedSessionCategory(normalizeOptionalString(p.category), context); const createdWorktree = preparedWorktree?.worktree ? { id: preparedWorktree.worktree.id, path: preparedWorktree.sessionRoot, branch: preparedWorktree.worktree.branch } : void 0; const responseEntry = sessionEntryForkedFromParent(created.entry) ? { ...created.entry, forkedFromParent: true } : created.entry; const runStarted = !created.resetExisting && runPayload !== void 0 && isFreshChatSendStarted({ payload: runPayload, cached: runMeta?.cached === true }); respond(true, { ok: true, key: created.key, sessionId: created.entry.sessionId, entry: responseEntry, runStarted, ...!created.resetExisting && runPayload ? runPayload : {}, ...!created.resetExisting && runError ? { runError } : {}, resolved: created.resolved, ...createdWorktree ? { worktree: createdWorktree } : {} }, void 0); emitSessionsChanged(context, { sessionKey: created.key, agentId: created.agentId, reason: created.resetExisting ? "new" : "create" }); if (runStarted) emitSessionsChanged(context, { sessionKey: created.key, agentId: created.agentId, reason: "send" }); } }; sessionCreateHandlers["sessions.create"] = idempotentSessionCreate(expectDefined(sessionCreateHandlers["sessions.create"], "sessions.create handler")); //#endregion export { isFreshChatSendStarted as n, sessionCreateHandlers as t };