53 lines
1.5 KiB
JavaScript
53 lines
1.5 KiB
JavaScript
const MAX_STEPS = 100;
|
|
|
|
export class ComputerUseSession {
|
|
constructor({ stepsMax = 20, clock = () => Date.now(), audit } = {}) {
|
|
this.clock = clock;
|
|
this.stepsMax = Math.min(MAX_STEPS, Math.max(1, stepsMax));
|
|
this.active = false;
|
|
this.stepsUsed = 0;
|
|
this.sessionId = null;
|
|
this.backend = 'none';
|
|
this.expiresAt = null;
|
|
this.audit = audit;
|
|
}
|
|
|
|
grant({ persist = false, monitors = 'focused' } = {}) {
|
|
this.active = true;
|
|
this.stepsUsed = 0;
|
|
this.sessionId = `cu_${this.clock().toString(36)}`;
|
|
this.expiresAt = this.clock() + 3 * 60 * 1000;
|
|
return { session_id: this.sessionId, restore_token_present: Boolean(persist), monitors, backend: this.backend };
|
|
}
|
|
|
|
setBackend(backend) { this.backend = ['portal-ei', 'ydotool', 'none'].includes(backend) ? backend : 'none'; return this.backend; }
|
|
|
|
revoke() {
|
|
this.active = false;
|
|
this.sessionId = null;
|
|
this.expiresAt = null;
|
|
this.backend = 'none';
|
|
void this.audit?.wipeTemp?.();
|
|
}
|
|
|
|
status() {
|
|
return {
|
|
active: this.active,
|
|
steps_used: this.stepsUsed,
|
|
steps_max: this.stepsMax,
|
|
grant_expires_at: this.expiresAt,
|
|
backend: this.backend,
|
|
};
|
|
}
|
|
|
|
beginStep() {
|
|
if (!this.active) throw new Error('computer-use grant is inactive');
|
|
if (this.expiresAt && this.clock() >= this.expiresAt) {
|
|
this.revoke();
|
|
throw new Error('computer-use grant expired');
|
|
}
|
|
if (this.stepsUsed >= this.stepsMax) throw new Error('computer-use step budget exhausted');
|
|
this.stepsUsed += 1;
|
|
}
|
|
}
|