zeno-mobile-runner 0.2.1 → 0.2.3

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 (76) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/FEATURES.md +1 -1
  3. package/README.md +1 -1
  4. package/build.zig +10 -0
  5. package/build.zig.zon +2 -2
  6. package/clients/kotlin/README.md +1 -1
  7. package/clients/kotlin/build.gradle.kts +1 -1
  8. package/clients/python/pyproject.toml +1 -1
  9. package/clients/rust/Cargo.lock +1 -1
  10. package/clients/rust/Cargo.toml +1 -1
  11. package/clients/typescript/package.json +1 -1
  12. package/docs/protocol-fixtures/core-session.responses.jsonl +1 -1
  13. package/docs/protocol.md +10 -10
  14. package/package.json +3 -1
  15. package/prebuilds/darwin-arm64/zmr +0 -0
  16. package/prebuilds/darwin-x64/zmr +0 -0
  17. package/prebuilds/linux-arm64/zmr +0 -0
  18. package/prebuilds/linux-x64/zmr +0 -0
  19. package/scripts/create-react-native-expo-demo-app.sh +11 -13
  20. package/shims/ios/ZMRShim.swift +40 -12
  21. package/shims/ios/ZMRShimUITestCase.swift +135 -15
  22. package/src/android.zig +10 -9
  23. package/src/android_emulator.zig +22 -11
  24. package/src/android_screen_recording.zig +11 -7
  25. package/src/bundle.zig +10 -9
  26. package/src/bundle_redaction.zig +29 -28
  27. package/src/bundle_tar.zig +15 -12
  28. package/src/cli_devices.zig +7 -3
  29. package/src/cli_discover.zig +7 -3
  30. package/src/cli_doctor.zig +7 -3
  31. package/src/cli_draft.zig +51 -47
  32. package/src/cli_explore.zig +7 -3
  33. package/src/cli_import.zig +8 -4
  34. package/src/cli_info.zig +13 -6
  35. package/src/cli_init.zig +9 -5
  36. package/src/cli_inspect.zig +8 -4
  37. package/src/cli_run.zig +22 -16
  38. package/src/cli_serve.zig +3 -3
  39. package/src/cli_trace.zig +25 -12
  40. package/src/cli_validate.zig +8 -4
  41. package/src/command.zig +81 -99
  42. package/src/config.zig +2 -1
  43. package/src/config_diagnostics.zig +2 -1
  44. package/src/config_paths.zig +2 -1
  45. package/src/doctor.zig +8 -7
  46. package/src/doctor_hints.zig +1 -1
  47. package/src/errors.zig +5 -5
  48. package/src/importer.zig +8 -7
  49. package/src/ios.zig +98 -19
  50. package/src/ios_devices.zig +6 -5
  51. package/src/ios_lifecycle.zig +4 -4
  52. package/src/ios_shim.zig +12 -0
  53. package/src/json_rpc.zig +39 -40
  54. package/src/json_rpc_methods.zig +8 -8
  55. package/src/json_rpc_observation.zig +9 -8
  56. package/src/json_rpc_params.zig +1 -1
  57. package/src/json_rpc_trace.zig +22 -21
  58. package/src/main.zig +19 -10
  59. package/src/mcp.zig +28 -19
  60. package/src/mcp_trace.zig +30 -29
  61. package/src/report.zig +39 -36
  62. package/src/report_html.zig +5 -4
  63. package/src/runner.zig +2 -1
  64. package/src/runner_actions.zig +20 -17
  65. package/src/runner_diagnostics.zig +4 -4
  66. package/src/runner_events.zig +55 -51
  67. package/src/runner_native.zig +21 -19
  68. package/src/runner_waits.zig +46 -41
  69. package/src/scaffold.zig +25 -24
  70. package/src/scenario.zig +4 -3
  71. package/src/stdio.zig +129 -0
  72. package/src/trace.zig +34 -26
  73. package/src/trace_summary.zig +3 -2
  74. package/src/trace_summary_diagnostic.zig +15 -13
  75. package/src/validation.zig +5 -4
  76. package/src/version.zig +1 -1
@@ -1,4 +1,5 @@
1
1
  const std = @import("std");
2
+ const stdio = @import("stdio.zig");
2
3
 
3
4
  const cli_draft = @import("cli_draft.zig");
4
5
  const cli_output = @import("cli_output.zig");
@@ -68,7 +69,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
68
69
  } else if (std.mem.eql(u8, arg, "--json")) {
69
70
  parsed.json = true;
70
71
  } else {
71
- return error.UnknownFlag;
72
+ return error.unknownFlag;
72
73
  }
73
74
  }
74
75
 
@@ -77,7 +78,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
77
78
  return parsed;
78
79
  }
79
80
 
80
- pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
81
+ pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
81
82
  var raw_args = std.ArrayList([]const u8).empty;
82
83
  defer raw_args.deinit(allocator);
83
84
  while (args.next()) |arg| try raw_args.append(allocator, arg);
@@ -86,7 +87,10 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
86
87
  var discovered = try discoverFromTrace(allocator, parsed);
87
88
  defer discovered.deinit(allocator);
88
89
 
89
- const stdout = std.fs.File.stdout().deprecatedWriter();
90
+ var stdout_io: stdio.Output = .{};
91
+ stdout_io.init(.stdout());
92
+ defer stdout_io.deinit();
93
+ const stdout = stdout_io.writer();
90
94
  if (parsed.json) {
91
95
  try writeJson(stdout, discovered.summary, discovered.validation);
92
96
  } else {
@@ -1,4 +1,5 @@
1
1
  const std = @import("std");
2
+ const stdio = @import("stdio.zig");
2
3
 
3
4
  const cli_output = @import("cli_output.zig");
4
5
  const config = @import("config.zig");
@@ -42,13 +43,13 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
42
43
  parsed.config_path = if (index < args.len) args[index] else return error.MissingConfigPath;
43
44
  parsed.explicit_config = true;
44
45
  } else {
45
- return error.UnknownFlag;
46
+ return error.unknownFlag;
46
47
  }
47
48
  }
48
49
  return parsed;
49
50
  }
50
51
 
51
- pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
52
+ pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
52
53
  var raw_args = std.ArrayList([]const u8).empty;
53
54
  defer raw_args.deinit(allocator);
54
55
  while (args.next()) |arg| try raw_args.append(allocator, arg);
@@ -104,7 +105,10 @@ fn runParsed(allocator: std.mem.Allocator, parsed: ParsedArgs) !void {
104
105
  allocator.free(checks);
105
106
  }
106
107
 
107
- const stdout = std.fs.File.stdout().deprecatedWriter();
108
+ var stdout_io: stdio.Output = .{};
109
+ stdout_io.init(.stdout());
110
+ defer stdout_io.deinit();
111
+ const stdout = stdout_io.writer();
108
112
  if (parsed.json) {
109
113
  try cli_output.writeDoctorJson(stdout, config_check, checks);
110
114
  } else {
package/src/cli_draft.zig CHANGED
@@ -1,4 +1,5 @@
1
1
  const std = @import("std");
2
+ const stdio = @import("stdio.zig");
2
3
 
3
4
  const cli_output = @import("cli_output.zig");
4
5
  const trace = @import("trace.zig");
@@ -100,7 +101,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
100
101
  } else if (std.mem.eql(u8, arg, "--json")) {
101
102
  parsed.json = true;
102
103
  } else {
103
- return error.UnknownFlag;
104
+ return error.unknownFlag;
104
105
  }
105
106
  }
106
107
 
@@ -109,7 +110,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
109
110
  return parsed;
110
111
  }
111
112
 
112
- pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
113
+ pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
113
114
  var raw_args = std.ArrayList([]const u8).empty;
114
115
  defer raw_args.deinit(allocator);
115
116
  while (args.next()) |arg| try raw_args.append(allocator, arg);
@@ -118,7 +119,10 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
118
119
  var draft = try draftFromTrace(allocator, parsed);
119
120
  defer draft.deinit(allocator);
120
121
 
121
- const stdout = std.fs.File.stdout().deprecatedWriter();
122
+ var stdout_io: stdio.Output = .{};
123
+ stdout_io.init(.stdout());
124
+ defer stdout_io.deinit();
125
+ const stdout = stdout_io.writer();
122
126
  if (parsed.json) {
123
127
  try writeJson(stdout, draft.summary);
124
128
  return;
@@ -150,7 +154,7 @@ pub fn draftFromTrace(allocator: std.mem.Allocator, parsed: ParsedArgs) !OwnedDr
150
154
 
151
155
  const manifest_path = try std.fs.path.join(allocator, &.{ from_trace, "trace.json" });
152
156
  defer allocator.free(manifest_path);
153
- const manifest_content = try std.fs.cwd().readFileAlloc(allocator, manifest_path, 1024 * 1024);
157
+ const manifest_content = try stdio.readFileAlloc(allocator, manifest_path, 1024 * 1024);
154
158
  defer allocator.free(manifest_content);
155
159
 
156
160
  var parsed_manifest = try std.json.parseFromSlice(std.json.Value, allocator, manifest_content, .{});
@@ -219,7 +223,7 @@ fn parseReplaySteps(
219
223
  ) !ReplayDraft {
220
224
  const events_path = try std.fs.path.join(allocator, &.{ trace_dir, metadata.events_path });
221
225
  defer allocator.free(events_path);
222
- const content = std.fs.cwd().readFileAlloc(allocator, events_path, 64 * 1024 * 1024) catch |err| switch (err) {
226
+ const content = stdio.readFileAlloc(allocator, events_path, 64 * 1024 * 1024) catch |err| switch (err) {
223
227
  error.FileNotFound => {
224
228
  try appendWarning(allocator, owned, "trace events were not found; action replay was skipped");
225
229
  return .{
@@ -393,14 +397,14 @@ fn latestSnapshotPath(
393
397
 
394
398
  const artifacts_path = try std.fs.path.join(allocator, &.{ trace_dir, metadata.artifacts_dir });
395
399
  defer allocator.free(artifacts_path);
396
- var dir = try std.fs.cwd().openDir(artifacts_path, .{ .iterate = true });
397
- defer dir.close();
400
+ var dir = try std.Io.Dir.cwd().openDir(stdio.io(), artifacts_path, .{ .iterate = true });
401
+ defer dir.close(stdio.io());
398
402
 
399
403
  var iterator = dir.iterate();
400
404
  var best_number: usize = 0;
401
405
  var best_name: ?[]u8 = null;
402
406
  defer if (best_name) |value| allocator.free(value);
403
- while (try iterator.next()) |entry| {
407
+ while (try iterator.next(stdio.io())) |entry| {
404
408
  if (entry.kind != .file) continue;
405
409
  const number = snapshotNumber(entry.name) orelse continue;
406
410
  if (best_name == null or number > best_number) {
@@ -422,7 +426,7 @@ fn parseSemanticSelectors(
422
426
  path: []const u8,
423
427
  owned: *OwnedDraft,
424
428
  ) ![]DraftSelector {
425
- const content = try std.fs.cwd().readFileAlloc(allocator, path, 8 * 1024 * 1024);
429
+ const content = try stdio.readFileAlloc(allocator, path, 8 * 1024 * 1024);
426
430
  defer allocator.free(content);
427
431
 
428
432
  var parsed = try std.json.parseFromSlice(std.json.Value, allocator, content, .{});
@@ -505,16 +509,16 @@ fn writeScenarioFile(
505
509
  force: bool,
506
510
  ) !void {
507
511
  if (std.fs.path.dirname(out_path)) |dir| {
508
- if (dir.len > 0) try std.fs.cwd().makePath(dir);
512
+ if (dir.len > 0) try std.Io.Dir.cwd().createDirPath(stdio.io(), dir);
509
513
  }
510
514
  var file = if (force)
511
- try std.fs.cwd().createFile(out_path, .{ .truncate = true })
515
+ try std.Io.Dir.cwd().createFile(stdio.io(), out_path, .{ .truncate = true })
512
516
  else
513
- try std.fs.cwd().createFile(out_path, .{ .exclusive = true });
514
- defer file.close();
517
+ try std.Io.Dir.cwd().createFile(stdio.io(), out_path, .{ .exclusive = true });
518
+ defer file.close(stdio.io());
515
519
 
516
520
  var write_buffer: [8192]u8 = undefined;
517
- var file_writer = file.writer(&write_buffer);
521
+ var file_writer = file.writerStreaming(stdio.io(), &write_buffer);
518
522
  try writeScenarioJson(&file_writer.interface, name, app_id, action_steps, selectors);
519
523
  try file_writer.interface.flush();
520
524
  }
@@ -609,9 +613,9 @@ fn actionWithStringField(
609
613
  key: []const u8,
610
614
  value: []const u8,
611
615
  ) ![]const u8 {
612
- var buffer = std.ArrayList(u8).empty;
613
- defer buffer.deinit(allocator);
614
- const writer = buffer.writer(allocator);
616
+ var buffer: std.Io.Writer.Allocating = .init(allocator);
617
+ defer buffer.deinit();
618
+ const writer = &buffer.writer;
615
619
  try writer.writeAll("{\"action\":");
616
620
  try trace.writeJsonString(writer, action);
617
621
  try writer.writeAll(",");
@@ -619,7 +623,7 @@ fn actionWithStringField(
619
623
  try writer.writeAll(":");
620
624
  try trace.writeJsonString(writer, value);
621
625
  try writer.writeAll("}");
622
- return try ownBytes(allocator, owned, buffer.items);
626
+ return try ownBytes(allocator, owned, buffer.writer.buffered());
623
627
  }
624
628
 
625
629
  fn actionWithIntField(
@@ -629,15 +633,15 @@ fn actionWithIntField(
629
633
  key: []const u8,
630
634
  value: usize,
631
635
  ) ![]const u8 {
632
- var buffer = std.ArrayList(u8).empty;
633
- defer buffer.deinit(allocator);
634
- const writer = buffer.writer(allocator);
636
+ var buffer: std.Io.Writer.Allocating = .init(allocator);
637
+ defer buffer.deinit();
638
+ const writer = &buffer.writer;
635
639
  try writer.writeAll("{\"action\":");
636
640
  try trace.writeJsonString(writer, action);
637
641
  try writer.writeAll(",");
638
642
  try trace.writeJsonString(writer, key);
639
643
  try writer.print(":{d}}}", .{value});
640
- return try ownBytes(allocator, owned, buffer.items);
644
+ return try ownBytes(allocator, owned, buffer.writer.buffered());
641
645
  }
642
646
 
643
647
  fn actionWithSelector(
@@ -646,15 +650,15 @@ fn actionWithSelector(
646
650
  action: []const u8,
647
651
  selector_value: std.json.Value,
648
652
  ) ![]const u8 {
649
- var buffer = std.ArrayList(u8).empty;
650
- defer buffer.deinit(allocator);
651
- const writer = buffer.writer(allocator);
653
+ var buffer: std.Io.Writer.Allocating = .init(allocator);
654
+ defer buffer.deinit();
655
+ const writer = &buffer.writer;
652
656
  try writer.writeAll("{\"action\":");
653
657
  try trace.writeJsonString(writer, action);
654
658
  try writer.writeAll(",\"selector\":");
655
659
  try writeJsonValue(writer, selector_value);
656
660
  try writer.writeAll("}");
657
- return try ownBytes(allocator, owned, buffer.items);
661
+ return try ownBytes(allocator, owned, buffer.writer.buffered());
658
662
  }
659
663
 
660
664
  fn actionWithSelectorAndString(
@@ -665,9 +669,9 @@ fn actionWithSelectorAndString(
665
669
  key: []const u8,
666
670
  value: []const u8,
667
671
  ) ![]const u8 {
668
- var buffer = std.ArrayList(u8).empty;
669
- defer buffer.deinit(allocator);
670
- const writer = buffer.writer(allocator);
672
+ var buffer: std.Io.Writer.Allocating = .init(allocator);
673
+ defer buffer.deinit();
674
+ const writer = &buffer.writer;
671
675
  try writer.writeAll("{\"action\":");
672
676
  try trace.writeJsonString(writer, action);
673
677
  try writer.writeAll(",\"selector\":");
@@ -677,7 +681,7 @@ fn actionWithSelectorAndString(
677
681
  try writer.writeAll(":");
678
682
  try trace.writeJsonString(writer, value);
679
683
  try writer.writeAll("}");
680
- return try ownBytes(allocator, owned, buffer.items);
684
+ return try ownBytes(allocator, owned, buffer.writer.buffered());
681
685
  }
682
686
 
683
687
  fn actionWithSelectorAndInt(
@@ -688,9 +692,9 @@ fn actionWithSelectorAndInt(
688
692
  key: []const u8,
689
693
  value: usize,
690
694
  ) ![]const u8 {
691
- var buffer = std.ArrayList(u8).empty;
692
- defer buffer.deinit(allocator);
693
- const writer = buffer.writer(allocator);
695
+ var buffer: std.Io.Writer.Allocating = .init(allocator);
696
+ defer buffer.deinit();
697
+ const writer = &buffer.writer;
694
698
  try writer.writeAll("{\"action\":");
695
699
  try trace.writeJsonString(writer, action);
696
700
  try writer.writeAll(",\"selector\":");
@@ -698,7 +702,7 @@ fn actionWithSelectorAndInt(
698
702
  try writer.writeAll(",");
699
703
  try trace.writeJsonString(writer, key);
700
704
  try writer.print(":{d}}}", .{value});
701
- return try ownBytes(allocator, owned, buffer.items);
705
+ return try ownBytes(allocator, owned, buffer.writer.buffered());
702
706
  }
703
707
 
704
708
  fn actionWithSelectors(
@@ -708,16 +712,16 @@ fn actionWithSelectors(
708
712
  selectors_value: std.json.Value,
709
713
  timeout_ms: ?usize,
710
714
  ) ![]const u8 {
711
- var buffer = std.ArrayList(u8).empty;
712
- defer buffer.deinit(allocator);
713
- const writer = buffer.writer(allocator);
715
+ var buffer: std.Io.Writer.Allocating = .init(allocator);
716
+ defer buffer.deinit();
717
+ const writer = &buffer.writer;
714
718
  try writer.writeAll("{\"action\":");
715
719
  try trace.writeJsonString(writer, action);
716
720
  try writer.writeAll(",\"selectors\":");
717
721
  try writeJsonValue(writer, selectors_value);
718
722
  if (timeout_ms) |actual| try writer.print(",\"timeoutMs\":{d}", .{actual});
719
723
  try writer.writeAll("}");
720
- return try ownBytes(allocator, owned, buffer.items);
724
+ return try ownBytes(allocator, owned, buffer.writer.buffered());
721
725
  }
722
726
 
723
727
  fn actionWithSwipe(
@@ -729,13 +733,13 @@ fn actionWithSwipe(
729
733
  y2: i32,
730
734
  duration_ms: ?usize,
731
735
  ) ![]const u8 {
732
- var buffer = std.ArrayList(u8).empty;
733
- defer buffer.deinit(allocator);
734
- const writer = buffer.writer(allocator);
736
+ var buffer: std.Io.Writer.Allocating = .init(allocator);
737
+ defer buffer.deinit();
738
+ const writer = &buffer.writer;
735
739
  try writer.print("{{\"action\":\"swipe\",\"x1\":{d},\"y1\":{d},\"x2\":{d},\"y2\":{d}", .{ x1, y1, x2, y2 });
736
740
  if (duration_ms) |actual| try writer.print(",\"durationMs\":{d}", .{actual});
737
741
  try writer.writeAll("}");
738
- return try ownBytes(allocator, owned, buffer.items);
742
+ return try ownBytes(allocator, owned, buffer.writer.buffered());
739
743
  }
740
744
 
741
745
  fn actionWithScrollUntilVisible(
@@ -745,9 +749,9 @@ fn actionWithScrollUntilVisible(
745
749
  direction: ?[]const u8,
746
750
  timeout_ms: ?usize,
747
751
  ) ![]const u8 {
748
- var buffer = std.ArrayList(u8).empty;
749
- defer buffer.deinit(allocator);
750
- const writer = buffer.writer(allocator);
752
+ var buffer: std.Io.Writer.Allocating = .init(allocator);
753
+ defer buffer.deinit();
754
+ const writer = &buffer.writer;
751
755
  try writer.writeAll("{\"action\":\"scrollUntilVisible\",\"selector\":");
752
756
  try writeJsonValue(writer, selector_value);
753
757
  if (direction) |actual| {
@@ -756,7 +760,7 @@ fn actionWithScrollUntilVisible(
756
760
  }
757
761
  if (timeout_ms) |actual| try writer.print(",\"timeoutMs\":{d}", .{actual});
758
762
  try writer.writeAll("}");
759
- return try ownBytes(allocator, owned, buffer.items);
763
+ return try ownBytes(allocator, owned, buffer.writer.buffered());
760
764
  }
761
765
 
762
766
  fn warnMissingReplayField(
@@ -919,6 +923,6 @@ fn snapshotNumber(name: []const u8) ?usize {
919
923
  }
920
924
 
921
925
  fn pathExists(path: []const u8) bool {
922
- std.fs.cwd().access(path, .{}) catch return false;
926
+ stdio.access(path) catch return false;
923
927
  return true;
924
928
  }
@@ -1,4 +1,5 @@
1
1
  const std = @import("std");
2
+ const stdio = @import("stdio.zig");
2
3
 
3
4
  const cli_discover = @import("cli_discover.zig");
4
5
  const cli_output = @import("cli_output.zig");
@@ -66,7 +67,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
66
67
  } else if (std.mem.eql(u8, arg, "--json")) {
67
68
  parsed.json = true;
68
69
  } else {
69
- return error.UnknownFlag;
70
+ return error.unknownFlag;
70
71
  }
71
72
  }
72
73
 
@@ -75,7 +76,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
75
76
  return parsed;
76
77
  }
77
78
 
78
- pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
79
+ pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
79
80
  var raw_args = std.ArrayList([]const u8).empty;
80
81
  defer raw_args.deinit(allocator);
81
82
  while (args.next()) |arg| try raw_args.append(allocator, arg);
@@ -84,7 +85,10 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
84
85
  var explored = try exploreFromTrace(allocator, parsed);
85
86
  defer explored.deinit(allocator);
86
87
 
87
- const stdout = std.fs.File.stdout().deprecatedWriter();
88
+ var stdout_io: stdio.Output = .{};
89
+ stdout_io.init(.stdout());
90
+ defer stdout_io.deinit();
91
+ const stdout = stdout_io.writer();
88
92
  if (parsed.json) {
89
93
  try writeJson(stdout, explored.summary, explored.discovered.summary, explored.discovered.validation);
90
94
  } else {
@@ -1,4 +1,5 @@
1
1
  const std = @import("std");
2
+ const stdio = @import("stdio.zig");
2
3
 
3
4
  const cli_output = @import("cli_output.zig");
4
5
  const importer = @import("importer.zig");
@@ -39,13 +40,13 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
39
40
  } else if (std.mem.eql(u8, arg, "--json")) {
40
41
  json = true;
41
42
  } else if (std.mem.startsWith(u8, arg, "--")) {
42
- return error.UnknownFlag;
43
+ return error.unknownFlag;
43
44
  } else if (format == null) {
44
45
  format = arg;
45
46
  } else if (source_path == null) {
46
47
  source_path = arg;
47
48
  } else {
48
- return error.UnknownFlag;
49
+ return error.unknownFlag;
49
50
  }
50
51
  }
51
52
  if (format == null) return error.MissingImportFormat;
@@ -62,7 +63,7 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
62
63
  };
63
64
  }
64
65
 
65
- pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
66
+ pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
66
67
  var raw_args = std.ArrayList([]const u8).empty;
67
68
  defer raw_args.deinit(allocator);
68
69
  while (args.next()) |arg| try raw_args.append(allocator, arg);
@@ -77,7 +78,10 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
77
78
  });
78
79
  defer result.deinit(allocator);
79
80
 
80
- const stdout = std.fs.File.stdout().deprecatedWriter();
81
+ var stdout_io: stdio.Output = .{};
82
+ stdout_io.init(.stdout());
83
+ defer stdout_io.deinit();
84
+ const stdout = stdout_io.writer();
81
85
  if (parsed.json) return try cli_output.writeImportJson(stdout, parsed.format, parsed.source_path, result);
82
86
  try stdout.print("wrote {s}\n", .{result.out_path});
83
87
  try stdout.writeAll("next: zmr validate ");
package/src/cli_info.zig CHANGED
@@ -1,4 +1,5 @@
1
1
  const std = @import("std");
2
+ const stdio = @import("stdio.zig");
2
3
 
3
4
  const schema_registry = @import("schema_registry.zig");
4
5
  const version = @import("version.zig");
@@ -9,29 +10,35 @@ pub fn parseJsonFlag(args: []const []const u8) !bool {
9
10
  if (std.mem.eql(u8, arg, "--json")) {
10
11
  json = true;
11
12
  } else {
12
- return error.UnknownFlag;
13
+ return error.unknownFlag;
13
14
  }
14
15
  }
15
16
  return json;
16
17
  }
17
18
 
18
- pub fn runVersion(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
19
+ pub fn runVersion(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
19
20
  const json = try parseArgIterator(allocator, args);
20
- const stdout = std.fs.File.stdout().deprecatedWriter();
21
+ var stdout_io: stdio.Output = .{};
22
+ stdout_io.init(.stdout());
23
+ defer stdout_io.deinit();
24
+ const stdout = stdout_io.writer();
21
25
  if (json) return try version.writeJson(stdout);
22
26
  try version.writePlain(stdout);
23
27
  }
24
28
 
25
- pub fn runSchemas(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
29
+ pub fn runSchemas(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
26
30
  const json = try parseArgIterator(allocator, args);
27
- const stdout = std.fs.File.stdout().deprecatedWriter();
31
+ var stdout_io: stdio.Output = .{};
32
+ stdout_io.init(.stdout());
33
+ defer stdout_io.deinit();
34
+ const stdout = stdout_io.writer();
28
35
  if (json) return try schema_registry.writeJson(stdout);
29
36
  for (schema_registry.all()) |schema_info| {
30
37
  try stdout.print("{s}\t{s}\n", .{ schema_info.name, schema_info.path });
31
38
  }
32
39
  }
33
40
 
34
- fn parseArgIterator(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !bool {
41
+ fn parseArgIterator(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !bool {
35
42
  var raw_args = std.ArrayList([]const u8).empty;
36
43
  defer raw_args.deinit(allocator);
37
44
  while (args.next()) |arg| try raw_args.append(allocator, arg);
package/src/cli_init.zig CHANGED
@@ -1,4 +1,5 @@
1
1
  const std = @import("std");
2
+ const stdio = @import("stdio.zig");
2
3
 
3
4
  const cli_output = @import("cli_output.zig");
4
5
  const scaffold = @import("scaffold.zig");
@@ -31,26 +32,29 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
31
32
  } else if (std.mem.eql(u8, arg, "--json")) {
32
33
  parsed.json = true;
33
34
  } else if (std.mem.startsWith(u8, arg, "--")) {
34
- return error.UnknownFlag;
35
+ return error.unknownFlag;
35
36
  } else if (parsed.app_scaffold) {
36
- return error.UnknownFlag;
37
+ return error.unknownFlag;
37
38
  } else if (!path_set) {
38
39
  parsed.path = arg;
39
40
  path_set = true;
40
41
  } else {
41
- return error.UnknownFlag;
42
+ return error.unknownFlag;
42
43
  }
43
44
  }
44
45
  return parsed;
45
46
  }
46
47
 
47
- pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
48
+ pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
48
49
  var raw_args = std.ArrayList([]const u8).empty;
49
50
  defer raw_args.deinit(allocator);
50
51
  while (args.next()) |arg| try raw_args.append(allocator, arg);
51
52
 
52
53
  const parsed = try parseArgs(raw_args.items);
53
- const stdout = std.fs.File.stdout().deprecatedWriter();
54
+ var stdout_io: stdio.Output = .{};
55
+ stdout_io.init(.stdout());
56
+ defer stdout_io.deinit();
57
+ const stdout = stdout_io.writer();
54
58
  if (parsed.app_scaffold) {
55
59
  try scaffold.writeAppScaffold(allocator, parsed.dir, parsed.app_id, parsed.force);
56
60
  if (parsed.json) return try cli_output.writeInitAppJson(stdout, parsed.dir, parsed.app_id);
@@ -1,4 +1,5 @@
1
1
  const std = @import("std");
2
+ const stdio = @import("stdio.zig");
2
3
 
3
4
  const config = @import("config.zig");
4
5
  const scaffold = @import("scaffold.zig");
@@ -59,13 +60,13 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
59
60
  index += 1;
60
61
  parsed.config_path = if (index < args.len) args[index] else return error.MissingParam;
61
62
  } else {
62
- return error.UnknownFlag;
63
+ return error.unknownFlag;
63
64
  }
64
65
  }
65
66
  return parsed;
66
67
  }
67
68
 
68
- pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
69
+ pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
69
70
  var raw_args = std.ArrayList([]const u8).empty;
70
71
  defer raw_args.deinit(allocator);
71
72
  while (args.next()) |arg| try raw_args.append(allocator, arg);
@@ -74,7 +75,10 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
74
75
  var owned = try inspect(allocator, parsed);
75
76
  defer owned.deinit(allocator);
76
77
 
77
- const stdout = std.fs.File.stdout().deprecatedWriter();
78
+ var stdout_io: stdio.Output = .{};
79
+ stdout_io.init(.stdout());
80
+ defer stdout_io.deinit();
81
+ const stdout = stdout_io.writer();
78
82
  if (parsed.json) {
79
83
  try writeJson(stdout, owned.inspection);
80
84
  } else {
@@ -140,7 +144,7 @@ fn appendPlatform(
140
144
  }
141
145
 
142
146
  fn pathExists(path: []const u8) bool {
143
- std.fs.cwd().access(path, .{}) catch return false;
147
+ stdio.access(path) catch return false;
144
148
  return true;
145
149
  }
146
150
 
package/src/cli_run.zig CHANGED
@@ -1,4 +1,5 @@
1
1
  const std = @import("std");
2
+ const stdio = @import("stdio.zig");
2
3
 
3
4
  const android = @import("android.zig");
4
5
  const android_emulator = @import("android_emulator.zig");
@@ -99,17 +100,17 @@ pub fn parseArgs(args: []const []const u8) !ParsedArgs {
99
100
  } else if (std.mem.eql(u8, arg, "--json")) {
100
101
  parsed.json = true;
101
102
  } else if (std.mem.startsWith(u8, arg, "--")) {
102
- return error.UnknownFlag;
103
+ return error.unknownFlag;
103
104
  } else if (parsed.raw.scenario_path == null) {
104
105
  parsed.raw.scenario_path = arg;
105
106
  } else {
106
- return error.UnknownFlag;
107
+ return error.unknownFlag;
107
108
  }
108
109
  }
109
110
  return parsed;
110
111
  }
111
112
 
112
- pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
113
+ pub fn run(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
113
114
  var raw_args = std.ArrayList([]const u8).empty;
114
115
  defer raw_args.deinit(allocator);
115
116
  while (args.next()) |arg| try raw_args.append(allocator, arg);
@@ -191,8 +192,8 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
191
192
  break :blk null;
192
193
  };
193
194
 
194
- var discovery_payload = std.ArrayList(u8).empty;
195
- defer discovery_payload.deinit(allocator);
195
+ var discovery_payload: std.Io.Writer.Allocating = .init(allocator);
196
+ defer discovery_payload.deinit();
196
197
  var run_discovery = cli_output.RunDiscovery{};
197
198
  if (parsed.discover_out) |out_path| {
198
199
  if (cli_discover.discoverFromTrace(allocator, .{
@@ -205,22 +206,27 @@ pub fn run(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
205
206
  })) |discovered_value| {
206
207
  var discovered = discovered_value;
207
208
  defer discovered.deinit(allocator);
208
- try cli_discover.writeJson(discovery_payload.writer(allocator), discovered.summary, discovered.validation);
209
- run_discovery = .{ .json = std.mem.trimRight(u8, discovery_payload.items, " \t\r\n") };
209
+ try cli_discover.writeJson(&discovery_payload.writer, discovered.summary, discovered.validation);
210
+ run_discovery = .{ .json = std.mem.trimEnd(u8, discovery_payload.writer.buffered(), " \t\r\n") };
210
211
  } else |err| {
211
212
  run_discovery = .{ .error_name = @errorName(err) };
212
213
  }
213
214
  }
214
215
 
215
- if (parsed.json) try cli_output.writeRunSummaryJson(
216
- allocator,
217
- std.fs.File.stdout().deprecatedWriter(),
218
- trace_dir,
219
- script.name,
220
- app_id,
221
- run_error,
222
- run_discovery,
223
- );
216
+ if (parsed.json) {
217
+ var stdout_io: stdio.Output = .{};
218
+ stdout_io.init(.stdout());
219
+ defer stdout_io.deinit();
220
+ try cli_output.writeRunSummaryJson(
221
+ allocator,
222
+ stdout_io.writer(),
223
+ trace_dir,
224
+ script.name,
225
+ app_id,
226
+ run_error,
227
+ run_discovery,
228
+ );
229
+ }
224
230
  if (run_error) |err| return err;
225
231
  }
226
232
 
package/src/cli_serve.zig CHANGED
@@ -66,7 +66,7 @@ pub fn parseMcpArgs(args: []const []const u8) !McpArgs {
66
66
  return parsed;
67
67
  }
68
68
 
69
- pub fn runServe(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
69
+ pub fn runServe(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
70
70
  var raw_args = std.ArrayList([]const u8).empty;
71
71
  defer raw_args.deinit(allocator);
72
72
  while (args.next()) |arg| try raw_args.append(allocator, arg);
@@ -98,7 +98,7 @@ pub fn runServe(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !v
98
98
  }
99
99
  }
100
100
 
101
- pub fn runMcp(allocator: std.mem.Allocator, args: *std.process.ArgIterator) !void {
101
+ pub fn runMcp(allocator: std.mem.Allocator, args: *std.process.Args.Iterator) !void {
102
102
  var raw_args = std.ArrayList([]const u8).empty;
103
103
  defer raw_args.deinit(allocator);
104
104
  while (args.next()) |arg| try raw_args.append(allocator, arg);
@@ -170,7 +170,7 @@ fn parseCommonArg(
170
170
  index.* += 1;
171
171
  config_path.* = if (index.* < args.len) args[index.*] else return error.MissingConfigPath;
172
172
  } else {
173
- return error.UnknownFlag;
173
+ return error.unknownFlag;
174
174
  }
175
175
  }
176
176