@midscene/computer 1.9.1-beta-20260605031620.0 → 1.9.1

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.
Binary file
Binary file
package/dist/es/cli.mjs CHANGED
@@ -520,7 +520,7 @@ Available Displays: ${displays.length > 0 ? displays.map((d)=>d.name).join(', ')
520
520
  }
521
521
  async healthCheck() {
522
522
  console.log('[HealthCheck] Starting health check...');
523
- console.log("[HealthCheck] @midscene/computer v1.9.1-beta-20260605031620.0");
523
+ console.log("[HealthCheck] @midscene/computer v1.9.1");
524
524
  console.log('[HealthCheck] Taking screenshot...');
525
525
  const screenshotTimeout = 15000;
526
526
  let timeoutId;
@@ -1239,8 +1239,7 @@ class RDPDevice {
1239
1239
  port: this.options.port,
1240
1240
  username: this.options.username
1241
1241
  });
1242
- const { backend: _backend, customActions: _customActions, ...config } = this.options;
1243
- this.connectionInfo = await this.backend.connect(config);
1242
+ this.connectionInfo = await this.backend.connect(this.options);
1244
1243
  this.cursorPosition = [
1245
1244
  Math.round(this.connectionInfo.size.width / 2),
1246
1245
  Math.round(this.connectionInfo.size.height / 2)
@@ -1698,7 +1697,7 @@ class ComputerMidsceneTools extends BaseMidsceneTools {
1698
1697
  const tools = new ComputerMidsceneTools();
1699
1698
  runToolsCLI(tools, 'midscene-computer', {
1700
1699
  stripPrefix: 'computer_',
1701
- version: "1.9.1-beta-20260605031620.0",
1700
+ version: "1.9.1",
1702
1701
  extraCommands: createReportCliCommands()
1703
1702
  }).catch((e)=>{
1704
1703
  process.exit(reportCLIError(e));
package/dist/es/index.mjs CHANGED
@@ -520,7 +520,7 @@ Available Displays: ${displays.length > 0 ? displays.map((d)=>d.name).join(', ')
520
520
  }
521
521
  async healthCheck() {
522
522
  console.log('[HealthCheck] Starting health check...');
523
- console.log("[HealthCheck] @midscene/computer v1.9.1-beta-20260605031620.0");
523
+ console.log("[HealthCheck] @midscene/computer v1.9.1");
524
524
  console.log('[HealthCheck] Taking screenshot...');
525
525
  const screenshotTimeout = 15000;
526
526
  let timeoutId;
@@ -1282,8 +1282,7 @@ class RDPDevice {
1282
1282
  port: this.options.port,
1283
1283
  username: this.options.username
1284
1284
  });
1285
- const { backend: _backend, customActions: _customActions, ...config } = this.options;
1286
- this.connectionInfo = await this.backend.connect(config);
1285
+ this.connectionInfo = await this.backend.connect(this.options);
1287
1286
  this.cursorPosition = [
1288
1287
  Math.round(this.connectionInfo.size.width / 2),
1289
1288
  Math.round(this.connectionInfo.size.height / 2)
@@ -1739,7 +1738,7 @@ class ComputerMidsceneTools extends BaseMidsceneTools {
1739
1738
  }
1740
1739
  }
1741
1740
  function version() {
1742
- const currentVersion = "1.9.1-beta-20260605031620.0";
1741
+ const currentVersion = "1.9.1";
1743
1742
  console.log(`@midscene/computer v${currentVersion}`);
1744
1743
  return currentVersion;
1745
1744
  }
@@ -520,7 +520,7 @@ Available Displays: ${displays.length > 0 ? displays.map((d)=>d.name).join(', ')
520
520
  }
521
521
  async healthCheck() {
522
522
  console.log('[HealthCheck] Starting health check...');
523
- console.log("[HealthCheck] @midscene/computer v1.9.1-beta-20260605031620.0");
523
+ console.log("[HealthCheck] @midscene/computer v1.9.1");
524
524
  console.log('[HealthCheck] Taking screenshot...');
525
525
  const screenshotTimeout = 15000;
526
526
  let timeoutId;
@@ -1239,8 +1239,7 @@ class RDPDevice {
1239
1239
  port: this.options.port,
1240
1240
  username: this.options.username
1241
1241
  });
1242
- const { backend: _backend, customActions: _customActions, ...config } = this.options;
1243
- this.connectionInfo = await this.backend.connect(config);
1242
+ this.connectionInfo = await this.backend.connect(this.options);
1244
1243
  this.cursorPosition = [
1245
1244
  Math.round(this.connectionInfo.size.width / 2),
1246
1245
  Math.round(this.connectionInfo.size.height / 2)
@@ -1702,7 +1701,7 @@ class ComputerMCPServer extends BaseMCPServer {
1702
1701
  constructor(toolsManager){
1703
1702
  super({
1704
1703
  name: '@midscene/computer-mcp',
1705
- version: "1.9.1-beta-20260605031620.0",
1704
+ version: "1.9.1",
1706
1705
  description: 'Control the computer desktop using natural language commands'
1707
1706
  }, toolsManager);
1708
1707
  }
package/dist/lib/cli.js CHANGED
@@ -546,7 +546,7 @@ Available Displays: ${displays.length > 0 ? displays.map((d)=>d.name).join(', ')
546
546
  }
547
547
  async healthCheck() {
548
548
  console.log('[HealthCheck] Starting health check...');
549
- console.log("[HealthCheck] @midscene/computer v1.9.1-beta-20260605031620.0");
549
+ console.log("[HealthCheck] @midscene/computer v1.9.1");
550
550
  console.log('[HealthCheck] Taking screenshot...');
551
551
  const screenshotTimeout = 15000;
552
552
  let timeoutId;
@@ -1266,8 +1266,7 @@ class RDPDevice {
1266
1266
  port: this.options.port,
1267
1267
  username: this.options.username
1268
1268
  });
1269
- const { backend: _backend, customActions: _customActions, ...config } = this.options;
1270
- this.connectionInfo = await this.backend.connect(config);
1269
+ this.connectionInfo = await this.backend.connect(this.options);
1271
1270
  this.cursorPosition = [
1272
1271
  Math.round(this.connectionInfo.size.width / 2),
1273
1272
  Math.round(this.connectionInfo.size.height / 2)
@@ -1725,7 +1724,7 @@ class ComputerMidsceneTools extends base_tools_namespaceObject.BaseMidsceneTools
1725
1724
  const tools = new ComputerMidsceneTools();
1726
1725
  (0, cli_namespaceObject.runToolsCLI)(tools, 'midscene-computer', {
1727
1726
  stripPrefix: 'computer_',
1728
- version: "1.9.1-beta-20260605031620.0",
1727
+ version: "1.9.1",
1729
1728
  extraCommands: (0, core_namespaceObject.createReportCliCommands)()
1730
1729
  }).catch((e)=>{
1731
1730
  process.exit((0, cli_namespaceObject.reportCLIError)(e));
package/dist/lib/index.js CHANGED
@@ -573,7 +573,7 @@ Available Displays: ${displays.length > 0 ? displays.map((d)=>d.name).join(', ')
573
573
  }
574
574
  async healthCheck() {
575
575
  console.log('[HealthCheck] Starting health check...');
576
- console.log("[HealthCheck] @midscene/computer v1.9.1-beta-20260605031620.0");
576
+ console.log("[HealthCheck] @midscene/computer v1.9.1");
577
577
  console.log('[HealthCheck] Taking screenshot...');
578
578
  const screenshotTimeout = 15000;
579
579
  let timeoutId;
@@ -1337,8 +1337,7 @@ class RDPDevice {
1337
1337
  port: this.options.port,
1338
1338
  username: this.options.username
1339
1339
  });
1340
- const { backend: _backend, customActions: _customActions, ...config } = this.options;
1341
- this.connectionInfo = await this.backend.connect(config);
1340
+ this.connectionInfo = await this.backend.connect(this.options);
1342
1341
  this.cursorPosition = [
1343
1342
  Math.round(this.connectionInfo.size.width / 2),
1344
1343
  Math.round(this.connectionInfo.size.height / 2)
@@ -1797,7 +1796,7 @@ class ComputerMidsceneTools extends base_tools_namespaceObject.BaseMidsceneTools
1797
1796
  }
1798
1797
  const env_namespaceObject = require("@midscene/shared/env");
1799
1798
  function version() {
1800
- const currentVersion = "1.9.1-beta-20260605031620.0";
1799
+ const currentVersion = "1.9.1";
1801
1800
  console.log(`@midscene/computer v${currentVersion}`);
1802
1801
  return currentVersion;
1803
1802
  }
@@ -560,7 +560,7 @@ Available Displays: ${displays.length > 0 ? displays.map((d)=>d.name).join(', ')
560
560
  }
561
561
  async healthCheck() {
562
562
  console.log('[HealthCheck] Starting health check...');
563
- console.log("[HealthCheck] @midscene/computer v1.9.1-beta-20260605031620.0");
563
+ console.log("[HealthCheck] @midscene/computer v1.9.1");
564
564
  console.log('[HealthCheck] Taking screenshot...');
565
565
  const screenshotTimeout = 15000;
566
566
  let timeoutId;
@@ -1280,8 +1280,7 @@ class RDPDevice {
1280
1280
  port: this.options.port,
1281
1281
  username: this.options.username
1282
1282
  });
1283
- const { backend: _backend, customActions: _customActions, ...config } = this.options;
1284
- this.connectionInfo = await this.backend.connect(config);
1283
+ this.connectionInfo = await this.backend.connect(this.options);
1285
1284
  this.cursorPosition = [
1286
1285
  Math.round(this.connectionInfo.size.width / 2),
1287
1286
  Math.round(this.connectionInfo.size.height / 2)
@@ -1745,7 +1744,7 @@ class ComputerMCPServer extends mcp_namespaceObject.BaseMCPServer {
1745
1744
  constructor(toolsManager){
1746
1745
  super({
1747
1746
  name: '@midscene/computer-mcp',
1748
- version: "1.9.1-beta-20260605031620.0",
1747
+ version: "1.9.1",
1749
1748
  description: 'Control the computer desktop using natural language commands'
1750
1749
  }, toolsManager);
1751
1750
  }
@@ -1,7 +1,5 @@
1
1
  #pragma once
2
2
 
3
- #include <atomic>
4
- #include <condition_variable>
5
3
  #include <cstdint>
6
4
  #include <mutex>
7
5
  #include <optional>
@@ -70,16 +68,6 @@ class FreeRdpSessionTransport final : public SessionTransport {
70
68
  bool IsConnected() const override;
71
69
  std::optional<ErrorPayload> LastError() const override;
72
70
  void MarkGdiInitialized();
73
- // Chain a frame-paint hook onto the GDI update pipeline so the session can
74
- // tell when the first real desktop frame has arrived. Must be called after
75
- // gdi_init() has installed its own EndPaint handler.
76
- void HookEndPaint(rdpUpdate* update);
77
- // Invoked from the event loop after each EndPaint; records that at least one
78
- // real paint has reached the local framebuffer and wakes Connect().
79
- void MarkFramePainted();
80
- BOOL CallOriginalEndPaint(rdpContext* context);
81
- // Mark the session as no longer active and wake any first-frame waiter.
82
- void SignalSessionInactive();
83
71
 
84
72
  FreeRdpSessionTransport(const FreeRdpSessionTransport&) = delete;
85
73
  FreeRdpSessionTransport& operator=(const FreeRdpSessionTransport&) = delete;
@@ -93,17 +81,6 @@ class FreeRdpSessionTransport final : public SessionTransport {
93
81
  bool running_ = false;
94
82
  bool connected_ = false;
95
83
  bool gdi_initialized_ = false;
96
- // Number of desktop paints that have reached the local framebuffer. A fresh
97
- // RDP session exposes a zero-filled (all black) buffer until the first paint
98
- // is processed, so screenshots taken before this is > 0 would be blank.
99
- std::atomic<uint64_t> frames_painted_{0};
100
- // Tracks whether the session is still alive while Connect() waits for the
101
- // first frame, so a drop during that window wakes the wait immediately
102
- // instead of stalling until the timeout.
103
- std::atomic<bool> session_active_{false};
104
- std::condition_variable frame_cv_;
105
- std::mutex frame_mutex_;
106
- pEndPaint original_end_paint_ = nullptr;
107
84
  uint16_t mouse_x_ = 0;
108
85
  uint16_t mouse_y_ = 0;
109
86
  std::string session_id_;
@@ -434,38 +434,29 @@ std::string ExtractRequestId(std::string_view line) {
434
434
  }
435
435
 
436
436
  std::optional<ParsedRequest> ParseRequestLine(std::string_view line) {
437
- // The JSON parser throws on malformed/partial input. Callers treat a missing
438
- // value as a recoverable "bad request" (logged and skipped), so a parse
439
- // failure must never escape this function — an uncaught exception here would
440
- // propagate out of main() and abort the whole helper process, tearing down
441
- // the live RDP session.
442
- try {
443
- JsonParser parser(line);
444
- JsonValue root = parser.Parse();
445
- if (!root.IsObject()) {
446
- return std::nullopt;
447
- }
448
-
449
- const JsonObject& request_object = root.AsObject();
450
- const auto request_id = GetStringField(request_object, "id");
451
- const JsonObject* payload = GetObjectField(request_object, "payload");
452
- if (!request_id.has_value() || !payload) {
453
- return std::nullopt;
454
- }
437
+ JsonParser parser(line);
438
+ JsonValue root = parser.Parse();
439
+ if (!root.IsObject()) {
440
+ return std::nullopt;
441
+ }
455
442
 
456
- const auto type_name = GetStringField(*payload, "type");
457
- if (!type_name.has_value()) {
458
- return std::nullopt;
459
- }
443
+ const JsonObject& request_object = root.AsObject();
444
+ const auto request_id = GetStringField(request_object, "id");
445
+ const JsonObject* payload = GetObjectField(request_object, "payload");
446
+ if (!request_id.has_value() || !payload) {
447
+ return std::nullopt;
448
+ }
460
449
 
461
- return ParsedRequest{
462
- *request_id,
463
- ParseRequestType(*type_name).value_or(RequestType::kUnknown),
464
- *payload,
465
- };
466
- } catch (const std::exception&) {
450
+ const auto type_name = GetStringField(*payload, "type");
451
+ if (!type_name.has_value()) {
467
452
  return std::nullopt;
468
453
  }
454
+
455
+ return ParsedRequest{
456
+ *request_id,
457
+ ParseRequestType(*type_name).value_or(RequestType::kUnknown),
458
+ *payload,
459
+ };
469
460
  }
470
461
 
471
462
  std::optional<std::string> GetStringField(const JsonObject& object,
@@ -285,32 +285,18 @@ int main() {
285
285
  midscene::rdp::FreeRdpSessionTransport transport;
286
286
  std::string line;
287
287
  while (std::getline(std::cin, line)) {
288
- // A single malformed request, or any unexpected exception while handling
289
- // one, must never abort the helper: that would kill the live RDP session
290
- // mid-automation. Degrade to an error response and keep serving.
291
- try {
292
- const auto request = midscene::rdp::ParseRequestLine(line);
293
- if (!request.has_value()) {
294
- std::fprintf(stderr, "Failed to parse helper request JSON\n");
295
- std::fflush(stderr);
296
- const std::string request_id = midscene::rdp::ExtractRequestId(line);
297
- std::cout << midscene::rdp::MakeErrorResponse(
298
- request_id, "invalid_request",
299
- "Failed to parse helper request JSON")
300
- << '\n';
301
- std::cout.flush();
302
- continue;
303
- }
304
-
305
- std::cout << midscene::rdp::HandleRequest(*request, transport) << '\n';
306
- std::cout.flush();
307
- } catch (const std::exception& error) {
308
- const std::string request_id = midscene::rdp::ExtractRequestId(line);
309
- std::cout << midscene::rdp::MakeErrorResponse(request_id, "internal_error",
310
- error.what())
311
- << '\n';
312
- std::cout.flush();
288
+ const auto request = midscene::rdp::ParseRequestLine(line);
289
+ const std::string request_id =
290
+ request.has_value() ? request->id : midscene::rdp::ExtractRequestId(line);
291
+
292
+ if (!request.has_value()) {
293
+ std::fprintf(stderr, "Failed to parse helper request JSON\n");
294
+ std::fflush(stderr);
295
+ continue;
313
296
  }
297
+
298
+ std::cout << midscene::rdp::HandleRequest(*request, transport) << '\n';
299
+ std::cout.flush();
314
300
  }
315
301
 
316
302
  transport.Disconnect();
@@ -29,26 +29,6 @@ struct MidsceneRdpContext {
29
29
  FreeRdpSessionTransport* owner = nullptr;
30
30
  };
31
31
 
32
- // Maximum time Connect() waits for the first desktop frame before giving up.
33
- // Normal sessions paint within a few hundred milliseconds; a session that
34
- // never paints within this window is treated as blank/locked and fails fast
35
- // instead of feeding an all-black screenshot to the caller.
36
- constexpr int kFirstFrameTimeoutMs = 10'000;
37
-
38
- // EndPaint hook chained in front of FreeRDP's GDI handler. FreeRDP invokes
39
- // this from the event loop after every paint PDU; we defer to the original
40
- // GDI EndPaint (which actually blits into the primary buffer) and then mark
41
- // that a real frame has landed.
42
- BOOL MidsceneEndPaint(rdpContext* context) {
43
- auto* typed_context = reinterpret_cast<MidsceneRdpContext*>(context);
44
- BOOL ok = TRUE;
45
- if (typed_context->owner) {
46
- ok = typed_context->owner->CallOriginalEndPaint(context);
47
- typed_context->owner->MarkFramePainted();
48
- }
49
- return ok;
50
- }
51
-
52
32
  std::string ToLower(std::string_view value) {
53
33
  std::string lowered(value);
54
34
  std::transform(lowered.begin(), lowered.end(), lowered.begin(), [](unsigned char ch) {
@@ -168,9 +148,6 @@ BOOL PostConnect(freerdp* instance) {
168
148
  reinterpret_cast<MidsceneRdpContext*>(instance->context);
169
149
  if (typed_context->owner) {
170
150
  typed_context->owner->MarkGdiInitialized();
171
- // gdi_init() just installed its EndPaint handler; chain ours on top so we
172
- // can observe when the first real frame is painted.
173
- typed_context->owner->HookEndPaint(instance->context->update);
174
151
  }
175
152
 
176
153
  rdpInput* input = instance->context ? instance->context->input : nullptr;
@@ -468,8 +445,6 @@ ConnectionInfo FreeRdpSessionTransport::Connect(const ConnectionConfig& config)
468
445
  instance_ = instance;
469
446
  mouse_x_ = 0;
470
447
  mouse_y_ = 0;
471
- frames_painted_.store(0, std::memory_order_relaxed);
472
- original_end_paint_ = nullptr;
473
448
  ClearSessionErrorLocked();
474
449
  }
475
450
 
@@ -504,47 +479,7 @@ ConnectionInfo FreeRdpSessionTransport::Connect(const ConnectionConfig& config)
504
479
  }
505
480
  }
506
481
 
507
- session_active_.store(true, std::memory_order_relaxed);
508
482
  event_thread_ = std::thread(&FreeRdpSessionTransport::EventLoop, this);
509
-
510
- // Block until the remote desktop paints its first frame. Without this the
511
- // primary buffer is still zero-filled (all black) and an immediate
512
- // screenshot would hand the caller a blank image, which the agent reads as
513
- // "nothing on screen" and aborts. This race is the root cause of the
514
- // intermittent blank-screenshot failures.
515
- bool painted = false;
516
- {
517
- std::unique_lock<std::mutex> frame_lock(frame_mutex_);
518
- painted = frame_cv_.wait_for(
519
- frame_lock, std::chrono::milliseconds(kFirstFrameTimeoutMs),
520
- [this] {
521
- return frames_painted_.load(std::memory_order_relaxed) > 0 ||
522
- !session_active_.load(std::memory_order_relaxed);
523
- });
524
- }
525
-
526
- // A wait that ended without a frame because the session dropped should
527
- // surface as a failure, not a false "painted" success.
528
- if (frames_painted_.load(std::memory_order_relaxed) == 0) {
529
- painted = false;
530
- }
531
-
532
- if (!painted) {
533
- std::string reason;
534
- {
535
- std::lock_guard<std::mutex> lock(mutex_);
536
- reason = connected_ ? std::string() : LastFreeRdpErrorLocked();
537
- }
538
- StopInstance(false);
539
- std::string message =
540
- "Connected to the RDP server but received no desktop frame within "
541
- "timeout; the remote desktop may be blank or locked";
542
- if (!reason.empty()) {
543
- message += " (" + reason + ")";
544
- }
545
- throw std::runtime_error(message);
546
- }
547
-
548
483
  return info;
549
484
  }
550
485
 
@@ -558,11 +493,6 @@ RawFrame FreeRdpSessionTransport::CaptureFrame() {
558
493
  throw std::runtime_error("No remote framebuffer is available");
559
494
  }
560
495
 
561
- if (frames_painted_.load(std::memory_order_relaxed) == 0) {
562
- throw std::runtime_error(
563
- "Remote framebuffer has not received its first paint yet");
564
- }
565
-
566
496
  rdpGdi* gdi = instance_->context->gdi;
567
497
  if (!gdi->primary_buffer || gdi->width <= 0 || gdi->height <= 0 || gdi->stride == 0) {
568
498
  throw std::runtime_error("Remote framebuffer is empty");
@@ -818,8 +748,6 @@ void FreeRdpSessionTransport::ResetStateLocked() {
818
748
  running_ = false;
819
749
  connected_ = false;
820
750
  gdi_initialized_ = false;
821
- frames_painted_.store(0, std::memory_order_relaxed);
822
- original_end_paint_ = nullptr;
823
751
  mouse_x_ = 0;
824
752
  mouse_y_ = 0;
825
753
  session_id_.clear();
@@ -829,37 +757,6 @@ void FreeRdpSessionTransport::MarkGdiInitialized() {
829
757
  gdi_initialized_ = true;
830
758
  }
831
759
 
832
- void FreeRdpSessionTransport::HookEndPaint(rdpUpdate* update) {
833
- if (!update) {
834
- return;
835
- }
836
- original_end_paint_ = update->EndPaint;
837
- update->EndPaint = &MidsceneEndPaint;
838
- }
839
-
840
- BOOL FreeRdpSessionTransport::CallOriginalEndPaint(rdpContext* context) {
841
- if (original_end_paint_) {
842
- return original_end_paint_(context);
843
- }
844
- return TRUE;
845
- }
846
-
847
- void FreeRdpSessionTransport::MarkFramePainted() {
848
- {
849
- std::lock_guard<std::mutex> lock(frame_mutex_);
850
- frames_painted_.fetch_add(1, std::memory_order_relaxed);
851
- }
852
- frame_cv_.notify_all();
853
- }
854
-
855
- void FreeRdpSessionTransport::SignalSessionInactive() {
856
- {
857
- std::lock_guard<std::mutex> lock(frame_mutex_);
858
- session_active_.store(false, std::memory_order_relaxed);
859
- }
860
- frame_cv_.notify_all();
861
- }
862
-
863
760
  void FreeRdpSessionTransport::ClearSessionErrorLocked() {
864
761
  last_error_.reset();
865
762
  }
@@ -925,8 +822,6 @@ void FreeRdpSessionTransport::StopInstance(bool preserve_session_error) {
925
822
  }
926
823
  }
927
824
 
928
- SignalSessionInactive();
929
-
930
825
  if (should_disconnect) {
931
826
  std::lock_guard<std::mutex> lock(mutex_);
932
827
  freerdp_disconnect(instance_);
@@ -977,7 +872,6 @@ void FreeRdpSessionTransport::EventLoop() {
977
872
  std::fprintf(stderr,
978
873
  "RDP session event loop failed: freerdp_get_event_handles returned no handles\n");
979
874
  std::fflush(stderr);
980
- SignalSessionInactive();
981
875
  return;
982
876
  }
983
877
 
@@ -993,7 +887,6 @@ void FreeRdpSessionTransport::EventLoop() {
993
887
  std::fprintf(stderr,
994
888
  "RDP session event loop failed: WaitForMultipleObjects failed\n");
995
889
  std::fflush(stderr);
996
- SignalSessionInactive();
997
890
  return;
998
891
  }
999
892
 
@@ -1023,7 +916,6 @@ void FreeRdpSessionTransport::EventLoop() {
1023
916
  std::fprintf(stderr, "RDP session event loop failed: %s\n",
1024
917
  failure_reason.c_str());
1025
918
  std::fflush(stderr);
1026
- SignalSessionInactive();
1027
919
  return;
1028
920
  }
1029
921
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midscene/computer",
3
- "version": "1.9.1-beta-20260605031620.0",
3
+ "version": "1.9.1",
4
4
  "description": "Midscene.js Computer Desktop Automation",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,8 +38,8 @@
38
38
  "@computer-use/libnut": "^4.2.0",
39
39
  "clipboardy": "^4.0.0",
40
40
  "screenshot-desktop": "^1.15.3",
41
- "@midscene/core": "1.9.1-beta-20260605031620.0",
42
- "@midscene/shared": "1.9.1-beta-20260605031620.0"
41
+ "@midscene/core": "1.9.1",
42
+ "@midscene/shared": "1.9.1"
43
43
  },
44
44
  "optionalDependencies": {
45
45
  "node-mac-permissions": "2.5.0"