lib/project-full-access.js
Rama main · réplica de lectura del repositorio original.
// Serialized, transactional owner for every per-session permission selection.
// Skip is Clay-managed and deliberately maps the SDK to default.
function createFullAccessService(ctx) {
var sm = ctx.sm;
var transitions = new Map();
function serialize(session, action) {
var prior = transitions.get(session.localId) || Promise.resolve();
var next = prior.catch(function () {}).then(action);
transitions.set(session.localId, next);
return next.finally(function () { if (transitions.get(session.localId) === next) transitions.delete(session.localId); });
}
function snapshot(session) {
return { permissionMode: session.permissionMode || null, permissionModeBeforeFullAccess: session.permissionModeBeforeFullAccess || null,
effectivePermissionMode: session.effectivePermissionMode || null, permissionModeFallbackReason: session.permissionModeFallbackReason || null,
enabled: session.permissionMode === "bypassPermissions" };
}
function persist(session) {
if (sm.saveSessionFile(session) === false) throw new Error("Could not persist permission mode.");
sm.broadcastSessionList();
if (typeof sm.sendToSession === "function") sm.sendToSession(session, { type: "session_full_access_changed", id: session.localId,
enabled: session.permissionMode === "bypassPermissions", permissionMode: session.permissionMode });
}
async function setNative(session, mode) {
if (!session.queryInstance || typeof session.queryInstance.setPermissionMode !== "function") return;
await session.queryInstance.setPermissionMode(mode === "bypassPermissions" ? "default" : mode);
}
async function applyMode(session, mode) {
var previous = snapshot(session);
if (previous.permissionMode === mode) return previous;
// Clear stale confirmation before the setter. An init/status event may
// arrive while it is pending; do not clear that newer observation later.
session.effectivePermissionMode = null;
session.permissionModeFallbackReason = null;
try {
await setNative(session, mode);
} catch (error) {
session.effectivePermissionMode = previous.effectivePermissionMode;
session.permissionModeFallbackReason = previous.permissionModeFallbackReason;
throw error;
}
session.permissionMode = mode;
session.permissionModeBeforeFullAccess = mode === "bypassPermissions" ? (previous.permissionMode || sm.currentPermissionMode || "default") : null;
try { persist(session); return previous; }
catch (error) {
session.permissionMode = previous.permissionMode;
session.permissionModeBeforeFullAccess = previous.permissionModeBeforeFullAccess;
session.effectivePermissionMode = previous.effectivePermissionMode;
session.permissionModeFallbackReason = previous.permissionModeFallbackReason;
try { await setNative(session, previous.permissionMode || "default"); }
catch (rollbackError) {
session.effectivePermissionMode = null;
session.permissionModeFallbackReason = "Permission rollback failed: " + (rollbackError.message || rollbackError);
}
throw error;
}
}
function setMode(session, mode, options) {
return serialize(session, function () {
if (!options || typeof options.revalidate !== "function") return applyMode(session, mode);
options.revalidate();
var observed = { revision: Number(session._permissionObservationRevision || 0), mode: session.effectivePermissionMode, reason: session.permissionModeFallbackReason };
return require("./session-config-transition").applySessionConfig({
sm: sm, session: session, revalidate: options.revalidate, method: "setPermissionMode", nativeValue: mode === "bypassPermissions" ? "default" : mode,
changes: function () {
var newer = Number(session._permissionObservationRevision || 0) !== observed.revision || session.effectivePermissionMode !== observed.mode || session.permissionModeFallbackReason !== observed.reason;
return { permissionMode: mode, permissionModeBeforeFullAccess: mode === "bypassPermissions" ? (session.permissionMode || sm.currentPermissionMode || "default") : null,
effectivePermissionMode: newer ? session.effectivePermissionMode : null, permissionModeFallbackReason: newer ? session.permissionModeFallbackReason : null };
},
publish: function () {
sm.broadcastSessionList();
if (typeof sm.sendToSession === "function") {
sm.sendToSession(session, { type: "session_full_access_changed", id: session.localId, enabled: mode === "bypassPermissions", permissionMode: mode });
sm.sendToSession(session, { type: "config_state", sessionId: session.localId, mode: mode, effectivePermissionMode: session.effectivePermissionMode || null, vendor: session.vendor || sm.defaultVendor || "claude" });
}
},
});
});
}
function setEnabled(session, enabled) {
return serialize(session, function () {
return applyMode(session, enabled ? "bypassPermissions" : (session.permissionModeBeforeFullAccess || "default"));
});
}
function restore(session, prior) {
if (!prior) return Promise.resolve();
return serialize(session, async function () {
var current = snapshot(session);
// Runtime-effective state is an observation, not part of the selection
// snapshot. Clear it before the native setter and preserve any newer
// init/status event that arrives while the acknowledgement is pending.
session.effectivePermissionMode = null;
session.permissionModeFallbackReason = null;
try {
await setNative(session, prior.permissionMode || "default");
} catch (error) {
session.effectivePermissionMode = current.effectivePermissionMode;
session.permissionModeFallbackReason = current.permissionModeFallbackReason;
throw error;
}
session.permissionMode = prior.permissionMode;
session.permissionModeBeforeFullAccess = prior.permissionModeBeforeFullAccess;
try { persist(session); }
catch (error) {
session.permissionMode = current.permissionMode;
session.permissionModeBeforeFullAccess = current.permissionModeBeforeFullAccess;
session.effectivePermissionMode = null;
session.permissionModeFallbackReason = null;
try { await setNative(session, current.permissionMode || "default"); }
catch (rollbackError) {
session.effectivePermissionMode = null;
session.permissionModeFallbackReason = "Permission rollback failed: " + (rollbackError.message || rollbackError);
}
throw error;
}
});
}
return { restore: restore, setEnabled: setEnabled, setMode: setMode, snapshot: snapshot };
}
module.exports = { createFullAccessService: createFullAccessService };