@moxxy/plugin-computer-control 0.41.2 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/win32-x64/moxxy-computer.exe +0 -0
- package/bin/win32-x64/moxxy-computer.exe.json +1 -1
- package/dist/backend/access.d.ts +129 -0
- package/dist/backend/access.d.ts.map +1 -0
- package/dist/backend/access.js +158 -0
- package/dist/backend/access.js.map +1 -0
- package/dist/backend/app-hints.d.ts +14 -0
- package/dist/backend/app-hints.d.ts.map +1 -0
- package/dist/backend/app-hints.js +30 -0
- package/dist/backend/app-hints.js.map +1 -0
- package/dist/backend/backend.d.ts +70 -0
- package/dist/backend/backend.d.ts.map +1 -0
- package/dist/backend/backend.js +466 -0
- package/dist/backend/backend.js.map +1 -0
- package/dist/backend/rpc.d.ts +1438 -0
- package/dist/backend/rpc.d.ts.map +1 -0
- package/dist/backend/rpc.js +75 -0
- package/dist/backend/rpc.js.map +1 -0
- package/dist/backend/turn-controls.d.ts +20 -0
- package/dist/backend/turn-controls.d.ts.map +1 -0
- package/dist/backend/turn-controls.js +115 -0
- package/dist/backend/turn-controls.js.map +1 -0
- package/dist/contract/guidance.d.ts +12 -0
- package/dist/contract/guidance.d.ts.map +1 -0
- package/dist/contract/guidance.js +42 -0
- package/dist/contract/guidance.js.map +1 -0
- package/dist/contract/image.d.ts +29 -0
- package/dist/contract/image.d.ts.map +1 -0
- package/dist/contract/image.js +46 -0
- package/dist/contract/image.js.map +1 -0
- package/dist/contract/keys.d.ts +15 -0
- package/dist/contract/keys.d.ts.map +1 -0
- package/dist/contract/keys.js +118 -0
- package/dist/contract/keys.js.map +1 -0
- package/dist/contract/outcome.d.ts +61 -0
- package/dist/contract/outcome.d.ts.map +1 -0
- package/dist/contract/outcome.js +63 -0
- package/dist/contract/outcome.js.map +1 -0
- package/dist/contract/progress.d.ts +27 -0
- package/dist/contract/progress.d.ts.map +1 -0
- package/dist/contract/progress.js +36 -0
- package/dist/contract/progress.js.map +1 -0
- package/dist/contract/tools.d.ts +338 -0
- package/dist/contract/tools.d.ts.map +1 -0
- package/dist/contract/tools.js +195 -0
- package/dist/contract/tools.js.map +1 -0
- package/dist/contract/untrusted.d.ts +3 -0
- package/dist/contract/untrusted.d.ts.map +1 -0
- package/dist/contract/untrusted.js +8 -0
- package/dist/contract/untrusted.js.map +1 -0
- package/dist/helper/artifact.d.ts +41 -0
- package/dist/helper/artifact.d.ts.map +1 -0
- package/dist/helper/artifact.js +189 -0
- package/dist/helper/artifact.js.map +1 -0
- package/dist/helper/protocol.d.ts +80 -0
- package/dist/helper/protocol.d.ts.map +1 -0
- package/dist/helper/protocol.js +49 -0
- package/dist/helper/protocol.js.map +1 -0
- package/dist/helper/transport.d.ts +43 -0
- package/dist/helper/transport.d.ts.map +1 -0
- package/dist/{windows → helper}/transport.js +45 -19
- package/dist/helper/transport.js.map +1 -0
- package/dist/index.d.ts +9 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -42
- package/dist/index.js.map +1 -1
- package/dist/jev/ladder.d.ts +32 -0
- package/dist/jev/ladder.d.ts.map +1 -0
- package/dist/jev/ladder.js +66 -0
- package/dist/jev/ladder.js.map +1 -0
- package/dist/jev/memory.d.ts +11 -0
- package/dist/jev/memory.d.ts.map +1 -0
- package/dist/jev/memory.js +16 -0
- package/dist/jev/memory.js.map +1 -0
- package/dist/jev/run.d.ts +93 -0
- package/dist/jev/run.d.ts.map +1 -0
- package/dist/jev/run.js +403 -0
- package/dist/jev/run.js.map +1 -0
- package/dist/jev/train.d.ts +97 -0
- package/dist/jev/train.d.ts.map +1 -0
- package/dist/jev/train.js +28 -0
- package/dist/jev/train.js.map +1 -0
- package/dist/linux/profile.d.ts +6 -0
- package/dist/linux/profile.d.ts.map +1 -0
- package/dist/linux/profile.js +21 -0
- package/dist/linux/profile.js.map +1 -0
- package/dist/macos/profile.d.ts +5 -0
- package/dist/macos/profile.d.ts.map +1 -0
- package/dist/macos/profile.js +17 -0
- package/dist/macos/profile.js.map +1 -0
- package/dist/preview/controller.d.ts +127 -0
- package/dist/preview/controller.d.ts.map +1 -0
- package/dist/preview/controller.js +203 -0
- package/dist/preview/controller.js.map +1 -0
- package/dist/preview/surface.d.ts +9 -0
- package/dist/preview/surface.d.ts.map +1 -0
- package/dist/preview/surface.js +50 -0
- package/dist/preview/surface.js.map +1 -0
- package/dist/windows/maintenance.d.ts +1 -1
- package/dist/windows/maintenance.d.ts.map +1 -1
- package/dist/windows/maintenance.js +6 -5
- package/dist/windows/maintenance.js.map +1 -1
- package/dist/windows/profile.d.ts +5 -0
- package/dist/windows/profile.d.ts.map +1 -0
- package/dist/windows/profile.js +17 -0
- package/dist/windows/profile.js.map +1 -0
- package/learned/README.md +26 -0
- package/learned/cases/com.apple.calculator.json +395 -0
- package/learned/cases/com.apple.finder.json +115 -0
- package/learned/cases/com.apple.safari.json +112 -0
- package/learned/cases/com.apple.systempreferences.json +255 -0
- package/learned/com.apple.calculator-eace95fc.json +334 -0
- package/learned/com.apple.finder-27cf6ce8.json +260 -0
- package/learned/com.apple.safari-7cd9df4f.json +143 -0
- package/learned/com.apple.systempreferences-02cf0b8b.json +535 -0
- package/package.json +13 -7
- package/scripts/promote-learned.mjs +8 -0
- package/scripts/summarize-trial.mjs +68 -0
- package/scripts/train-learned.mjs +64 -0
- package/skills/computer-apps/blender.md +29 -0
- package/skills/computer-apps/browsers.md +50 -0
- package/skills/computer-apps/design-tools.md +37 -0
- package/skills/computer-apps/finder.md +23 -0
- package/skills/computer-apps/office.md +46 -0
- package/skills/computer-apps/video-editors.md +44 -0
- package/skills/computer-control.md +154 -191
- package/src/backend/access.test.ts +158 -0
- package/src/backend/access.ts +168 -0
- package/src/backend/app-hints.test.ts +59 -0
- package/src/backend/app-hints.ts +39 -0
- package/src/backend/backend.test.ts +725 -0
- package/src/backend/backend.ts +482 -0
- package/src/backend/contract-helper.fixture.mjs +138 -0
- package/src/backend/helper.fixture.ts +38 -0
- package/src/backend/rpc.ts +90 -0
- package/src/backend/turn-controls.test.ts +178 -0
- package/src/backend/turn-controls.ts +120 -0
- package/src/contract/guidance.test.ts +75 -0
- package/src/contract/guidance.ts +48 -0
- package/src/contract/image.test.ts +74 -0
- package/src/contract/image.ts +54 -0
- package/src/contract/keys.test.ts +103 -0
- package/src/contract/keys.ts +117 -0
- package/src/contract/outcome.test.ts +71 -0
- package/src/contract/outcome.ts +72 -0
- package/src/contract/progress.test.ts +56 -0
- package/src/contract/progress.ts +43 -0
- package/src/contract/tools.test.ts +210 -0
- package/src/contract/tools.ts +212 -0
- package/src/contract/untrusted.test.ts +20 -0
- package/src/contract/untrusted.ts +8 -0
- package/src/helper/artifact.test.ts +131 -0
- package/src/helper/artifact.ts +182 -0
- package/src/helper/protocol.test.ts +29 -0
- package/src/helper/protocol.ts +50 -0
- package/src/{windows → helper}/transport.test.ts +76 -19
- package/src/{windows → helper}/transport.ts +54 -16
- package/src/index.test.ts +112 -0
- package/src/index.ts +36 -53
- package/src/jev/ladder.test.ts +113 -0
- package/src/jev/ladder.ts +88 -0
- package/src/jev/memory.ts +20 -0
- package/src/jev/run.test.ts +700 -0
- package/src/jev/run.ts +443 -0
- package/src/jev/train.test.ts +40 -0
- package/src/jev/train.ts +41 -0
- package/src/linux/helper.test.ts +481 -0
- package/src/linux/profile.ts +25 -0
- package/src/macos/helper.test.ts +988 -0
- package/src/macos/profile.ts +19 -0
- package/src/preview/controller.test.ts +308 -0
- package/src/preview/controller.ts +262 -0
- package/src/preview/surface.test.ts +68 -0
- package/src/preview/surface.ts +45 -0
- package/src/skill.test.ts +34 -0
- package/src/windows/maintenance.ts +8 -7
- package/src/windows/profile.ts +19 -0
- package/dist/shell.d.ts +0 -56
- package/dist/shell.d.ts.map +0 -1
- package/dist/shell.js +0 -189
- package/dist/shell.js.map +0 -1
- package/dist/temporary-files.d.ts +0 -2
- package/dist/temporary-files.d.ts.map +0 -1
- package/dist/temporary-files.js +0 -10
- package/dist/temporary-files.js.map +0 -1
- package/dist/tools/applescript.d.ts +0 -2
- package/dist/tools/applescript.d.ts.map +0 -1
- package/dist/tools/applescript.js +0 -50
- package/dist/tools/applescript.js.map +0 -1
- package/dist/tools/click.d.ts +0 -2
- package/dist/tools/click.d.ts.map +0 -1
- package/dist/tools/click.js +0 -58
- package/dist/tools/click.js.map +0 -1
- package/dist/tools/clipboard.d.ts +0 -2
- package/dist/tools/clipboard.d.ts.map +0 -1
- package/dist/tools/clipboard.js +0 -71
- package/dist/tools/clipboard.js.map +0 -1
- package/dist/tools/key.d.ts +0 -11
- package/dist/tools/key.d.ts.map +0 -1
- package/dist/tools/key.js +0 -143
- package/dist/tools/key.js.map +0 -1
- package/dist/tools/open.d.ts +0 -2
- package/dist/tools/open.d.ts.map +0 -1
- package/dist/tools/open.js +0 -91
- package/dist/tools/open.js.map +0 -1
- package/dist/tools/screenshot.d.ts +0 -2
- package/dist/tools/screenshot.d.ts.map +0 -1
- package/dist/tools/screenshot.js +0 -162
- package/dist/tools/screenshot.js.map +0 -1
- package/dist/tools/type.d.ts +0 -8
- package/dist/tools/type.d.ts.map +0 -1
- package/dist/tools/type.js +0 -65
- package/dist/tools/type.js.map +0 -1
- package/dist/windows/artifact.d.ts +0 -3
- package/dist/windows/artifact.d.ts.map +0 -1
- package/dist/windows/artifact.js +0 -57
- package/dist/windows/artifact.js.map +0 -1
- package/dist/windows/backend.d.ts +0 -11
- package/dist/windows/backend.d.ts.map +0 -1
- package/dist/windows/backend.js +0 -122
- package/dist/windows/backend.js.map +0 -1
- package/dist/windows/contracts.d.ts +0 -1627
- package/dist/windows/contracts.d.ts.map +0 -1
- package/dist/windows/contracts.js +0 -137
- package/dist/windows/contracts.js.map +0 -1
- package/dist/windows/control-service.d.ts +0 -12
- package/dist/windows/control-service.d.ts.map +0 -1
- package/dist/windows/control-service.js +0 -65
- package/dist/windows/control-service.js.map +0 -1
- package/dist/windows/guidance.d.ts +0 -3
- package/dist/windows/guidance.d.ts.map +0 -1
- package/dist/windows/guidance.js +0 -20
- package/dist/windows/guidance.js.map +0 -1
- package/dist/windows/protocol.d.ts +0 -9
- package/dist/windows/protocol.d.ts.map +0 -1
- package/dist/windows/protocol.js +0 -32
- package/dist/windows/protocol.js.map +0 -1
- package/dist/windows/transport.d.ts +0 -23
- package/dist/windows/transport.d.ts.map +0 -1
- package/dist/windows/transport.js.map +0 -1
- package/src/shell.test.ts +0 -186
- package/src/shell.ts +0 -213
- package/src/temporary-files.test.ts +0 -18
- package/src/temporary-files.ts +0 -9
- package/src/tools/applescript-serialize.test.ts +0 -74
- package/src/tools/applescript.ts +0 -53
- package/src/tools/click.ts +0 -60
- package/src/tools/clipboard.ts +0 -72
- package/src/tools/key.ts +0 -155
- package/src/tools/open.ts +0 -96
- package/src/tools/screenshot.test.ts +0 -137
- package/src/tools/screenshot.ts +0 -180
- package/src/tools/type.ts +0 -68
- package/src/tools.test.ts +0 -94
- package/src/windows/action-contracts.test.ts +0 -13
- package/src/windows/artifact.test.ts +0 -16
- package/src/windows/artifact.ts +0 -57
- package/src/windows/backend.test.ts +0 -41
- package/src/windows/backend.ts +0 -122
- package/src/windows/contracts.test.ts +0 -81
- package/src/windows/contracts.ts +0 -143
- package/src/windows/control-service.test.ts +0 -58
- package/src/windows/control-service.ts +0 -68
- package/src/windows/guidance.test.ts +0 -29
- package/src/windows/guidance.ts +0 -21
- package/src/windows/model-contract.test.ts +0 -37
- package/src/windows/protocol.ts +0 -27
- package/src/windows/text-contracts.test.ts +0 -14
- package/src/windows/window-typing.test.ts +0 -14
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { CONTRACT_PROTOCOL_VERSION } from '../backend/rpc.js';
|
|
3
|
+
import { verifyHelperArtifact } from '../helper/artifact.js';
|
|
4
|
+
/** The universal helper built by `native/macos/build.sh`. */
|
|
5
|
+
export const macosHelperPath = fileURLToPath(new URL('../../bin/darwin-universal/moxxy-computer', import.meta.url));
|
|
6
|
+
export const macosProfile = {
|
|
7
|
+
platform: 'darwin',
|
|
8
|
+
protocolVersion: CONTRACT_PROTOCOL_VERSION,
|
|
9
|
+
helperPath: macosHelperPath,
|
|
10
|
+
helperArgs: [],
|
|
11
|
+
verifyHelper: () => verifyHelperArtifact(macosHelperPath, CONTRACT_PROTOCOL_VERSION),
|
|
12
|
+
unavailableMessage: 'The macOS Computer Use helper is missing or does not match this version. Reinstall Moxxy; chat remains available.',
|
|
13
|
+
// Launching an app and letting it settle can take several seconds on its own.
|
|
14
|
+
timeoutMs: 30_000,
|
|
15
|
+
previewCodecs: ['h264', 'jpeg'],
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/macos/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,6DAA6D;AAC7D,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,2CAA2C,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEpH,MAAM,CAAC,MAAM,YAAY,GAAoB;IAC3C,QAAQ,EAAE,QAAQ;IAClB,eAAe,EAAE,yBAAyB;IAC1C,UAAU,EAAE,eAAe;IAC3B,UAAU,EAAE,EAAE;IACd,YAAY,EAAE,GAAG,EAAE,CAAC,oBAAoB,CAAC,eAAe,EAAE,yBAAyB,CAAC;IACpF,kBAAkB,EAAE,mHAAmH;IACvI,8EAA8E;IAC9E,SAAS,EAAE,MAAM;IACjB,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;CAChC,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/** What the human sees of the app the agent works in. Never shown to the model or written to the session log. */
|
|
2
|
+
export interface PreviewImage {
|
|
3
|
+
readonly mediaType: 'image/jpeg';
|
|
4
|
+
readonly base64: string;
|
|
5
|
+
readonly width: number;
|
|
6
|
+
readonly height: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* `live`: frames are current. `stale`: the producer went quiet. `unavailable`:
|
|
10
|
+
* it cannot produce (with the reason). `stopped`: no turn is using the computer.
|
|
11
|
+
*/
|
|
12
|
+
export type PreviewState = 'live' | 'stale' | 'unavailable' | 'stopped';
|
|
13
|
+
/** How the picture travels: single JPEG frames, or an H.264 stream for viewers that can decode one. */
|
|
14
|
+
export type PreviewCodec = 'jpeg' | 'h264';
|
|
15
|
+
/** The codecs in `value` this controller knows; anything else in the list is ignored. */
|
|
16
|
+
export declare const previewCodecs: (value: unknown) => PreviewCodec[];
|
|
17
|
+
/** One access unit of the video, Annex B, base64. A key chunk decodes without anything before it. */
|
|
18
|
+
export interface PreviewChunk {
|
|
19
|
+
readonly seq: number;
|
|
20
|
+
readonly key: boolean;
|
|
21
|
+
/** RFC 6381 codec string, e.g. `avc1.4d001f`. */
|
|
22
|
+
readonly codec: string;
|
|
23
|
+
readonly data: string;
|
|
24
|
+
/** Microseconds. */
|
|
25
|
+
readonly timestamp: number;
|
|
26
|
+
readonly width: number;
|
|
27
|
+
readonly height: number;
|
|
28
|
+
}
|
|
29
|
+
export type PreviewMessage = {
|
|
30
|
+
readonly type: 'frame';
|
|
31
|
+
readonly seq: number;
|
|
32
|
+
readonly image: PreviewImage;
|
|
33
|
+
} | ({
|
|
34
|
+
readonly type: 'chunk';
|
|
35
|
+
} & PreviewChunk) | {
|
|
36
|
+
readonly type: 'state';
|
|
37
|
+
readonly state: PreviewState;
|
|
38
|
+
readonly reason?: string;
|
|
39
|
+
};
|
|
40
|
+
export interface PreviewSnapshot {
|
|
41
|
+
readonly state: PreviewState;
|
|
42
|
+
readonly reason?: string;
|
|
43
|
+
readonly frame?: {
|
|
44
|
+
readonly seq: number;
|
|
45
|
+
readonly image: PreviewImage;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** One turn's helper, as far as the preview is concerned. `start` on a running producer changes its rate. */
|
|
49
|
+
export interface PreviewSource {
|
|
50
|
+
/** What this helper can produce. */
|
|
51
|
+
readonly codecs: readonly PreviewCodec[];
|
|
52
|
+
start(fps: number, codec: PreviewCodec): Promise<void>;
|
|
53
|
+
stop(): Promise<void>;
|
|
54
|
+
/** Make the next chunk a key frame. */
|
|
55
|
+
keyframe(): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
/** Pictures a second. Video is smooth; single pictures are each a whole JPEG, so they stay slow. */
|
|
58
|
+
export declare const PREVIEW_FPS: {
|
|
59
|
+
readonly h264: {
|
|
60
|
+
readonly default: 30;
|
|
61
|
+
readonly max: 30;
|
|
62
|
+
};
|
|
63
|
+
readonly jpeg: {
|
|
64
|
+
readonly default: 2;
|
|
65
|
+
readonly max: 5;
|
|
66
|
+
};
|
|
67
|
+
readonly min: 1;
|
|
68
|
+
};
|
|
69
|
+
type Listener = (message: PreviewMessage) => void;
|
|
70
|
+
/**
|
|
71
|
+
* Connects the viewers of the preview to the helper of the turn that is using
|
|
72
|
+
* the computer. The helper captures only while someone watches; viewers get the
|
|
73
|
+
* latest frame at the chosen rate, never a backlog. Video is used when the
|
|
74
|
+
* helper makes it and every viewer can decode it; a viewer that cannot follow
|
|
75
|
+
* the stream gets nothing until the next key frame.
|
|
76
|
+
*/
|
|
77
|
+
export declare class PreviewController {
|
|
78
|
+
private readonly listeners;
|
|
79
|
+
private readonly staleAfterMs;
|
|
80
|
+
/** What the viewer asked for; without a wish each kind of stream runs at its own default. */
|
|
81
|
+
private wish?;
|
|
82
|
+
/** The newest attached turn; older ones are ignored. */
|
|
83
|
+
private active?;
|
|
84
|
+
/** What the active producer was last asked to do. */
|
|
85
|
+
private running?;
|
|
86
|
+
/** Sequence number of the last chunk the producer sent. */
|
|
87
|
+
private lastChunk?;
|
|
88
|
+
private state;
|
|
89
|
+
private reason?;
|
|
90
|
+
private seq;
|
|
91
|
+
private latest?;
|
|
92
|
+
private deliveredAt;
|
|
93
|
+
private flush?;
|
|
94
|
+
private quiet?;
|
|
95
|
+
constructor(options?: {
|
|
96
|
+
fps?: number;
|
|
97
|
+
staleAfterMs?: number;
|
|
98
|
+
});
|
|
99
|
+
/** A viewer joins: it gets the current state and latest frame at once, then every change. */
|
|
100
|
+
subscribe(listener: Listener, codecs?: readonly PreviewCodec[]): () => void;
|
|
101
|
+
/** A viewer says what it can show, after it joined. */
|
|
102
|
+
accept(listener: Listener, codecs: readonly PreviewCodec[]): void;
|
|
103
|
+
/** A viewer lost its place in the video (it dropped chunks or its decoder failed). */
|
|
104
|
+
keyframe(listener: Listener): void;
|
|
105
|
+
snapshot(): PreviewSnapshot;
|
|
106
|
+
setFps(fps: number): void;
|
|
107
|
+
/** A turn started using the computer. Returns the detach to call when its helper is gone. */
|
|
108
|
+
attach(source: PreviewSource): () => void;
|
|
109
|
+
/** A frame from a producer, or `undefined` for "still running, nothing changed". */
|
|
110
|
+
frame(source: PreviewSource, image: PreviewImage | undefined): void;
|
|
111
|
+
/** A piece of the video from a producer. */
|
|
112
|
+
chunk(source: PreviewSource, chunk: PreviewChunk): void;
|
|
113
|
+
failed(source: PreviewSource, reason: string): void;
|
|
114
|
+
private alive;
|
|
115
|
+
private askForKey;
|
|
116
|
+
private codecFor;
|
|
117
|
+
private rate;
|
|
118
|
+
private deliver;
|
|
119
|
+
/** Makes the producer match what is wanted: running at the current rate and codec only while watched. */
|
|
120
|
+
private sync;
|
|
121
|
+
private forget;
|
|
122
|
+
private setState;
|
|
123
|
+
private stateMessage;
|
|
124
|
+
private emit;
|
|
125
|
+
}
|
|
126
|
+
export {};
|
|
127
|
+
//# sourceMappingURL=controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/preview/controller.ts"],"names":[],"mappings":"AAAA,iHAAiH;AACjH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,SAAS,CAAC;AAExE,uGAAuG;AACvG,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3C,yFAAyF;AACzF,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,YAAY,EAAyD,CAAC;AAErH,qGAAqG;AACrG,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oBAAoB;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAA;CAAE,GAC9E,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,YAAY,CAAC,GAC3C;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAA;KAAE,CAAC;CACzE;AAED,6GAA6G;AAC7G,MAAM,WAAW,aAAa;IAC5B,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;IACzC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,uCAAuC;IACvC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,oGAAoG;AACpG,eAAO,MAAM,WAAW;;;;;;;;;;CAAoF,CAAC;AAE7G,KAAK,QAAQ,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;AAQlD;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;IACzD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,6FAA6F;IAC7F,OAAO,CAAC,IAAI,CAAC,CAAS;IACtB,wDAAwD;IACxD,OAAO,CAAC,MAAM,CAAC,CAAgB;IAC/B,qDAAqD;IACrD,OAAO,CAAC,OAAO,CAAC,CAAyF;IACzG,2DAA2D;IAC3D,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,MAAM,CAAC,CAAuC;IACtD,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,KAAK,CAAC,CAAgC;IAC9C,OAAO,CAAC,KAAK,CAAC,CAAgC;gBAElC,OAAO,GAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAO;IAKjE,6FAA6F;IAC7F,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAE,SAAS,YAAY,EAAa,GAAG,MAAM,IAAI;IAWrF,uDAAuD;IACvD,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI;IAOjE,sFAAsF;IACtF,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAOlC,QAAQ,IAAI,eAAe;IAI3B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKzB,6FAA6F;IAC7F,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,IAAI;IAczC,oFAAoF;IACpF,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI;IAWnE,4CAA4C;IAC5C,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI;IAgBvD,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAMnD,OAAO,CAAC,KAAK;IAMb,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,OAAO;IAQf,yGAAyG;IACzG,OAAO,CAAC,IAAI;IA0BZ,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,IAAI;CAGb"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
const isCodec = (value) => value === 'jpeg' || value === 'h264';
|
|
2
|
+
/** The codecs in `value` this controller knows; anything else in the list is ignored. */
|
|
3
|
+
export const previewCodecs = (value) => (Array.isArray(value) ? value.filter(isCodec) : []);
|
|
4
|
+
/** Pictures a second. Video is smooth; single pictures are each a whole JPEG, so they stay slow. */
|
|
5
|
+
export const PREVIEW_FPS = { h264: { default: 30, max: 30 }, jpeg: { default: 2, max: 5 }, min: 1 };
|
|
6
|
+
/**
|
|
7
|
+
* Connects the viewers of the preview to the helper of the turn that is using
|
|
8
|
+
* the computer. The helper captures only while someone watches; viewers get the
|
|
9
|
+
* latest frame at the chosen rate, never a backlog. Video is used when the
|
|
10
|
+
* helper makes it and every viewer can decode it; a viewer that cannot follow
|
|
11
|
+
* the stream gets nothing until the next key frame.
|
|
12
|
+
*/
|
|
13
|
+
export class PreviewController {
|
|
14
|
+
listeners = new Map();
|
|
15
|
+
staleAfterMs;
|
|
16
|
+
/** What the viewer asked for; without a wish each kind of stream runs at its own default. */
|
|
17
|
+
wish;
|
|
18
|
+
/** The newest attached turn; older ones are ignored. */
|
|
19
|
+
active;
|
|
20
|
+
/** What the active producer was last asked to do. */
|
|
21
|
+
running;
|
|
22
|
+
/** Sequence number of the last chunk the producer sent. */
|
|
23
|
+
lastChunk;
|
|
24
|
+
state = 'stopped';
|
|
25
|
+
reason;
|
|
26
|
+
seq = 0;
|
|
27
|
+
latest;
|
|
28
|
+
deliveredAt = Number.NEGATIVE_INFINITY;
|
|
29
|
+
flush;
|
|
30
|
+
quiet;
|
|
31
|
+
constructor(options = {}) {
|
|
32
|
+
this.wish = options.fps;
|
|
33
|
+
this.staleAfterMs = options.staleAfterMs ?? 3000;
|
|
34
|
+
}
|
|
35
|
+
/** A viewer joins: it gets the current state and latest frame at once, then every change. */
|
|
36
|
+
subscribe(listener, codecs = ['jpeg']) {
|
|
37
|
+
this.listeners.set(listener, { codecs, waiting: true });
|
|
38
|
+
listener(this.stateMessage());
|
|
39
|
+
if (this.latest)
|
|
40
|
+
listener({ type: 'frame', ...this.latest });
|
|
41
|
+
this.sync();
|
|
42
|
+
return () => {
|
|
43
|
+
if (!this.listeners.delete(listener))
|
|
44
|
+
return;
|
|
45
|
+
this.sync();
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** A viewer says what it can show, after it joined. */
|
|
49
|
+
accept(listener, codecs) {
|
|
50
|
+
const viewer = this.listeners.get(listener);
|
|
51
|
+
if (!viewer)
|
|
52
|
+
return;
|
|
53
|
+
viewer.codecs = codecs;
|
|
54
|
+
this.sync();
|
|
55
|
+
}
|
|
56
|
+
/** A viewer lost its place in the video (it dropped chunks or its decoder failed). */
|
|
57
|
+
keyframe(listener) {
|
|
58
|
+
const viewer = this.listeners.get(listener);
|
|
59
|
+
if (!viewer || this.running?.codec !== 'h264')
|
|
60
|
+
return;
|
|
61
|
+
viewer.waiting = true;
|
|
62
|
+
this.askForKey(this.running.source);
|
|
63
|
+
}
|
|
64
|
+
snapshot() {
|
|
65
|
+
return { state: this.state, ...(this.reason ? { reason: this.reason } : {}), ...(this.latest ? { frame: this.latest } : {}) };
|
|
66
|
+
}
|
|
67
|
+
setFps(fps) {
|
|
68
|
+
this.wish = fps;
|
|
69
|
+
this.sync();
|
|
70
|
+
}
|
|
71
|
+
/** A turn started using the computer. Returns the detach to call when its helper is gone. */
|
|
72
|
+
attach(source) {
|
|
73
|
+
this.active = source;
|
|
74
|
+
this.forget();
|
|
75
|
+
this.sync();
|
|
76
|
+
return () => {
|
|
77
|
+
if (this.active !== source)
|
|
78
|
+
return;
|
|
79
|
+
this.active = undefined;
|
|
80
|
+
// The helper leaves with its turn, so there is nothing left to stop.
|
|
81
|
+
this.running = undefined;
|
|
82
|
+
this.forget();
|
|
83
|
+
this.setState('stopped');
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/** A frame from a producer, or `undefined` for "still running, nothing changed". */
|
|
87
|
+
frame(source, image) {
|
|
88
|
+
if (source !== this.active || this.listeners.size === 0)
|
|
89
|
+
return;
|
|
90
|
+
this.alive();
|
|
91
|
+
// A producer asked for video that sends a picture cannot make video: the picture is shown.
|
|
92
|
+
if (!image)
|
|
93
|
+
return;
|
|
94
|
+
this.latest = { seq: ++this.seq, image };
|
|
95
|
+
const wait = this.deliveredAt + 1000 / this.rate('jpeg') - Date.now();
|
|
96
|
+
if (wait <= 0)
|
|
97
|
+
this.deliver();
|
|
98
|
+
else
|
|
99
|
+
this.flush ??= setTimeout(() => this.deliver(), wait);
|
|
100
|
+
}
|
|
101
|
+
/** A piece of the video from a producer. */
|
|
102
|
+
chunk(source, chunk) {
|
|
103
|
+
if (source !== this.active || this.running?.codec !== 'h264' || this.listeners.size === 0)
|
|
104
|
+
return;
|
|
105
|
+
this.alive();
|
|
106
|
+
// A chunk went missing: what follows cannot be decoded until the stream starts again.
|
|
107
|
+
const lost = !chunk.key && this.lastChunk !== undefined && chunk.seq !== this.lastChunk + 1;
|
|
108
|
+
this.lastChunk = chunk.seq;
|
|
109
|
+
if (lost) {
|
|
110
|
+
for (const viewer of this.listeners.values())
|
|
111
|
+
viewer.waiting = true;
|
|
112
|
+
this.askForKey(source);
|
|
113
|
+
}
|
|
114
|
+
for (const [listener, viewer] of this.listeners) {
|
|
115
|
+
if (chunk.key)
|
|
116
|
+
viewer.waiting = false;
|
|
117
|
+
if (!viewer.waiting)
|
|
118
|
+
listener({ type: 'chunk', ...chunk });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
failed(source, reason) {
|
|
122
|
+
if (source !== this.active)
|
|
123
|
+
return;
|
|
124
|
+
clearTimeout(this.quiet);
|
|
125
|
+
this.setState('unavailable', reason);
|
|
126
|
+
}
|
|
127
|
+
alive() {
|
|
128
|
+
this.setState('live');
|
|
129
|
+
clearTimeout(this.quiet);
|
|
130
|
+
this.quiet = setTimeout(() => this.setState('stale'), this.staleAfterMs);
|
|
131
|
+
}
|
|
132
|
+
askForKey(source) {
|
|
133
|
+
void source.keyframe().catch(() => undefined);
|
|
134
|
+
}
|
|
135
|
+
codecFor(source) {
|
|
136
|
+
const everyone = [...this.listeners.values()].every((viewer) => viewer.codecs.includes('h264'));
|
|
137
|
+
return everyone && source.codecs.includes('h264') ? 'h264' : 'jpeg';
|
|
138
|
+
}
|
|
139
|
+
rate(codec) {
|
|
140
|
+
const { default: usual, max } = PREVIEW_FPS[codec];
|
|
141
|
+
return Math.min(max, Math.max(PREVIEW_FPS.min, Math.round(this.wish ?? usual)));
|
|
142
|
+
}
|
|
143
|
+
deliver() {
|
|
144
|
+
clearTimeout(this.flush);
|
|
145
|
+
this.flush = undefined;
|
|
146
|
+
if (!this.latest)
|
|
147
|
+
return;
|
|
148
|
+
this.deliveredAt = Date.now();
|
|
149
|
+
this.emit({ type: 'frame', ...this.latest });
|
|
150
|
+
}
|
|
151
|
+
/** Makes the producer match what is wanted: running at the current rate and codec only while watched. */
|
|
152
|
+
sync() {
|
|
153
|
+
const codec = this.active && this.codecFor(this.active);
|
|
154
|
+
const wanted = this.active && codec && this.listeners.size > 0 ? { source: this.active, fps: this.rate(codec), codec } : undefined;
|
|
155
|
+
const running = this.running;
|
|
156
|
+
if (running && running.source !== wanted?.source) {
|
|
157
|
+
this.running = undefined;
|
|
158
|
+
clearTimeout(this.quiet);
|
|
159
|
+
clearTimeout(this.flush);
|
|
160
|
+
this.flush = undefined;
|
|
161
|
+
void running.source.stop().catch(() => undefined);
|
|
162
|
+
}
|
|
163
|
+
if (!wanted)
|
|
164
|
+
return;
|
|
165
|
+
const same = this.running?.source === wanted.source && this.running.fps === wanted.fps && this.running.codec === wanted.codec;
|
|
166
|
+
if (!same) {
|
|
167
|
+
if (this.running?.codec !== wanted.codec) {
|
|
168
|
+
// The other kind of stream starts from nothing: no old picture, no place in the old video.
|
|
169
|
+
this.forget();
|
|
170
|
+
for (const viewer of this.listeners.values())
|
|
171
|
+
viewer.waiting = true;
|
|
172
|
+
}
|
|
173
|
+
this.running = wanted;
|
|
174
|
+
wanted.source.start(wanted.fps, wanted.codec).catch((error) => this.failed(wanted.source, error instanceof Error ? error.message : String(error)));
|
|
175
|
+
}
|
|
176
|
+
// Whoever is waiting in a video stream (a new viewer, or all of them after a switch) needs a key frame.
|
|
177
|
+
if (wanted.codec === 'h264' && [...this.listeners.values()].some((viewer) => viewer.waiting) && this.lastChunk !== undefined)
|
|
178
|
+
this.askForKey(wanted.source);
|
|
179
|
+
}
|
|
180
|
+
forget() {
|
|
181
|
+
clearTimeout(this.quiet);
|
|
182
|
+
clearTimeout(this.flush);
|
|
183
|
+
this.flush = undefined;
|
|
184
|
+
this.latest = undefined;
|
|
185
|
+
this.lastChunk = undefined;
|
|
186
|
+
this.deliveredAt = Number.NEGATIVE_INFINITY;
|
|
187
|
+
}
|
|
188
|
+
setState(state, reason) {
|
|
189
|
+
if (this.state === state && this.reason === reason)
|
|
190
|
+
return;
|
|
191
|
+
this.state = state;
|
|
192
|
+
this.reason = reason;
|
|
193
|
+
this.emit(this.stateMessage());
|
|
194
|
+
}
|
|
195
|
+
stateMessage() {
|
|
196
|
+
return { type: 'state', state: this.state, ...(this.reason ? { reason: this.reason } : {}) };
|
|
197
|
+
}
|
|
198
|
+
emit(message) {
|
|
199
|
+
for (const listener of this.listeners.keys())
|
|
200
|
+
listener(message);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controller.js","sourceRoot":"","sources":["../../src/preview/controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type SurfaceDef } from '@moxxy/sdk';
|
|
2
|
+
import { type PreviewController } from './controller.js';
|
|
3
|
+
export declare const COMPUTER_PREVIEW_SURFACE = "computer-preview";
|
|
4
|
+
/**
|
|
5
|
+
* The live picture of the app the agent works in, for the human. Opening the
|
|
6
|
+
* surface is what starts the capture; with no viewer nothing is captured.
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildComputerPreviewSurface(controller: PreviewController): SurfaceDef;
|
|
9
|
+
//# sourceMappingURL=surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/preview/surface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAoC,KAAK,iBAAiB,EAAuB,MAAM,iBAAiB,CAAC;AAEhH,eAAO,MAAM,wBAAwB,qBAAqB,CAAC;AAE3D;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,iBAAiB,GAAG,UAAU,CAmCrF"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { defineSurface } from '@moxxy/sdk';
|
|
2
|
+
import { previewCodecs } from './controller.js';
|
|
3
|
+
export const COMPUTER_PREVIEW_SURFACE = 'computer-preview';
|
|
4
|
+
/**
|
|
5
|
+
* The live picture of the app the agent works in, for the human. Opening the
|
|
6
|
+
* surface is what starts the capture; with no viewer nothing is captured.
|
|
7
|
+
*/
|
|
8
|
+
export function buildComputerPreviewSurface(controller) {
|
|
9
|
+
return defineSurface({
|
|
10
|
+
kind: COMPUTER_PREVIEW_SURFACE,
|
|
11
|
+
description: 'A live view of the application Computer Use is working in.',
|
|
12
|
+
open: () => {
|
|
13
|
+
const leaving = new Map();
|
|
14
|
+
// One surface instance is one client; what it can decode applies to every subscription it holds.
|
|
15
|
+
let codecs = ['jpeg'];
|
|
16
|
+
return {
|
|
17
|
+
id: COMPUTER_PREVIEW_SURFACE,
|
|
18
|
+
kind: COMPUTER_PREVIEW_SURFACE,
|
|
19
|
+
onData: (callback) => {
|
|
20
|
+
const listener = (message) => { callback(message); };
|
|
21
|
+
const leave = controller.subscribe(listener, codecs);
|
|
22
|
+
leaving.set(listener, leave);
|
|
23
|
+
return () => { leaving.delete(listener); leave(); };
|
|
24
|
+
},
|
|
25
|
+
snapshot: () => controller.snapshot(),
|
|
26
|
+
input: (message) => {
|
|
27
|
+
if (message.type === 'keyframe')
|
|
28
|
+
for (const listener of leaving.keys())
|
|
29
|
+
controller.keyframe(listener);
|
|
30
|
+
if (message.type !== 'configure')
|
|
31
|
+
return;
|
|
32
|
+
if (typeof message.fps === 'number')
|
|
33
|
+
controller.setFps(message.fps);
|
|
34
|
+
if (message.codecs !== undefined) {
|
|
35
|
+
// A viewer always shows pictures; video is what it may add.
|
|
36
|
+
codecs = [...new Set(['jpeg', ...previewCodecs(message.codecs)])];
|
|
37
|
+
for (const listener of leaving.keys())
|
|
38
|
+
controller.accept(listener, codecs);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
close: () => {
|
|
42
|
+
for (const leave of leaving.values())
|
|
43
|
+
leave();
|
|
44
|
+
leaving.clear();
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=surface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface.js","sourceRoot":"","sources":["../../src/preview/surface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAmB,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAkE,MAAM,iBAAiB,CAAC;AAEhH,MAAM,CAAC,MAAM,wBAAwB,GAAG,kBAAkB,CAAC;AAE3D;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAAC,UAA6B;IACvE,OAAO,aAAa,CAAC;QACnB,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EAAE,4DAA4D;QACzE,IAAI,EAAE,GAAG,EAAE;YACT,MAAM,OAAO,GAAG,IAAI,GAAG,EAAiD,CAAC;YACzE,iGAAiG;YACjG,IAAI,MAAM,GAAmB,CAAC,MAAM,CAAC,CAAC;YACtC,OAAO;gBACL,EAAE,EAAE,wBAAwB;gBAC5B,IAAI,EAAE,wBAAwB;gBAC9B,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE;oBACnB,MAAM,QAAQ,GAAG,CAAC,OAAuB,EAAE,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;oBACrE,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;oBACrD,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;oBAC7B,OAAO,GAAG,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;gBACtD,CAAC;gBACD,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE;gBACrC,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE;oBACjB,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU;wBAAE,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE;4BAAE,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBACtG,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;wBAAE,OAAO;oBACzC,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ;wBAAE,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;oBACpE,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;wBACjC,4DAA4D;wBAC5D,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAe,CAAC,MAAM,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;wBAChF,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE;4BAAE,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;oBAC7E,CAAC;gBACH,CAAC;gBACD,KAAK,EAAE,GAAG,EAAE;oBACV,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE;wBAAE,KAAK,EAAE,CAAC;oBAC9C,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClB,CAAC;aACF,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { CONTRACT_PROTOCOL_VERSION as COMPUTER_PROTOCOL_VERSION } from '../backend/rpc.js';
|
|
2
2
|
/** Installer-only coordination; deliberately not exposed as a model tool. */
|
|
3
3
|
export declare function acquireComputerMaintenance(executable: string): Promise<{
|
|
4
4
|
assertHeld: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"maintenance.d.ts","sourceRoot":"","sources":["../../src/windows/maintenance.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"maintenance.d.ts","sourceRoot":"","sources":["../../src/windows/maintenance.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,yBAAyB,IAAI,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAE3F,6EAA6E;AAC7E,wBAAsB,0BAA0B,CAAC,UAAU,EAAE,MAAM;;;GAYlE"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { CONTRACT_PROTOCOL_VERSION } from '../backend/rpc.js';
|
|
3
|
+
import { verifyHelperArtifact } from '../helper/artifact.js';
|
|
4
|
+
import { HelperTransport } from '../helper/transport.js';
|
|
5
|
+
export { CONTRACT_PROTOCOL_VERSION as COMPUTER_PROTOCOL_VERSION } from '../backend/rpc.js';
|
|
5
6
|
/** Installer-only coordination; deliberately not exposed as a model tool. */
|
|
6
7
|
export async function acquireComputerMaintenance(executable) {
|
|
7
|
-
await verifyHelperArtifact(executable);
|
|
8
|
-
const transport = new HelperTransport(executable, ['--parent', String(process.pid)]);
|
|
8
|
+
await verifyHelperArtifact(executable, CONTRACT_PROTOCOL_VERSION);
|
|
9
|
+
const transport = new HelperTransport(executable, ['--parent', String(process.pid)], { protocolVersion: CONTRACT_PROTOCOL_VERSION });
|
|
9
10
|
try {
|
|
10
11
|
z.object({ maintenanceReady: z.literal(true) }).strict().parse(await transport.request('maintenance', {}, new AbortController().signal));
|
|
11
12
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"maintenance.js","sourceRoot":"","sources":["../../src/windows/maintenance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"maintenance.js","sourceRoot":"","sources":["../../src/windows/maintenance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,yBAAyB,IAAI,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAE3F,6EAA6E;AAC7E,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,UAAkB;IACjE,MAAM,oBAAoB,CAAC,UAAU,EAAE,yBAAyB,CAAC,CAAC;IAClE,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,UAAU,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,eAAe,EAAE,yBAAyB,EAAE,CAAC,CAAC;IACrI,IAAI,CAAC;QACH,CAAC,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAC5D,MAAM,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,EAAE,IAAI,eAAe,EAAE,CAAC,MAAM,CAAC,CACzE,CAAC;QACF,OAAO;YACL,UAAU,EAAE,GAAG,EAAE,GAAG,IAAI,SAAS,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC,CAAC,CAAC;YACnG,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE;SAC/B,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAAC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QAAC,MAAM,KAAK,CAAC;IAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/windows/profile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAI7D,0DAA0D;AAC1D,eAAO,MAAM,iBAAiB,QAAoF,CAAC;AAEnH,eAAO,MAAM,cAAc,EAAE,eAU5B,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { CONTRACT_PROTOCOL_VERSION } from '../backend/rpc.js';
|
|
3
|
+
import { verifyHelperArtifact } from '../helper/artifact.js';
|
|
4
|
+
/** The x64 helper built by `native/Build-Windows.ps1`. */
|
|
5
|
+
export const windowsHelperPath = fileURLToPath(new URL('../../bin/win32-x64/moxxy-computer.exe', import.meta.url));
|
|
6
|
+
export const windowsProfile = {
|
|
7
|
+
platform: 'win32',
|
|
8
|
+
protocolVersion: CONTRACT_PROTOCOL_VERSION,
|
|
9
|
+
helperPath: windowsHelperPath,
|
|
10
|
+
helperArgs: [],
|
|
11
|
+
verifyHelper: () => verifyHelperArtifact(windowsHelperPath, CONTRACT_PROTOCOL_VERSION),
|
|
12
|
+
unavailableMessage: 'The Windows Computer Use helper is missing or does not match this version. Install the matching x64 build from a full installer; chat remains available.',
|
|
13
|
+
// Launching an app and letting it settle can take several seconds on its own.
|
|
14
|
+
timeoutMs: 30_000,
|
|
15
|
+
previewCodecs: ['h264', 'jpeg'],
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/windows/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,0DAA0D;AAC1D,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,wCAAwC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEnH,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,QAAQ,EAAE,OAAO;IACjB,eAAe,EAAE,yBAAyB;IAC1C,UAAU,EAAE,iBAAiB;IAC7B,UAAU,EAAE,EAAE;IACd,YAAY,EAAE,GAAG,EAAE,CAAC,oBAAoB,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;IACtF,kBAAkB,EAAE,0JAA0J;IAC9K,8EAA8E;IAC9E,SAAS,EAAE,MAAM;IACjB,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;CAChC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Lessons that ship with Computer Use
|
|
2
|
+
|
|
3
|
+
One file per app: which element a described target was, which way of acting
|
|
4
|
+
worked, what a click made appear, and whole routes that reached their end.
|
|
5
|
+
`computer_run` reads these first, then what the user's own computer learned
|
|
6
|
+
(`~/.moxxy/computer-use/learned/`), and asks Jev only for what neither has.
|
|
7
|
+
|
|
8
|
+
The files are written by training, before a release, on a real machine with
|
|
9
|
+
the apps installed; do not edit them by hand:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
TYPESAFE_API_KEY=… pnpm --filter @moxxy/plugin-computer-control learned:train # every app in cases/
|
|
13
|
+
TYPESAFE_API_KEY=… pnpm --filter @moxxy/plugin-computer-control learned:train com.apple.finder --passes 3
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
It runs the cases of `cases/<app>.json` on the live apps (keep your hands off
|
|
17
|
+
the keyboard and mouse), learns into an empty folder so nothing from everyday
|
|
18
|
+
use is shipped, and adds the result here. The second pass shows what the first
|
|
19
|
+
one taught: a case that runs from its lessons asks Jev nothing. Read the diff
|
|
20
|
+
before committing. To teach a new app, add its `cases/<app>.json`: the app's
|
|
21
|
+
identifier and the runs to try, each a goal and `computer_run` steps.
|
|
22
|
+
|
|
23
|
+
`learned:promote [directory]` adds lessons from a folder instead (by default
|
|
24
|
+
everything this computer learned in everyday use, so check what it brings). Elements are matched by their role and title as the system shows them,
|
|
25
|
+
so a lesson helps only where the app speaks the same language as the machine
|
|
26
|
+
it was learned on (these: macOS in Polish). Elsewhere it is skipped.
|