first commit
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import { access } from 'node:fs/promises';
|
||||
import { constants } from 'node:fs';
|
||||
import { execFile } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
|
||||
const run = promisify(execFile);
|
||||
const checks = [
|
||||
['session', async () => process.env.XDG_SESSION_TYPE || 'unknown'],
|
||||
['portal', async () => { await access('/usr/share/dbus-1/services/org.freedesktop.portal.Desktop.service', constants.F_OK); return 'installed'; }],
|
||||
['pipewire', async () => { await run('sh', ['-lc', 'command -v pw-cat']); return 'installed'; }],
|
||||
['at-spi', async () => { await run('sh', ['-lc', 'command -v gsettings']); return 'desktop tools present'; }],
|
||||
['libei', async () => { await run('sh', ['-lc', 'ldconfig -p 2>/dev/null | grep -q libei']); return 'installed'; }],
|
||||
['ydotool', async () => { await run('sh', ['-lc', 'command -v ydotool']); return 'optional fallback present'; }],
|
||||
];
|
||||
|
||||
let failed = 0;
|
||||
for (const [name, check] of checks) {
|
||||
try { console.log(`ok ${name}: ${await check()}`); }
|
||||
catch { failed += 1; console.log(`---- ${name}: unavailable`); }
|
||||
}
|
||||
console.log(failed ? `cu-doctor: ${failed} optional/required checks unavailable` : 'cu-doctor: all checks passed');
|
||||
process.exitCode = failed ? 1 : 0;
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "@jarvis-qvac/computer-use",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "session.js"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
const MAX_STEPS = 100;
|
||||
|
||||
export class ComputerUseSession {
|
||||
constructor({ stepsMax = 20, clock = () => Date.now() } = {}) {
|
||||
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;
|
||||
}
|
||||
|
||||
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 };
|
||||
}
|
||||
|
||||
revoke() {
|
||||
this.active = false;
|
||||
this.sessionId = null;
|
||||
this.expiresAt = null;
|
||||
this.backend = 'none';
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user