@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.
Files changed (269) hide show
  1. package/bin/win32-x64/moxxy-computer.exe +0 -0
  2. package/bin/win32-x64/moxxy-computer.exe.json +1 -1
  3. package/dist/backend/access.d.ts +129 -0
  4. package/dist/backend/access.d.ts.map +1 -0
  5. package/dist/backend/access.js +158 -0
  6. package/dist/backend/access.js.map +1 -0
  7. package/dist/backend/app-hints.d.ts +14 -0
  8. package/dist/backend/app-hints.d.ts.map +1 -0
  9. package/dist/backend/app-hints.js +30 -0
  10. package/dist/backend/app-hints.js.map +1 -0
  11. package/dist/backend/backend.d.ts +70 -0
  12. package/dist/backend/backend.d.ts.map +1 -0
  13. package/dist/backend/backend.js +466 -0
  14. package/dist/backend/backend.js.map +1 -0
  15. package/dist/backend/rpc.d.ts +1438 -0
  16. package/dist/backend/rpc.d.ts.map +1 -0
  17. package/dist/backend/rpc.js +75 -0
  18. package/dist/backend/rpc.js.map +1 -0
  19. package/dist/backend/turn-controls.d.ts +20 -0
  20. package/dist/backend/turn-controls.d.ts.map +1 -0
  21. package/dist/backend/turn-controls.js +115 -0
  22. package/dist/backend/turn-controls.js.map +1 -0
  23. package/dist/contract/guidance.d.ts +12 -0
  24. package/dist/contract/guidance.d.ts.map +1 -0
  25. package/dist/contract/guidance.js +42 -0
  26. package/dist/contract/guidance.js.map +1 -0
  27. package/dist/contract/image.d.ts +29 -0
  28. package/dist/contract/image.d.ts.map +1 -0
  29. package/dist/contract/image.js +46 -0
  30. package/dist/contract/image.js.map +1 -0
  31. package/dist/contract/keys.d.ts +15 -0
  32. package/dist/contract/keys.d.ts.map +1 -0
  33. package/dist/contract/keys.js +118 -0
  34. package/dist/contract/keys.js.map +1 -0
  35. package/dist/contract/outcome.d.ts +61 -0
  36. package/dist/contract/outcome.d.ts.map +1 -0
  37. package/dist/contract/outcome.js +63 -0
  38. package/dist/contract/outcome.js.map +1 -0
  39. package/dist/contract/progress.d.ts +27 -0
  40. package/dist/contract/progress.d.ts.map +1 -0
  41. package/dist/contract/progress.js +36 -0
  42. package/dist/contract/progress.js.map +1 -0
  43. package/dist/contract/tools.d.ts +338 -0
  44. package/dist/contract/tools.d.ts.map +1 -0
  45. package/dist/contract/tools.js +195 -0
  46. package/dist/contract/tools.js.map +1 -0
  47. package/dist/contract/untrusted.d.ts +3 -0
  48. package/dist/contract/untrusted.d.ts.map +1 -0
  49. package/dist/contract/untrusted.js +8 -0
  50. package/dist/contract/untrusted.js.map +1 -0
  51. package/dist/helper/artifact.d.ts +41 -0
  52. package/dist/helper/artifact.d.ts.map +1 -0
  53. package/dist/helper/artifact.js +189 -0
  54. package/dist/helper/artifact.js.map +1 -0
  55. package/dist/helper/protocol.d.ts +80 -0
  56. package/dist/helper/protocol.d.ts.map +1 -0
  57. package/dist/helper/protocol.js +49 -0
  58. package/dist/helper/protocol.js.map +1 -0
  59. package/dist/helper/transport.d.ts +43 -0
  60. package/dist/helper/transport.d.ts.map +1 -0
  61. package/dist/{windows → helper}/transport.js +45 -19
  62. package/dist/helper/transport.js.map +1 -0
  63. package/dist/index.d.ts +9 -22
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +35 -42
  66. package/dist/index.js.map +1 -1
  67. package/dist/jev/ladder.d.ts +32 -0
  68. package/dist/jev/ladder.d.ts.map +1 -0
  69. package/dist/jev/ladder.js +66 -0
  70. package/dist/jev/ladder.js.map +1 -0
  71. package/dist/jev/memory.d.ts +11 -0
  72. package/dist/jev/memory.d.ts.map +1 -0
  73. package/dist/jev/memory.js +16 -0
  74. package/dist/jev/memory.js.map +1 -0
  75. package/dist/jev/run.d.ts +93 -0
  76. package/dist/jev/run.d.ts.map +1 -0
  77. package/dist/jev/run.js +403 -0
  78. package/dist/jev/run.js.map +1 -0
  79. package/dist/jev/train.d.ts +97 -0
  80. package/dist/jev/train.d.ts.map +1 -0
  81. package/dist/jev/train.js +28 -0
  82. package/dist/jev/train.js.map +1 -0
  83. package/dist/linux/profile.d.ts +6 -0
  84. package/dist/linux/profile.d.ts.map +1 -0
  85. package/dist/linux/profile.js +21 -0
  86. package/dist/linux/profile.js.map +1 -0
  87. package/dist/macos/profile.d.ts +5 -0
  88. package/dist/macos/profile.d.ts.map +1 -0
  89. package/dist/macos/profile.js +17 -0
  90. package/dist/macos/profile.js.map +1 -0
  91. package/dist/preview/controller.d.ts +127 -0
  92. package/dist/preview/controller.d.ts.map +1 -0
  93. package/dist/preview/controller.js +203 -0
  94. package/dist/preview/controller.js.map +1 -0
  95. package/dist/preview/surface.d.ts +9 -0
  96. package/dist/preview/surface.d.ts.map +1 -0
  97. package/dist/preview/surface.js +50 -0
  98. package/dist/preview/surface.js.map +1 -0
  99. package/dist/windows/maintenance.d.ts +1 -1
  100. package/dist/windows/maintenance.d.ts.map +1 -1
  101. package/dist/windows/maintenance.js +6 -5
  102. package/dist/windows/maintenance.js.map +1 -1
  103. package/dist/windows/profile.d.ts +5 -0
  104. package/dist/windows/profile.d.ts.map +1 -0
  105. package/dist/windows/profile.js +17 -0
  106. package/dist/windows/profile.js.map +1 -0
  107. package/learned/README.md +26 -0
  108. package/learned/cases/com.apple.calculator.json +395 -0
  109. package/learned/cases/com.apple.finder.json +115 -0
  110. package/learned/cases/com.apple.safari.json +112 -0
  111. package/learned/cases/com.apple.systempreferences.json +255 -0
  112. package/learned/com.apple.calculator-eace95fc.json +334 -0
  113. package/learned/com.apple.finder-27cf6ce8.json +260 -0
  114. package/learned/com.apple.safari-7cd9df4f.json +143 -0
  115. package/learned/com.apple.systempreferences-02cf0b8b.json +535 -0
  116. package/package.json +13 -7
  117. package/scripts/promote-learned.mjs +8 -0
  118. package/scripts/summarize-trial.mjs +68 -0
  119. package/scripts/train-learned.mjs +64 -0
  120. package/skills/computer-apps/blender.md +29 -0
  121. package/skills/computer-apps/browsers.md +50 -0
  122. package/skills/computer-apps/design-tools.md +37 -0
  123. package/skills/computer-apps/finder.md +23 -0
  124. package/skills/computer-apps/office.md +46 -0
  125. package/skills/computer-apps/video-editors.md +44 -0
  126. package/skills/computer-control.md +154 -191
  127. package/src/backend/access.test.ts +158 -0
  128. package/src/backend/access.ts +168 -0
  129. package/src/backend/app-hints.test.ts +59 -0
  130. package/src/backend/app-hints.ts +39 -0
  131. package/src/backend/backend.test.ts +725 -0
  132. package/src/backend/backend.ts +482 -0
  133. package/src/backend/contract-helper.fixture.mjs +138 -0
  134. package/src/backend/helper.fixture.ts +38 -0
  135. package/src/backend/rpc.ts +90 -0
  136. package/src/backend/turn-controls.test.ts +178 -0
  137. package/src/backend/turn-controls.ts +120 -0
  138. package/src/contract/guidance.test.ts +75 -0
  139. package/src/contract/guidance.ts +48 -0
  140. package/src/contract/image.test.ts +74 -0
  141. package/src/contract/image.ts +54 -0
  142. package/src/contract/keys.test.ts +103 -0
  143. package/src/contract/keys.ts +117 -0
  144. package/src/contract/outcome.test.ts +71 -0
  145. package/src/contract/outcome.ts +72 -0
  146. package/src/contract/progress.test.ts +56 -0
  147. package/src/contract/progress.ts +43 -0
  148. package/src/contract/tools.test.ts +210 -0
  149. package/src/contract/tools.ts +212 -0
  150. package/src/contract/untrusted.test.ts +20 -0
  151. package/src/contract/untrusted.ts +8 -0
  152. package/src/helper/artifact.test.ts +131 -0
  153. package/src/helper/artifact.ts +182 -0
  154. package/src/helper/protocol.test.ts +29 -0
  155. package/src/helper/protocol.ts +50 -0
  156. package/src/{windows → helper}/transport.test.ts +76 -19
  157. package/src/{windows → helper}/transport.ts +54 -16
  158. package/src/index.test.ts +112 -0
  159. package/src/index.ts +36 -53
  160. package/src/jev/ladder.test.ts +113 -0
  161. package/src/jev/ladder.ts +88 -0
  162. package/src/jev/memory.ts +20 -0
  163. package/src/jev/run.test.ts +700 -0
  164. package/src/jev/run.ts +443 -0
  165. package/src/jev/train.test.ts +40 -0
  166. package/src/jev/train.ts +41 -0
  167. package/src/linux/helper.test.ts +481 -0
  168. package/src/linux/profile.ts +25 -0
  169. package/src/macos/helper.test.ts +988 -0
  170. package/src/macos/profile.ts +19 -0
  171. package/src/preview/controller.test.ts +308 -0
  172. package/src/preview/controller.ts +262 -0
  173. package/src/preview/surface.test.ts +68 -0
  174. package/src/preview/surface.ts +45 -0
  175. package/src/skill.test.ts +34 -0
  176. package/src/windows/maintenance.ts +8 -7
  177. package/src/windows/profile.ts +19 -0
  178. package/dist/shell.d.ts +0 -56
  179. package/dist/shell.d.ts.map +0 -1
  180. package/dist/shell.js +0 -189
  181. package/dist/shell.js.map +0 -1
  182. package/dist/temporary-files.d.ts +0 -2
  183. package/dist/temporary-files.d.ts.map +0 -1
  184. package/dist/temporary-files.js +0 -10
  185. package/dist/temporary-files.js.map +0 -1
  186. package/dist/tools/applescript.d.ts +0 -2
  187. package/dist/tools/applescript.d.ts.map +0 -1
  188. package/dist/tools/applescript.js +0 -50
  189. package/dist/tools/applescript.js.map +0 -1
  190. package/dist/tools/click.d.ts +0 -2
  191. package/dist/tools/click.d.ts.map +0 -1
  192. package/dist/tools/click.js +0 -58
  193. package/dist/tools/click.js.map +0 -1
  194. package/dist/tools/clipboard.d.ts +0 -2
  195. package/dist/tools/clipboard.d.ts.map +0 -1
  196. package/dist/tools/clipboard.js +0 -71
  197. package/dist/tools/clipboard.js.map +0 -1
  198. package/dist/tools/key.d.ts +0 -11
  199. package/dist/tools/key.d.ts.map +0 -1
  200. package/dist/tools/key.js +0 -143
  201. package/dist/tools/key.js.map +0 -1
  202. package/dist/tools/open.d.ts +0 -2
  203. package/dist/tools/open.d.ts.map +0 -1
  204. package/dist/tools/open.js +0 -91
  205. package/dist/tools/open.js.map +0 -1
  206. package/dist/tools/screenshot.d.ts +0 -2
  207. package/dist/tools/screenshot.d.ts.map +0 -1
  208. package/dist/tools/screenshot.js +0 -162
  209. package/dist/tools/screenshot.js.map +0 -1
  210. package/dist/tools/type.d.ts +0 -8
  211. package/dist/tools/type.d.ts.map +0 -1
  212. package/dist/tools/type.js +0 -65
  213. package/dist/tools/type.js.map +0 -1
  214. package/dist/windows/artifact.d.ts +0 -3
  215. package/dist/windows/artifact.d.ts.map +0 -1
  216. package/dist/windows/artifact.js +0 -57
  217. package/dist/windows/artifact.js.map +0 -1
  218. package/dist/windows/backend.d.ts +0 -11
  219. package/dist/windows/backend.d.ts.map +0 -1
  220. package/dist/windows/backend.js +0 -122
  221. package/dist/windows/backend.js.map +0 -1
  222. package/dist/windows/contracts.d.ts +0 -1627
  223. package/dist/windows/contracts.d.ts.map +0 -1
  224. package/dist/windows/contracts.js +0 -137
  225. package/dist/windows/contracts.js.map +0 -1
  226. package/dist/windows/control-service.d.ts +0 -12
  227. package/dist/windows/control-service.d.ts.map +0 -1
  228. package/dist/windows/control-service.js +0 -65
  229. package/dist/windows/control-service.js.map +0 -1
  230. package/dist/windows/guidance.d.ts +0 -3
  231. package/dist/windows/guidance.d.ts.map +0 -1
  232. package/dist/windows/guidance.js +0 -20
  233. package/dist/windows/guidance.js.map +0 -1
  234. package/dist/windows/protocol.d.ts +0 -9
  235. package/dist/windows/protocol.d.ts.map +0 -1
  236. package/dist/windows/protocol.js +0 -32
  237. package/dist/windows/protocol.js.map +0 -1
  238. package/dist/windows/transport.d.ts +0 -23
  239. package/dist/windows/transport.d.ts.map +0 -1
  240. package/dist/windows/transport.js.map +0 -1
  241. package/src/shell.test.ts +0 -186
  242. package/src/shell.ts +0 -213
  243. package/src/temporary-files.test.ts +0 -18
  244. package/src/temporary-files.ts +0 -9
  245. package/src/tools/applescript-serialize.test.ts +0 -74
  246. package/src/tools/applescript.ts +0 -53
  247. package/src/tools/click.ts +0 -60
  248. package/src/tools/clipboard.ts +0 -72
  249. package/src/tools/key.ts +0 -155
  250. package/src/tools/open.ts +0 -96
  251. package/src/tools/screenshot.test.ts +0 -137
  252. package/src/tools/screenshot.ts +0 -180
  253. package/src/tools/type.ts +0 -68
  254. package/src/tools.test.ts +0 -94
  255. package/src/windows/action-contracts.test.ts +0 -13
  256. package/src/windows/artifact.test.ts +0 -16
  257. package/src/windows/artifact.ts +0 -57
  258. package/src/windows/backend.test.ts +0 -41
  259. package/src/windows/backend.ts +0 -122
  260. package/src/windows/contracts.test.ts +0 -81
  261. package/src/windows/contracts.ts +0 -143
  262. package/src/windows/control-service.test.ts +0 -58
  263. package/src/windows/control-service.ts +0 -68
  264. package/src/windows/guidance.test.ts +0 -29
  265. package/src/windows/guidance.ts +0 -21
  266. package/src/windows/model-contract.test.ts +0 -37
  267. package/src/windows/protocol.ts +0 -27
  268. package/src/windows/text-contracts.test.ts +0 -14
  269. package/src/windows/window-typing.test.ts +0 -14
@@ -0,0 +1,45 @@
1
+ import { defineSurface, type SurfaceDef } from '@moxxy/sdk';
2
+ import { previewCodecs, type PreviewCodec, type PreviewController, type PreviewMessage } from './controller.js';
3
+
4
+ export const COMPUTER_PREVIEW_SURFACE = 'computer-preview';
5
+
6
+ /**
7
+ * The live picture of the app the agent works in, for the human. Opening the
8
+ * surface is what starts the capture; with no viewer nothing is captured.
9
+ */
10
+ export function buildComputerPreviewSurface(controller: PreviewController): SurfaceDef {
11
+ return defineSurface({
12
+ kind: COMPUTER_PREVIEW_SURFACE,
13
+ description: 'A live view of the application Computer Use is working in.',
14
+ open: () => {
15
+ const leaving = new Map<(message: PreviewMessage) => void, () => void>();
16
+ // One surface instance is one client; what it can decode applies to every subscription it holds.
17
+ let codecs: PreviewCodec[] = ['jpeg'];
18
+ return {
19
+ id: COMPUTER_PREVIEW_SURFACE,
20
+ kind: COMPUTER_PREVIEW_SURFACE,
21
+ onData: (callback) => {
22
+ const listener = (message: PreviewMessage) => { callback(message); };
23
+ const leave = controller.subscribe(listener, codecs);
24
+ leaving.set(listener, leave);
25
+ return () => { leaving.delete(listener); leave(); };
26
+ },
27
+ snapshot: () => controller.snapshot(),
28
+ input: (message) => {
29
+ if (message.type === 'keyframe') for (const listener of leaving.keys()) controller.keyframe(listener);
30
+ if (message.type !== 'configure') return;
31
+ if (typeof message.fps === 'number') controller.setFps(message.fps);
32
+ if (message.codecs !== undefined) {
33
+ // A viewer always shows pictures; video is what it may add.
34
+ codecs = [...new Set<PreviewCodec>(['jpeg', ...previewCodecs(message.codecs)])];
35
+ for (const listener of leaving.keys()) controller.accept(listener, codecs);
36
+ }
37
+ },
38
+ close: () => {
39
+ for (const leave of leaving.values()) leave();
40
+ leaving.clear();
41
+ },
42
+ };
43
+ },
44
+ });
45
+ }
@@ -0,0 +1,34 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { asSkillId, mentionedSkills, parseFrontmatterFile, skillFrontmatterSchema } from '@moxxy/sdk';
4
+ import { expect, it } from 'vitest';
5
+ import { computerTools } from './contract/tools.js';
6
+
7
+ const skill = parseFrontmatterFile(readFileSync(fileURLToPath(new URL('../skills/computer-control.md', import.meta.url)), 'utf8'));
8
+
9
+ it('allows exactly the tools the plugin can offer, on any platform', () => {
10
+ const frontmatter = skillFrontmatterSchema.parse(skill.frontmatter);
11
+ expect([...(frontmatter['allowed-tools'] ?? [])].sort()).toEqual(Object.keys(computerTools).sort());
12
+ });
13
+
14
+ it('teaches the shared contract and no longer mentions removed tools', () => {
15
+ expect(skill.body).toContain('computer_get_app_state');
16
+ expect(skill.body).toContain('computer_request_access');
17
+ expect(skill.body).not.toMatch(/computer_applescript|osascript|AppleScript/);
18
+ expect(skill.body).not.toMatch(/computer_observe|computer_windows|computer_app_catalog|observationId|captureId/);
19
+ });
20
+
21
+ it('teaches to wait for a followed link instead of clicking it again, and to explain a failure from what was seen', () => {
22
+ expect(skill.body).toContain('page_loading');
23
+ expect(skill.body).toMatch(/never click it again, double-click it or press\s+Return on it/);
24
+ expect(skill.body).toMatch(/asks why[\s\S]*look at the app again[\s\S]*never guess/i);
25
+ });
26
+
27
+ it('answers @computer_use in a chat prompt and keeps the in-window browser out of that request', () => {
28
+ const frontmatter = skillFrontmatterSchema.parse(skill.frontmatter);
29
+ const loaded = { id: asSkillId('plugin/computer-control'), path: 'computer-control.md', scope: 'plugin' as const, frontmatter, body: skill.body };
30
+
31
+ expect(mentionedSkills('@computer_use zrób prezentację w Canvie w Arc', [loaded])).toEqual([loaded]);
32
+ expect(frontmatter['disallowed-tools']).toEqual(['browser_*']);
33
+ expect(frontmatter.label).toBe('Computer Use');
34
+ });
@@ -1,15 +1,16 @@
1
1
  import { z } from 'zod';
2
- import { verifyHelperArtifact } from './artifact.js';
3
- import { HelperTransport } from './transport.js';
4
- export { PROTOCOL_VERSION as COMPUTER_PROTOCOL_VERSION } from './contracts.js';
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
 
6
7
  /** Installer-only coordination; deliberately not exposed as a model tool. */
7
8
  export async function acquireComputerMaintenance(executable: string) {
8
- await verifyHelperArtifact(executable);
9
- const transport=new HelperTransport(executable,['--parent',String(process.pid)]);
9
+ await verifyHelperArtifact(executable, CONTRACT_PROTOCOL_VERSION);
10
+ const transport = new HelperTransport(executable, ['--parent', String(process.pid)], { protocolVersion: CONTRACT_PROTOCOL_VERSION });
10
11
  try {
11
- z.object({maintenanceReady:z.literal(true)}).strict().parse(
12
- await transport.request('maintenance',{},new AbortController().signal),
12
+ z.object({ maintenanceReady: z.literal(true) }).strict().parse(
13
+ await transport.request('maintenance', {}, new AbortController().signal),
13
14
  );
14
15
  return {
15
16
  assertHeld: () => { if (transport.closed) throw new Error('Computer Use maintenance lease lost'); },
@@ -0,0 +1,19 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ import type { PlatformProfile } from '../backend/backend.js';
3
+ import { CONTRACT_PROTOCOL_VERSION } from '../backend/rpc.js';
4
+ import { verifyHelperArtifact } from '../helper/artifact.js';
5
+
6
+ /** The x64 helper built by `native/Build-Windows.ps1`. */
7
+ export const windowsHelperPath = fileURLToPath(new URL('../../bin/win32-x64/moxxy-computer.exe', import.meta.url));
8
+
9
+ export const windowsProfile: PlatformProfile = {
10
+ platform: 'win32',
11
+ protocolVersion: CONTRACT_PROTOCOL_VERSION,
12
+ helperPath: windowsHelperPath,
13
+ helperArgs: [],
14
+ verifyHelper: () => verifyHelperArtifact(windowsHelperPath, CONTRACT_PROTOCOL_VERSION),
15
+ 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.',
16
+ // Launching an app and letting it settle can take several seconds on its own.
17
+ timeoutMs: 30_000,
18
+ previewCodecs: ['h264', 'jpeg'],
19
+ };
package/dist/shell.d.ts DELETED
@@ -1,56 +0,0 @@
1
- export declare const IS_DARWIN: boolean;
2
- /**
3
- * Hard ceiling on combined stdout+stderr a child may emit before it is
4
- * force-killed. The wall-clock timeout caps duration but not throughput —
5
- * a runaway or hostile child (e.g. `pbpaste` on a gigabyte clipboard, or an
6
- * `osascript` snippet that streams unbounded output) can accumulate hundreds
7
- * of MB well inside the timeout and OOM the host. 16 MB is far above any
8
- * legitimate tool output here (the screenshot path caps its own encoded file
9
- * separately) while still bounding worst-case memory.
10
- */
11
- export declare const MAX_OUTPUT_BYTES: number;
12
- export interface ProcResult {
13
- readonly exitCode: number;
14
- readonly stdout: string;
15
- readonly stderr: string;
16
- /**
17
- * True when the child was force-killed because it exceeded `timeoutMs`.
18
- * A timed-out child still resolves (via 'close') with `exitCode: -1`, so
19
- * this flag is the only reliable way for callers to distinguish a timeout
20
- * from a genuine non-zero exit and surface an actionable message.
21
- */
22
- readonly timedOut: boolean;
23
- /** True when the child was force-killed because `opts.signal` aborted. */
24
- readonly aborted: boolean;
25
- /**
26
- * True when the child was force-killed because its combined stdout+stderr
27
- * exceeded `MAX_OUTPUT_BYTES`. The captured output is whatever had been
28
- * read up to the cap.
29
- */
30
- readonly tooLarge: boolean;
31
- }
32
- /**
33
- * Build a uniform failure suffix that names a timeout/abort when the process
34
- * was force-killed, so a stuck `osascript` (etc.) is reported as a clear
35
- * cause rather than a bare `exit -1`. Returns '' for a normal exit.
36
- */
37
- export declare function procFailureCause(proc: ProcResult, timeoutMs?: number): string;
38
- /**
39
- * Spawn a process with array-form args (no shell). Returns stdout +
40
- * stderr + exit code. Optional `input` is written to stdin. Optional
41
- * `signal` propagates aborts from the tool ctx so a stuck `osascript`
42
- * dies with the turn instead of hanging the parent.
43
- *
44
- * Never use this with string interpolation into a single command —
45
- * each argument MUST be a separate array entry. The `bash -c` shape
46
- * would re-introduce the shell-injection risk this helper exists to
47
- * eliminate.
48
- */
49
- export declare function runProcess(cmd: string, args: ReadonlyArray<string>, opts?: {
50
- readonly input?: string | Buffer;
51
- readonly signal?: AbortSignal;
52
- readonly timeoutMs?: number;
53
- }): Promise<ProcResult>;
54
- /** Throw a clear error when a tool is invoked on a non-darwin host. */
55
- export declare function ensureDarwin(toolName: string): void;
56
- //# sourceMappingURL=shell.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,SAAgC,CAAC;AAEvD;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,QAAmB,CAAC;AAKjD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAO7E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,EAC3B,IAAI,GAAE;IACJ,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CACxB,GACL,OAAO,CAAC,UAAU,CAAC,CAgIrB;AAED,uEAAuE;AACvE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAQnD"}
package/dist/shell.js DELETED
@@ -1,189 +0,0 @@
1
- import { spawn } from 'node:child_process';
2
- import { MoxxyError } from '@moxxy/sdk';
3
- export const IS_DARWIN = process.platform === 'darwin';
4
- /**
5
- * Hard ceiling on combined stdout+stderr a child may emit before it is
6
- * force-killed. The wall-clock timeout caps duration but not throughput —
7
- * a runaway or hostile child (e.g. `pbpaste` on a gigabyte clipboard, or an
8
- * `osascript` snippet that streams unbounded output) can accumulate hundreds
9
- * of MB well inside the timeout and OOM the host. 16 MB is far above any
10
- * legitimate tool output here (the screenshot path caps its own encoded file
11
- * separately) while still bounding worst-case memory.
12
- */
13
- export const MAX_OUTPUT_BYTES = 16 * 1024 * 1024;
14
- /** Grace period after SIGTERM before escalating to SIGKILL. */
15
- const SIGKILL_GRACE_MS = 2_500;
16
- /**
17
- * Build a uniform failure suffix that names a timeout/abort when the process
18
- * was force-killed, so a stuck `osascript` (etc.) is reported as a clear
19
- * cause rather than a bare `exit -1`. Returns '' for a normal exit.
20
- */
21
- export function procFailureCause(proc, timeoutMs) {
22
- if (proc.tooLarge)
23
- return `output exceeded ${MAX_OUTPUT_BYTES} bytes (killed)`;
24
- if (proc.timedOut) {
25
- return timeoutMs ? `timed out after ${timeoutMs}ms` : 'timed out';
26
- }
27
- if (proc.aborted)
28
- return 'aborted (turn cancelled)';
29
- return '';
30
- }
31
- /**
32
- * Spawn a process with array-form args (no shell). Returns stdout +
33
- * stderr + exit code. Optional `input` is written to stdin. Optional
34
- * `signal` propagates aborts from the tool ctx so a stuck `osascript`
35
- * dies with the turn instead of hanging the parent.
36
- *
37
- * Never use this with string interpolation into a single command —
38
- * each argument MUST be a separate array entry. The `bash -c` shape
39
- * would re-introduce the shell-injection risk this helper exists to
40
- * eliminate.
41
- */
42
- export function runProcess(cmd, args, opts = {}) {
43
- return new Promise((resolve, reject) => {
44
- // An ALREADY-aborted signal never emits 'abort' to a listener added after
45
- // the fact (DOM semantics), so without this short-circuit a cancelled turn
46
- // would still spawn the child and run it to completion — defeating the
47
- // abort contract. Resolve immediately as an aborted no-op without spawning.
48
- if (opts.signal?.aborted) {
49
- resolve({
50
- exitCode: -1,
51
- stdout: '',
52
- stderr: '',
53
- timedOut: false,
54
- aborted: true,
55
- tooLarge: false,
56
- });
57
- return;
58
- }
59
- const child = spawn(cmd, [...args], { stdio: ['pipe', 'pipe', 'pipe'] });
60
- // Collect BOTH stdout and stderr as chunks and concat ONCE at close.
61
- // Re-concatenating the whole accumulated buffer on every 'data' event is
62
- // O(n^2) and churns the GC; decoding each chunk with `.toString('utf8')`
63
- // in isolation also corrupts any multibyte sequence (e.g. an osascript
64
- // error containing a non-ASCII app name) that straddles a chunk boundary.
65
- const stdoutChunks = [];
66
- const stderrChunks = [];
67
- let outputBytes = 0;
68
- let settled = false;
69
- let timedOut = false;
70
- let aborted = false;
71
- let tooLarge = false;
72
- let killTimer = null;
73
- // Force the child to die: SIGTERM first, then escalate to SIGKILL after a
74
- // grace period for a child that traps/ignores SIGTERM (a wedged GUI helper
75
- // or an osascript stuck behind an Accessibility prompt). Without the
76
- // escalation the tool's timeout/abort isn't actually enforced — the parent
77
- // hangs until the child closes on its own, which may be never.
78
- const forceKill = () => {
79
- try {
80
- child.kill('SIGTERM');
81
- }
82
- catch {
83
- /* ignore */
84
- }
85
- if (killTimer)
86
- return;
87
- killTimer = setTimeout(() => {
88
- if (settled)
89
- return;
90
- try {
91
- child.kill('SIGKILL');
92
- }
93
- catch {
94
- /* ignore */
95
- }
96
- }, SIGKILL_GRACE_MS);
97
- killTimer.unref?.();
98
- };
99
- const onAbort = () => {
100
- if (settled)
101
- return;
102
- aborted = true;
103
- forceKill();
104
- };
105
- opts.signal?.addEventListener('abort', onAbort, { once: true });
106
- const timer = opts.timeoutMs
107
- ? setTimeout(() => {
108
- if (settled)
109
- return;
110
- timedOut = true;
111
- forceKill();
112
- }, opts.timeoutMs)
113
- : null;
114
- child.stdout.on('data', (chunk) => {
115
- outputBytes += chunk.length;
116
- // Once over the cap we stop retaining further chunks (the child is being
117
- // killed) so a flood between the cap-trip and SIGTERM landing can't keep
118
- // growing memory; we still account the bytes to keep `outputBytes` honest.
119
- if (!tooLarge)
120
- stdoutChunks.push(chunk);
121
- if (!tooLarge && outputBytes > MAX_OUTPUT_BYTES) {
122
- tooLarge = true;
123
- forceKill();
124
- }
125
- });
126
- child.stderr.on('data', (chunk) => {
127
- outputBytes += chunk.length;
128
- if (!tooLarge)
129
- stderrChunks.push(chunk);
130
- if (!tooLarge && outputBytes > MAX_OUTPUT_BYTES) {
131
- tooLarge = true;
132
- forceKill();
133
- }
134
- });
135
- // A child that exits/closes stdin before our write completes makes the
136
- // stdin Writable emit 'error' (EPIPE/ECONNRESET). With no listener that
137
- // throws and surfaces as an unhandled rejection that can take down the
138
- // parent — swallow it; the child 'error'/'close' path reports the real
139
- // failure. Same defensiveness on stdout/stderr for symmetry.
140
- child.stdin.on('error', () => { });
141
- child.stdout.on('error', () => { });
142
- child.stderr.on('error', () => { });
143
- const cleanup = () => {
144
- if (timer)
145
- clearTimeout(timer);
146
- if (killTimer)
147
- clearTimeout(killTimer);
148
- opts.signal?.removeEventListener('abort', onAbort);
149
- };
150
- child.once('error', (err) => {
151
- if (settled)
152
- return;
153
- settled = true;
154
- cleanup();
155
- reject(err);
156
- });
157
- child.once('close', (code) => {
158
- if (settled)
159
- return;
160
- settled = true;
161
- cleanup();
162
- resolve({
163
- exitCode: code ?? -1,
164
- stdout: Buffer.concat(stdoutChunks).toString('utf8'),
165
- stderr: Buffer.concat(stderrChunks).toString('utf8'),
166
- timedOut,
167
- aborted,
168
- tooLarge,
169
- });
170
- });
171
- if (opts.input !== undefined) {
172
- child.stdin.end(opts.input);
173
- }
174
- else {
175
- child.stdin.end();
176
- }
177
- });
178
- }
179
- /** Throw a clear error when a tool is invoked on a non-darwin host. */
180
- export function ensureDarwin(toolName) {
181
- if (!IS_DARWIN) {
182
- throw new MoxxyError({
183
- code: 'TOOL_ERROR',
184
- message: `${toolName}: @moxxy/plugin-computer-control currently only supports macOS (process.platform = ${process.platform})`,
185
- context: { tool: toolName, platform: process.platform },
186
- });
187
- }
188
- }
189
- //# sourceMappingURL=shell.js.map
package/dist/shell.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export declare function withTemporaryFiles<T>(paths: readonly string[], work: () => Promise<T>): Promise<T>;
2
- //# sourceMappingURL=temporary-files.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"temporary-files.d.ts","sourceRoot":"","sources":["../src/temporary-files.ts"],"names":[],"mappings":"AAEA,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAMxG"}
@@ -1,10 +0,0 @@
1
- import { rm } from 'node:fs/promises';
2
- export async function withTemporaryFiles(paths, work) {
3
- try {
4
- return await work();
5
- }
6
- finally {
7
- await Promise.all(paths.map((path) => rm(path, { force: true })));
8
- }
9
- }
10
- //# sourceMappingURL=temporary-files.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"temporary-files.js","sourceRoot":"","sources":["../src/temporary-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAEtC,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAI,KAAwB,EAAE,IAAsB;IAC1F,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,EAAE,CAAC;IACtB,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC;AACH,CAAC"}
@@ -1,2 +0,0 @@
1
- export declare const applescriptTool: import("@moxxy/sdk").ToolDef;
2
- //# sourceMappingURL=applescript.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"applescript.d.ts","sourceRoot":"","sources":["../../src/tools/applescript.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,8BAiD1B,CAAC"}
@@ -1,50 +0,0 @@
1
- import { defineTool, MoxxyError, z } from '@moxxy/sdk';
2
- import { ensureDarwin, procFailureCause, runProcess } from '../shell.js';
3
- export const applescriptTool = defineTool({
4
- name: 'computer_applescript',
5
- description: 'Escape hatch: run an arbitrary AppleScript snippet via `osascript`. Use ' +
6
- 'for anything the dedicated tools can\'t cover (frontmost app name, list ' +
7
- 'open Safari tabs, drive a specific app via its scripting dictionary, etc.). ' +
8
- 'Returns the script\'s stdout. The user approves every invocation — keep ' +
9
- 'scripts focused and reversible.',
10
- inputSchema: z.object({
11
- script: z
12
- .string()
13
- .min(1)
14
- .max(8000)
15
- .describe('AppleScript source. Multi-line is fine — pass `\\n` between statements. ' +
16
- 'For JavaScript for Automation, prefix with `#!/usr/bin/osascript -l JavaScript`'),
17
- }),
18
- permission: { action: 'prompt' },
19
- // Arbitrary AppleScript is an escape hatch on par with a shell: the script
20
- // can itself shell out (`do shell script`) and reach the network, so the
21
- // honest bounds are subprocess + any net — a confining isolator must not
22
- // assume osascript stays offline. Budget = the 30s child timeout + kill grace.
23
- isolation: {
24
- capabilities: {
25
- subprocess: true,
26
- commands: ['osascript'],
27
- net: { mode: 'any' },
28
- timeMs: 40_000,
29
- },
30
- },
31
- async handler({ script }, ctx) {
32
- ensureDarwin('computer_applescript');
33
- const proc = await runProcess('osascript', ['-e', script], {
34
- ...(ctx.signal ? { signal: ctx.signal } : {}),
35
- timeoutMs: 30_000,
36
- });
37
- if (proc.exitCode !== 0) {
38
- const cause = procFailureCause(proc, 30_000);
39
- throw new MoxxyError({
40
- code: 'TOOL_ERROR',
41
- message: cause
42
- ? `osascript ${cause}`
43
- : `osascript failed (exit ${proc.exitCode}): ${proc.stderr.trim() || '(no error message)'}`,
44
- context: { tool: 'computer_applescript', exitCode: proc.exitCode, timedOut: proc.timedOut ? 1 : 0 },
45
- });
46
- }
47
- return { ok: true, output: proc.stdout.trim() };
48
- },
49
- });
50
- //# sourceMappingURL=applescript.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"applescript.js","sourceRoot":"","sources":["../../src/tools/applescript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzE,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,CAAC;IACxC,IAAI,EAAE,sBAAsB;IAC5B,WAAW,EACT,0EAA0E;QAC1E,0EAA0E;QAC1E,8EAA8E;QAC9E,0EAA0E;QAC1E,iCAAiC;IACnC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,MAAM,EAAE,CAAC;aACN,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,IAAI,CAAC;aACT,QAAQ,CACP,0EAA0E;YACxE,iFAAiF,CACpF;KACJ,CAAC;IACF,UAAU,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;IAChC,2EAA2E;IAC3E,yEAAyE;IACzE,yEAAyE;IACzE,+EAA+E;IAC/E,SAAS,EAAE;QACT,YAAY,EAAE;YACZ,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,CAAC,WAAW,CAAC;YACvB,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;YACpB,MAAM,EAAE,MAAM;SACf;KACF;IACD,KAAK,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG;QAC3B,YAAY,CAAC,sBAAsB,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;YACzD,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7C,SAAS,EAAE,MAAM;SAClB,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC7C,MAAM,IAAI,UAAU,CAAC;gBACnB,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,KAAK;oBACZ,CAAC,CAAC,aAAa,KAAK,EAAE;oBACtB,CAAC,CAAC,0BAA0B,IAAI,CAAC,QAAQ,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,oBAAoB,EAAE;gBAC7F,OAAO,EAAE,EAAE,IAAI,EAAE,sBAAsB,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;aACpG,CAAC,CAAC;QACL,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;IAClD,CAAC;CACF,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export declare const clickTool: import("@moxxy/sdk").ToolDef;
2
- //# sourceMappingURL=click.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"click.d.ts","sourceRoot":"","sources":["../../src/tools/click.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,8BAwDpB,CAAC"}
@@ -1,58 +0,0 @@
1
- import { defineTool, MoxxyError, z } from '@moxxy/sdk';
2
- import { ensureDarwin, procFailureCause, runProcess } from '../shell.js';
3
- export const clickTool = defineTool({
4
- name: 'computer_click',
5
- description: 'Click the mouse at screen-pixel coordinates (top-left origin). Uses macOS ' +
6
- 'System Events; requires Accessibility permission on first use. Pass count=2 ' +
7
- 'for a double-click. Right/middle buttons are not supported via this tool — ' +
8
- 'use computer_applescript for those (rare).',
9
- inputSchema: z.object({
10
- x: z.number().int().min(0).describe('X pixel from the top-left of the display.'),
11
- y: z.number().int().min(0).describe('Y pixel from the top-left of the display.'),
12
- count: z
13
- .number()
14
- .int()
15
- .min(1)
16
- .max(3)
17
- .optional()
18
- .describe('Number of consecutive clicks. 1 = single, 2 = double, 3 = triple. Default 1.'),
19
- }),
20
- permission: { action: 'prompt' },
21
- isolation: {
22
- capabilities: {
23
- subprocess: true,
24
- commands: ['osascript'],
25
- net: { mode: 'none' },
26
- timeMs: 15_000,
27
- },
28
- },
29
- async handler({ x, y, count }, ctx) {
30
- ensureDarwin('computer_click');
31
- const n = count ?? 1;
32
- // `click at {x, y}` repeats N times via a repeat block. Use a
33
- // bare AppleScript string with numeric interpolation — no
34
- // user-supplied text reaches the script, so injection isn't a
35
- // risk here.
36
- const script = `tell application "System Events"\n` +
37
- ` repeat ${n} times\n` +
38
- ` click at {${Math.round(x)}, ${Math.round(y)}}\n` +
39
- ` end repeat\n` +
40
- `end tell`;
41
- const proc = await runProcess('osascript', ['-e', script], {
42
- ...(ctx.signal ? { signal: ctx.signal } : {}),
43
- timeoutMs: 10_000,
44
- });
45
- if (proc.exitCode !== 0) {
46
- const cause = procFailureCause(proc, 10_000);
47
- throw new MoxxyError({
48
- code: 'TOOL_ERROR',
49
- message: cause
50
- ? `click ${cause}`
51
- : `click failed (exit ${proc.exitCode}): ${proc.stderr.trim() || '(check Accessibility permission in System Settings → Privacy & Security → Accessibility)'}`,
52
- context: { tool: 'computer_click', exitCode: proc.exitCode, timedOut: proc.timedOut ? 1 : 0 },
53
- });
54
- }
55
- return { ok: true, x, y, count: n };
56
- },
57
- });
58
- //# sourceMappingURL=click.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"click.js","sourceRoot":"","sources":["../../src/tools/click.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzE,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAAC;IAClC,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,4EAA4E;QAC5E,8EAA8E;QAC9E,6EAA6E;QAC7E,4CAA4C;IAC9C,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,2CAA2C,CAAC;QAChF,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,2CAA2C,CAAC;QAChF,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,CAAC,8EAA8E,CAAC;KAC5F,CAAC;IACF,UAAU,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;IAChC,SAAS,EAAE;QACT,YAAY,EAAE;YACZ,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,CAAC,WAAW,CAAC;YACvB,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;YACrB,MAAM,EAAE,MAAM;SACf;KACF;IACD,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,GAAG;QAChC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QAC/B,MAAM,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;QACrB,8DAA8D;QAC9D,0DAA0D;QAC1D,8DAA8D;QAC9D,aAAa;QACb,MAAM,MAAM,GACV,oCAAoC;YACpC,YAAY,CAAC,UAAU;YACvB,iBAAiB,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;YACrD,gBAAgB;YAChB,UAAU,CAAC;QACb,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;YACzD,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7C,SAAS,EAAE,MAAM;SAClB,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC7C,MAAM,IAAI,UAAU,CAAC;gBACnB,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,KAAK;oBACZ,CAAC,CAAC,SAAS,KAAK,EAAE;oBAClB,CAAC,CAAC,sBAAsB,IAAI,CAAC,QAAQ,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,0FAA0F,EAAE;gBAC/J,OAAO,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;aAC9F,CAAC,CAAC;QACL,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IACtC,CAAC;CACF,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export declare const clipboardTool: import("@moxxy/sdk").ToolDef;
2
- //# sourceMappingURL=clipboard.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../src/tools/clipboard.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,aAAa,8BAoExB,CAAC"}
@@ -1,71 +0,0 @@
1
- import { defineTool, MoxxyError, z } from '@moxxy/sdk';
2
- import { ensureDarwin, procFailureCause, runProcess } from '../shell.js';
3
- export const clipboardTool = defineTool({
4
- name: 'computer_clipboard',
5
- icon: 'clipboard',
6
- description: 'Read from or write to the macOS clipboard. Use `read` to fetch what the ' +
7
- 'user just copied; use `write` to stage text the user can then paste with ' +
8
- '⌘V. Writing the clipboard does NOT trigger a paste — call computer_key ' +
9
- 'with cmd+v after if you need to paste.',
10
- inputSchema: z.object({
11
- action: z.enum(['read', 'write']),
12
- text: z
13
- .string()
14
- .max(64_000)
15
- .optional()
16
- .describe('Text to put on the clipboard. Required when action="write".'),
17
- }),
18
- permission: { action: 'prompt' },
19
- isolation: {
20
- capabilities: {
21
- subprocess: true,
22
- commands: ['pbpaste', 'pbcopy'],
23
- net: { mode: 'none' },
24
- timeMs: 10_000,
25
- },
26
- },
27
- async handler({ action, text }, ctx) {
28
- ensureDarwin('computer_clipboard');
29
- if (action === 'read') {
30
- const proc = await runProcess('pbpaste', [], {
31
- ...(ctx.signal ? { signal: ctx.signal } : {}),
32
- timeoutMs: 5_000,
33
- });
34
- if (proc.exitCode !== 0) {
35
- const cause = procFailureCause(proc, 5_000);
36
- throw new MoxxyError({
37
- code: 'TOOL_ERROR',
38
- message: cause
39
- ? `pbpaste ${cause}`
40
- : `pbpaste failed (exit ${proc.exitCode}): ${proc.stderr.trim()}`,
41
- context: { tool: 'computer_clipboard', exitCode: proc.exitCode, timedOut: proc.timedOut ? 1 : 0 },
42
- });
43
- }
44
- return { ok: true, text: proc.stdout };
45
- }
46
- if (text === undefined) {
47
- throw new MoxxyError({
48
- code: 'TOOL_ERROR',
49
- message: 'computer_clipboard: `text` is required when action="write"',
50
- context: { tool: 'computer_clipboard' },
51
- });
52
- }
53
- const proc = await runProcess('pbcopy', [], {
54
- ...(ctx.signal ? { signal: ctx.signal } : {}),
55
- input: text,
56
- timeoutMs: 5_000,
57
- });
58
- if (proc.exitCode !== 0) {
59
- const cause = procFailureCause(proc, 5_000);
60
- throw new MoxxyError({
61
- code: 'TOOL_ERROR',
62
- message: cause
63
- ? `pbcopy ${cause}`
64
- : `pbcopy failed (exit ${proc.exitCode}): ${proc.stderr.trim()}`,
65
- context: { tool: 'computer_clipboard', exitCode: proc.exitCode, timedOut: proc.timedOut ? 1 : 0 },
66
- });
67
- }
68
- return { ok: true, length: text.length };
69
- },
70
- });
71
- //# sourceMappingURL=clipboard.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/tools/clipboard.ts"],"names":[],"mappings":"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"}