usecomputer 0.0.3 → 0.1.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 (61) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +324 -0
  3. package/build.zig +95 -11
  4. package/build.zig.zon +5 -0
  5. package/dist/bridge-contract.test.js +61 -67
  6. package/dist/bridge.d.ts.map +1 -1
  7. package/dist/bridge.js +241 -46
  8. package/dist/cli-parsing.test.js +34 -11
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cli.js +323 -28
  11. package/dist/coord-map.d.ts +14 -0
  12. package/dist/coord-map.d.ts.map +1 -0
  13. package/dist/coord-map.js +75 -0
  14. package/dist/coord-map.test.d.ts +2 -0
  15. package/dist/coord-map.test.d.ts.map +1 -0
  16. package/dist/coord-map.test.js +157 -0
  17. package/dist/darwin-arm64/usecomputer.node +0 -0
  18. package/dist/darwin-x64/usecomputer.node +0 -0
  19. package/dist/debug-point-image.d.ts +8 -0
  20. package/dist/debug-point-image.d.ts.map +1 -0
  21. package/dist/debug-point-image.js +43 -0
  22. package/dist/debug-point-image.test.d.ts +2 -0
  23. package/dist/debug-point-image.test.d.ts.map +1 -0
  24. package/dist/debug-point-image.test.js +44 -0
  25. package/dist/index.d.ts +2 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +3 -1
  28. package/dist/lib.d.ts +26 -0
  29. package/dist/lib.d.ts.map +1 -0
  30. package/dist/lib.js +88 -0
  31. package/dist/native-click-smoke.test.js +69 -29
  32. package/dist/native-lib.d.ts +59 -1
  33. package/dist/native-lib.d.ts.map +1 -1
  34. package/dist/terminal-table.d.ts +10 -0
  35. package/dist/terminal-table.d.ts.map +1 -0
  36. package/dist/terminal-table.js +55 -0
  37. package/dist/terminal-table.test.d.ts +2 -0
  38. package/dist/terminal-table.test.d.ts.map +1 -0
  39. package/dist/terminal-table.test.js +41 -0
  40. package/dist/types.d.ts +45 -0
  41. package/dist/types.d.ts.map +1 -1
  42. package/package.json +19 -5
  43. package/src/bridge-contract.test.ts +68 -73
  44. package/src/bridge.ts +293 -53
  45. package/src/cli-parsing.test.ts +61 -0
  46. package/src/cli.ts +393 -32
  47. package/src/coord-map.test.ts +178 -0
  48. package/src/coord-map.ts +105 -0
  49. package/src/debug-point-image.test.ts +50 -0
  50. package/src/debug-point-image.ts +69 -0
  51. package/src/index.ts +3 -1
  52. package/src/lib.ts +125 -0
  53. package/src/native-click-smoke.test.ts +81 -63
  54. package/src/native-lib.ts +39 -1
  55. package/src/terminal-table.test.ts +44 -0
  56. package/src/terminal-table.ts +88 -0
  57. package/src/types.ts +50 -0
  58. package/zig/src/lib.zig +1966 -270
  59. package/zig/src/main.zig +382 -0
  60. package/zig/src/scroll.zig +213 -0
  61. package/zig/src/window.zig +123 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,73 @@
4
4
 
5
5
  All notable changes to `usecomputer` will be documented in this file.
6
6
 
7
+ ## 0.1.0
8
+
9
+ 1. **Standalone executable** — `usecomputer` now ships as a self-contained binary.
10
+ Install once and run anywhere without needing Node.js at runtime:
11
+
12
+ ```bash
13
+ npm install -g usecomputer
14
+ usecomputer screenshot ./shot.png --json
15
+ ```
16
+
17
+ 2. **Linux X11 screenshot support** — capture screens on Linux desktops via XShm
18
+ (with automatic fallback to XGetImage on XWayland). Returns the same JSON
19
+ output shape as macOS:
20
+
21
+ ```bash
22
+ usecomputer screenshot ./shot.png --json
23
+ ```
24
+
25
+ 3. **Screenshot coord-map and scaling** — screenshots are scaled so the longest edge
26
+ is at most 1568 px (model-friendly size). Output includes a `coordMap` field
27
+ for accurate pointer remapping:
28
+
29
+ ```bash
30
+ usecomputer screenshot ./shot.png --json
31
+ # use the emitted coord-map for all subsequent pointer commands
32
+ usecomputer click -x 400 -y 220 --coord-map "0,0,1600,900,1568,882"
33
+ ```
34
+
35
+ 4. **New `debug-point` command** — validate a click target before clicking. Captures
36
+ a screenshot and draws a red marker at the mapped coordinate:
37
+
38
+ ```bash
39
+ usecomputer debug-point -x 400 -y 220 --coord-map "0,0,1600,900,1568,882"
40
+ ```
41
+
42
+ 5. **Keyboard synthesis** — new `type` and `press` commands for text input and key
43
+ chords:
44
+
45
+ ```bash
46
+ usecomputer type "hello from usecomputer"
47
+ usecomputer press "cmd+s"
48
+ usecomputer press "down" --count 10 --delay 30
49
+ cat ./notes.txt | usecomputer type --stdin --chunk-size 4000
50
+ ```
51
+
52
+ 6. **Native scroll support** — scroll in any direction at any position:
53
+
54
+ ```bash
55
+ usecomputer scroll --direction down --amount 5
56
+ usecomputer scroll --direction up --amount 3 -x 800 -y 400
57
+ ```
58
+
59
+ 7. **Library exports** — import `usecomputer` as a Node.js library to reuse all
60
+ commands in your own agent harness:
61
+
62
+ ```ts
63
+ import * as usecomputer from 'usecomputer'
64
+
65
+ const shot = await usecomputer.screenshot({ path: './shot.png', display: null, window: null, region: null, annotate: null })
66
+ const coordMap = usecomputer.parseCoordMapOrThrow(shot.coordMap)
67
+ await usecomputer.click({ point: usecomputer.mapPointFromCoordMap({ point: { x: 400, y: 220 }, coordMap }), button: 'left', count: 1 })
68
+ ```
69
+
70
+ 8. **OpenAI and Anthropic computer-use examples** — README now includes full
71
+ agentic loop examples for both providers showing screenshot → action → result
72
+ cycles.
73
+
7
74
  ## 0.0.3
8
75
 
9
76
  - Implement real screenshot capture + PNG file writing on macOS.
package/README.md CHANGED
@@ -7,6 +7,14 @@
7
7
  It can move the mouse, click, drag, and query cursor position using native
8
8
  Quartz events through a Zig N-API module.
9
9
 
10
+ Keyboard synthesis (`type` and `press`) is also available. The native backend
11
+ includes platform-specific key injection paths for macOS, Windows, and Linux
12
+ X11.
13
+
14
+ The package also exports the native commands as plain library functions, so you
15
+ can `import * as usecomputer from "usecomputer"` and reuse the same screenshot,
16
+ mouse, keyboard, and coord-map behavior from Node.js.
17
+
10
18
  ## Install
11
19
 
12
20
  ```bash
@@ -24,8 +32,321 @@ npm install -g usecomputer
24
32
  usecomputer mouse position --json
25
33
  usecomputer mouse move -x 500 -y 500
26
34
  usecomputer click -x 500 -y 500 --button left --count 1
35
+ usecomputer type "hello"
36
+ usecomputer press "cmd+s"
37
+ ```
38
+
39
+ ## Library usage
40
+
41
+ ```ts
42
+ import * as usecomputer from 'usecomputer'
43
+
44
+ const screenshot = await usecomputer.screenshot({
45
+ path: './tmp/shot.png',
46
+ display: null,
47
+ window: null,
48
+ region: null,
49
+ annotate: null,
50
+ })
51
+
52
+ const coordMap = usecomputer.parseCoordMapOrThrow(screenshot.coordMap)
53
+ const point = usecomputer.mapPointFromCoordMap({
54
+ point: { x: 400, y: 220 },
55
+ coordMap,
56
+ })
57
+
58
+ await usecomputer.click({
59
+ point,
60
+ button: 'left',
61
+ count: 1,
62
+ })
63
+ ```
64
+
65
+ These exported functions intentionally mirror the native command shapes used by
66
+ the Zig N-API module. Optional native fields are passed as `null` when absent.
67
+
68
+ ## OpenAI computer tool example
69
+
70
+ ```ts
71
+ import fs from 'node:fs'
72
+ import * as usecomputer from 'usecomputer'
73
+
74
+ async function sendComputerScreenshot() {
75
+ const screenshot = await usecomputer.screenshot({
76
+ path: './tmp/computer-tool.png',
77
+ display: null,
78
+ window: null,
79
+ region: null,
80
+ annotate: null,
81
+ })
82
+
83
+ return {
84
+ screenshot,
85
+ imageBase64: await fs.promises.readFile(screenshot.path, 'base64'),
86
+ }
87
+ }
88
+
89
+ async function runComputerAction(action, coordMap) {
90
+ if (action.type === 'click') {
91
+ await usecomputer.click({
92
+ point: usecomputer.mapPointFromCoordMap({
93
+ point: { x: action.x, y: action.y },
94
+ coordMap: usecomputer.parseCoordMapOrThrow(coordMap),
95
+ }),
96
+ button: action.button ?? 'left',
97
+ count: 1,
98
+ })
99
+ return
100
+ }
101
+
102
+ if (action.type === 'double_click') {
103
+ await usecomputer.click({
104
+ point: usecomputer.mapPointFromCoordMap({
105
+ point: { x: action.x, y: action.y },
106
+ coordMap: usecomputer.parseCoordMapOrThrow(coordMap),
107
+ }),
108
+ button: action.button ?? 'left',
109
+ count: 2,
110
+ })
111
+ return
112
+ }
113
+
114
+ if (action.type === 'scroll') {
115
+ await usecomputer.scroll({
116
+ direction: action.scrollY && action.scrollY < 0 ? 'up' : 'down',
117
+ amount: Math.abs(action.scrollY ?? 0),
118
+ at: typeof action.x === 'number' && typeof action.y === 'number'
119
+ ? usecomputer.mapPointFromCoordMap({
120
+ point: { x: action.x, y: action.y },
121
+ coordMap: usecomputer.parseCoordMapOrThrow(coordMap),
122
+ })
123
+ : null,
124
+ })
125
+ return
126
+ }
127
+
128
+ if (action.type === 'keypress') {
129
+ await usecomputer.press({
130
+ key: action.keys.join('+'),
131
+ count: 1,
132
+ delayMs: null,
133
+ })
134
+ return
135
+ }
136
+
137
+ if (action.type === 'type') {
138
+ await usecomputer.typeText({
139
+ text: action.text,
140
+ delayMs: null,
141
+ })
142
+ }
143
+ }
144
+ ```
145
+
146
+ ## Anthropic computer use example
147
+
148
+ Anthropic's computer tool uses action names like `left_click`, `double_click`,
149
+ `mouse_move`, `key`, `type`, `scroll`, and `screenshot`. `usecomputer`
150
+ provides the execution layer for those actions.
151
+
152
+ ```ts
153
+ import fs from 'node:fs'
154
+ import Anthropic from '@anthropic-ai/sdk'
155
+ import type {
156
+ BetaToolResultBlockParam,
157
+ BetaToolUseBlock,
158
+ } from '@anthropic-ai/sdk/resources/beta/messages/messages'
159
+ import * as usecomputer from 'usecomputer'
160
+
161
+ const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY })
162
+
163
+ const message = await anthropic.beta.messages.create({
164
+ model: 'claude-opus-4-6',
165
+ max_tokens: 1024,
166
+ tools: [
167
+ {
168
+ type: 'computer_20251124',
169
+ name: 'computer',
170
+ display_width_px: 1024,
171
+ display_height_px: 768,
172
+ display_number: 1,
173
+ },
174
+ ],
175
+ messages: [{ role: 'user', content: 'Open Safari and search for usecomputer.' }],
176
+ betas: ['computer-use-2025-11-24'],
177
+ })
178
+
179
+ for (const block of message.content) {
180
+ if (block.type !== 'tool_use' || block.name !== 'computer') {
181
+ continue
182
+ }
183
+
184
+ const toolUse = block as BetaToolUseBlock
185
+ await usecomputer.screenshot({
186
+ path: './tmp/claude-current-screen.png',
187
+ display: null,
188
+ window: null,
189
+ region: null,
190
+ annotate: null,
191
+ })
192
+ const coordinate = Array.isArray(toolUse.input.coordinate)
193
+ ? toolUse.input.coordinate
194
+ : null
195
+ const point = coordinate
196
+ ? { x: coordinate[0] ?? 0, y: coordinate[1] ?? 0 }
197
+ : null
198
+
199
+ switch (toolUse.input.action) {
200
+ case 'screenshot': {
201
+ break
202
+ }
203
+ case 'left_click': {
204
+ if (point) {
205
+ await usecomputer.click({ point, button: 'left', count: 1 })
206
+ }
207
+ break
208
+ }
209
+ case 'double_click': {
210
+ if (point) {
211
+ await usecomputer.click({ point, button: 'left', count: 2 })
212
+ }
213
+ break
214
+ }
215
+ case 'mouse_move': {
216
+ if (point) {
217
+ await usecomputer.mouseMove(point)
218
+ }
219
+ break
220
+ }
221
+ case 'type': {
222
+ if (typeof toolUse.input.text === 'string') {
223
+ await usecomputer.typeText({ text: toolUse.input.text, delayMs: null })
224
+ }
225
+ break
226
+ }
227
+ case 'key': {
228
+ if (typeof toolUse.input.text === 'string') {
229
+ await usecomputer.press({ key: toolUse.input.text, count: 1, delayMs: null })
230
+ }
231
+ break
232
+ }
233
+ case 'scroll': {
234
+ await usecomputer.scroll({
235
+ direction: toolUse.input.scroll_direction === 'up' || toolUse.input.scroll_direction === 'down' || toolUse.input.scroll_direction === 'left' || toolUse.input.scroll_direction === 'right'
236
+ ? toolUse.input.scroll_direction
237
+ : 'down',
238
+ amount: typeof toolUse.input.scroll_amount === 'number' ? toolUse.input.scroll_amount : 3,
239
+ at: point,
240
+ })
241
+ break
242
+ }
243
+ default: {
244
+ throw new Error(`Unsupported Claude computer action: ${String(toolUse.input.action)}`)
245
+ }
246
+ }
247
+
248
+ const afterActionScreenshot = await usecomputer.screenshot({
249
+ path: './tmp/claude-computer-tool.png',
250
+ display: null,
251
+ window: null,
252
+ region: null,
253
+ annotate: null,
254
+ })
255
+ const imageBase64 = await fs.promises.readFile(afterActionScreenshot.path, 'base64')
256
+ const toolResult: BetaToolResultBlockParam = {
257
+ type: 'tool_result',
258
+ tool_use_id: toolUse.id,
259
+ content: [
260
+ {
261
+ type: 'image',
262
+ source: {
263
+ type: 'base64',
264
+ media_type: 'image/png',
265
+ data: imageBase64,
266
+ },
267
+ },
268
+ ],
269
+ }
270
+ // Append toolResult to the next user message in your agent loop.
271
+ }
272
+ ```
273
+
274
+ ## Screenshot scaling and coord-map
275
+
276
+ `usecomputer screenshot` always scales the output image so the longest edge is
277
+ at most `1568` px. This keeps screenshots in a model-friendly size for
278
+ computer-use agents.
279
+
280
+ Screenshot output includes:
281
+
282
+ - `desktopIndex` (display index used for capture)
283
+ - `coordMap` in the form `captureX,captureY,captureWidth,captureHeight,imageWidth,imageHeight`
284
+ - `hint` with usage text for coordinate mapping
285
+
286
+ Always pass the exact `--coord-map` value emitted by `usecomputer screenshot`
287
+ to pointer commands when you are clicking coordinates from that screenshot.
288
+ This maps screenshot-space coordinates back to real screen coordinates:
289
+
290
+ ```bash
291
+ usecomputer screenshot ./shot.png --json
292
+ usecomputer click -x 400 -y 220 --coord-map "0,0,1600,900,1568,882"
293
+ usecomputer mouse move -x 100 -y 80 --coord-map "0,0,1600,900,1568,882"
294
+ ```
295
+
296
+ To validate a target before clicking, use `debug-point`. It takes the same
297
+ coordinates and `--coord-map`, captures a fresh full-desktop screenshot, and
298
+ draws a red marker where the click would land. When `--coord-map` is present,
299
+ it captures that same region so the overlay matches the screenshot you are
300
+ targeting:
301
+
302
+ ```bash
303
+ usecomputer debug-point -x 400 -y 220 --coord-map "0,0,1600,900,1568,882"
304
+ ```
305
+
306
+ ## Keyboard commands
307
+
308
+ ### Type text
309
+
310
+ ```bash
311
+ # Short text
312
+ usecomputer type "hello from usecomputer"
313
+
314
+ # Type from stdin (good for multiline or very long text)
315
+ cat ./notes.txt | usecomputer type --stdin --chunk-size 4000 --chunk-delay 15
316
+
317
+ # Simulate slower typing for apps that drop fast input
318
+ usecomputer type "hello" --delay 20
27
319
  ```
28
320
 
321
+ `--delay` is the per-character delay in milliseconds.
322
+
323
+ For very long text, prefer `--stdin` + `--chunk-size` so shell argument limits
324
+ and app input buffers are less likely to cause dropped characters.
325
+
326
+ ### Press keys and shortcuts
327
+
328
+ ```bash
329
+ # Single key
330
+ usecomputer press "enter"
331
+
332
+ # Chords
333
+ usecomputer press "cmd+s"
334
+ usecomputer press "cmd+shift+p"
335
+ usecomputer press "ctrl+s"
336
+
337
+ # Repeats
338
+ usecomputer press "down" --count 10 --delay 30
339
+ ```
340
+
341
+ Modifier aliases: `cmd`/`command`/`meta`, `ctrl`/`control`, `alt`/`option`,
342
+ `shift`, `fn`.
343
+
344
+ Platform note:
345
+
346
+ - macOS: `cmd` maps to Command.
347
+ - Windows/Linux: `cmd` maps to Win/Super.
348
+ - For app shortcuts that should work on Windows/Linux too, prefer `ctrl+...`.
349
+
29
350
  ## Coordinate options
30
351
 
31
352
  Commands that target coordinates accept `-x` and `-y` flags:
@@ -34,6 +355,9 @@ Commands that target coordinates accept `-x` and `-y` flags:
34
355
  - `usecomputer hover -x <n> -y <n>`
35
356
  - `usecomputer mouse move -x <n> -y <n>`
36
357
 
358
+ `mouse move` is optional before `click` when click coordinates are already
359
+ provided.
360
+
37
361
  Legacy coordinate forms are also accepted where available.
38
362
 
39
363
  ## Display index options
package/build.zig CHANGED
@@ -1,36 +1,64 @@
1
- // Build script for usecomputer Zig N-API native module artifacts.
1
+ // Build script for usecomputer produces both:
2
+ // 1. Dynamic library (.node) for N-API consumption from Node.js
3
+ // 2. Standalone executable CLI (no Node.js required, uses zeke)
2
4
 
3
5
  const std = @import("std");
4
6
  const napigen = @import("napigen");
5
7
 
6
8
  const LIB_NAME = "usecomputer";
7
9
 
10
+ /// Link platform-specific libraries needed by the native core.
11
+ fn linkPlatformDeps(mod: *std.Build.Module, target_os: std.Target.Os.Tag) void {
12
+ if (target_os == .macos) {
13
+ mod.linkFramework("CoreGraphics", .{});
14
+ mod.linkFramework("CoreFoundation", .{});
15
+ mod.linkFramework("ImageIO", .{});
16
+ }
17
+ if (target_os == .linux) {
18
+ mod.linkSystemLibrary("X11", .{});
19
+ mod.linkSystemLibrary("Xext", .{});
20
+ mod.linkSystemLibrary("Xtst", .{});
21
+ mod.linkSystemLibrary("png", .{});
22
+ }
23
+ if (target_os == .windows) {
24
+ mod.linkSystemLibrary("user32", .{});
25
+ }
26
+ }
27
+
8
28
  pub fn build(b: *std.Build) void {
9
29
  const target = b.standardTargetOptions(.{});
10
30
  const optimize = b.standardOptimizeOption(.{});
31
+ const target_os = target.result.os.tag;
32
+
33
+ // ── N-API dynamic library (.node) ──
34
+
35
+ // Build options for lib.zig: enable_napigen controls N-API glue
36
+ const lib_options = b.addOptions();
37
+ lib_options.addOption(bool, "enable_napigen", true);
38
+ const lib_options_mod = lib_options.createModule();
11
39
 
12
40
  const lib_mod = b.createModule(.{
13
41
  .root_source_file = b.path("zig/src/lib.zig"),
14
42
  .target = target,
15
43
  .optimize = optimize,
16
44
  });
45
+ lib_mod.addImport("build_options", lib_options_mod);
17
46
  lib_mod.addImport("napigen", b.dependency("napigen", .{}).module("napigen"));
18
- lib_mod.addImport("objc", b.dependency("zig_objc", .{
19
- .target = target,
20
- .optimize = optimize,
21
- }).module("objc"));
47
+ if (target_os == .macos) {
48
+ if (b.lazyDependency("zig_objc", .{
49
+ .target = target,
50
+ .optimize = optimize,
51
+ })) |dep| {
52
+ lib_mod.addImport("objc", dep.module("objc"));
53
+ }
54
+ }
22
55
 
23
56
  const lib = b.addLibrary(.{
24
57
  .name = LIB_NAME,
25
58
  .root_module = lib_mod,
26
59
  .linkage = .dynamic,
27
60
  });
28
-
29
- if (target.result.os.tag == .macos) {
30
- lib.root_module.linkFramework("CoreGraphics", .{});
31
- lib.root_module.linkFramework("CoreFoundation", .{});
32
- lib.root_module.linkFramework("ImageIO", .{});
33
- }
61
+ linkPlatformDeps(lib.root_module, target_os);
34
62
 
35
63
  napigen.setup(lib);
36
64
  b.installArtifact(lib);
@@ -38,16 +66,72 @@ pub fn build(b: *std.Build) void {
38
66
  const copy_node_step = b.addInstallLibFile(lib.getEmittedBin(), LIB_NAME ++ ".node");
39
67
  b.getInstallStep().dependOn(&copy_node_step.step);
40
68
 
69
+ // ── Standalone executable CLI ──
70
+ //
71
+ // Uses a separate copy of lib.zig WITHOUT napigen so the executable
72
+ // doesn't try to link N-API symbols (those only exist in Node.js).
73
+
74
+ const exe_options = b.addOptions();
75
+ exe_options.addOption(bool, "enable_napigen", false);
76
+ const exe_options_mod = exe_options.createModule();
77
+
78
+ const exe_lib_mod = b.createModule(.{
79
+ .root_source_file = b.path("zig/src/lib.zig"),
80
+ .target = target,
81
+ .optimize = optimize,
82
+ });
83
+ exe_lib_mod.addImport("build_options", exe_options_mod);
84
+ if (target_os == .macos) {
85
+ if (b.lazyDependency("zig_objc", .{
86
+ .target = target,
87
+ .optimize = optimize,
88
+ })) |dep| {
89
+ exe_lib_mod.addImport("objc", dep.module("objc"));
90
+ }
91
+ }
92
+
93
+ const exe_mod = b.createModule(.{
94
+ .root_source_file = b.path("zig/src/main.zig"),
95
+ .target = target,
96
+ .optimize = optimize,
97
+ });
98
+ exe_mod.addImport("usecomputer_lib", exe_lib_mod);
99
+ exe_mod.addImport("zeke", b.dependency("zeke", .{
100
+ .target = target,
101
+ .optimize = optimize,
102
+ }).module("zeke"));
103
+
104
+ const exe = b.addExecutable(.{
105
+ .name = LIB_NAME,
106
+ .root_module = exe_mod,
107
+ });
108
+ linkPlatformDeps(exe.root_module, target_os);
109
+ b.installArtifact(exe);
110
+
111
+ const run_exe = b.addRunArtifact(exe);
112
+ if (b.args) |args| {
113
+ run_exe.addArgs(args);
114
+ }
115
+ const run_step = b.step("run", "Run the CLI");
116
+ run_step.dependOn(&run_exe.step);
117
+
118
+ // ── Tests ──
119
+
120
+ const test_options = b.addOptions();
121
+ test_options.addOption(bool, "enable_napigen", false);
122
+
41
123
  const test_mod = b.createModule(.{
42
124
  .root_source_file = b.path("zig/src/lib.zig"),
43
125
  .target = target,
44
126
  .optimize = optimize,
45
127
  });
128
+ test_mod.addImport("build_options", test_options.createModule());
46
129
 
47
130
  const test_step = b.step("test", "Run Zig unit tests");
48
131
  const test_exe = b.addTest(.{
49
132
  .root_module = test_mod,
50
133
  });
134
+ linkPlatformDeps(test_exe.root_module, target_os);
51
135
  const run_test = b.addRunArtifact(test_exe);
52
136
  test_step.dependOn(&run_test.step);
53
137
  }
package/build.zig.zon CHANGED
@@ -11,6 +11,11 @@
11
11
  .zig_objc = .{
12
12
  .url = "git+https://github.com/mitchellh/zig-objc?ref=main#27d0e03242e7ee6842bf8a86d2e0bb1f586a9847",
13
13
  .hash = "zig_objc-0.0.0-Ir_Sp7oUAQC3JpeR9EGUFGcHRSx_33IehitnjBCy-CwD",
14
+ .lazy = true,
15
+ },
16
+ .zeke = .{
17
+ .url = "https://github.com/remorses/zeke/archive/refs/heads/main.tar.gz",
18
+ .hash = "zeke-0.1.0-fnPIzP2mAADBDhCqMNuyU5TV7PEG9rEb2GDDjwMXCZYN",
14
19
  },
15
20
  },
16
21
  .paths = .{