UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

211 lines (210 loc) • 10.2 kB
import { a as getNodeSqliteKysely, r as executeSqliteQuerySync } from "./kysely-sync-K7ftY-g4.mjs"; import { i as requestSqliteWorkerOperationAdmission } from "./sqlite-worker-operation-admission-cNGSH5v0.mjs"; import { l as runOpenClawStateWriteTransaction, r as openOpenClawStateDatabase } from "./openclaw-state-db-D1jWDzK3.mjs"; import { t as createOpenClawStateSchemaEnsurer } from "./openclaw-state-feature-schema-gpylD4Gq.mjs"; import { _ as worktreeGcRevision, d as getRegistryWorktreeProvisionedChunkInDatabase, f as getRegistryWorktreeProvisionedPathsInDatabase, g as rowToRecord$1, h as listRegistryWorktreesInDatabase, l as WORKTREE_RECORD_COLUMNS, m as listLiveRegistryWorktreeIdsInDatabase, n as releaseWorktreeRunLeaseInDatabase, p as getRegistryWorktreeProvisionedStateInDatabase, s as reapWorktreeRunLeasesInDatabase, t as admitWorktreeRunLeaseInDatabase, u as getRegistryWorktreeInDatabase } from "./run-lease-store.kernel-CMstqu0z.mjs"; import { t as hasLocalWorkspaceProjectionInDatabase } from "./local-workspace-store-BrnU7gz2.mjs"; //#region src/agents/worktrees/registry-retirement.worker.ts function deferWorktreeCleanupInWorker({ observed, reason }, options) { return runOpenClawStateWriteTransaction(({ db }) => { requestSqliteWorkerOperationAdmission({ stage: "transaction", facts: void 0 }); const current = getRegistryWorktreeInDatabase(db, observed.id); const revision = worktreeGcRevision(observed); if (!current || current.removedAt !== void 0 || worktreeGcRevision(current) !== revision) return false; executeSqliteQuerySync(db, getNodeSqliteKysely(db).updateTable("worktrees").set({ gc_protection_json: reason === null ? null : JSON.stringify({ revision, reason }) }).where("id", "=", observed.id)); requestSqliteWorkerOperationAdmission({ stage: "commit", facts: void 0 }); return true; }, options, { operationLabel: "worktrees.deferCleanup" }); } function retireMissingWorktreeInWorker({ observed, removedAt }, options) { return runOpenClawStateWriteTransaction(({ db }) => { requestSqliteWorkerOperationAdmission({ stage: "transaction", facts: void 0 }); if (hasLocalWorkspaceProjectionInDatabase(db, observed.id)) return { record: getRegistryWorktreeInDatabase(db, observed.id), protection: "local-workspace-projection" }; const retired = executeSqliteQuerySync(db, getNodeSqliteKysely(db).updateTable("worktrees").set({ removed_at: removedAt }).where("id", "=", observed.id).where("removed_at", "is", null).where((eb) => eb.or([eb("snapshot_ref", "is", null), eb("snapshot_ref", "not like", "refs/openclaw/snapshots/exact-%")])).where("path", "=", observed.path).where("last_active_at", "=", observed.lastActiveAt).where("repo_root", "=", observed.repoRoot).where("repo_fingerprint", "=", observed.repoFingerprint).returning(WORKTREE_RECORD_COLUMNS)).rows[0]; const record = retired ? rowToRecord$1(retired) : getRegistryWorktreeInDatabase(db, observed.id); requestSqliteWorkerOperationAdmission({ stage: "commit", facts: void 0 }); return { record }; }, options, { operationLabel: "worktrees.retireMissing" }); } //#endregion //#region src/agents/worktrees/run-lease-store.worker.ts function worktreeRunLeaseOperation(operationLabel, mutate) { return (input, context) => { const database = context.open(); runOpenClawStateWriteTransaction(({ db }) => { requestSqliteWorkerOperationAdmission({ stage: "transaction", facts: void 0 }); mutate(db, input); requestSqliteWorkerOperationAdmission({ stage: "commit", facts: void 0 }); }, { ...context.stateOptions(), database }, { operationLabel }); }; } //#endregion //#region src/agents/worktrees/template-registry.ts const ensureTemplateSchema = createOpenClawStateSchemaEnsurer({ table: "worktree_templates", operationLabel: "agents.worktrees.templates.schema.ensure" }); function kyselyFor(db) { return getNodeSqliteKysely(db); } function rowToRecord(row) { if (row.status !== "preparing" && row.status !== "ready") throw new Error(`Invalid worktree template status: ${row.status}`); return { cacheKey: row.cache_key, id: row.id, repoRoot: row.repo_root, commonDir: row.common_dir, worktreeRoot: row.worktree_root, path: row.path, backend: row.backend, sourceCommit: row.source_commit, contentKey: row.content_key, status: row.status, createdAt: row.created_at, lastUsedAt: row.last_used_at }; } function openTemplateDatabase(env) { ensureTemplateSchema({ env }); return openOpenClawStateDatabase({ env }).db; } function readTemplate(env, cacheKey) { const db = openTemplateDatabase(env); const row = executeSqliteQuerySync(db, kyselyFor(db).selectFrom("worktree_templates").selectAll().where("cache_key", "=", cacheKey)).rows[0]; return row ? rowToRecord(row) : void 0; } function hasTemplates(env) { const db = openTemplateDatabase(env); return executeSqliteQuerySync(db, kyselyFor(db).selectFrom("worktree_templates").select("cache_key").limit(1)).rows.length > 0; } function listTemplates(env) { const db = openTemplateDatabase(env); return executeSqliteQuerySync(db, kyselyFor(db).selectFrom("worktree_templates").selectAll().orderBy("last_used_at", "asc").orderBy("id", "asc")).rows.map(rowToRecord); } function mutateTemplate(env, commitGuard, operationLabel, mutate) { commitGuard(); ensureTemplateSchema({ env }); return runOpenClawStateWriteTransaction(({ db }) => { commitGuard(); return mutate(db); }, { env }, { operationLabel }); } /** Reserve before creating the artifact; an occupied slot must be retired first. */ function reserveTemplate(env, record, commitGuard) { mutateTemplate(env, commitGuard, "agents.worktrees.templates.reserve", (db) => { executeSqliteQuerySync(db, kyselyFor(db).insertInto("worktree_templates").values({ cache_key: record.cacheKey, id: record.id, repo_root: record.repoRoot, common_dir: record.commonDir, worktree_root: record.worktreeRoot, path: record.path, backend: record.backend, source_commit: record.sourceCommit, content_key: record.contentKey, status: record.status, created_at: record.createdAt, last_used_at: record.lastUsedAt })); }); } function markTemplateReady(env, id, now, commitGuard) { return mutateTemplate(env, commitGuard, "agents.worktrees.templates.ready", (db) => { return executeSqliteQuerySync(db, kyselyFor(db).updateTable("worktree_templates").set({ status: "ready", last_used_at: now }).where("id", "=", id).where("status", "=", "preparing")).numAffectedRows === 1n; }); } function touchTemplate(env, id, now, commitGuard) { return mutateTemplate(env, commitGuard, "agents.worktrees.templates.touch", (db) => { return executeSqliteQuerySync(db, kyselyFor(db).updateTable("worktree_templates").set({ last_used_at: now }).where("id", "=", id).where("status", "=", "ready")).numAffectedRows === 1n; }); } /** A stale cleanup must never delete a replacement occupying the same cache key. */ function deleteTemplate(env, id, commitGuard) { return mutateTemplate(env, commitGuard, "agents.worktrees.templates.delete", (db) => { return executeSqliteQuerySync(db, kyselyFor(db).deleteFrom("worktree_templates").where("id", "=", id)).numAffectedRows === 1n; }); } //#endregion //#region src/agents/worktrees/template-registry.worker.ts function worktreeTemplateMutation(operationLabel, mutate) { return (input, context) => { const database = context.open(); const options = context.stateOptions(); return runOpenClawStateWriteTransaction(() => { const result = mutate(options.env, input, () => { requestSqliteWorkerOperationAdmission({ stage: "transaction", facts: void 0 }); }); requestSqliteWorkerOperationAdmission({ stage: "commit", facts: void 0 }); return result; }, { ...options, database }, { operationLabel }); }; } //#endregion //#region src/agents/worktrees/dispatch.worker.ts const worktreeOperations = { "worktrees.get": ({ id }, { open }) => getRegistryWorktreeInDatabase(open().db, id), "worktrees.list": (input, { open }) => listRegistryWorktreesInDatabase(open().db, input), "worktrees.liveIds": (_input, { open }) => listLiveRegistryWorktreeIdsInDatabase(open().db), "worktrees.provisionedPaths": ({ id }, { open }) => getRegistryWorktreeProvisionedPathsInDatabase(open().db, id), "worktrees.provisionedState": ({ id }, { open }) => getRegistryWorktreeProvisionedStateInDatabase(open().db, id), "worktrees.provisionedChunk": (input, { open }) => getRegistryWorktreeProvisionedChunkInDatabase(open().db, input), "worktrees.retireMissing": (input, { open, stateOptions }) => retireMissingWorktreeInWorker(input, { ...stateOptions(), database: open() }), "worktrees.deferCleanup": (input, { open, stateOptions }) => deferWorktreeCleanupInWorker(input, { ...stateOptions(), database: open() }), "worktrees.admitRunLease": worktreeRunLeaseOperation("worktrees.admitRunLease", admitWorktreeRunLeaseInDatabase), "worktrees.releaseRunLease": worktreeRunLeaseOperation("worktrees.releaseRunLease", (db, { worktreeId, token }) => releaseWorktreeRunLeaseInDatabase(db, worktreeId, token)), "worktrees.reapRunLeases": worktreeRunLeaseOperation("worktrees.reapRunLeases", (db, { scopes }) => reapWorktreeRunLeasesInDatabase(db, scopes)), "worktrees.templates.read": ({ cacheKey }, { stateOptions }) => readTemplate(stateOptions().env, cacheKey), "worktrees.templates.has": (_input, { stateOptions }) => hasTemplates(stateOptions().env), "worktrees.templates.list": (_input, { stateOptions }) => listTemplates(stateOptions().env), "worktrees.templates.reserve": worktreeTemplateMutation("worktrees.templates.reserve", reserveTemplate), "worktrees.templates.ready": worktreeTemplateMutation("worktrees.templates.ready", (env, { id, now }, commitGuard) => markTemplateReady(env, id, now, commitGuard)), "worktrees.templates.touch": worktreeTemplateMutation("worktrees.templates.touch", (env, { id, now }, commitGuard) => touchTemplate(env, id, now, commitGuard)), "worktrees.templates.delete": worktreeTemplateMutation("worktrees.templates.delete", (env, { id }, commitGuard) => deleteTemplate(env, id, commitGuard)) }; //#endregion export { worktreeOperations };