witbitz-code 1.9.0__tar.gz → 1.9.1__tar.gz

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 (117) hide show
  1. {witbitz_code-1.9.0/src/witbitz_code.egg-info → witbitz_code-1.9.1}/PKG-INFO +1 -1
  2. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/pyproject.toml +1 -1
  3. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/__init__.py +1 -1
  4. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/opencode_plugins/witbitz-browse-publisher.mjs +66 -7
  5. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/opencode_plugins/witbitz-browse-tree.mjs +5 -5
  6. {witbitz_code-1.9.0 → witbitz_code-1.9.1/src/witbitz_code.egg-info}/PKG-INFO +1 -1
  7. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/LICENSE +0 -0
  8. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/README.md +0 -0
  9. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/setup.cfg +0 -0
  10. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/__main__.py +0 -0
  11. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/_js.py +0 -0
  12. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/account.py +0 -0
  13. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/asks.py +0 -0
  14. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/attachments.py +0 -0
  15. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/auto.py +0 -0
  16. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/auto_runner.py +0 -0
  17. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/browse.py +0 -0
  18. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/browsetree.py +0 -0
  19. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/cli.py +0 -0
  20. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/codekeys.py +0 -0
  21. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/codetools.py +0 -0
  22. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/compress.py +0 -0
  23. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/computers.py +0 -0
  24. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/confidential.py +0 -0
  25. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/confidential_models.json +0 -0
  26. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/connector.py +0 -0
  27. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/devicelink.py +0 -0
  28. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/dirs.py +0 -0
  29. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/folders.py +0 -0
  30. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/gateway.py +0 -0
  31. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/icons/witbitz-code-wsl.ico +0 -0
  32. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/icons/witbitz-code.ico +0 -0
  33. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/images.py +0 -0
  34. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/keys.py +0 -0
  35. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/link.py +0 -0
  36. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/mkdir.py +0 -0
  37. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/models.py +0 -0
  38. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/net.py +0 -0
  39. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/offered_models.json +0 -0
  40. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/opencode_plugins/notes-init.md +0 -0
  41. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/opencode_plugins/witbitz-browse-cdp.mjs +0 -0
  42. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/opencode_plugins/witbitz-browse-local.mjs +0 -0
  43. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/opencode_plugins/witbitz-browser.js +0 -0
  44. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/opencode_plugins/witbitz-media-server.mjs +0 -0
  45. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/opencode_plugins/witbitz-notes.js +0 -0
  46. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/opencode_plugins/witbitz-progress.js +0 -0
  47. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/outputs.py +0 -0
  48. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/pair.py +0 -0
  49. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/pairings.py +0 -0
  50. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/payers.py +0 -0
  51. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/plugins.py +0 -0
  52. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/policy.py +0 -0
  53. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/ports.py +0 -0
  54. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/qr.py +0 -0
  55. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/receipt.py +0 -0
  56. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/relay.py +0 -0
  57. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/remind.py +0 -0
  58. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/seccheck.py +0 -0
  59. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/seen.py +0 -0
  60. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/selfupdate.py +0 -0
  61. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/tinfoil_read.py +0 -0
  62. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/tools_catalog.json +0 -0
  63. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/tools_probe.py +0 -0
  64. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/toolsetup.py +0 -0
  65. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/ui.py +0 -0
  66. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/ui_static/app.css +0 -0
  67. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/ui_static/app.js +0 -0
  68. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/ui_static/index.html +0 -0
  69. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/uitools.py +0 -0
  70. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/uninstall.py +0 -0
  71. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/winagent.py +0 -0
  72. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/winbg.py +0 -0
  73. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/winconsole.py +0 -0
  74. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/wizard.py +0 -0
  75. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code/wslstart.py +0 -0
  76. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code.egg-info/SOURCES.txt +0 -0
  77. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code.egg-info/dependency_links.txt +0 -0
  78. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code.egg-info/entry_points.txt +0 -0
  79. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code.egg-info/requires.txt +0 -0
  80. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/src/witbitz_code.egg-info/top_level.txt +0 -0
  81. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_asks.py +0 -0
  82. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_attachments.py +0 -0
  83. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_auto.py +0 -0
  84. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_browse.py +0 -0
  85. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_browsetree.py +0 -0
  86. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_cli.py +0 -0
  87. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_codekeys.py +0 -0
  88. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_codetools.py +0 -0
  89. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_confidential.py +0 -0
  90. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_connector_e2e.py +0 -0
  91. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_devicelink.py +0 -0
  92. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_dirs.py +0 -0
  93. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_files_and_compress.py +0 -0
  94. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_folders.py +0 -0
  95. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_images.py +0 -0
  96. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_outputs.py +0 -0
  97. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_pair_flows.py +0 -0
  98. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_plugins.py +0 -0
  99. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_policy.py +0 -0
  100. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_ports.py +0 -0
  101. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_ports_win.py +0 -0
  102. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_registry.py +0 -0
  103. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_relay_codec.py +0 -0
  104. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_remind.py +0 -0
  105. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_seccheck.py +0 -0
  106. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_selfupdate.py +0 -0
  107. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_setup.py +0 -0
  108. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_tools_probe.py +0 -0
  109. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_toolsetup.py +0 -0
  110. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_ui.py +0 -0
  111. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_uitools.py +0 -0
  112. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_uninstall.py +0 -0
  113. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_winagent.py +0 -0
  114. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_winbg.py +0 -0
  115. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_winconsole.py +0 -0
  116. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_windows_files.py +0 -0
  117. {witbitz_code-1.9.0 → witbitz_code-1.9.1}/tests/test_wslstart.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: witbitz-code
3
- Version: 1.9.0
3
+ Version: 1.9.1
4
4
  Summary: Reach OpenCode on this computer from the Witbitz Spaces Code section, through an end-to-end sealed relay.
5
5
  Author: Witbitz
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "witbitz-code"
7
- version = "1.9.0"
7
+ version = "1.9.1"
8
8
  description = "Reach OpenCode on this computer from the Witbitz Spaces Code section, through an end-to-end sealed relay."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -4,4 +4,4 @@ The Python implementation of tools/witbitz-code.mjs (docs/opencode-relay.md phas
4
4
  vectors and cross-implementation tests.
5
5
  """
6
6
 
7
- __version__ = "1.9.0"
7
+ __version__ = "1.9.1"
@@ -258,16 +258,28 @@ function createCast({ cdpHttp, onFrame, onState = () => {
258
258
  const sh = c.h + BARS(c.h);
259
259
  await onPage("Emulation.setDeviceMetricsOverride", { width: c.w, height: pageFull ? sh : c.h, deviceScaleFactor: c.dpr, mobile, screenWidth: c.w, screenHeight: sh });
260
260
  await onPage("Emulation.setTouchEmulationEnabled", mobile ? { enabled: true, maxTouchPoints: 5 } : { enabled: false });
261
- if (desktopUA) await onPage("Emulation.setUserAgentOverride", { userAgent: mobile ? phoneUA(desktopUA) : desktopUA });
261
+ if (desktopUA) await onPage("Emulation.setUserAgentOverride", uaOverride(desktopUA, await realHints(), mobile));
262
262
  } else {
263
263
  await onPage("Emulation.clearDeviceMetricsOverride").catch(() => {
264
264
  });
265
265
  await onPage("Emulation.setTouchEmulationEnabled", { enabled: false }).catch(() => {
266
266
  });
267
- if (desktopUA) await onPage("Emulation.setUserAgentOverride", { userAgent: desktopUA }).catch(() => {
267
+ if (desktopUA) await onPage("Emulation.setUserAgentOverride", uaOverride(desktopUA, await realHints(), false)).catch(() => {
268
268
  });
269
269
  }
270
270
  }
271
+ let hintsOf = null;
272
+ async function realHints() {
273
+ if (hintsOf) return hintsOf;
274
+ const r = await onPage("Runtime.evaluate", { expression: HINTS_NOW, returnByValue: true, awaitPromise: true }).catch(() => null);
275
+ const v = r && r.result && r.result.value;
276
+ if (v && Array.isArray(v.brands) && v.brands.length) hintsOf = v;
277
+ if (!hintsOf) {
278
+ const b = await send("Browser.getVersion").catch(() => null);
279
+ hintsOf = hintsFromVersion(b && b.product, desktopUA);
280
+ }
281
+ return hintsOf;
282
+ }
271
283
  async function hookFullscreen() {
272
284
  await onPage("Runtime.enable");
273
285
  await onPage("Runtime.addBinding", { name: FS_BINDING });
@@ -467,6 +479,20 @@ function norm(v) {
467
479
  return { w, h, dpr: dpr >= 1 && dpr <= 4 ? dpr : 1, mobile: !!v.mobile };
468
480
  }
469
481
  var PHONE = { w: 412, h: 915, dpr: 2, mobile: true };
482
+ var HINTS_NOW = `(async () => { const d = navigator.userAgentData; if (!d) return null; let h = {}; try { h = await d.getHighEntropyValues(['platformVersion', 'architecture', 'bitness', 'model', 'fullVersionList', 'wow64']) } catch (e) {} return { brands: d.brands, fullVersionList: h.fullVersionList || d.brands, platform: d.platform, platformVersion: h.platformVersion || '', architecture: h.architecture || '', bitness: h.bitness || '', model: h.model || '', wow64: !!h.wow64 } })()`;
483
+ function hintsFromVersion(product, ua = "") {
484
+ const full = (/\/(\d+(?:\.\d+){1,3})/.exec(String(product || "")) || [])[1];
485
+ if (!full) return null;
486
+ const major = full.split(".")[0];
487
+ const platform = /Windows/.test(ua) ? "Windows" : /Mac OS X/.test(ua) ? "macOS" : /CrOS/.test(ua) ? "Chrome OS" : "Linux";
488
+ return { brands: [{ brand: "Chromium", version: major }, { brand: "Not)A;Brand", version: "99" }], fullVersionList: [{ brand: "Chromium", version: full }, { brand: "Not)A;Brand", version: "99.0.0.0" }], platform, platformVersion: "", architecture: /arm|aarch64/i.test(ua) ? "arm" : "x86", bitness: "64", model: "", wow64: false };
489
+ }
490
+ function uaOverride(desktop, real, mobile) {
491
+ const userAgent = mobile ? phoneUA(desktop) : desktop;
492
+ if (!real || !Array.isArray(real.brands) || !real.brands.length) return { userAgent };
493
+ const meta = { brands: real.brands, fullVersionList: real.fullVersionList || real.brands, platform: real.platform || "", platformVersion: real.platformVersion || "", architecture: real.architecture || "", model: real.model || "", mobile: false, bitness: real.bitness || "", wow64: !!real.wow64 };
494
+ return mobile ? { userAgent, platform: "Linux armv8l", userAgentMetadata: { ...meta, platform: "Android", platformVersion: "14.0.0", architecture: "", bitness: "", model: "Pixel 8", mobile: true, wow64: false } } : { userAgent, userAgentMetadata: meta };
495
+ }
470
496
  function phoneUA(desktop) {
471
497
  return desktop.replace(/\([^)]*\)/, "(Linux; Android 14; Pixel 8)").replace(/ Safari\//, " Mobile Safari/");
472
498
  }
@@ -476,6 +502,7 @@ var BINDING = "__wbm";
476
502
  var MAX_BATCH = 8 << 20;
477
503
  var MAX_SINCE_SNAPSHOT = 48 << 20;
478
504
  var ASSET_CACHE = 96 << 20;
505
+ var MAX_ANSWER = 2900 << 10;
479
506
  var MAX_SIDE2 = 1600;
480
507
  var STILL_MS = 500;
481
508
  var STILL_SIDE = 480;
@@ -607,12 +634,19 @@ function createMirrors({ liveHttp, mirrorHttp, rrwebUmd, onFrame, log: log2 = ()
607
634
  for (const h of c.handlers) h(m);
608
635
  };
609
636
  ws.onclose = () => {
637
+ c.closed = true;
638
+ log2("mirror: the CDP connection to", http, "closed");
610
639
  for (const p of c.pending.values()) p.reject(new Error("cdp: closed"));
611
640
  c.pending.clear();
612
641
  };
613
642
  return c;
614
643
  }
615
644
  async function attachLive() {
645
+ if (live && live.closed) {
646
+ live = null;
647
+ liveSid = null;
648
+ liveTargetId = null;
649
+ }
616
650
  const t = liveTarget();
617
651
  if (!t || t === liveTargetId) return;
618
652
  if (!live) {
@@ -698,8 +732,14 @@ function createMirrors({ liveHttp, mirrorHttp, rrwebUmd, onFrame, log: log2 = ()
698
732
  body: body ? Buffer.from(body).toString("base64") : ""
699
733
  }, tab.sid).catch(() => {
700
734
  });
735
+ const tooBig = (b) => b && Buffer.byteLength(b) > MAX_ANSWER;
736
+ const send = (status, headers, body) => tooBig(body) ? (tab.refused++, log2("mirror: not sent,", Math.round(Buffer.byteLength(body) / 1024), "KB \u2014", url.slice(0, 100)), done(404, {}, "")) : done(status, headers, body);
701
737
  if (url === "http://mirror.invalid/") return done(200, { "content-type": "text/html; charset=utf-8" }, shell);
702
738
  if (p.request.method !== "GET" || !/^https?:\/\//.test(url)) return done(404, {}, "");
739
+ if (p.resourceType === "Media") {
740
+ tab.refused++;
741
+ return done(404, {}, "");
742
+ }
703
743
  if (p.resourceType === "Document") {
704
744
  let host = "";
705
745
  try {
@@ -714,14 +754,14 @@ function createMirrors({ liveHttp, mirrorHttp, rrwebUmd, onFrame, log: log2 = ()
714
754
  try {
715
755
  const r = await live.send("Network.getResponseBody", { requestId: known.requestId }, liveSid);
716
756
  tab.served++;
717
- return done(known.status || 200, { "content-type": known.mime || "application/octet-stream" }, r.base64Encoded ? Buffer.from(r.body, "base64") : r.body);
757
+ return send(known.status || 200, { "content-type": known.mime || "application/octet-stream" }, r.base64Encoded ? Buffer.from(r.body, "base64") : r.body);
718
758
  } catch {
719
759
  }
720
760
  }
721
761
  if (assets.has(url)) {
722
762
  tab.served++;
723
763
  const a = assets.get(url);
724
- return done(a.status, a.headers, a.body);
764
+ return send(a.status, a.headers, a.body);
725
765
  }
726
766
  if (!STATIC.has(p.resourceType) || !liveSid) {
727
767
  tab.refused++;
@@ -730,7 +770,7 @@ function createMirrors({ liveHttp, mirrorHttp, rrwebUmd, onFrame, log: log2 = ()
730
770
  try {
731
771
  const a = await loadCredentialless(url);
732
772
  tab.loaded++;
733
- return done(a.status, a.headers, a.body);
773
+ return send(a.status, a.headers, a.body);
734
774
  } catch (e) {
735
775
  tab.refused++;
736
776
  log2("mirror: could not load", url.slice(0, 100), "\u2014", String(e.message || e).slice(0, 120));
@@ -816,7 +856,7 @@ function createMirrors({ liveHttp, mirrorHttp, rrwebUmd, onFrame, log: log2 = ()
816
856
  });
817
857
  }
818
858
  async function open2(stream, shape) {
819
- if (!mirror) {
859
+ if (!mirror || mirror.closed) {
820
860
  mirror = await connect(mirrorHttp);
821
861
  mirror.handlers.push(onMirror);
822
862
  }
@@ -881,6 +921,10 @@ function createMirrors({ liveHttp, mirrorHttp, rrwebUmd, onFrame, log: log2 = ()
881
921
  /** Make the set of mirrors equal `wanted` (stream → shape). Opens, reshapes and closes as needed. */
882
922
  async set(wanted) {
883
923
  await attachLive();
924
+ if (mirror && mirror.closed) {
925
+ mirror = null;
926
+ tabs.clear();
927
+ }
884
928
  for (const [stream] of tabs) if (!wanted.has(stream)) await close(stream);
885
929
  for (const [stream, shape] of wanted) {
886
930
  const tab = tabs.get(stream);
@@ -1225,7 +1269,22 @@ async function assignNow() {
1225
1269
  } catch {
1226
1270
  }
1227
1271
  }
1228
- if (mirrors) await mirrors.set(wanted);
1272
+ if (!mirrors) return;
1273
+ try {
1274
+ await mirrors.set(wanted);
1275
+ } catch (e) {
1276
+ const why = "mirror could not open: " + String(e.message || e).slice(0, 80);
1277
+ for (const [vid, s] of assigned) {
1278
+ if (!wanted.has(s)) continue;
1279
+ assigned.set(vid, "live");
1280
+ if (relay && relay.readyState === 1) relay.send(await sealCtl(key, { wb: "stream", vid, stream: "live", why }));
1281
+ }
1282
+ const l = cast && cast.last();
1283
+ if (l) outOrder(async () => {
1284
+ if (relay && relay.readyState === 1) relay.send(await seal(key, KIND_FRAME, packFrame(l.header, l.jpeg)));
1285
+ });
1286
+ throw e;
1287
+ }
1229
1288
  }
1230
1289
  async function startCast() {
1231
1290
  const c = ensureCast();
@@ -4,14 +4,14 @@
4
4
  // tools/browse-tree/pin.json
5
5
  var pin_default = {
6
6
  _: "THE CLOUD COMPUTER'S BROWSER FOR LINUX that this release installs (tools/browse-tree; make.sh writes it). The files are public at <base><tag>/; both sha256s are checked before anything is unpacked.",
7
- tag: "p2v",
7
+ tag: "p2x",
8
8
  base: "https://drwev5vxt2t2e.cloudfront.net/browse-tree/",
9
- pcr0: "87162d8648af94daec37f9d022c43546f6dc5c9018b7225ee5ccaf3cecd1c7924c7681f0ca48fddb84f5d0a2f987f719",
10
- commit: "e303d54e2295c148c5177b2216eca21de6b6f3a3",
9
+ pcr0: "050541844610fd5ed4b586259906d9219edbabc4445ed7943885ac737ee4918e144af2e49838a8313f5823184bc503cf",
10
+ commit: "235ef2b815ef74b46e954f48f860197d8d2b612c",
11
11
  tree: {
12
12
  file: "tree.tar.zst",
13
- sha256: "1fceee1d2ddbda8a6ec9f792755a960a877af6342645b8a29fbbf94b28b9536e",
14
- size: 664712218
13
+ sha256: "839b7cc06c70946a4912578115e6cd053cb6b2811cc458457e012ece885b36b6",
14
+ size: 664701891
15
15
  },
16
16
  lab: {
17
17
  file: "ccvm-lab.bin",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: witbitz-code
3
- Version: 1.9.0
3
+ Version: 1.9.1
4
4
  Summary: Reach OpenCode on this computer from the Witbitz Spaces Code section, through an end-to-end sealed relay.
5
5
  Author: Witbitz
6
6
  License-Expression: MIT
File without changes
File without changes
File without changes