mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-04 19:28:46 +01:00
fix(server): bind Cursor mode at recovery identity boundaries
Reject missing, foreign, or changed observed modes before accepting suspended checkpoints or interaction-driven identity transitions. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
c867cff960
commit
ceb28bdba4
2 files changed
+73
No files matched your search
@@ -5429,6 +5429,7 @@ export function providerSessionIdentityFromDurableProviderState(input: {
|
||||
identity.requestedModel !== expectedModel ||
|
||||
identity.effectiveModel !== expectedModel ||
|
||||
identity.permissionMode !== input.execution.provider.permissionMode ||
|
||||
!acpxRecoveryCursorModeMatches(input.execution.provider, descriptor.cursorMode, identity.cursorMode) ||
|
||||
!["approve-all", "approve-paperclip", "approve-reads", "deny-all"].includes(
|
||||
String(identity.permissionMode),
|
||||
) ||
|
||||
@@ -5513,11 +5514,30 @@ function providerSessionIdentityIsPresent(value: unknown): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
// Recovery consumes observed identities; it must never apply the fresh-config
|
||||
// default to a missing persisted mode or allow another provider to carry it.
|
||||
function acpxRecoveryCursorModeMatches(
|
||||
provider: NativeExecutionInput["provider"],
|
||||
...observedModes: unknown[]
|
||||
): boolean {
|
||||
const expected = record(provider).cursorMode;
|
||||
if (provider.kind === "acpx" && provider.agent === "cursor") {
|
||||
return (expected === "agent" || expected === "plan" || expected === "ask")
|
||||
&& observedModes.every(mode => mode === expected);
|
||||
}
|
||||
return expected === undefined && observedModes.every(mode => mode === undefined);
|
||||
}
|
||||
|
||||
export function providerSessionIdentityTransitionIsAllowed(input: {
|
||||
execution: NativeExecutionInput;
|
||||
previous: unknown;
|
||||
current: unknown;
|
||||
}): boolean {
|
||||
if (input.execution.provider.kind === "acpx" && !acpxRecoveryCursorModeMatches(
|
||||
input.execution.provider,
|
||||
record(record(input.previous).providerSessionIdentity).cursorMode,
|
||||
record(record(input.current).providerSessionIdentity).cursorMode,
|
||||
)) return false;
|
||||
if (canonicalJson(input.previous) === canonicalJson(input.current)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user