@@ -9,6 +9,7 @@ import { ComputerUseSession } from '../computer-use/session.js';
|
||||
import { ComputerActuator } from '../computer-use/actuator.js';
|
||||
import { PortalInputBackend } from '../computer-use/portal-input.js';
|
||||
import { createComputerObserveTools } from '../skills/computer-observe.js';
|
||||
import { createComputerActTools } from '../skills/computer-act.js';
|
||||
import { createPhase2Tools, filesystemRoots } from '../skills/phase2-tools.js';
|
||||
import { VoiceStateMachine } from '../daemon/voice-state.js';
|
||||
import { assertLocalEndpoint } from '../daemon/network-policy.js';
|
||||
@@ -83,11 +84,16 @@ test('stale semantic refs fail before input and revocation during preview preven
|
||||
await assert.rejects(actuator.click({ x: 1, y: 1 }), /inactive/);
|
||||
});
|
||||
|
||||
test('desktop observation does not wait for a second Allow after Grant desktop', () => {
|
||||
test('desktop observation and actuation do not wait for a second Allow after Grant desktop', () => {
|
||||
const id = 'cu-observe-permission';
|
||||
try {
|
||||
custom.register(id, createComputerObserveTools({ computer: { status: () => ({ active: true }) }, observer: {} }));
|
||||
custom.register(id, [
|
||||
...createComputerObserveTools({ computer: { status: () => ({ active: true }) }, observer: {} }),
|
||||
...createComputerActTools({ actuator: {} }),
|
||||
]);
|
||||
assert.equal(custom.needsPermission(id, 'cu_observe', 'ask'), false);
|
||||
assert.equal(custom.needsPermission(id, 'cu_click', 'ask'), false);
|
||||
assert.equal(custom.needsPermission(id, 'cu_type', 'ask'), false);
|
||||
} finally { custom.clear(id); }
|
||||
});
|
||||
|
||||
@@ -97,6 +103,29 @@ test('expired grants prevent desktop observation', async () => {
|
||||
await assert.rejects(observe.execute(), /grant/);
|
||||
});
|
||||
|
||||
test('observe tools return compact tree nodes without accessibility state dumps', async () => {
|
||||
const computer = { status: () => ({ active: true }) };
|
||||
const observer = {
|
||||
observe: async () => ({
|
||||
focused: { name: 'Discord' },
|
||||
windows: [{ id: 1 }],
|
||||
tree: [{ ref: 'r1', role: 'frame', name: 'Discord', rect: [0, 0, 10, 10], state: ['1', '8', '24'] }],
|
||||
frame_source: 'pipewire',
|
||||
screenshot_path: '/tmp/x.webp',
|
||||
unavailable: [],
|
||||
}),
|
||||
find: async () => [{ ref: 'r1', role: 'entry', name: 'Message', rect: [1, 2, 3, 4], score: 90, state: ['focused'] }],
|
||||
};
|
||||
const tools = Object.fromEntries(createComputerObserveTools({ computer, observer }).map((tool) => [tool.name, tool]));
|
||||
const seen = await tools.cu_observe.execute({});
|
||||
assert.equal(seen.tree[0].ref, 'r1');
|
||||
assert.equal(seen.tree[0].state, undefined);
|
||||
assert.match(seen.hint, /Do not paste/);
|
||||
const hits = await tools.cu_find.execute({ query: 'message' });
|
||||
assert.equal(hits[0].score, 90);
|
||||
assert.equal(hits[0].state, undefined);
|
||||
});
|
||||
|
||||
function helper() {
|
||||
const child = new EventEmitter();
|
||||
child.stdout = new EventEmitter(); child.stderr = new EventEmitter(); child.stdin = new EventEmitter(); child.stdin.writable = true; child.stdin.write = () => {};
|
||||
|
||||
Reference in New Issue
Block a user