sideby 0.12.1 → 0.13.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.
Files changed (86) hide show
  1. package/README.md +1 -1
  2. package/dist/build.json +1 -1
  3. package/dist/src/cli/commands.d.ts +5 -2
  4. package/dist/src/cli/commands.js +165 -20
  5. package/dist/src/cli/json-schemas.js +100 -2
  6. package/dist/src/cli/main.js +72 -4
  7. package/dist/src/core/brand-mark.d.ts +5 -7
  8. package/dist/src/core/brand-mark.js +18 -5
  9. package/dist/src/core/browser-profiles.d.ts +71 -0
  10. package/dist/src/core/browser-profiles.js +361 -0
  11. package/dist/src/core/config.d.ts +15 -0
  12. package/dist/src/core/config.js +13 -1
  13. package/dist/src/core/create.js +2 -1
  14. package/dist/src/core/desktop-app.d.ts +3 -1
  15. package/dist/src/core/desktop-app.js +29 -8
  16. package/dist/src/core/launch.d.ts +7 -0
  17. package/dist/src/core/launch.js +22 -2
  18. package/dist/src/core/leveldb-keys.d.ts +14 -0
  19. package/dist/src/core/leveldb-keys.js +291 -0
  20. package/dist/src/core/remote-control.d.ts +17 -6
  21. package/dist/src/core/remote-control.js +40 -17
  22. package/dist/src/core/skill-check.d.ts +13 -0
  23. package/dist/src/core/skill-check.js +29 -1
  24. package/dist/src/core/update.d.ts +55 -3
  25. package/dist/src/core/update.js +124 -4
  26. package/dist/src/core/version.d.ts +11 -0
  27. package/dist/src/core/version.js +26 -0
  28. package/dist/src/desktop/app.d.ts +2 -0
  29. package/dist/src/desktop/app.js +39 -3
  30. package/dist/src/families/browser.d.ts +20 -0
  31. package/dist/src/families/browser.js +23 -0
  32. package/dist/src/families/claude/browser.d.ts +3 -0
  33. package/dist/src/families/claude/browser.js +14 -0
  34. package/dist/src/families/claude/desktop.js +1 -0
  35. package/dist/src/families/codex/browser.d.ts +7 -0
  36. package/dist/src/families/codex/browser.js +26 -0
  37. package/dist/src/families/desktop.d.ts +5 -1
  38. package/dist/src/families/pi/index.js +2 -0
  39. package/dist/src/panel/handler.d.ts +9 -1
  40. package/dist/src/panel/handler.js +54 -6
  41. package/dist/src/panel/i18n.d.ts +74 -4
  42. package/dist/src/panel/i18n.js +160 -20
  43. package/dist/src/panel/page-logic.d.ts +23 -0
  44. package/dist/src/panel/page-logic.js +44 -0
  45. package/dist/src/panel/page-script.js +587 -183
  46. package/dist/src/panel/page-styles.js +61 -18
  47. package/dist/src/panel/page.d.ts +5 -0
  48. package/dist/src/panel/page.js +10 -9
  49. package/dist/src/runtime.d.ts +6 -1
  50. package/dist/src/runtime.js +22 -11
  51. package/dist/src/types.d.ts +2 -0
  52. package/package.json +5 -3
  53. package/schemas/alias.json +62 -0
  54. package/schemas/app-install.json +62 -0
  55. package/schemas/app-uninstall.json +62 -0
  56. package/schemas/browser-open.json +109 -0
  57. package/schemas/browser-switch.json +104 -0
  58. package/schemas/browser.json +161 -0
  59. package/schemas/config.json +11 -0
  60. package/schemas/desktop-remove.json +62 -0
  61. package/schemas/desktop.json +62 -0
  62. package/schemas/doctor.json +62 -0
  63. package/schemas/error.json +62 -0
  64. package/schemas/families.json +68 -0
  65. package/schemas/handoff-disable.json +62 -0
  66. package/schemas/handoff-enable.json +62 -0
  67. package/schemas/handoff-ready.json +62 -0
  68. package/schemas/handoff-setup.json +62 -0
  69. package/schemas/handoff-status.json +62 -0
  70. package/schemas/handoff-teardown.json +62 -0
  71. package/schemas/list.json +68 -0
  72. package/schemas/model.json +62 -0
  73. package/schemas/new.json +62 -0
  74. package/schemas/next.json +62 -0
  75. package/schemas/plugins.json +62 -0
  76. package/schemas/quota-setup.json +62 -0
  77. package/schemas/quota-teardown.json +62 -0
  78. package/schemas/quota.json +62 -0
  79. package/schemas/remote-control.json +66 -0
  80. package/schemas/tune-change.json +62 -0
  81. package/schemas/tune.json +62 -0
  82. package/schemas/update.json +111 -1
  83. package/skills/sideby/SKILL.md +8 -4
  84. package/skills/sideby/references/diagnose.md +1 -1
  85. package/skills/sideby/references/setup.md +1 -1
  86. package/skills/sideby/references/update.md +16 -0
@@ -1,5 +1,6 @@
1
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
2
  import { type AppProfileStatus } from '../core/app-profiles.ts';
3
+ import { type BrowserReport } from '../core/browser-profiles.ts';
3
4
  import { type HandoffSettings } from '../core/config.ts';
4
5
  import { type AccountModel } from '../core/model-choice.ts';
5
6
  import type { RemoteControlGroup } from '../core/remote-control.ts';
@@ -91,8 +92,10 @@ export interface PanelUpdate {
91
92
  command?: string;
92
93
  canRun: boolean;
93
94
  releaseNotes?: string;
94
- /** The command that updates the sideby skill, which sideby never runs itself. */
95
+ /** The command that installs the sideby skill by hand. */
95
96
  skill: string;
97
+ /** The installed sideby skill, which an Update brings along (spec §3.23); absent when none is installed. */
98
+ skillUpdate?: import('../core/update.ts').SkillUpdatePlan;
96
99
  }
97
100
  export interface PanelState {
98
101
  schemaVersion: 1;
@@ -132,6 +135,11 @@ export interface PanelState {
132
135
  appProfiles?: AppProfileStatus[];
133
136
  /** Update Check result and Auto Update setting (spec §3.23); absent with `updates: false`. */
134
137
  update?: PanelUpdate;
138
+ /**
139
+ * Browser Sign-ins (spec §3.24): which Chrome browser user signed in to which Account, read on this computer only.
140
+ * Absent without Claude, Codex or Grok subscription Accounts. Nothing of the browser is read while `enabled` is false.
141
+ */
142
+ browser?: BrowserReport;
135
143
  }
136
144
  /** The `handoff` map of the Panel state, from the statuses and Quota already read for the page. */
137
145
  export declare function handoffByFamily(rt: Runtime, accounts: readonly PanelAccount[], now: Date): Record<string, string>;
@@ -3,6 +3,7 @@ import { randomBytes, timingSafeEqual } from 'node:crypto';
3
3
  import { aliasesByAccount } from '../core/accounts.js';
4
4
  import { listAppProfiles, openAppProfile, removeAppProfile, } from '../core/app-profiles.js';
5
5
  import { FAVICON_SVG, ICON_SVG } from '../core/brand-mark.js';
6
+ import { browserReport, openInBrowser, setBrowserSignIns, } from '../core/browser-profiles.js';
6
7
  import { aliasArgs, aliasRefs, editConfigUpdate } from '../core/config.js';
7
8
  import { openDesktopApp, withDesktopApps } from '../core/desktop-app.js';
8
9
  import { UserError } from '../core/errors.js';
@@ -15,7 +16,7 @@ import { tildify } from '../core/paths.js';
15
16
  import { SKILL_INSTALL } from '../core/skill-check.js';
16
17
  import { MIN_CALLS } from '../core/tuning.js';
17
18
  import * as update from '../core/update.js';
18
- import { buildId, packageVersion } from '../core/version.js';
19
+ import { buildId, localBuild, packageVersion } from '../core/version.js';
19
20
  import { HOOK_FAMILIES } from '../handoff/hook.js';
20
21
  import { renderPage } from './page.js';
21
22
  import { resolveTheme } from './theme.js';
@@ -60,6 +61,9 @@ async function updateState(rt, readOnly) {
60
61
  });
61
62
  const method = await update.installMethod(rt.env);
62
63
  const plan = cache.latest ? update.shownPlan(update.planFrom(method, current, cache.latest, rt.env)) : null;
64
+ const skillUpdate = await update
65
+ .skillUpdatePlan(rt.paths.home, plan?.available ? plan.latest : current)
66
+ .catch(() => null);
63
67
  return {
64
68
  current,
65
69
  ...(cache.latest ? { latest: cache.latest } : {}),
@@ -71,6 +75,7 @@ async function updateState(rt, readOnly) {
71
75
  ...(plan ? { command: plan.command, releaseNotes: plan.releaseNotes } : {}),
72
76
  canRun: Boolean(plan?.canRun),
73
77
  skill: SKILL_INSTALL,
78
+ ...(skillUpdate ? { skillUpdate } : {}),
74
79
  };
75
80
  }
76
81
  /** The `handoff` map of the Panel state, from the statuses and Quota already read for the page. */
@@ -265,6 +270,8 @@ async function buildState(rt, opts) {
265
270
  };
266
271
  });
267
272
  const handoff = handoffByFamily(rt, list, ctx.now);
273
+ const browser = await browserReport(rt, accounts).catch(() => undefined);
274
+ const showBrowser = browser && (browser.families.matched.length || browser.families.openOnly.length);
268
275
  return {
269
276
  schemaVersion: 1,
270
277
  version: opts.version,
@@ -273,7 +280,8 @@ async function buildState(rt, opts) {
273
280
  generatedAt: ctx.now.toISOString(),
274
281
  families: families.map((f) => {
275
282
  const logo = rt.families.get(f.id)?.logo;
276
- return logo ? { ...f, logo } : f;
283
+ const g = f.brokenBin ? { ...f, brokenBin: tildify(f.brokenBin, ctx.home) } : f;
284
+ return logo ? { ...g, logo } : g;
277
285
  }),
278
286
  accounts: list,
279
287
  pluginErrors: rt.pluginErrors.map((e) => ({ where: e.where, message: e.message })),
@@ -294,6 +302,7 @@ async function buildState(rt, opts) {
294
302
  .map((f) => f.id),
295
303
  },
296
304
  ...(upd ? { update: upd } : {}),
305
+ ...(showBrowser ? { browser } : {}),
297
306
  };
298
307
  }
299
308
  /** The `change` of a /api/handoff/configure body, with every field checked; unknown fields are refused. */
@@ -351,6 +360,7 @@ export function createPanelHandler(opts) {
351
360
  const readOnly = Boolean(opts.readOnly);
352
361
  const version = opts.version ?? PANEL_VERSION;
353
362
  const build = buildId();
363
+ const local = localBuild();
354
364
  const theme = resolveTheme(opts.theme);
355
365
  const lang = resolveLang(opts.lang);
356
366
  const updates = opts.updates !== false;
@@ -450,8 +460,8 @@ export function createPanelHandler(opts) {
450
460
  return { ref: found.ref, undone: r.ok, message: r.message };
451
461
  },
452
462
  },
453
- // Remote Control off by default (spec §3.22, ADR-0017): writes `remoteControlAtStartup: false` into each Claude
454
- // settings file that turns it on or leaves it to the default; the page shows the files first, from the state.
463
+ // Remote Control at startup (spec §3.22, ADR-0017): writes `remoteControlAtStartup` (false for off, true for on)
464
+ // into each Claude settings file that does not hold it yet; the page shows the files first, from the state.
455
465
  '/api/remote-control/off': {
456
466
  async run() {
457
467
  const rt = await getRuntime();
@@ -460,6 +470,14 @@ export function createPanelHandler(opts) {
460
470
  return { ...r, results: r.results.map((x) => ({ ...x, file: tildify(x.file, home) })) };
461
471
  },
462
472
  },
473
+ '/api/remote-control/on': {
474
+ async run() {
475
+ const rt = await getRuntime();
476
+ const r = await rt.remoteControlOn();
477
+ const home = rt.paths.home;
478
+ return { ...r, results: r.results.map((x) => ({ ...x, file: tildify(x.file, home) })) };
479
+ },
480
+ },
463
481
  '/api/remote-control/undo': {
464
482
  async run() {
465
483
  const rt = await getRuntime();
@@ -524,6 +542,29 @@ export function createPanelHandler(opts) {
524
542
  };
525
543
  },
526
544
  },
545
+ // Browser Sign-ins on or off (spec §3.24): config `browser.signIns`, shown first like every config change.
546
+ '/api/browser/settings': {
547
+ writes: (body) => body.confirm === true,
548
+ async run(body) {
549
+ if (typeof body.enabled !== 'boolean')
550
+ throw new HttpError(400, '"enabled" must be true or false');
551
+ const rt = await getRuntime();
552
+ const r = await setBrowserSignIns(rt, body.enabled, { apply: optBool(body, 'confirm') });
553
+ return { ...r, file: tildify(r.file, rt.paths.home) };
554
+ },
555
+ },
556
+ // Opens the Account's website in one Chrome browser user (spec §3.24). It starts a program, so a read-only Panel
557
+ // refuses it (writes defaults to true).
558
+ '/api/browser/open': {
559
+ async run(body) {
560
+ const account = optString(body, 'account');
561
+ if (!account)
562
+ throw new HttpError(400, '"account" is required');
563
+ const rt = await getRuntime();
564
+ const profile = optString(body, 'profile');
565
+ return openInBrowser(rt, await rt.resolve(account), profile);
566
+ },
567
+ },
527
568
  // Opens a Grok Bot window, creating it when the name is new, or brings it to the front (ADR-0019).
528
569
  '/api/app-profile/open': {
529
570
  async run(body) {
@@ -600,7 +641,14 @@ export function createPanelHandler(opts) {
600
641
  });
601
642
  if (!r.ok)
602
643
  throw new UserError(r.message);
603
- return { ...shown, updated: true, message: r.message, restartedPanel: r.restartedPanel };
644
+ return {
645
+ ...shown,
646
+ updated: true,
647
+ message: r.message,
648
+ restartedPanel: r.restartedPanel,
649
+ refreshedApp: r.refreshedApp,
650
+ ...(r.skillUpdated === undefined ? {} : { skillUpdated: r.skillUpdated }),
651
+ };
604
652
  },
605
653
  },
606
654
  // The Auto Update switch: config `update.auto`, shown as a diff first like every config change.
@@ -671,7 +719,7 @@ export function createPanelHandler(opts) {
671
719
  });
672
720
  res.end(method === 'HEAD'
673
721
  ? undefined
674
- : renderPage({ basePath, token, nonce, version, build, readOnly, theme, lang, updates }));
722
+ : renderPage({ basePath, token, nonce, version, build, local, readOnly, theme, lang, updates }));
675
723
  return true;
676
724
  }
677
725
  // The mark, for a Portal's tab and for this page's favicon (ADR-0006 amendment).
@@ -6,7 +6,7 @@ declare const en: {
6
6
  'top.refreshing': string;
7
7
  'top.updated': string;
8
8
  'top.updatedTitle': string;
9
- 'top.language': string;
9
+ 'top.stale': string;
10
10
  'foot.text': string;
11
11
  'foot.textChecks': string;
12
12
  'upd.label': string;
@@ -20,12 +20,21 @@ declare const en: {
20
20
  'upd.after': string;
21
21
  'upd.cannot': string;
22
22
  'upd.skill': string;
23
+ 'upd.skillToo': string;
24
+ 'upd.skillDone': string;
25
+ 'upd.skillManaged': string;
23
26
  'upd.checksOff': string;
24
27
  'upd.latest': string;
25
28
  'upd.latestNow': string;
26
29
  'upd.check': string;
27
30
  'upd.checking': string;
28
31
  'upd.verTitle': string;
32
+ 'upd.local': string;
33
+ 'upd.localDirty': string;
34
+ 'upd.open': string;
35
+ 'upd.autoIsOn': string;
36
+ 'upd.autoIsOff': string;
37
+ 'upd.settings': string;
29
38
  'upd.checked': string;
30
39
  'upd.notYet': string;
31
40
  'upd.auto': string;
@@ -42,9 +51,6 @@ declare const en: {
42
51
  'upd.reloading': string;
43
52
  'upd.restartHint': string;
44
53
  'acct.title': string;
45
- 'theme.system': string;
46
- 'theme.light': string;
47
- 'theme.dark': string;
48
54
  'err.noAnswer': string;
49
55
  'err.session': string;
50
56
  'err.expired': string;
@@ -124,6 +130,7 @@ declare const en: {
124
130
  'why.health-fail': string;
125
131
  'why.signed-out': string;
126
132
  'why.not-installed': string;
133
+ 'why.broken': string;
127
134
  'why.quota-high': string;
128
135
  'why.health-warn': string;
129
136
  'tb.search': string;
@@ -138,6 +145,7 @@ declare const en: {
138
145
  'tb.used': string;
139
146
  'tb.left': string;
140
147
  'tb.view': string;
148
+ 'tb.display': string;
141
149
  'tb.list': string;
142
150
  'tb.cards': string;
143
151
  'tb.hideEmails': string;
@@ -155,6 +163,7 @@ declare const en: {
155
163
  'group.collapse': string;
156
164
  'row.collapse': string;
157
165
  'row.expand': string;
166
+ 'row.runs': string;
158
167
  'group.toggle': string;
159
168
  'group.attention.one': string;
160
169
  'group.attention.other': string;
@@ -176,6 +185,10 @@ declare const en: {
176
185
  'acct.installHost': string;
177
186
  'acct.nearLimit': string;
178
187
  'acct.installIt': string;
188
+ 'acct.installHostCmd': string;
189
+ 'acct.brokenHost': string;
190
+ 'acct.installDocs': string;
191
+ 'acct.broken': string;
179
192
  'quota.pctUsed': string;
180
193
  'quota.pctLeft': string;
181
194
  'quota.meterUsed': string;
@@ -186,6 +199,13 @@ declare const en: {
186
199
  'quota.dataFrom': string;
187
200
  'quota.asOf': string;
188
201
  'quota.sharedFrom': string;
202
+ 'quota.readFrom': string;
203
+ 'login.count': string;
204
+ 'login.label': string;
205
+ 'login.hint': string;
206
+ 'login.sharedAbove': string;
207
+ 'login.collapse': string;
208
+ 'login.expand': string;
189
209
  'quota.noWindows': string;
190
210
  'quota.off': string;
191
211
  'quota.turnOnFamily': string;
@@ -280,6 +300,32 @@ declare const en: {
280
300
  'desk.started': string;
281
301
  'desk.focused': string;
282
302
  'desk.failed': string;
303
+ 'br.open': string;
304
+ 'br.signedIn': string;
305
+ 'br.signedInMore': string;
306
+ 'br.hint': string;
307
+ 'br.title': string;
308
+ 'br.offIntro': string;
309
+ 'br.reads': string;
310
+ 'br.read1': string;
311
+ 'br.read2': string;
312
+ 'br.read3': string;
313
+ 'br.never': string;
314
+ 'br.enable': string;
315
+ 'br.enabled': string;
316
+ 'br.disable': string;
317
+ 'br.disabled': string;
318
+ 'br.local': string;
319
+ 'br.found': string;
320
+ 'br.none': string;
321
+ 'br.noMatch': string;
322
+ 'br.others': string;
323
+ 'br.all': string;
324
+ 'br.noChrome': string;
325
+ 'br.openIt': string;
326
+ 'br.opened': string;
327
+ 'br.failed': string;
328
+ 'br.changed': string;
283
329
  'app.apart': string;
284
330
  'app.apartTip': string;
285
331
  'app.mainName': string;
@@ -435,6 +481,7 @@ declare const en: {
435
481
  'nf.accounts.other': string;
436
482
  'nf.runOnce': string;
437
483
  'nf.notInstalled': string;
484
+ 'nf.broken': string;
438
485
  'nf.name': string;
439
486
  'nf.namePh': string;
440
487
  'nf.api': string;
@@ -535,6 +582,29 @@ declare const en: {
535
582
  'rc.confirm': string;
536
583
  'rc.done': string;
537
584
  'rc.failed': string;
585
+ 'set.button': string;
586
+ 'set.lang': string;
587
+ 'set.theme': string;
588
+ 'set.theme.system': string;
589
+ 'set.theme.light': string;
590
+ 'set.theme.dark': string;
591
+ 'set.rcOn': string;
592
+ 'rc.button': string;
593
+ 'rc.state.on': string;
594
+ 'rc.state.default': string;
595
+ 'rc.state.off': string;
596
+ 'rc.state.missing': string;
597
+ 'rc.state.blocked': string;
598
+ 'rc.dialogTitle': string;
599
+ 'rc.explain': string;
600
+ 'rc.allOff': string;
601
+ 'rc.undo': string;
602
+ 'rc.switch': string;
603
+ 'rc.confirmOn': string;
604
+ 'rc.onWarn': string;
605
+ 'rc.doneOn': string;
606
+ 'rc.failedOn': string;
607
+ 'rc.readOnlyBoth': string;
538
608
  'rc.undone': string;
539
609
  'banner.readOnly': string;
540
610
  'banner.plugins.one': string;