Updates
Rolling release / release (push) Successful in 8m31s

This commit is contained in:
2026-09-13 15:08:05 -04:00
parent b56171da9b
commit c5ccaa490b
29 changed files with 933 additions and 146 deletions
+31 -2
View File
@@ -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 = () => {};