privateboard 0.1.20 → 0.1.21

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.
@@ -922,8 +922,8 @@
922
922
  /* Run consolidation pill · accent-leaning border on hover so it
923
923
  reads as the slightly-heavier action vs the neutral "add note". */
924
924
  .ap-dream-trigger:hover {
925
- border-color: var(--lime, #6FB572);
926
- color: var(--lime, #6FB572);
925
+ border-color: var(--lime);
926
+ color: var(--lime);
927
927
  }
928
928
  .ap-dream-trigger:disabled {
929
929
  opacity: 0.5;
@@ -968,8 +968,8 @@
968
968
  z-index: 1;
969
969
  width: 100%;
970
970
  max-width: 540px;
971
- background: var(--panel, #131312);
972
- border: 0.5px solid var(--lime-dim, #2D5532);
971
+ background: var(--panel);
972
+ border: 0.5px solid var(--lime-dim);
973
973
  color: var(--text);
974
974
  display: flex;
975
975
  flex-direction: column;
@@ -986,10 +986,10 @@
986
986
  animation: dream-modal-rise 0.24s ease-out;
987
987
  }
988
988
  .dream-overlay.is-done .dream-modal {
989
- border-color: var(--lime, #6FB572);
989
+ border-color: var(--lime);
990
990
  }
991
991
  .dream-overlay.is-error .dream-modal {
992
- border-color: var(--red, #B5706A);
992
+ border-color: var(--red);
993
993
  }
994
994
  @keyframes dream-modal-rise {
995
995
  from { opacity: 0; transform: translateY(8px); }
@@ -1020,7 +1020,7 @@
1020
1020
  font-weight: 700;
1021
1021
  letter-spacing: 0.18em;
1022
1022
  text-transform: uppercase;
1023
- color: var(--lime, #6FB572);
1023
+ color: var(--lime);
1024
1024
  }
1025
1025
  .dream-modal-glyph {
1026
1026
  font-family: var(--font-human);
@@ -1042,8 +1042,8 @@
1042
1042
  transition: border-color 0.12s, color 0.12s;
1043
1043
  }
1044
1044
  .dream-modal-close:hover {
1045
- border-color: var(--lime, #6FB572);
1046
- color: var(--lime, #6FB572);
1045
+ border-color: var(--lime);
1046
+ color: var(--lime);
1047
1047
  }
1048
1048
  /* Body · pinned min-height so the modal doesn't visibly resize
1049
1049
  between running ↔ done states. Both states use `.dream-stage-pad`
@@ -1104,10 +1104,10 @@
1104
1104
  background: var(--panel-2);
1105
1105
  }
1106
1106
  .dream-step.is-quiet { color: var(--text-dim); border-color: var(--line); }
1107
- .dream-step.is-shrink { color: var(--lime, #6FB572); border-color: var(--lime, #6FB572); }
1108
- .dream-step.is-grow { color: var(--cyan, #6A9B97); border-color: var(--cyan, #6A9B97); }
1107
+ .dream-step.is-shrink { color: var(--lime); border-color: var(--lime); }
1108
+ .dream-step.is-grow { color: var(--cyan); border-color: var(--cyan); }
1109
1109
  .dream-step.is-flat { color: var(--text-soft); border-color: var(--line-bright); }
1110
- .dream-step.is-error { color: var(--red, #B5706A); border-color: var(--red, #B5706A); }
1110
+ .dream-step.is-error { color: var(--red); border-color: var(--red); }
1111
1111
 
1112
1112
  /* Hairline divider between hero and footer. Mirrors the dotted
1113
1113
  separator style the chair Memory section uses in the agent
@@ -1159,7 +1159,7 @@
1159
1159
  bottom: 0;
1160
1160
  font-family: var(--font-human);
1161
1161
  font-weight: 700;
1162
- color: var(--lime, #6FB572);
1162
+ color: var(--lime);
1163
1163
  opacity: 0;
1164
1164
  animation: dream-z-float 3.4s ease-out infinite;
1165
1165
  text-shadow: 0 0 6px rgba(111, 181, 114, 0.3);
@@ -1221,7 +1221,7 @@
1221
1221
  background: linear-gradient(
1222
1222
  to right,
1223
1223
  transparent,
1224
- var(--lime, #6FB572) 50%,
1224
+ var(--lime) 50%,
1225
1225
  transparent
1226
1226
  );
1227
1227
  animation: dream-sweep 1.8s ease-in-out infinite;
@@ -1262,7 +1262,7 @@
1262
1262
  .dream-phase {
1263
1263
  font-size: 11px;
1264
1264
  letter-spacing: 0.02em;
1265
- color: var(--lime, #6FB572);
1265
+ color: var(--lime);
1266
1266
  line-height: 1.4;
1267
1267
  /* Subtle flicker so the static word doesn't feel dead between
1268
1268
  the 1.6s text rotations. Low amplitude · doesn't compete with
@@ -1314,14 +1314,14 @@
1314
1314
  width: 44px; height: 44px;
1315
1315
  font-size: 22px;
1316
1316
  line-height: 1;
1317
- border: 0.5px solid var(--lime, #6FB572);
1318
- color: var(--lime, #6FB572);
1317
+ border: 0.5px solid var(--lime);
1318
+ color: var(--lime);
1319
1319
  background: var(--panel-2);
1320
1320
  flex-shrink: 0;
1321
1321
  }
1322
1322
  .dream-overlay.is-error .dream-hero-glyph {
1323
- border-color: var(--red, #B5706A);
1324
- color: var(--red, #B5706A);
1323
+ border-color: var(--red);
1324
+ color: var(--red);
1325
1325
  }
1326
1326
  .dream-hero-text {
1327
1327
  display: flex;
@@ -1376,13 +1376,13 @@
1376
1376
  align-items: center;
1377
1377
  justify-content: center;
1378
1378
  padding: 8px 18px;
1379
- border: 1px solid var(--lime, #6FB572);
1379
+ border: 1px solid var(--lime);
1380
1380
  background: var(--panel-2);
1381
1381
  box-shadow: 0 0 24px rgba(111, 181, 114, 0.12);
1382
1382
  }
1383
1383
  .dream-num.now {
1384
1384
  font-size: 38px;
1385
- color: var(--lime, #6FB572);
1385
+ color: var(--lime);
1386
1386
  }
1387
1387
  .dream-hero-unit {
1388
1388
  font-family: var(--mono);
@@ -1429,14 +1429,14 @@
1429
1429
  text-transform: uppercase;
1430
1430
  color: var(--text-faint);
1431
1431
  }
1432
- .dream-tile.is-decay { border-color: var(--text-faint, #3A382F); }
1432
+ .dream-tile.is-decay { border-color: var(--text-faint); }
1433
1433
  .dream-tile.is-decay .dream-tile-n { color: var(--text-soft); }
1434
- .dream-tile.is-merge { border-color: var(--cyan, #6A9B97); }
1435
- .dream-tile.is-merge .dream-tile-n { color: var(--cyan, #6A9B97); }
1436
- .dream-tile.is-supersede { border-color: var(--amber, #B59560); }
1437
- .dream-tile.is-supersede .dream-tile-n { color: var(--amber, #B59560); }
1438
- .dream-tile.is-promote { border-color: var(--lime, #6FB572); }
1439
- .dream-tile.is-promote .dream-tile-n { color: var(--lime, #6FB572); }
1434
+ .dream-tile.is-merge { border-color: var(--cyan); }
1435
+ .dream-tile.is-merge .dream-tile-n { color: var(--cyan); }
1436
+ .dream-tile.is-supersede { border-color: var(--amber); }
1437
+ .dream-tile.is-supersede .dream-tile-n { color: var(--amber); }
1438
+ .dream-tile.is-promote { border-color: var(--lime); }
1439
+ .dream-tile.is-promote .dream-tile-n { color: var(--lime); }
1440
1440
  .ap-sec-hint {
1441
1441
  font-family: var(--mono);
1442
1442
  font-size: 9px;
@@ -1616,13 +1616,13 @@
1616
1616
  on idle, full red fill on hover so the destructive action is
1617
1617
  unmistakeably distinct from the regular ones. */
1618
1618
  .ap-id-menu-item-danger {
1619
- color: var(--red, #B5706A);
1619
+ color: var(--red);
1620
1620
  }
1621
1621
  .ap-id-menu-item-danger .ap-id-menu-mark {
1622
- color: var(--red, #B5706A);
1622
+ color: var(--red);
1623
1623
  }
1624
1624
  .ap-id-menu-item-danger:hover {
1625
- background: var(--red, #B5706A);
1625
+ background: var(--red);
1626
1626
  color: var(--bg);
1627
1627
  }
1628
1628
  .ap-id-menu-item-danger:hover .ap-id-menu-mark { color: var(--bg); }
@@ -2162,8 +2162,8 @@
2162
2162
  transition: border-color 0.12s, color 0.12s, background 0.12s;
2163
2163
  }
2164
2164
  .ap-skill-info-uninstall:hover {
2165
- border-color: var(--red, #C85A5A);
2166
- color: var(--red, #C85A5A);
2165
+ border-color: var(--red);
2166
+ color: var(--red);
2167
2167
  }
2168
2168
 
2169
2169
  /* System skill variant · row tinted lime, "system" badge, locked notice
@@ -2563,7 +2563,7 @@
2563
2563
  border-radius: 3px;
2564
2564
  }
2565
2565
  .ap-model-stale-mark {
2566
- color: var(--amber, #C9A46B);
2566
+ color: var(--amber);
2567
2567
  font-size: 11px;
2568
2568
  line-height: 1;
2569
2569
  }
@@ -2932,7 +2932,7 @@
2932
2932
  text-transform: uppercase;
2933
2933
  color: var(--text-faint);
2934
2934
  }
2935
- .ap-intel-edit-hint.error { color: var(--red, #C85A5A); text-transform: none; letter-spacing: 0; }
2935
+ .ap-intel-edit-hint.error { color: var(--red); text-transform: none; letter-spacing: 0; }
2936
2936
  .ap-intel-edit-actions { display: flex; gap: 8px; }
2937
2937
 
2938
2938
  /* RULES block · editable numbered list + add button. */
@@ -3267,7 +3267,7 @@
3267
3267
  .ap-memory-delete { font-size: 14px; font-weight: 300; }
3268
3268
  .ap-memory-delete:hover {
3269
3269
  opacity: 1;
3270
- color: var(--red, #C85A5A);
3270
+ color: var(--red);
3271
3271
  background: var(--line-bright);
3272
3272
  }
3273
3273
 
@@ -3421,18 +3421,18 @@
3421
3421
  rgba(200, 152, 90, 0.04) 4px
3422
3422
  ),
3423
3423
  linear-gradient(135deg, rgba(200, 152, 90, 0.18) 0%, var(--panel-3) 60%);
3424
- border-color: var(--amber, #C8985A);
3424
+ border-color: var(--amber);
3425
3425
  border-width: 1px;
3426
3426
  }
3427
3427
  .ap-memory-tile-self::before,
3428
3428
  .ap-memory-tile-self::after {
3429
- border-color: var(--amber, #C8985A);
3429
+ border-color: var(--amber);
3430
3430
  border-width: 2px;
3431
3431
  width: 11px;
3432
3432
  height: 11px;
3433
3433
  }
3434
3434
  .ap-memory-tile-self:hover {
3435
- border-color: var(--amber, #C8985A);
3435
+ border-color: var(--amber);
3436
3436
  background:
3437
3437
  repeating-linear-gradient(
3438
3438
  0deg,
@@ -3444,13 +3444,13 @@
3444
3444
  linear-gradient(135deg, rgba(200, 152, 90, 0.26) 0%, var(--panel-3) 60%);
3445
3445
  }
3446
3446
  .ap-memory-tile-self .ap-memory-tile-num {
3447
- color: var(--amber, #C8985A);
3447
+ color: var(--amber);
3448
3448
  }
3449
3449
  .ap-memory-tile-self .ap-memory-tile-num::before {
3450
3450
  color: rgba(200, 152, 90, 0.7);
3451
3451
  }
3452
3452
  .ap-memory-tile-self .ap-memory-tile-num-id {
3453
- color: var(--amber, #C8985A);
3453
+ color: var(--amber);
3454
3454
  font-size: 22px;
3455
3455
  letter-spacing: 0.08em;
3456
3456
  }
@@ -3458,7 +3458,7 @@
3458
3458
  border-top-color: rgba(200, 152, 90, 0.28);
3459
3459
  color: rgba(200, 152, 90, 0.7);
3460
3460
  }
3461
- .ap-memory-tile-self .ap-memory-tile-hint::after { color: var(--amber, #C8985A); }
3461
+ .ap-memory-tile-self .ap-memory-tile-hint::after { color: var(--amber); }
3462
3462
  /* Watermark star top-right */
3463
3463
  .ap-memory-self-mark {
3464
3464
  position: absolute;
@@ -3466,7 +3466,7 @@
3466
3466
  right: 8px;
3467
3467
  font-size: 14px;
3468
3468
  line-height: 1;
3469
- color: var(--amber, #C8985A);
3469
+ color: var(--amber);
3470
3470
  pointer-events: none;
3471
3471
  opacity: 0.7;
3472
3472
  }
@@ -3609,7 +3609,7 @@
3609
3609
  font-size: 10px;
3610
3610
  letter-spacing: 0.18em;
3611
3611
  text-transform: uppercase;
3612
- color: var(--text-faint, #3A382F);
3612
+ color: var(--text-faint);
3613
3613
  font-weight: 600;
3614
3614
  }
3615
3615
  .ap-skill-row-toggle-track {
@@ -3617,8 +3617,8 @@
3617
3617
  width: 30px;
3618
3618
  height: 16px;
3619
3619
  border-radius: 8px;
3620
- background: var(--panel-3, #21211E);
3621
- border: 1px solid var(--line-strong, #4D4B45);
3620
+ background: var(--panel-3);
3621
+ border: 1px solid var(--line-strong);
3622
3622
  transition: background 0.15s ease, border-color 0.15s ease;
3623
3623
  }
3624
3624
  .ap-skill-row-toggle-knob {
@@ -3632,20 +3632,20 @@
3632
3632
  against the dark track without depending on theme nuance. The
3633
3633
  `on` state below overrides this with the bg color so the gold
3634
3634
  knob pops on the gold track. */
3635
- background: var(--text-soft, #8E8B83);
3635
+ background: var(--text-soft);
3636
3636
  transition: left 0.15s ease, background 0.15s ease;
3637
3637
  }
3638
3638
  .ap-skill-row-toggle.on .ap-skill-row-toggle-track {
3639
- background: var(--lime, #6FB572);
3640
- border-color: var(--lime-deep, #427A48);
3639
+ background: var(--lime);
3640
+ border-color: var(--lime-deep);
3641
3641
  }
3642
3642
  .ap-skill-row-toggle.on .ap-skill-row-toggle-knob {
3643
3643
  left: 17px;
3644
- background: var(--bg, #0A0A0A);
3644
+ background: var(--bg);
3645
3645
  }
3646
- .ap-skill-row-toggle.on .ap-skill-row-toggle-text { color: var(--text, #C8C5BE); }
3646
+ .ap-skill-row-toggle.on .ap-skill-row-toggle-text { color: var(--text); }
3647
3647
  .ap-skill-row-toggle:hover .ap-skill-row-toggle-track {
3648
- border-color: var(--text-soft, #8E8B83);
3648
+ border-color: var(--text-soft);
3649
3649
  }
3650
3650
 
3651
3651
  /* ─── Web Search · "needs key" state · same toggle shape, dotted
@@ -3653,21 +3653,21 @@
3653
3653
  Configure-key action live in the JS handler + ⋯ popover. ─── */
3654
3654
  .ap-skill-row-toggle.needs-key .ap-skill-row-toggle-track {
3655
3655
  background: transparent;
3656
- border: 1px dashed var(--line-strong, #4D4B45);
3656
+ border: 1px dashed var(--line-strong);
3657
3657
  }
3658
3658
  .ap-skill-row-toggle.needs-key .ap-skill-row-toggle-knob {
3659
- background: var(--text-faint, #5C5A4D);
3659
+ background: var(--text-faint);
3660
3660
  opacity: 0.65;
3661
3661
  }
3662
3662
  .ap-skill-row-toggle.needs-key .ap-skill-row-toggle-text {
3663
- color: var(--text-faint, #5C5A4D);
3663
+ color: var(--text-faint);
3664
3664
  }
3665
3665
  .ap-skill-row-toggle.needs-key:hover .ap-skill-row-toggle-track {
3666
- border-color: var(--lime, #6FB572);
3666
+ border-color: var(--lime);
3667
3667
  border-style: solid;
3668
3668
  }
3669
3669
  .ap-skill-row-toggle.needs-key:hover .ap-skill-row-toggle-text {
3670
- color: var(--lime, #6FB572);
3670
+ color: var(--lime);
3671
3671
  }
3672
3672
 
3673
3673
  /* ─── Configure-key action inside the ⋯ skill-info popover ─── */
@@ -3677,21 +3677,21 @@
3677
3677
  gap: 8px;
3678
3678
  width: 100%;
3679
3679
  background: transparent;
3680
- border: 0.5px solid var(--lime, #6FB572);
3680
+ border: 0.5px solid var(--lime);
3681
3681
  padding: 8px 12px;
3682
3682
  cursor: pointer;
3683
3683
  font-family: var(--mono, "Inter", system-ui, sans-serif);
3684
3684
  font-size: 10px;
3685
3685
  letter-spacing: 0.14em;
3686
3686
  text-transform: uppercase;
3687
- color: var(--lime, #6FB572);
3687
+ color: var(--lime);
3688
3688
  font-weight: 700;
3689
3689
  transition: background 0.12s ease, color 0.12s ease;
3690
3690
  margin-bottom: 8px;
3691
3691
  }
3692
3692
  .ap-skill-info-configure:hover {
3693
- background: var(--lime, #6FB572);
3694
- color: var(--bg, #0A0A0A);
3693
+ background: var(--lime);
3694
+ color: var(--bg);
3695
3695
  }
3696
3696
  .ap-skill-info-configure-mark { font-size: 12px; }
3697
3697
 
@@ -4009,7 +4009,7 @@
4009
4009
  }
4010
4010
  .ap-voice-advanced {
4011
4011
  margin-top: 10px;
4012
- border-top: 1px solid var(--line, #222);
4012
+ border-top: 1px solid var(--line);
4013
4013
  padding-top: 8px;
4014
4014
  }
4015
4015
  /* Header row · label on the left, custom expand/collapse indicator
@@ -4027,7 +4027,7 @@
4027
4027
  font-size: 10px;
4028
4028
  letter-spacing: 0.04em;
4029
4029
  text-transform: uppercase;
4030
- color: var(--text-soft, #999);
4030
+ color: var(--text-soft);
4031
4031
  cursor: pointer;
4032
4032
  user-select: none;
4033
4033
  list-style: none;
@@ -4044,7 +4044,7 @@
4044
4044
  transition: color 0.12s;
4045
4045
  }
4046
4046
  .ap-voice-advanced[open] summary::after { content: "−"; }
4047
- .ap-voice-advanced summary:hover { color: var(--text, #eee); }
4047
+ .ap-voice-advanced summary:hover { color: var(--text); }
4048
4048
  .ap-voice-advanced summary:hover::after { color: var(--text); }
4049
4049
 
4050
4050
  /* ────────────────────────────────────────────────────────────
@@ -4312,7 +4312,7 @@
4312
4312
  }
4313
4313
  .ap-persona-overlay-dl:hover {
4314
4314
  background: var(--lime);
4315
- color: var(--bg, #0c0c0c);
4315
+ color: var(--bg);
4316
4316
  }
4317
4317
  .ap-persona-overlay-close {
4318
4318
  position: relative;
@@ -4377,7 +4377,7 @@ html.is-electron-mac .ap-persona-overlay-backdrop {
4377
4377
  text-align: center;
4378
4378
  padding: 60px 0;
4379
4379
  }
4380
- .ap-persona-overlay-error { color: var(--ink, #c97373); }
4380
+ .ap-persona-overlay-error { color: var(--ink); }
4381
4381
  .ap-persona-overlay-md {
4382
4382
  font-family: var(--font-human);
4383
4383
  font-size: 14px;
@@ -2420,31 +2420,28 @@
2420
2420
  for (const m of cache.reachable) {
2421
2421
  const directOk = !!(m.routes && m.routes.direct);
2422
2422
  const orOk = !!(m.routes && m.routes.openrouter);
2423
+ const baiOk = !!(m.routes && m.routes.bai);
2423
2424
  const provider = providerLabel(m.provider);
2424
- // Both routes available · expand into two rows. Direct first
2425
- // (matches the adapter's default preference for non-openrouterOnly
2426
- // models), then OR. Each row is independently clickable so the
2427
- // user can pin EITHER carrier explicitly.
2428
- if (directOk && orOk) {
2429
- out.push({
2430
- id: m.modelV + "@" + m.provider,
2431
- v: m.modelV,
2432
- carrier: m.provider,
2433
- name: m.displayName,
2434
- provider,
2435
- deck: m.deck || "",
2436
- route: "via " + provider + " direct",
2437
- });
2438
- out.push({
2439
- id: m.modelV + "@openrouter",
2440
- v: m.modelV,
2441
- carrier: "openrouter",
2442
- name: m.displayName,
2443
- provider,
2444
- deck: m.deck || "",
2445
- route: "via OpenRouter",
2446
- });
2447
- } else if (directOk) {
2425
+ // For each carrier that can serve this model, emit a separate
2426
+ // pickable row · users can pin EITHER carrier explicitly. Order
2427
+ // mirrors the adapter's default precedence so the natural top
2428
+ // pick when the user just clicks "the model" is the same one
2429
+ // the orchestrator would resolve unpinned. When only ONE
2430
+ // carrier serves the model, we collapse to a single row with
2431
+ // `carrier: null` so the agent uses default routing (and
2432
+ // automatically follows the carrier if the user later
2433
+ // reconfigures keys).
2434
+ const reachableCarriers = [];
2435
+ if (directOk) reachableCarriers.push({ carrier: m.provider, route: "via " + provider + " direct" });
2436
+ if (baiOk) reachableCarriers.push({ carrier: "bai", route: "via B.AI" });
2437
+ if (orOk) reachableCarriers.push({ carrier: "openrouter", route: "via OpenRouter" });
2438
+ if (reachableCarriers.length === 0) continue;
2439
+ if (reachableCarriers.length === 1) {
2440
+ // Only one carrier serves this model · use the bare modelV
2441
+ // id and `carrier: null` so the saved agent record uses
2442
+ // default routing rather than a sticky pin to a carrier the
2443
+ // user might later swap.
2444
+ const only = reachableCarriers[0];
2448
2445
  out.push({
2449
2446
  id: m.modelV,
2450
2447
  v: m.modelV,
@@ -2452,17 +2449,21 @@
2452
2449
  name: m.displayName,
2453
2450
  provider,
2454
2451
  deck: m.deck || "",
2455
- route: "direct",
2452
+ route: only.carrier === m.provider ? "direct" : only.route,
2456
2453
  });
2457
- } else if (orOk) {
2454
+ continue;
2455
+ }
2456
+ // Multi-carrier · one row per carrier · composite id
2457
+ // `${modelV}@${carrier}` distinguishes them in the picker.
2458
+ for (const { carrier, route } of reachableCarriers) {
2458
2459
  out.push({
2459
- id: m.modelV,
2460
+ id: m.modelV + "@" + carrier,
2460
2461
  v: m.modelV,
2461
- carrier: null,
2462
+ carrier,
2462
2463
  name: m.displayName,
2463
2464
  provider,
2464
2465
  deck: m.deck || "",
2465
- route: "via OpenRouter",
2466
+ route,
2466
2467
  });
2467
2468
  }
2468
2469
  }
@@ -2607,8 +2608,8 @@
2607
2608
  const current = modelForAgent(slug, fallback);
2608
2609
  const reachable = isReachable(current.v);
2609
2610
  // Stale-model warning · the agent's stored modelV isn't reachable
2610
- // with the current key set (e.g. user revoked OpenRouter, but
2611
- // the agent was set to opus-4-7 which is openrouterOnly). Surface
2611
+ // with the current key set (e.g. user revoked both OR + B.AI but
2612
+ // the agent was set to a viaUniversalOnly model). Surface
2612
2613
  // it as a small note under the trigger so the user knows clicks
2613
2614
  // here will fall back at runtime; the runtime resolver in
2614
2615
  // `effectiveDefaultModel()` does the actual fallback.