synabun 2026.4.26-beta → 2026.4.26-beta.10

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.
package/CHANGELOG.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Raw internal changelogs are archived in [changelog/](changelog/).
4
4
 
5
- ## 2026-04-26.beta-1
5
+ ## 2026-04-25
6
6
 
7
7
  ### Added — Dedicated Schedules Studio
8
8
  - **Standalone schedule window** — Added `neural-interface/public/shared/ui-schedules-studio.js` and initialized it from both `neural-interface/public/variant/2d/main.js` and `neural-interface/public/variant/3d/main.js`. The new window opens from `automations:open-schedules` and keeps schedule management out of the Automation Studio detail pane.
@@ -399,8 +399,8 @@ let _cliInstallFailureForced = false;
399
399
  function ensureCliBannerEl() {
400
400
  if (!_panel) return null;
401
401
  const container = panelEl('#cxp-messages-container');
402
- if (!container) return null;
403
- let banner = container.querySelector(':scope > .cxp-cli-banner');
402
+ if (!container || !container.parentNode) return null;
403
+ let banner = container.parentNode.querySelector(':scope > .cxp-cli-banner');
404
404
  if (banner) return banner;
405
405
  const label = getCliLabel('codex');
406
406
  const cmd = getCliInstallCommand('codex');
@@ -418,7 +418,7 @@ function ensureCliBannerEl() {
418
418
  <button class="cxp-cli-banner-recheck" type="button">Re-check</button>
419
419
  </div>
420
420
  `;
421
- container.insertBefore(banner, container.firstChild);
421
+ container.parentNode.insertBefore(banner, container);
422
422
  const btn = banner.querySelector('.cxp-cli-banner-recheck');
423
423
  btn?.addEventListener('click', async () => {
424
424
  btn.disabled = true;
@@ -437,7 +437,7 @@ function ensureCliBannerEl() {
437
437
  function removeCliBannerEl() {
438
438
  if (!_panel) return;
439
439
  const container = panelEl('#cxp-messages-container');
440
- const banner = container?.querySelector(':scope > .cxp-cli-banner');
440
+ const banner = container?.parentNode?.querySelector(':scope > .cxp-cli-banner');
441
441
  banner?.remove();
442
442
  }
443
443
 
@@ -990,7 +990,7 @@ export function injectStyles() {
990
990
  grid-template-columns: auto 1fr auto;
991
991
  gap: 10px;
992
992
  align-items: center;
993
- margin: 8px 12px 0;
993
+ margin: 6px 8px 0;
994
994
  padding: 10px 12px;
995
995
  border: 1px solid rgba(255,180,80,0.45);
996
996
  border-radius: 8px;
@@ -1526,8 +1526,8 @@ let _cliInstallFailureForced = false;
1526
1526
  function ensureCliBannerEl() {
1527
1527
  if (!_panel) return null;
1528
1528
  const container = _panel.querySelector('.ocp-messages-container');
1529
- if (!container) return null;
1530
- let banner = container.querySelector(':scope > .ocp-cli-banner');
1529
+ if (!container || !container.parentNode) return null;
1530
+ let banner = container.parentNode.querySelector(':scope > .ocp-cli-banner');
1531
1531
  if (banner) return banner;
1532
1532
  const label = getCliLabel('opencode');
1533
1533
  const cmd = getCliInstallCommand('opencode');
@@ -1545,7 +1545,7 @@ function ensureCliBannerEl() {
1545
1545
  <button class="ocp-cli-banner-recheck" type="button">Re-check</button>
1546
1546
  </div>
1547
1547
  `;
1548
- container.insertBefore(banner, container.firstChild);
1548
+ container.parentNode.insertBefore(banner, container);
1549
1549
  const btn = banner.querySelector('.ocp-cli-banner-recheck');
1550
1550
  btn?.addEventListener('click', async () => {
1551
1551
  btn.disabled = true;
@@ -1563,7 +1563,8 @@ function ensureCliBannerEl() {
1563
1563
 
1564
1564
  function removeCliBannerEl() {
1565
1565
  if (!_panel) return;
1566
- const banner = _panel.querySelector('.ocp-messages-container > .ocp-cli-banner');
1566
+ const container = _panel.querySelector('.ocp-messages-container');
1567
+ const banner = container?.parentNode?.querySelector(':scope > .ocp-cli-banner');
1567
1568
  banner?.remove();
1568
1569
  }
1569
1570
 
@@ -1527,7 +1527,7 @@ export function injectStyles() {
1527
1527
  grid-template-columns: auto 1fr auto;
1528
1528
  gap: 10px;
1529
1529
  align-items: center;
1530
- margin: 8px 12px 0;
1530
+ margin: 6px 8px 0;
1531
1531
  padding: 10px 12px;
1532
1532
  border: 1px solid rgba(255,180,80,0.45);
1533
1533
  border-radius: 8px;
@@ -19449,150 +19449,150 @@
19449
19449
  }
19450
19450
  .sched-sidebar-new:hover { background: rgba(255,255,255,0.07); color: var(--t-bright); }
19451
19451
  .sched-sidebar-empty { color: var(--t-muted); font-size: 11px; padding: 8px 6px; }
19452
- .sched-sidebar-prompt {
19453
- margin-top: auto; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
19454
- border: 1px solid rgba(255,255,255,0.09); border-radius: 8px;
19455
- background: rgba(255,255,255,0.04);
19456
- color: var(--t-secondary); min-height: 34px; cursor: pointer; font-family: inherit;
19457
- font-size: 12px; font-weight: 600; letter-spacing: 0;
19458
- box-shadow: var(--shadow-highlight);
19459
- transition: border-color 160ms ease, color 160ms ease, background 160ms ease, transform 120ms ease;
19460
- }
19461
- .sched-sidebar-prompt:hover {
19462
- background: rgba(255,255,255,0.075);
19463
- border-color: rgba(255,255,255,0.14);
19464
- color: var(--t-bright);
19465
- transform: translateY(-1px);
19466
- }
19467
- .sched-sidebar-prompt svg { width: 13px; height: 13px; color: var(--t-muted); }
19468
-
19469
- .sched-prompt-backdrop {
19470
- position: fixed; inset: 0; background: rgba(5,7,12,0.58);
19471
- backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px);
19472
- z-index: 300010; opacity: 0; transition: opacity 160ms ease-out;
19473
- pointer-events: auto;
19474
- }
19475
- .sched-prompt-backdrop.open { opacity: 1; }
19476
- .sched-prompt-modal {
19477
- position: fixed; left: 50%; top: 50%; transform: translate(-50%, -52%) scale(0.98);
19478
- width: min(512px, calc(100vw - 32px)); padding: 0;
19479
- border-radius: 12px; z-index: 300011;
19480
- opacity: 0; transition: opacity 160ms ease-out, transform 200ms ease-out;
19481
- background:
19482
- linear-gradient(to bottom, rgba(255,255,255,0.035), rgba(255,255,255,0.01)),
19483
- rgba(13,15,20,0.96);
19484
- border: 1px solid rgba(255,255,255,0.085);
19485
- box-shadow: 0 22px 64px rgba(0,0,0,0.58), var(--shadow-highlight);
19486
- overflow: hidden;
19487
- }
19488
- .sched-prompt-modal.open { opacity: 1; transform: translate(-50%, -50%) scale(1); }
19489
- .sched-prompt-head {
19490
- display: flex; align-items: center; justify-content: space-between; gap: 12px;
19491
- padding: 15px 16px 13px;
19492
- border-bottom: 1px solid rgba(255,255,255,0.055);
19493
- }
19494
- .sched-prompt-head-text {
19495
- display: flex; align-items: center; gap: 10px; min-width: 0;
19496
- }
19497
- .sched-prompt-icon {
19498
- display: inline-flex; align-items: center; justify-content: center;
19499
- width: 30px; height: 30px; border-radius: 8px; flex: 0 0 auto;
19500
- background: rgba(255,255,255,0.055);
19501
- border: 1px solid rgba(255,255,255,0.075);
19502
- color: var(--t-secondary);
19503
- box-shadow: var(--shadow-highlight);
19504
- }
19505
- .sched-prompt-icon svg { width: 14px; height: 14px; }
19506
- .sched-prompt-head h3 {
19507
- margin: 0; font-family: var(--ff-heading); font-size: 14px; font-weight: 650;
19508
- color: var(--t-bright); letter-spacing: 0;
19509
- }
19510
- .sched-prompt-head p {
19511
- margin: 2px 0 0; font-size: 11.5px; line-height: 1.35; color: var(--t-muted);
19512
- }
19513
- .sched-prompt-close {
19514
- display: inline-flex; align-items: center; justify-content: center;
19515
- width: 28px; height: 28px; flex: 0 0 auto;
19516
- background: transparent; border: 1px solid transparent; border-radius: 7px;
19517
- color: var(--t-muted); cursor: pointer; padding: 0;
19518
- transition: background 150ms ease, border-color 150ms ease, color 150ms ease;
19519
- }
19520
- .sched-prompt-close:hover {
19521
- background: rgba(255,255,255,0.055);
19522
- border-color: rgba(255,255,255,0.075);
19523
- color: var(--t-bright);
19524
- }
19525
- .sched-prompt-close svg { width: 14px; height: 14px; }
19526
- .sched-prompt-tiles {
19527
- display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px;
19528
- padding: 14px 16px 16px;
19529
- }
19530
- @media (max-width: 560px) { .sched-prompt-tiles { grid-template-columns: 1fr; } }
19531
- .sched-prompt-tile {
19532
- position: relative; display: grid; grid-template-columns: 32px minmax(0, 1fr);
19533
- grid-template-areas: "logo pill" "body body"; align-content: start; gap: 10px 8px;
19534
- min-height: 96px; padding: 12px; border-radius: 10px; cursor: pointer; font-family: inherit;
19535
- background: rgba(255,255,255,0.032);
19536
- border: 1px solid rgba(255,255,255,0.065);
19537
- color: var(--t-secondary); text-align: left;
19538
- backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
19539
- transition: background 180ms ease, border-color 180ms ease, transform 160ms ease, box-shadow 180ms ease;
19540
- overflow: hidden;
19541
- }
19542
- .sched-prompt-tile:not(.disabled) {
19543
- background: rgba(255,255,255,0.045);
19544
- border-color: rgba(255,255,255,0.095);
19545
- box-shadow: var(--shadow-highlight);
19546
- }
19547
- .sched-prompt-tile:not(.disabled):hover {
19548
- background: rgba(255,255,255,0.065);
19549
- border-color: rgba(255,255,255,0.13);
19550
- color: var(--t-bright); transform: translateY(-1px);
19551
- box-shadow: var(--shadow-xs), var(--shadow-highlight);
19552
- }
19553
- .sched-prompt-tile:not(.disabled):active { transform: translateY(0); }
19554
- .sched-prompt-tile:focus-visible {
19555
- outline: none;
19556
- border-color: rgba(255,255,255,0.18);
19557
- box-shadow: 0 0 0 2px rgba(255,255,255,0.14), var(--shadow-highlight);
19558
- }
19559
- .sched-prompt-tile.disabled { opacity: 0.58; cursor: not-allowed; pointer-events: none; }
19560
- .sched-prompt-tile-logo {
19561
- grid-area: logo;
19562
- display: inline-flex; align-items: center; justify-content: center;
19563
- width: 32px; height: 32px; border-radius: 8px;
19564
- background: rgba(255,255,255,0.045);
19565
- border: 1px solid rgba(255,255,255,0.075);
19566
- color: color-mix(in srgb, var(--provider-color, #fff) 62%, var(--t-secondary));
19567
- box-shadow: var(--shadow-highlight);
19568
- }
19569
- .sched-prompt-tile-logo svg { width: 16px; height: 16px; display: block; }
19570
- .sched-prompt-tile-body {
19571
- grid-area: body; display: flex; flex-direction: column; gap: 2px; min-width: 0;
19572
- }
19573
- .sched-prompt-tile-title {
19574
- font-size: 12.5px; font-weight: 650; color: var(--t-secondary); letter-spacing: 0;
19575
- line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
19576
- }
19577
- .sched-prompt-tile:not(.disabled) .sched-prompt-tile-title {
19578
- color: color-mix(in srgb, var(--provider-color, #fff) 56%, var(--t-bright));
19579
- }
19580
- .sched-prompt-tile-sub {
19581
- font-size: 10.5px; color: var(--t-muted); letter-spacing: 0; line-height: 1.2;
19582
- white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
19583
- }
19584
- .sched-prompt-pill {
19585
- grid-area: pill; justify-self: end; align-self: start;
19586
- font-size: 10px; font-weight: 600; letter-spacing: 0;
19587
- padding: 2px 6px; border-radius: var(--r-pill);
19588
- background: rgba(255,255,255,0.045); color: var(--t-muted);
19589
- border: 1px solid rgba(255,255,255,0.06);
19590
- }
19591
- .sched-prompt-pill--active {
19592
- background: rgba(255,255,255,0.075);
19593
- border-color: rgba(255,255,255,0.12);
19594
- color: var(--t-secondary);
19595
- }
19452
+ .sched-sidebar-prompt {
19453
+ margin-top: auto; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
19454
+ border: 1px solid rgba(255,255,255,0.09); border-radius: 8px;
19455
+ background: rgba(255,255,255,0.04);
19456
+ color: var(--t-secondary); min-height: 34px; cursor: pointer; font-family: inherit;
19457
+ font-size: 12px; font-weight: 600; letter-spacing: 0;
19458
+ box-shadow: var(--shadow-highlight);
19459
+ transition: border-color 160ms ease, color 160ms ease, background 160ms ease, transform 120ms ease;
19460
+ }
19461
+ .sched-sidebar-prompt:hover {
19462
+ background: rgba(255,255,255,0.075);
19463
+ border-color: rgba(255,255,255,0.14);
19464
+ color: var(--t-bright);
19465
+ transform: translateY(-1px);
19466
+ }
19467
+ .sched-sidebar-prompt svg { width: 13px; height: 13px; color: var(--t-muted); }
19468
+
19469
+ .sched-prompt-backdrop {
19470
+ position: fixed; inset: 0; background: rgba(5,7,12,0.58);
19471
+ backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px);
19472
+ z-index: 300010; opacity: 0; transition: opacity 160ms ease-out;
19473
+ pointer-events: auto;
19474
+ }
19475
+ .sched-prompt-backdrop.open { opacity: 1; }
19476
+ .sched-prompt-modal {
19477
+ position: fixed; left: 50%; top: 50%; transform: translate(-50%, -52%) scale(0.98);
19478
+ width: min(512px, calc(100vw - 32px)); padding: 0;
19479
+ border-radius: 12px; z-index: 300011;
19480
+ opacity: 0; transition: opacity 160ms ease-out, transform 200ms ease-out;
19481
+ background:
19482
+ linear-gradient(to bottom, rgba(255,255,255,0.035), rgba(255,255,255,0.01)),
19483
+ rgba(13,15,20,0.96);
19484
+ border: 1px solid rgba(255,255,255,0.085);
19485
+ box-shadow: 0 22px 64px rgba(0,0,0,0.58), var(--shadow-highlight);
19486
+ overflow: hidden;
19487
+ }
19488
+ .sched-prompt-modal.open { opacity: 1; transform: translate(-50%, -50%) scale(1); }
19489
+ .sched-prompt-head {
19490
+ display: flex; align-items: center; justify-content: space-between; gap: 12px;
19491
+ padding: 15px 16px 13px;
19492
+ border-bottom: 1px solid rgba(255,255,255,0.055);
19493
+ }
19494
+ .sched-prompt-head-text {
19495
+ display: flex; align-items: center; gap: 10px; min-width: 0;
19496
+ }
19497
+ .sched-prompt-icon {
19498
+ display: inline-flex; align-items: center; justify-content: center;
19499
+ width: 30px; height: 30px; border-radius: 8px; flex: 0 0 auto;
19500
+ background: rgba(255,255,255,0.055);
19501
+ border: 1px solid rgba(255,255,255,0.075);
19502
+ color: var(--t-secondary);
19503
+ box-shadow: var(--shadow-highlight);
19504
+ }
19505
+ .sched-prompt-icon svg { width: 14px; height: 14px; }
19506
+ .sched-prompt-head h3 {
19507
+ margin: 0; font-family: var(--ff-heading); font-size: 14px; font-weight: 650;
19508
+ color: var(--t-bright); letter-spacing: 0;
19509
+ }
19510
+ .sched-prompt-head p {
19511
+ margin: 2px 0 0; font-size: 11.5px; line-height: 1.35; color: var(--t-muted);
19512
+ }
19513
+ .sched-prompt-close {
19514
+ display: inline-flex; align-items: center; justify-content: center;
19515
+ width: 28px; height: 28px; flex: 0 0 auto;
19516
+ background: transparent; border: 1px solid transparent; border-radius: 7px;
19517
+ color: var(--t-muted); cursor: pointer; padding: 0;
19518
+ transition: background 150ms ease, border-color 150ms ease, color 150ms ease;
19519
+ }
19520
+ .sched-prompt-close:hover {
19521
+ background: rgba(255,255,255,0.055);
19522
+ border-color: rgba(255,255,255,0.075);
19523
+ color: var(--t-bright);
19524
+ }
19525
+ .sched-prompt-close svg { width: 14px; height: 14px; }
19526
+ .sched-prompt-tiles {
19527
+ display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px;
19528
+ padding: 14px 16px 16px;
19529
+ }
19530
+ @media (max-width: 560px) { .sched-prompt-tiles { grid-template-columns: 1fr; } }
19531
+ .sched-prompt-tile {
19532
+ position: relative; display: grid; grid-template-columns: 32px minmax(0, 1fr);
19533
+ grid-template-areas: "logo pill" "body body"; align-content: start; gap: 10px 8px;
19534
+ min-height: 96px; padding: 12px; border-radius: 10px; cursor: pointer; font-family: inherit;
19535
+ background: rgba(255,255,255,0.032);
19536
+ border: 1px solid rgba(255,255,255,0.065);
19537
+ color: var(--t-secondary); text-align: left;
19538
+ backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
19539
+ transition: background 180ms ease, border-color 180ms ease, transform 160ms ease, box-shadow 180ms ease;
19540
+ overflow: hidden;
19541
+ }
19542
+ .sched-prompt-tile:not(.disabled) {
19543
+ background: rgba(255,255,255,0.045);
19544
+ border-color: rgba(255,255,255,0.095);
19545
+ box-shadow: var(--shadow-highlight);
19546
+ }
19547
+ .sched-prompt-tile:not(.disabled):hover {
19548
+ background: rgba(255,255,255,0.065);
19549
+ border-color: rgba(255,255,255,0.13);
19550
+ color: var(--t-bright); transform: translateY(-1px);
19551
+ box-shadow: var(--shadow-xs), var(--shadow-highlight);
19552
+ }
19553
+ .sched-prompt-tile:not(.disabled):active { transform: translateY(0); }
19554
+ .sched-prompt-tile:focus-visible {
19555
+ outline: none;
19556
+ border-color: rgba(255,255,255,0.18);
19557
+ box-shadow: 0 0 0 2px rgba(255,255,255,0.14), var(--shadow-highlight);
19558
+ }
19559
+ .sched-prompt-tile.disabled { opacity: 0.58; cursor: not-allowed; pointer-events: none; }
19560
+ .sched-prompt-tile-logo {
19561
+ grid-area: logo;
19562
+ display: inline-flex; align-items: center; justify-content: center;
19563
+ width: 32px; height: 32px; border-radius: 8px;
19564
+ background: rgba(255,255,255,0.045);
19565
+ border: 1px solid rgba(255,255,255,0.075);
19566
+ color: color-mix(in srgb, var(--provider-color, #fff) 62%, var(--t-secondary));
19567
+ box-shadow: var(--shadow-highlight);
19568
+ }
19569
+ .sched-prompt-tile-logo svg { width: 16px; height: 16px; display: block; }
19570
+ .sched-prompt-tile-body {
19571
+ grid-area: body; display: flex; flex-direction: column; gap: 2px; min-width: 0;
19572
+ }
19573
+ .sched-prompt-tile-title {
19574
+ font-size: 12.5px; font-weight: 650; color: var(--t-secondary); letter-spacing: 0;
19575
+ line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
19576
+ }
19577
+ .sched-prompt-tile:not(.disabled) .sched-prompt-tile-title {
19578
+ color: color-mix(in srgb, var(--provider-color, #fff) 56%, var(--t-bright));
19579
+ }
19580
+ .sched-prompt-tile-sub {
19581
+ font-size: 10.5px; color: var(--t-muted); letter-spacing: 0; line-height: 1.2;
19582
+ white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
19583
+ }
19584
+ .sched-prompt-pill {
19585
+ grid-area: pill; justify-self: end; align-self: start;
19586
+ font-size: 10px; font-weight: 600; letter-spacing: 0;
19587
+ padding: 2px 6px; border-radius: var(--r-pill);
19588
+ background: rgba(255,255,255,0.045); color: var(--t-muted);
19589
+ border: 1px solid rgba(255,255,255,0.06);
19590
+ }
19591
+ .sched-prompt-pill--active {
19592
+ background: rgba(255,255,255,0.075);
19593
+ border-color: rgba(255,255,255,0.12);
19594
+ color: var(--t-secondary);
19595
+ }
19596
19596
 
19597
19597
  .sched-main { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
19598
19598
  .sched-tabs {
@@ -24315,3 +24315,73 @@
24315
24315
  .ig-lb-prev { left: 16px; }
24316
24316
  .ig-lb-next { right: 16px; }
24317
24317
 
24318
+ /* ── Update-check toast (Apps > Check for updates) ── */
24319
+ .update-check-toast {
24320
+ position: fixed;
24321
+ right: 20px;
24322
+ bottom: 80px;
24323
+ z-index: 300050;
24324
+ display: flex;
24325
+ gap: 12px;
24326
+ align-items: flex-start;
24327
+ min-width: 240px;
24328
+ max-width: 360px;
24329
+ padding: 12px 14px;
24330
+ border-radius: 14px;
24331
+ background: rgba(20, 20, 24, 0.85);
24332
+ backdrop-filter: blur(20px) saturate(160%);
24333
+ -webkit-backdrop-filter: blur(20px) saturate(160%);
24334
+ border: 1px solid rgba(255, 255, 255, 0.08);
24335
+ color: var(--t-text);
24336
+ font-size: 12px;
24337
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
24338
+ opacity: 0;
24339
+ transform: translateY(8px);
24340
+ transition: opacity 0.25s ease, transform 0.25s ease, background 0.15s ease;
24341
+ pointer-events: auto;
24342
+ }
24343
+ .update-check-toast.show { opacity: 1; transform: translateY(0); }
24344
+ .update-check-toast--clickable { cursor: pointer; }
24345
+ .update-check-toast--clickable:hover { background: rgba(28, 28, 32, 0.92); }
24346
+ .update-check-toast .utc-icon {
24347
+ width: 24px; height: 24px;
24348
+ border-radius: 50%;
24349
+ display: flex; align-items: center; justify-content: center;
24350
+ font-weight: 700; font-size: 14px;
24351
+ flex-shrink: 0;
24352
+ }
24353
+ .update-check-toast .utc-icon--up { background: rgba(52, 199, 89, 0.18); color: #34c759; }
24354
+ .update-check-toast .utc-icon--ok { background: rgba(52, 199, 89, 0.18); color: #34c759; }
24355
+ .update-check-toast .utc-icon--err { background: rgba(255, 69, 58, 0.18); color: #ff453a; }
24356
+ .update-check-toast .utc-body { flex: 1; min-width: 0; }
24357
+ .update-check-toast .utc-title { font-weight: 600; margin-bottom: 4px; }
24358
+ .update-check-toast .utc-list { list-style: none; margin: 0; padding: 0; }
24359
+ .update-check-toast .utc-list li { padding: 2px 0; color: var(--t-muted); }
24360
+ .update-check-toast .utc-list li .utc-src {
24361
+ display: inline-block;
24362
+ padding: 1px 6px;
24363
+ margin-left: 6px;
24364
+ border-radius: 6px;
24365
+ font-size: 10px;
24366
+ background: rgba(255, 255, 255, 0.08);
24367
+ color: var(--t-text);
24368
+ }
24369
+ .update-check-toast .utc-sub { color: var(--t-muted); }
24370
+ .update-check-toast .utc-hint { color: var(--t-muted); opacity: 0.7; margin-top: 6px; font-size: 11px; }
24371
+
24372
+ .update-channel-pill {
24373
+ display: inline-block;
24374
+ padding: 2px 8px;
24375
+ margin-left: 8px;
24376
+ font-size: 10px;
24377
+ font-weight: 600;
24378
+ letter-spacing: 0.04em;
24379
+ text-transform: uppercase;
24380
+ border-radius: 6px;
24381
+ vertical-align: middle;
24382
+ background: rgba(255, 159, 10, 0.18);
24383
+ color: #ff9f0a;
24384
+ }
24385
+ .update-channel-pill--beta { background: rgba(255, 159, 10, 0.18); color: #ff9f0a; }
24386
+
24387
+
@@ -439,7 +439,7 @@ function injectStyles() {
439
439
  grid-template-columns: auto 1fr auto;
440
440
  gap: 10px;
441
441
  align-items: center;
442
- margin: 8px 12px 0;
442
+ margin: 6px 8px 0;
443
443
  padding: 10px 12px;
444
444
  border: 1px solid rgba(255,180,80,0.45);
445
445
  border-radius: 8px;
@@ -7331,8 +7331,8 @@ let _cliInstallFailureForced = false;
7331
7331
  function _ensureCliBannerEl() {
7332
7332
  if (!_panel) return null;
7333
7333
  const container = _panel.querySelector('#cp-messages-container');
7334
- if (!container) return null;
7335
- let banner = container.querySelector(':scope > .cp-cli-banner');
7334
+ if (!container || !container.parentNode) return null;
7335
+ let banner = container.parentNode.querySelector(':scope > .cp-cli-banner');
7336
7336
  if (banner) return banner;
7337
7337
  const label = getCliLabel('claude-code');
7338
7338
  const cmd = getCliInstallCommand('claude-code');
@@ -7350,7 +7350,7 @@ function _ensureCliBannerEl() {
7350
7350
  <button class="cp-cli-banner-recheck" type="button">Re-check</button>
7351
7351
  </div>
7352
7352
  `;
7353
- container.insertBefore(banner, container.firstChild);
7353
+ container.parentNode.insertBefore(banner, container);
7354
7354
  const btn = banner.querySelector('.cp-cli-banner-recheck');
7355
7355
  btn?.addEventListener('click', async () => {
7356
7356
  btn.disabled = true;
@@ -7368,7 +7368,7 @@ function _ensureCliBannerEl() {
7368
7368
 
7369
7369
  function _removeCliBannerEl() {
7370
7370
  if (!_panel) return;
7371
- const banner = _panel.querySelector('#cp-messages-container > .cp-cli-banner');
7371
+ const banner = _panel.querySelector(':scope > .cp-cli-banner');
7372
7372
  banner?.remove();
7373
7373
  }
7374
7374
 
@@ -12,7 +12,8 @@ import { openHelp } from './ui-help.js';
12
12
  import { registerAction } from './ui-keybinds.js';
13
13
  import { isGuest, hasPermission } from './ui-sync.js';
14
14
  import { sendToPanel } from './ui-claude-panel.js';
15
- import { forceCheckToolUpdates } from './ui-tool-updates.js';
15
+ import { forceCheckToolUpdates, showUpdateToast, TOOL_LABELS } from './ui-tool-updates.js';
16
+ import { forceCheckSynabunUpdate, openSynabunUpdateModal } from './ui-update.js';
16
17
 
17
18
  const $ = (id) => document.getElementById(id);
18
19
 
@@ -127,12 +128,12 @@ export function initMenubar() {
127
128
  'menu-open-skills-studio': 'skills',
128
129
  'menu-skills-new': 'skills',
129
130
  'menu-skills-import': 'skills',
130
- 'menu-open-automation-studio': 'automations',
131
- 'menu-automations-schedule-new': 'automations',
132
- 'menu-automations-quick-timer': 'automations',
133
- 'menu-automations-schedule-groups': 'automations',
134
- 'menu-automations-new': 'automations',
135
- 'menu-automations-import': 'automations',
131
+ 'menu-open-automation-studio': 'automations',
132
+ 'menu-automations-schedule-new': 'automations',
133
+ 'menu-automations-quick-timer': 'automations',
134
+ 'menu-automations-schedule-groups': 'automations',
135
+ 'menu-automations-new': 'automations',
136
+ 'menu-automations-import': 'automations',
136
137
  'menu-terminal-claude': 'terminal',
137
138
  'menu-terminal-codex': 'terminal',
138
139
  'menu-terminal-gemini': 'terminal',
@@ -316,34 +317,34 @@ function wireAutomationsMenu() {
316
317
  emit('automations:open');
317
318
  });
318
319
  }
319
- const schedulesItem = $('menu-automations-schedules');
320
- if (schedulesItem) {
321
- schedulesItem.addEventListener('click', () => {
322
- closeAll();
323
- emit('automations:open-schedules');
324
- });
325
- }
326
- const newScheduleItem = $('menu-automations-schedule-new');
327
- if (newScheduleItem) {
328
- newScheduleItem.addEventListener('click', () => {
329
- closeAll();
330
- emit('automations:open-schedules', { action: 'new-schedule' });
331
- });
332
- }
333
- const quickTimerItem = $('menu-automations-quick-timer');
334
- if (quickTimerItem) {
335
- quickTimerItem.addEventListener('click', () => {
336
- closeAll();
337
- emit('automations:open-schedules', { action: 'quick-timer' });
338
- });
339
- }
340
- const scheduleGroupsItem = $('menu-automations-schedule-groups');
341
- if (scheduleGroupsItem) {
342
- scheduleGroupsItem.addEventListener('click', () => {
343
- closeAll();
344
- emit('automations:open-schedules', { tab: 'groups' });
345
- });
346
- }
320
+ const schedulesItem = $('menu-automations-schedules');
321
+ if (schedulesItem) {
322
+ schedulesItem.addEventListener('click', () => {
323
+ closeAll();
324
+ emit('automations:open-schedules');
325
+ });
326
+ }
327
+ const newScheduleItem = $('menu-automations-schedule-new');
328
+ if (newScheduleItem) {
329
+ newScheduleItem.addEventListener('click', () => {
330
+ closeAll();
331
+ emit('automations:open-schedules', { action: 'new-schedule' });
332
+ });
333
+ }
334
+ const quickTimerItem = $('menu-automations-quick-timer');
335
+ if (quickTimerItem) {
336
+ quickTimerItem.addEventListener('click', () => {
337
+ closeAll();
338
+ emit('automations:open-schedules', { action: 'quick-timer' });
339
+ });
340
+ }
341
+ const scheduleGroupsItem = $('menu-automations-schedule-groups');
342
+ if (scheduleGroupsItem) {
343
+ scheduleGroupsItem.addEventListener('click', () => {
344
+ closeAll();
345
+ emit('automations:open-schedules', { tab: 'groups' });
346
+ });
347
+ }
347
348
  const newItem = $('menu-automations-new');
348
349
  if (newItem) {
349
350
  newItem.addEventListener('click', () => {
@@ -370,7 +371,34 @@ function wireTerminalMenu() {
370
371
  'menu-terminal-codex': () => emit('terminal:open', { profile: 'codex' }),
371
372
  'menu-terminal-gemini': () => emit('terminal:open', { profile: 'gemini' }),
372
373
  'menu-terminal-opencode': () => emit('terminal:open', { profile: 'opencode' }),
373
- 'menu-check-cli-updates': () => forceCheckToolUpdates(),
374
+ 'menu-check-cli-updates': async () => {
375
+ const [tools, syn] = await Promise.all([
376
+ forceCheckToolUpdates(),
377
+ forceCheckSynabunUpdate(),
378
+ ]);
379
+
380
+ const updates = [];
381
+ for (const [key, info] of Object.entries(tools?.tools || {})) {
382
+ if (info?.updateAvailable) {
383
+ const label = `${TOOL_LABELS[key] || key} v${info.installed} → v${info.latest}`;
384
+ updates.push({ label });
385
+ }
386
+ }
387
+ if (syn?.updateAvailable) {
388
+ const srcLabel = syn.source === 'both' ? 'npm + GitHub' : syn.source === 'github' ? 'GitHub' : 'npm';
389
+ updates.push({ label: `SynaBun v${syn.current} → v${syn.latest}`, source: srcLabel });
390
+ }
391
+
392
+ const errors = [];
393
+ if (!tools) errors.push('CLI versions');
394
+ if (!syn) errors.push('SynaBun version');
395
+
396
+ showUpdateToast({
397
+ updates,
398
+ errors,
399
+ onClick: syn?.updateAvailable ? () => openSynabunUpdateModal() : null,
400
+ });
401
+ },
374
402
  'menu-terminal-shell': () => emit('terminal:open', { profile: 'shell' }),
375
403
  'menu-terminal-browser': () => emit('browser:open'),
376
404
  'menu-terminal-youtube': () => emit('browser:open', { url: 'https://www.youtube.com' }),