sideby 0.14.0 → 0.15.0
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/README.md +1 -0
- package/dist/build.json +1 -1
- package/dist/src/cli/commands.d.ts +2 -0
- package/dist/src/cli/commands.js +176 -9
- package/dist/src/cli/json-schemas.js +90 -2
- package/dist/src/cli/main.js +24 -5
- package/dist/src/core/config.d.ts +1 -0
- package/dist/src/core/config.js +8 -2
- package/dist/src/core/skill-check.d.ts +14 -0
- package/dist/src/core/skill-check.js +29 -3
- package/dist/src/core/update.d.ts +67 -1
- package/dist/src/core/update.js +147 -23
- package/dist/src/panel/handler.d.ts +7 -1
- package/dist/src/panel/handler.js +21 -5
- package/dist/src/panel/i18n.d.ts +118 -5
- package/dist/src/panel/i18n.js +266 -40
- package/dist/src/panel/page-logic.d.ts +41 -0
- package/dist/src/panel/page-logic.js +46 -0
- package/dist/src/panel/page-script.js +571 -162
- package/dist/src/panel/page-styles.js +71 -23
- package/dist/src/panel/page.js +3 -0
- package/dist/src/runtime.d.ts +2 -0
- package/package.json +3 -2
- package/schemas/alias.json +1 -1
- package/schemas/app-install.json +1 -1
- package/schemas/app-uninstall.json +1 -1
- package/schemas/browser-open.json +1 -1
- package/schemas/browser-switch.json +1 -1
- package/schemas/browser.json +1 -1
- package/schemas/config.json +15 -1
- package/schemas/desktop-remove.json +1 -1
- package/schemas/desktop.json +1 -1
- package/schemas/doctor.json +1 -1
- package/schemas/error.json +1 -1
- package/schemas/families.json +1 -1
- package/schemas/handoff-disable.json +1 -1
- package/schemas/handoff-enable.json +1 -1
- package/schemas/handoff-ready.json +1 -1
- package/schemas/handoff-setup.json +1 -1
- package/schemas/handoff-status.json +282 -1
- package/schemas/handoff-teardown.json +1 -1
- package/schemas/list.json +6 -1
- package/schemas/model.json +1 -1
- package/schemas/new.json +1 -1
- package/schemas/next.json +1 -1
- package/schemas/order.json +148 -0
- package/schemas/pin.json +126 -0
- package/schemas/plugins.json +1 -1
- package/schemas/quota-check.json +88 -0
- package/schemas/quota-setup.json +1 -1
- package/schemas/quota-teardown.json +1 -1
- package/schemas/quota.json +1 -1
- package/schemas/remote-control.json +1 -1
- package/schemas/tune-change.json +1 -1
- package/schemas/tune.json +1 -1
- package/schemas/unpin.json +126 -0
- package/schemas/update-auto.json +84 -0
- package/schemas/update.json +79 -1
- package/skills/sideby/SKILL.md +7 -3
- package/skills/sideby/references/handoff.md +8 -0
- package/skills/sideby/references/panel.md +28 -0
- package/skills/sideby/references/quota.md +6 -0
- package/skills/sideby/references/update.md +6 -2
package/dist/src/panel/i18n.js
CHANGED
|
@@ -21,7 +21,6 @@ const en = {
|
|
|
21
21
|
'upd.runs': 'Updating runs:',
|
|
22
22
|
'upd.after': 'A background panel restarts by itself and this page reloads. A sideby ui running in a terminal and sessions already running keep the old version until you restart them.',
|
|
23
23
|
'upd.cannot': 'sideby cannot update itself here: {why}. Run this yourself:',
|
|
24
|
-
'upd.skill': 'If you use the sideby skill, install it with:',
|
|
25
24
|
'upd.skillToo': 'The sideby skill agents read is updated with it.',
|
|
26
25
|
'upd.skillDone': 'The sideby skill was updated too; agents load it in their next session.',
|
|
27
26
|
'upd.skillManaged': 'sideby leaves the skill alone ({why}). Update it with:',
|
|
@@ -52,6 +51,29 @@ const en = {
|
|
|
52
51
|
'upd.done': 'Updated to sideby {v}.',
|
|
53
52
|
'upd.reloading': 'Waiting for the new version; this page reloads by itself.',
|
|
54
53
|
'upd.restartHint': 'This page still runs the old version. Restart sideby ui (or reload the page in your portal) to use the new one.',
|
|
54
|
+
'upd.skillLabel': 'Update skill',
|
|
55
|
+
'upd.skillLater': 'Once the new version is installed, open this again to bring the sideby skill agents read along.',
|
|
56
|
+
'upd.skillLabelLong': 'The sideby skill agents read is for {s}; this sideby is {cur}. Click to update it.',
|
|
57
|
+
'upd.skillBehind': 'The sideby skill agents read is still for {s}.',
|
|
58
|
+
'upd.skillNoVer': 'an older sideby',
|
|
59
|
+
'upd.skillWhat': 'Updating brings it to {cur}; agents use it from their next session.',
|
|
60
|
+
'upd.skillNow': 'Update skill',
|
|
61
|
+
'upd.skillDoneOnly': 'The sideby skill is up to date; agents use it from their next session.',
|
|
62
|
+
'upd.skillChanged': 'Nothing to update any more: sideby or the skill changed meanwhile. Look again below.',
|
|
63
|
+
'upd.manual': 'Update by hand',
|
|
64
|
+
'upd.localAvail': 'You are running a local build, and sideby {v} is out. Run this in the sideby checkout to go back to npm; the skill comes along:',
|
|
65
|
+
'upd.autoLocal': 'A local build does not update by itself.',
|
|
66
|
+
'why.local-build': 'this is a local build',
|
|
67
|
+
'why.npx': 'it runs from the npx cache, which fetches a version per run',
|
|
68
|
+
'why.volta': 'Volta manages this install',
|
|
69
|
+
'why.not-writable': '{at} cannot be written by you',
|
|
70
|
+
'why.project': 'it is a dependency of a project',
|
|
71
|
+
'why.source': 'it runs from a source checkout',
|
|
72
|
+
'why.skill-in-git': 'it is in the git repository {at}',
|
|
73
|
+
'off.local-build': 'Update checks are off for a local build.',
|
|
74
|
+
'off.env': 'Update checks are off ({why}).',
|
|
75
|
+
'off.config': 'Update checks are off (update.check is false in the config).',
|
|
76
|
+
'off.ci': 'Update checks are off in CI.',
|
|
55
77
|
'acct.title': 'Accounts',
|
|
56
78
|
'err.noAnswer': 'sideby did not answer. Retry once it is back.',
|
|
57
79
|
'err.session': 'Could not renew the session. Reload the page.',
|
|
@@ -107,8 +129,8 @@ const en = {
|
|
|
107
129
|
'stat.api.one': '{n} API',
|
|
108
130
|
'stat.api.other': '{n} API',
|
|
109
131
|
'stat.attention': 'Needs attention',
|
|
110
|
-
'stat.attentionOn': 'Show only these
|
|
111
|
-
'stat.attentionOff': 'Show all
|
|
132
|
+
'stat.attentionOn': 'Show only these',
|
|
133
|
+
'stat.attentionOff': 'Show all',
|
|
112
134
|
'stat.btnLabel': '{label}: {value} ({sub}). {action}',
|
|
113
135
|
'stat.allClear': 'All clear',
|
|
114
136
|
'stat.tokens': 'Tokens · {n} days',
|
|
@@ -149,9 +171,28 @@ const en = {
|
|
|
149
171
|
'order.moveAccount': 'Move {name}',
|
|
150
172
|
'order.position': '{name}: place {n} of {total}',
|
|
151
173
|
'order.failed': 'Could not save the order: {msg}. It is back as it was.',
|
|
174
|
+
'sort.arrange': 'Arrange order…',
|
|
175
|
+
'set.order': 'Account order and pins',
|
|
176
|
+
'set.orderMine': 'Yours',
|
|
177
|
+
'set.orderDefault': 'Default',
|
|
152
178
|
'order.resetButton': 'Default order',
|
|
153
|
-
'order.resetHint': 'Forget the order you
|
|
154
|
-
'order.reset': 'Back to the default order',
|
|
179
|
+
'order.resetHint': 'Forget the order you gave tools and accounts. Pinned accounts stay pinned.',
|
|
180
|
+
'order.reset': 'Back to the default order. Pinned accounts stay pinned.',
|
|
181
|
+
'order.bar': 'Drag, or use ↑ ↓, to change the order. Each change is saved at once.',
|
|
182
|
+
'order.done': 'Done',
|
|
183
|
+
'order.saved': 'Order saved',
|
|
184
|
+
'order.undo': 'Undo',
|
|
185
|
+
'order.undone': 'Order put back',
|
|
186
|
+
'order.up': 'Move {name} up',
|
|
187
|
+
'order.down': 'Move {name} down',
|
|
188
|
+
'order.sameFamily': 'Accounts move only within {title}.',
|
|
189
|
+
'pin.pin': 'Pin to top',
|
|
190
|
+
'pin.unpin': 'Unpin',
|
|
191
|
+
'pin.pinName': 'Pin {name} to the top of {title}',
|
|
192
|
+
'pin.unpinName': 'Unpin {name}',
|
|
193
|
+
'pin.full': 'At most {n} pinned per tool',
|
|
194
|
+
'pin.mark': 'Pinned',
|
|
195
|
+
'pin.failed': 'Could not save the pin: {msg}. It is back as it was.',
|
|
155
196
|
'quota.fetchFailed': 'Could not get the quota',
|
|
156
197
|
'quota.checkOff': 'Quota check off',
|
|
157
198
|
'quota.checkOffHint': 'Turn it on in Settings to see this quota.',
|
|
@@ -197,9 +238,11 @@ const en = {
|
|
|
197
238
|
'acct.signedOut': 'Signed out',
|
|
198
239
|
'acct.signInHint': 'Copy the sign-in command',
|
|
199
240
|
'acct.signedOutLabel': '{ref} is signed out: copy the sign-in command',
|
|
200
|
-
'acct.next': '
|
|
201
|
-
'acct.
|
|
202
|
-
'acct.
|
|
241
|
+
'acct.next': 'Suggested',
|
|
242
|
+
'acct.nextWhy': 'Of the {title} accounts, this one has the most quota left, so it is the one to use next. sideby never switches by itself.',
|
|
243
|
+
'acct.nextCopy': 'Copy the command that starts it',
|
|
244
|
+
'stat.needWho': '{names}',
|
|
245
|
+
'stat.needWhoMore': '{names} and {n} more',
|
|
203
246
|
'acct.sameLogin': 'Same login as {names}',
|
|
204
247
|
'acct.sameLoginHint': 'Signed in as the same login as {names}. The vendor counts one quota for all of them, so they show the same quota and a handoff never moves between them.',
|
|
205
248
|
'acct.notInstalled': 'Tool missing',
|
|
@@ -222,8 +265,14 @@ const en = {
|
|
|
222
265
|
'quota.asOf': 'As of {ago}',
|
|
223
266
|
'quota.sharedFrom': 'Same login as {name}; quota read from {name}, {ago}',
|
|
224
267
|
'login.label': 'Same login: {names}',
|
|
225
|
-
'login.
|
|
226
|
-
'login.
|
|
268
|
+
'login.dirs': '{n} directories · shared quota',
|
|
269
|
+
'login.explain': 'These directories are signed in to the same account, so their quota counts as one.',
|
|
270
|
+
'login.copyRun': 'Copy start command',
|
|
271
|
+
'login.showAs': 'Show this name',
|
|
272
|
+
'login.showAsHint': 'Name the row {name} instead',
|
|
273
|
+
'login.shown': 'Shown name',
|
|
274
|
+
'login.shownHint': 'The row is named after this directory',
|
|
275
|
+
'login.section': '{name}',
|
|
227
276
|
'login.hint': '{names} are signed in as the same login. The vendor counts one quota for all of them, so it shows once here, and a handoff never moves between them.',
|
|
228
277
|
'quota.noWindows': 'No quota windows reported.',
|
|
229
278
|
'quota.off': 'Quota not on',
|
|
@@ -243,8 +292,38 @@ const en = {
|
|
|
243
292
|
'quota.missing': 'No {label} window right now; it shows once that window starts.',
|
|
244
293
|
'quota.waiting': 'Waiting for the first status line… open a {host} session and send a message.',
|
|
245
294
|
'col.account': 'Account',
|
|
246
|
-
'col.used': '{label} used',
|
|
247
|
-
'col.left': '{label} left',
|
|
295
|
+
'col.used': '{label} · used',
|
|
296
|
+
'col.left': '{label} · left',
|
|
297
|
+
'finding.link.real-file': "{item} is this account's own copy, but it should be shared with the main account. sideby leaves it alone; see the details for how to share it.",
|
|
298
|
+
'finding.symlink-forbidden': "{item} is shared with another account, but it must be this account's own copy.",
|
|
299
|
+
'finding.link.other-target': '{item} is shared with somewhere other than the main account. Fine if you meant it.',
|
|
300
|
+
'finding.link.dangling': '{item} points to something that no longer exists.',
|
|
301
|
+
'finding.missing': '{item} is missing from this account.',
|
|
302
|
+
'finding.copy.type-mismatch': "{item} is a different kind of item than the main account's.",
|
|
303
|
+
'finding.copy.main-empty': "{item} differs, but the main account's copy is empty, so nothing is copied.",
|
|
304
|
+
'finding.copy.stale': "{item} is an older copy than the main account's.",
|
|
305
|
+
'finding.unsupported-type': '{item} is not a file, folder or link.',
|
|
306
|
+
'finding.json-key.symlink': '{item} is shared with another account, which would mix their sign-ins.',
|
|
307
|
+
'finding.json-key.main-unreadable': "The main account's {item} cannot be read.",
|
|
308
|
+
'finding.json-key.main-not-object': "The main account's {item} has an unexpected format.",
|
|
309
|
+
'finding.json-key.not-object': '{item} has an unexpected format; sideby will not change it.',
|
|
310
|
+
'finding.json-key.would-remove': '{item} has entries the main account does not; matching it would remove them.',
|
|
311
|
+
'finding.json-key.drift': '{item} no longer matches the main account.',
|
|
312
|
+
'finding.credential.mode': '{item} can be read by other users of this computer; it should be private.',
|
|
313
|
+
'finding.path.invalid': '{item} is a path outside the account folder, so sideby skips it.',
|
|
314
|
+
'finding.local.is-link': "{item} is shared with another account, but it must be this account's own.",
|
|
315
|
+
'finding.api.needs-own': "{item} must be this API account's own file.",
|
|
316
|
+
'finding.main.missing': 'There is no main account to share from.',
|
|
317
|
+
'finding.name.backup-like': 'This folder looks like a backup, not an account.',
|
|
318
|
+
'finding.secret.not-file': 'proxy.env must be a regular file.',
|
|
319
|
+
'finding.plugin.error': 'A plugin could not finish its check.',
|
|
320
|
+
'finding.extra-check.error': 'An extra check could not finish.',
|
|
321
|
+
'finding.fixHint': 'Click Fix all to fix it.',
|
|
322
|
+
'finding.raw': 'Details',
|
|
323
|
+
'win.5h': '5-hour',
|
|
324
|
+
'win.7d': 'Weekly',
|
|
325
|
+
'quota.resetsIn': 'resets in {d}',
|
|
326
|
+
'quota.staleShort': 'from {ago}',
|
|
248
327
|
'col.tokens': 'Tokens · {n} days',
|
|
249
328
|
'col.last': 'Last used',
|
|
250
329
|
'col.health': 'Health',
|
|
@@ -296,13 +375,45 @@ const en = {
|
|
|
296
375
|
'fix.hintAction': 'use Fix all',
|
|
297
376
|
'fix.off': 'Fix all is off: {why}',
|
|
298
377
|
'fix.whyNoCheck': 'Run a check first.',
|
|
299
|
-
'fix.whyManual': 'None of these findings has an automatic fix; follow the hint under each one.',
|
|
378
|
+
'fix.whyManual': 'None of these findings has an automatic fix; follow the hint under each one, or use Copy for AI to hand them to your AI agent.',
|
|
379
|
+
'fix.whyButton': 'Use the button beside each finding.',
|
|
380
|
+
'fix.copyAi': 'Copy for AI',
|
|
381
|
+
'fix.copyAiTitle': 'Copy a prompt for your AI agent that asks it to fix the findings without an automatic fix',
|
|
382
|
+
'fix.promptShown': 'the prompt for your AI agent',
|
|
383
|
+
'fix.promptLead': "sideby's health check found these problems that it cannot fix by itself. Fix each one by following its hint. Ask me before you delete, move or overwrite any of my files. For sideby commands, use the sideby skill, or read https://github.com/Adonis0123/sideby/blob/main/llms.txt.",
|
|
384
|
+
'fix.promptHint': 'Hint: ',
|
|
385
|
+
'fix.promptFixFirst': 'First run `sideby doctor --fix`: it fixes the other findings by itself.',
|
|
386
|
+
'fix.promptCheck': 'When you are done, run `sideby doctor` and tell me what is left.',
|
|
300
387
|
'fix.whyNothing': 'Nothing to fix.',
|
|
301
388
|
'fix.result': 'Fixed {ok} of {n}.',
|
|
302
389
|
'fix.nothing': 'Nothing needed fixing.',
|
|
303
390
|
'menu.title': 'More actions',
|
|
304
391
|
'menu.label': 'Actions for {ref}',
|
|
305
392
|
'menu.copyRun': 'Copy run command',
|
|
393
|
+
'menu.groupOpen': 'Open',
|
|
394
|
+
'ai.title': 'Ask your AI to do it',
|
|
395
|
+
'ai.installed': 'Skill installed',
|
|
396
|
+
'ai.notInstalled': 'How',
|
|
397
|
+
'ai.intro': 'Everything on this page can also be done by your AI coding assistant (Claude Code, Codex, Grok Build and others) with the sideby skill. Say what you want in plain words.',
|
|
398
|
+
'ai.ready': 'The sideby skill is installed on this computer. Open your assistant and ask.',
|
|
399
|
+
'ai.install': 'Install the skill once, in a terminal:',
|
|
400
|
+
'ai.examples': 'Things you can say (click to copy):',
|
|
401
|
+
'ai.copy': 'Copy',
|
|
402
|
+
'ai.ask.quota': 'Which of my Claude accounts has the most quota left?',
|
|
403
|
+
'ai.ask.new': 'Add another Claude account with the short command cc009.',
|
|
404
|
+
'ai.ask.pin': 'Pin claude:work to the top.',
|
|
405
|
+
'ai.ask.fix': 'Check my accounts and fix what they should share.',
|
|
406
|
+
'ai.ask.handoff': 'Turn on Auto Handoff.',
|
|
407
|
+
'ai.ask.rc': 'Turn off Remote Control for every Claude account.',
|
|
408
|
+
'ai.orderHint': 'or ask your AI',
|
|
409
|
+
'ai.emptyHint': 'Or let your AI assistant set it up for you.',
|
|
410
|
+
'ai.how': 'How',
|
|
411
|
+
'att.quota': 'Almost full',
|
|
412
|
+
'att.fix': 'Needs a fix',
|
|
413
|
+
'att.check': 'Take a look',
|
|
414
|
+
'menu.groupCopy': 'Copy',
|
|
415
|
+
'menu.groupManage': 'Manage',
|
|
416
|
+
'row.copyRun': 'Copy the start command: {cmd}',
|
|
306
417
|
'menu.copyAlias': 'Copy alias',
|
|
307
418
|
'menu.copyLogin': 'Copy sign-in command',
|
|
308
419
|
'menu.copyDir': 'Copy folder path',
|
|
@@ -404,7 +515,7 @@ const en = {
|
|
|
404
515
|
'hp.how3': 'After a {s}-second countdown (Enter cancels), the next account starts in the same terminal and carries on from the note.',
|
|
405
516
|
'hp.noStarters': 'None of your accounts can start a hand-over yet. Add a Claude, Codex or Grok account first.',
|
|
406
517
|
'hp.sameFamily': 'Also switch between accounts of the same tool (for example cc001 to cc002)',
|
|
407
|
-
'hp.turnOn': 'Turn on',
|
|
518
|
+
'hp.turnOn': 'Turn on Auto Handoff',
|
|
408
519
|
'hp.turnOff': 'Turn off',
|
|
409
520
|
'hp.willDo': 'To turn it on, sideby will:',
|
|
410
521
|
'hp.step.config': 'Switch Auto Handoff on in sideby’s settings',
|
|
@@ -471,6 +582,7 @@ const en = {
|
|
|
471
582
|
'tune.hostDefaultLong': 'Default (Claude Code decides)',
|
|
472
583
|
'tune.suggestedTag': 'suggested',
|
|
473
584
|
'tune.useThis': 'Use this',
|
|
585
|
+
'tune.custom': 'Choose a size yourself',
|
|
474
586
|
'tune.working': 'One moment…',
|
|
475
587
|
'tune.confirmTitle': 'This will change:',
|
|
476
588
|
'tune.change': 'Auto-compact size',
|
|
@@ -494,7 +606,8 @@ const en = {
|
|
|
494
606
|
'tpage.none': 'No account has been used enough to estimate yet.',
|
|
495
607
|
'tpage.idle': 'No use in this period: {list}',
|
|
496
608
|
'nf.title': 'New account',
|
|
497
|
-
'nf.intro': '
|
|
609
|
+
'nf.intro': 'A new local setup for the tool, next to your other accounts, sharing their skills and settings. You sign in to it after it is made.',
|
|
610
|
+
'nf.more': 'More options',
|
|
498
611
|
'nf.tool': 'Tool',
|
|
499
612
|
'nf.accounts.one': '{n} account',
|
|
500
613
|
'nf.accounts.other': '{n} accounts',
|
|
@@ -503,8 +616,8 @@ const en = {
|
|
|
503
616
|
'nf.broken': 'Install broken',
|
|
504
617
|
'nf.name': 'Name',
|
|
505
618
|
'nf.namePh': 'name',
|
|
506
|
-
'nf.api': 'API key
|
|
507
|
-
'nf.apiHint': '
|
|
619
|
+
'nf.api': 'Pay with an API key instead of a subscription',
|
|
620
|
+
'nf.apiHint': 'Leave off if you sign in with a subscription.',
|
|
508
621
|
'nf.dir': 'Folder',
|
|
509
622
|
'nf.launch': 'Start with',
|
|
510
623
|
'nf.create': 'Create account',
|
|
@@ -608,9 +721,9 @@ const en = {
|
|
|
608
721
|
'set.theme.light': 'Light',
|
|
609
722
|
'set.theme.dark': 'Dark',
|
|
610
723
|
'set.rcOn': 'Remote Control starts by itself',
|
|
611
|
-
'rc.button': 'Remote Control',
|
|
724
|
+
'rc.button': 'Remote Control (continue on phone or web)',
|
|
612
725
|
'rc.state.on': 'On',
|
|
613
|
-
'rc.state.default': '
|
|
726
|
+
'rc.state.default': 'Left to Claude Code',
|
|
614
727
|
'rc.state.off': 'Off',
|
|
615
728
|
'rc.state.missing': 'No settings file',
|
|
616
729
|
'rc.state.blocked': 'Cannot read',
|
|
@@ -650,7 +763,6 @@ const zh = {
|
|
|
650
763
|
'upd.runs': '更新会运行:',
|
|
651
764
|
'upd.after': '后台面板会自己重启,本页随后自动刷新。终端里运行的 sideby ui 和已经在跑的会话要重启后才用新版本。',
|
|
652
765
|
'upd.cannot': '这种安装方式下 sideby 不能自己更新:{why}。请自己运行:',
|
|
653
|
-
'upd.skill': '如果要用 sideby skill,用这条命令安装:',
|
|
654
766
|
'upd.skillToo': 'agent 读的 sideby skill 会一起更新。',
|
|
655
767
|
'upd.skillDone': 'sideby skill 也已更新,agent 下次开会话时生效。',
|
|
656
768
|
'upd.skillManaged': 'sideby 不会自动更新这个 skill({why})。请用这条命令更新:',
|
|
@@ -681,6 +793,29 @@ const zh = {
|
|
|
681
793
|
'upd.done': '已更新到 sideby {v}。',
|
|
682
794
|
'upd.reloading': '等待新版本启动,本页会自动刷新。',
|
|
683
795
|
'upd.restartHint': '本页仍在运行旧版本。重启 sideby ui(在 Portal 里就刷新页面)后使用新版本。',
|
|
796
|
+
'upd.skillLabel': '更新 skill',
|
|
797
|
+
'upd.skillLater': '装好新版本后,再打开这里把 agent 用的 sideby skill 一起更新。',
|
|
798
|
+
'upd.skillLabelLong': 'agent 用的 sideby skill 还是 {s},当前 sideby 是 {cur}。点击更新。',
|
|
799
|
+
'upd.skillBehind': 'agent 用的 sideby skill 还是 {s}。',
|
|
800
|
+
'upd.skillNoVer': '旧版本',
|
|
801
|
+
'upd.skillWhat': '更新后变成 {cur},agent 下次开会话时生效。',
|
|
802
|
+
'upd.skillNow': '更新 skill',
|
|
803
|
+
'upd.skillDoneOnly': 'sideby skill 已是最新,agent 下次开会话时生效。',
|
|
804
|
+
'upd.skillChanged': '现在没有要更新的了:sideby 或 skill 刚刚变过。请看下面的最新状态。',
|
|
805
|
+
'upd.manual': '手动更新',
|
|
806
|
+
'upd.localAvail': '你在用本地构建,sideby {v} 已发布。在 sideby 仓库运行这条命令切回 npm 版,skill 会一起同步:',
|
|
807
|
+
'upd.autoLocal': '本地构建不自动更新。',
|
|
808
|
+
'why.local-build': '这是本地构建',
|
|
809
|
+
'why.npx': '它从 npx 缓存运行,每次运行都会取一个版本',
|
|
810
|
+
'why.volta': '这个安装由 Volta 管理',
|
|
811
|
+
'why.not-writable': '你没有 {at} 的写权限',
|
|
812
|
+
'why.project': '它是某个项目的依赖',
|
|
813
|
+
'why.source': '它从源码仓库运行',
|
|
814
|
+
'why.skill-in-git': '它在 git 仓库 {at} 里',
|
|
815
|
+
'off.local-build': '本地构建不检查更新。',
|
|
816
|
+
'off.env': '检查更新已关闭({why})。',
|
|
817
|
+
'off.config': '检查更新已关闭(配置里 update.check 为 false)。',
|
|
818
|
+
'off.ci': 'CI 里不检查更新。',
|
|
684
819
|
'acct.title': '账号',
|
|
685
820
|
'err.noAnswer': 'sideby 没有响应,恢复后再重试。',
|
|
686
821
|
'err.session': '无法续期会话,请刷新页面。',
|
|
@@ -736,14 +871,14 @@ const zh = {
|
|
|
736
871
|
'stat.api.one': '{n} 个 API',
|
|
737
872
|
'stat.api.other': '{n} 个 API',
|
|
738
873
|
'stat.attention': '需要处理',
|
|
739
|
-
'stat.attentionOn': '
|
|
740
|
-
'stat.attentionOff': '
|
|
874
|
+
'stat.attentionOn': '只看这些',
|
|
875
|
+
'stat.attentionOff': '显示全部',
|
|
741
876
|
'stat.btnLabel': '{label}:{value}({sub})。{action}',
|
|
742
877
|
'stat.allClear': '一切正常',
|
|
743
878
|
'stat.tokens': '近 {n} 天 tokens',
|
|
744
879
|
'stat.sessions.one': '{n} 个会话',
|
|
745
880
|
'stat.sessions.other': '{n} 个会话',
|
|
746
|
-
'stat.nextReset': '
|
|
881
|
+
'stat.nextReset': '下一次额度重置',
|
|
747
882
|
'stat.noQuota': '暂无额度数据',
|
|
748
883
|
'need.error.one': '{n} 个读取失败',
|
|
749
884
|
'need.error.other': '{n} 个读取失败',
|
|
@@ -778,9 +913,28 @@ const zh = {
|
|
|
778
913
|
'order.moveAccount': '移动 {name}',
|
|
779
914
|
'order.position': '{name}:第 {n} 个,共 {total} 个',
|
|
780
915
|
'order.failed': '顺序没有保存:{msg}。已恢复原来的顺序。',
|
|
781
|
-
'
|
|
782
|
-
'order
|
|
783
|
-
'
|
|
916
|
+
'sort.arrange': '调整顺序…',
|
|
917
|
+
'set.order': '账号顺序与置顶',
|
|
918
|
+
'set.orderMine': '已调整',
|
|
919
|
+
'set.orderDefault': '默认',
|
|
920
|
+
'order.resetButton': '恢复默认顺序',
|
|
921
|
+
'order.resetHint': '忘掉你排的工具和账号顺序,置顶会保留',
|
|
922
|
+
'order.reset': '已恢复默认顺序,置顶保留',
|
|
923
|
+
'order.bar': '拖动或用 ↑ ↓ 调整顺序,改动立即保存',
|
|
924
|
+
'order.done': '完成',
|
|
925
|
+
'order.saved': '已保存顺序',
|
|
926
|
+
'order.undo': '撤销',
|
|
927
|
+
'order.undone': '已恢复原来的顺序',
|
|
928
|
+
'order.up': '上移 {name}',
|
|
929
|
+
'order.down': '下移 {name}',
|
|
930
|
+
'order.sameFamily': '账号只能在 {title} 里调整。',
|
|
931
|
+
'pin.pin': '置顶',
|
|
932
|
+
'pin.unpin': '取消置顶',
|
|
933
|
+
'pin.pinName': '把 {name} 置顶到 {title} 最前',
|
|
934
|
+
'pin.unpinName': '取消置顶 {name}',
|
|
935
|
+
'pin.full': '每组最多置顶 {n} 个',
|
|
936
|
+
'pin.mark': '已置顶',
|
|
937
|
+
'pin.failed': '置顶没有保存:{msg}。已恢复原样。',
|
|
784
938
|
'quota.fetchFailed': '没拿到额度',
|
|
785
939
|
'quota.checkOff': '额度查询已关',
|
|
786
940
|
'quota.checkOffHint': '在「设置」里打开,就能看到这份额度。',
|
|
@@ -826,9 +980,11 @@ const zh = {
|
|
|
826
980
|
'acct.signedOut': '未登录',
|
|
827
981
|
'acct.signInHint': '复制登录命令',
|
|
828
982
|
'acct.signedOutLabel': '{ref} 未登录:复制登录命令',
|
|
829
|
-
'acct.next': '
|
|
830
|
-
'acct.
|
|
831
|
-
'acct.
|
|
983
|
+
'acct.next': '建议使用',
|
|
984
|
+
'acct.nextWhy': '{title} 的账号里,这个剩余额度最多,接下来用它最合适。sideby 不会自己切换。',
|
|
985
|
+
'acct.nextCopy': '复制启动它的命令',
|
|
986
|
+
'stat.needWho': '{names}',
|
|
987
|
+
'stat.needWhoMore': '{names} 等 {n} 个',
|
|
832
988
|
'acct.sameLogin': '与 {names} 同一登录',
|
|
833
989
|
'acct.sameLoginHint': '与 {names} 用同一个身份登录。供应商只算一份额度,所以它们显示同一份额度,交接也不会在它们之间进行。',
|
|
834
990
|
'acct.notInstalled': '未安装工具',
|
|
@@ -851,8 +1007,14 @@ const zh = {
|
|
|
851
1007
|
'quota.asOf': '截至 {ago}',
|
|
852
1008
|
'quota.sharedFrom': '与 {name} 同一登录;额度读自 {name},{ago}',
|
|
853
1009
|
'login.label': '同一登录:{names}',
|
|
854
|
-
'login.
|
|
855
|
-
'login.
|
|
1010
|
+
'login.dirs': '{n} 个目录 · 共用额度',
|
|
1011
|
+
'login.explain': '这几个目录登录的是同一个账号,额度一起算。',
|
|
1012
|
+
'login.copyRun': '复制启动命令',
|
|
1013
|
+
'login.showAs': '设为显示名',
|
|
1014
|
+
'login.showAsHint': '这一行改用 {name} 的名字显示',
|
|
1015
|
+
'login.shown': '显示名',
|
|
1016
|
+
'login.shownHint': '这一行用这个目录的名字显示',
|
|
1017
|
+
'login.section': '{name}',
|
|
856
1018
|
'login.hint': '{names} 用同一个身份登录。供应商只算一份额度,所以这里只显示一次,交接也不会在它们之间进行。',
|
|
857
1019
|
'quota.noWindows': '没有额度窗口数据。',
|
|
858
1020
|
'quota.off': '额度未开启',
|
|
@@ -872,8 +1034,38 @@ const zh = {
|
|
|
872
1034
|
'quota.missing': '暂无 {label} 窗口,窗口开始后显示。',
|
|
873
1035
|
'quota.waiting': '等待第一次状态栏刷新…打开 {host} 会话并发一条消息。',
|
|
874
1036
|
'col.account': '账号',
|
|
875
|
-
'col.used': '{label} 已用',
|
|
876
|
-
'col.left': '{label} 剩余',
|
|
1037
|
+
'col.used': '{label} · 已用',
|
|
1038
|
+
'col.left': '{label} · 剩余',
|
|
1039
|
+
'finding.link.real-file': '{item} 是这个账号自己的一份,本应和主账号共用。sideby 不会动它,怎么改成共用见详情。',
|
|
1040
|
+
'finding.symlink-forbidden': '{item} 现在和别的账号共用,但它必须是这个账号自己的一份。',
|
|
1041
|
+
'finding.link.other-target': '{item} 共用的不是主账号的那份。如果是你故意这样设的,可以不管。',
|
|
1042
|
+
'finding.link.dangling': '{item} 指向的东西已经不存在了。',
|
|
1043
|
+
'finding.missing': '这个账号缺少 {item}。',
|
|
1044
|
+
'finding.copy.type-mismatch': '{item} 的类型和主账号的不一样。',
|
|
1045
|
+
'finding.copy.main-empty': '{item} 和主账号不同,但主账号那份是空的,所以没有复制。',
|
|
1046
|
+
'finding.copy.stale': '{item} 比主账号的旧。',
|
|
1047
|
+
'finding.unsupported-type': '{item} 不是文件、文件夹或链接。',
|
|
1048
|
+
'finding.json-key.symlink': '{item} 和别的账号共用,会把两个账号的登录混在一起。',
|
|
1049
|
+
'finding.json-key.main-unreadable': '读不了主账号的 {item}。',
|
|
1050
|
+
'finding.json-key.main-not-object': '主账号的 {item} 格式不对。',
|
|
1051
|
+
'finding.json-key.not-object': '{item} 格式不对,sideby 不会改它。',
|
|
1052
|
+
'finding.json-key.would-remove': '{item} 里有主账号没有的条目,同步会把它们删掉。',
|
|
1053
|
+
'finding.json-key.drift': '{item} 和主账号的不一致了。',
|
|
1054
|
+
'finding.credential.mode': '{item} 这台电脑上的其他用户也能读到,应该只有你能读。',
|
|
1055
|
+
'finding.path.invalid': '{item} 的路径跑到账号文件夹外面了,sideby 跳过它。',
|
|
1056
|
+
'finding.local.is-link': '{item} 现在和别的账号共用,但它必须是这个账号自己的。',
|
|
1057
|
+
'finding.api.needs-own': '{item} 必须是这个 API 账号自己的文件。',
|
|
1058
|
+
'finding.main.missing': '没有可以共享的主账号。',
|
|
1059
|
+
'finding.name.backup-like': '这个文件夹看起来是备份,不是账号。',
|
|
1060
|
+
'finding.secret.not-file': 'proxy.env 必须是普通文件。',
|
|
1061
|
+
'finding.plugin.error': '有一个插件没能完成检查。',
|
|
1062
|
+
'finding.extra-check.error': '有一项额外检查没能完成。',
|
|
1063
|
+
'finding.fixHint': '点「全部修复」就能修好。',
|
|
1064
|
+
'finding.raw': '详情',
|
|
1065
|
+
'win.5h': '5 小时额度',
|
|
1066
|
+
'win.7d': '每周额度',
|
|
1067
|
+
'quota.resetsIn': '{d}后重置',
|
|
1068
|
+
'quota.staleShort': '{ago}的数据',
|
|
877
1069
|
'col.tokens': 'Tokens · 近 {n} 天',
|
|
878
1070
|
'col.last': '最近使用',
|
|
879
1071
|
'col.health': '健康',
|
|
@@ -925,13 +1117,45 @@ const zh = {
|
|
|
925
1117
|
'fix.hintAction': '点「全部修复」',
|
|
926
1118
|
'fix.off': '“全部修复”不可用:{why}',
|
|
927
1119
|
'fix.whyNoCheck': '请先运行检查。',
|
|
928
|
-
'fix.whyManual': '
|
|
1120
|
+
'fix.whyManual': '这些发现都不能自动修复:按每条下面的提示处理,或点「复制给 AI 修复」交给你的 AI agent。',
|
|
1121
|
+
'fix.whyButton': '点每条旁边的按钮修复。',
|
|
1122
|
+
'fix.copyAi': '复制给 AI 修复',
|
|
1123
|
+
'fix.copyAiTitle': '复制一段提示词,粘贴给你的 AI agent,让它修好不能自动修复的问题',
|
|
1124
|
+
'fix.promptShown': '给 AI 的提示词',
|
|
1125
|
+
'fix.promptLead': 'sideby 的健康检查发现了下面这些它不能自动修复的问题。请逐条按提示修好。删除、移动或覆盖我的文件前先问我。sideby 的命令用法看 sideby skill,或读 https://github.com/Adonis0123/sideby/blob/main/llms.txt。',
|
|
1126
|
+
'fix.promptHint': '提示:',
|
|
1127
|
+
'fix.promptFixFirst': '先运行 `sideby doctor --fix`,它会自动修好其余的问题。',
|
|
1128
|
+
'fix.promptCheck': '修完运行 `sideby doctor`,告诉我还剩什么。',
|
|
929
1129
|
'fix.whyNothing': '没有需要修复的内容。',
|
|
930
1130
|
'fix.result': '已修复 {ok} / {n} 项。',
|
|
931
1131
|
'fix.nothing': '没有需要修复的内容。',
|
|
932
1132
|
'menu.title': '更多操作',
|
|
933
1133
|
'menu.label': '{ref} 的操作',
|
|
934
1134
|
'menu.copyRun': '复制启动命令',
|
|
1135
|
+
'menu.groupOpen': '打开',
|
|
1136
|
+
'ai.title': '让 AI 帮你操作',
|
|
1137
|
+
'ai.installed': '已安装 skill',
|
|
1138
|
+
'ai.notInstalled': '怎么用',
|
|
1139
|
+
'ai.intro': '这个页面能做的事,你的 AI 编程助手(Claude Code、Codex、Grok Build 等)装上 sideby skill 后也都能做。用大白话说你想做什么就行。',
|
|
1140
|
+
'ai.ready': '这台电脑已经装好 sideby skill,打开你的编程助手直接说就行。',
|
|
1141
|
+
'ai.install': '先在终端里装一次 skill:',
|
|
1142
|
+
'ai.examples': '可以这样说(点一下复制):',
|
|
1143
|
+
'ai.copy': '复制',
|
|
1144
|
+
'ai.ask.quota': '我哪个 Claude 账号剩余额度最多?',
|
|
1145
|
+
'ai.ask.new': '再加一个 Claude 账号,短命令叫 cc009。',
|
|
1146
|
+
'ai.ask.pin': '把 claude:work 置顶。',
|
|
1147
|
+
'ai.ask.fix': '检查一下我的账号,把该共享的修好。',
|
|
1148
|
+
'ai.ask.handoff': '帮我开启自动交接。',
|
|
1149
|
+
'ai.ask.rc': '把所有 Claude 账号的远程控制关掉。',
|
|
1150
|
+
'ai.orderHint': '也可以让 AI 帮你排',
|
|
1151
|
+
'ai.emptyHint': '也可以让你的 AI 编程助手帮你装好、加账号。',
|
|
1152
|
+
'ai.how': '怎么做',
|
|
1153
|
+
'att.quota': '快用完',
|
|
1154
|
+
'att.fix': '需要修复',
|
|
1155
|
+
'att.check': '看一下',
|
|
1156
|
+
'menu.groupCopy': '复制',
|
|
1157
|
+
'menu.groupManage': '管理',
|
|
1158
|
+
'row.copyRun': '复制启动命令:{cmd}',
|
|
935
1159
|
'menu.copyAlias': '复制别名',
|
|
936
1160
|
'menu.copyLogin': '复制登录命令',
|
|
937
1161
|
'menu.copyDir': '复制目录路径',
|
|
@@ -1033,7 +1257,7 @@ const zh = {
|
|
|
1033
1257
|
'hp.how3': '倒计时 {s} 秒后(按回车可取消),下一个账号在同一个终端里按小结接着做。',
|
|
1034
1258
|
'hp.noStarters': '你的账号里还没有能发起交接的。先添加一个 Claude、Codex 或 Grok 账号。',
|
|
1035
1259
|
'hp.sameFamily': '同一个工具的账号之间也切换(例如 cc001 到 cc002)',
|
|
1036
|
-
'hp.turnOn': '
|
|
1260
|
+
'hp.turnOn': '开启自动交接',
|
|
1037
1261
|
'hp.turnOff': '关闭',
|
|
1038
1262
|
'hp.willDo': '开启时 sideby 会:',
|
|
1039
1263
|
'hp.step.config': '在 sideby 的设置里打开自动交接',
|
|
@@ -1100,6 +1324,7 @@ const zh = {
|
|
|
1100
1324
|
'tune.hostDefaultLong': '默认(由 Claude Code 自己决定)',
|
|
1101
1325
|
'tune.suggestedTag': '建议',
|
|
1102
1326
|
'tune.useThis': '使用这个',
|
|
1327
|
+
'tune.custom': '自己选一个大小',
|
|
1103
1328
|
'tune.working': '稍等…',
|
|
1104
1329
|
'tune.confirmTitle': '将会修改:',
|
|
1105
1330
|
'tune.change': '自动压缩大小',
|
|
@@ -1123,7 +1348,8 @@ const zh = {
|
|
|
1123
1348
|
'tpage.none': '还没有账号用得够多,没法估算。',
|
|
1124
1349
|
'tpage.idle': '这段时间没有使用:{list}',
|
|
1125
1350
|
'nf.title': '新建账号',
|
|
1126
|
-
'nf.intro': '
|
|
1351
|
+
'nf.intro': '为这个工具新建一份本地配置,和其他账号并排运行,共用它们的技能和设置。建好后再登录。',
|
|
1352
|
+
'nf.more': '更多选项',
|
|
1127
1353
|
'nf.tool': '工具',
|
|
1128
1354
|
'nf.accounts.one': '{n} 个账号',
|
|
1129
1355
|
'nf.accounts.other': '{n} 个账号',
|
|
@@ -1132,8 +1358,8 @@ const zh = {
|
|
|
1132
1358
|
'nf.broken': '安装已损坏',
|
|
1133
1359
|
'nf.name': '名称',
|
|
1134
1360
|
'nf.namePh': '名称',
|
|
1135
|
-
'nf.api': 'API key
|
|
1136
|
-
'nf.apiHint': '
|
|
1361
|
+
'nf.api': '用 API key 付费(不用订阅登录)',
|
|
1362
|
+
'nf.apiHint': '用订阅登录的账号不要勾选。',
|
|
1137
1363
|
'nf.dir': '目录',
|
|
1138
1364
|
'nf.launch': '启动命令',
|
|
1139
1365
|
'nf.create': '创建账号',
|
|
@@ -1237,9 +1463,9 @@ const zh = {
|
|
|
1237
1463
|
'set.theme.light': '浅色',
|
|
1238
1464
|
'set.theme.dark': '深色',
|
|
1239
1465
|
'set.rcOn': 'Remote Control 会自动打开',
|
|
1240
|
-
'rc.button': 'Remote Control',
|
|
1466
|
+
'rc.button': '远程控制(Remote Control)',
|
|
1241
1467
|
'rc.state.on': '开',
|
|
1242
|
-
'rc.state.default': '
|
|
1468
|
+
'rc.state.default': '由 Claude Code 决定',
|
|
1243
1469
|
'rc.state.off': '关',
|
|
1244
1470
|
'rc.state.missing': '没有设置文件',
|
|
1245
1471
|
'rc.state.blocked': '读不了',
|
|
@@ -106,6 +106,22 @@ export declare function reorder(all: readonly string[], shown: readonly (readonl
|
|
|
106
106
|
* Display Order `order`, names not in it after). The Main Account leads ties.
|
|
107
107
|
*/
|
|
108
108
|
export declare function sortAccounts<T extends LogicAccount>(list: T[], mode: string, now: number, order?: readonly string[]): T[];
|
|
109
|
+
/**
|
|
110
|
+
* Whether an Account is pinned (spec §3.25): its name is in `pinned`, or, for a Same Login, the name of any of its
|
|
111
|
+
* directories, so the login is pinned as a whole.
|
|
112
|
+
*/
|
|
113
|
+
export declare function pinnedIn(a: {
|
|
114
|
+
name: string;
|
|
115
|
+
sameLogin?: readonly string[];
|
|
116
|
+
}, pinned: readonly string[]): boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Pinned Accounts first (spec §3.25): the names in `pinned`, in that order, then the rest in the order they came.
|
|
119
|
+
* A Same Login follows any of its pinned directories, so it stays together. Names no longer there are simply not met.
|
|
120
|
+
*/
|
|
121
|
+
export declare function withPinned<T extends {
|
|
122
|
+
name: string;
|
|
123
|
+
sameLogin?: readonly string[];
|
|
124
|
+
}>(list: readonly T[], pinned?: readonly string[]): T[];
|
|
109
125
|
/**
|
|
110
126
|
* The sorted list with each Same Login together (spec §3.21): an Account, or the shown members of one login, in
|
|
111
127
|
* order, at the place of its first member. A login with one shown member stays a plain Account.
|
|
@@ -157,6 +173,31 @@ export declare function suggestName(names: string[]): string;
|
|
|
157
173
|
* that are not fixable, and `--fix --force`, keep the command: Fix all would not do them.
|
|
158
174
|
*/
|
|
159
175
|
export declare function panelHint(hint: string, fixable: boolean, action: string): string;
|
|
176
|
+
/**
|
|
177
|
+
* Whether the Panel fixes Finding `f` with a button of its own: a sideby skill behind this version while the
|
|
178
|
+
* Update plan says sideby may update it (`skillUpdatable`). Such Findings stay out of the prompt for an AI agent.
|
|
179
|
+
*/
|
|
180
|
+
export declare function panelFixes(f: {
|
|
181
|
+
code?: string;
|
|
182
|
+
}, skillUpdatable: boolean): boolean;
|
|
183
|
+
/**
|
|
184
|
+
* The prompt "Copy for AI" puts on the clipboard: `words.lead`, then each Finding that has no automatic fix
|
|
185
|
+
* (numbered, with its account, item, level, message and hint), then `words.fixFirst` when some Findings do have
|
|
186
|
+
* one, then `words.check`. Empty when every Finding has an automatic fix. `words.hint` labels a hint line.
|
|
187
|
+
*/
|
|
188
|
+
export declare function fixPrompt(findings: readonly {
|
|
189
|
+
account: string;
|
|
190
|
+
item: string;
|
|
191
|
+
level: string;
|
|
192
|
+
message: string;
|
|
193
|
+
hint?: string;
|
|
194
|
+
fixable?: boolean;
|
|
195
|
+
}[], words: {
|
|
196
|
+
lead: string;
|
|
197
|
+
hint: string;
|
|
198
|
+
fixFirst: string;
|
|
199
|
+
check: string;
|
|
200
|
+
}): string;
|
|
160
201
|
/**
|
|
161
202
|
* A short command to offer for a new Account `name` of a Family, from the config aliases of its existing Accounts:
|
|
162
203
|
* an alias that is a prefix plus its Account's name (`cc001` for `claude:001`) gives the prefix, the most common
|
|
@@ -181,6 +181,27 @@ export function sortAccounts(list, mode, now, order) {
|
|
|
181
181
|
out.sort((x, y) => pressure(y) - pressure(x) || byName(x, y));
|
|
182
182
|
return out;
|
|
183
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Whether an Account is pinned (spec §3.25): its name is in `pinned`, or, for a Same Login, the name of any of its
|
|
186
|
+
* directories, so the login is pinned as a whole.
|
|
187
|
+
*/
|
|
188
|
+
export function pinnedIn(a, pinned) {
|
|
189
|
+
return (pinned.includes(a.name) || (a.sameLogin ?? []).some((r) => pinned.includes(r.slice(r.indexOf(':') + 1))));
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Pinned Accounts first (spec §3.25): the names in `pinned`, in that order, then the rest in the order they came.
|
|
193
|
+
* A Same Login follows any of its pinned directories, so it stays together. Names no longer there are simply not met.
|
|
194
|
+
*/
|
|
195
|
+
export function withPinned(list, pinned) {
|
|
196
|
+
if (!pinned?.length)
|
|
197
|
+
return list.slice();
|
|
198
|
+
const top = [];
|
|
199
|
+
for (const n of pinned)
|
|
200
|
+
for (const a of list)
|
|
201
|
+
if (!top.includes(a) && pinnedIn(a, [n]))
|
|
202
|
+
top.push(a);
|
|
203
|
+
return top.concat(list.filter((a) => !top.includes(a)));
|
|
204
|
+
}
|
|
184
205
|
/**
|
|
185
206
|
* The sorted list with each Same Login together (spec §3.21): an Account, or the shown members of one login, in
|
|
186
207
|
* order, at the place of its first member. A login with one shown member stays a plain Account.
|
|
@@ -336,6 +357,31 @@ export function panelHint(hint, fixable, action) {
|
|
|
336
357
|
return hint;
|
|
337
358
|
return hint.replace(/run `sideby doctor --fix`/g, (_m, at) => at === 0 ? action.charAt(0).toUpperCase() + action.slice(1) : action);
|
|
338
359
|
}
|
|
360
|
+
/**
|
|
361
|
+
* Whether the Panel fixes Finding `f` with a button of its own: a sideby skill behind this version while the
|
|
362
|
+
* Update plan says sideby may update it (`skillUpdatable`). Such Findings stay out of the prompt for an AI agent.
|
|
363
|
+
*/
|
|
364
|
+
export function panelFixes(f, skillUpdatable) {
|
|
365
|
+
return skillUpdatable && f.code === 'skill.outdated';
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* The prompt "Copy for AI" puts on the clipboard: `words.lead`, then each Finding that has no automatic fix
|
|
369
|
+
* (numbered, with its account, item, level, message and hint), then `words.fixFirst` when some Findings do have
|
|
370
|
+
* one, then `words.check`. Empty when every Finding has an automatic fix. `words.hint` labels a hint line.
|
|
371
|
+
*/
|
|
372
|
+
export function fixPrompt(findings, words) {
|
|
373
|
+
const manual = findings.filter((f) => !f.fixable);
|
|
374
|
+
if (!manual.length)
|
|
375
|
+
return '';
|
|
376
|
+
const items = manual.map((f, i) => {
|
|
377
|
+
const lines = [i + 1 + '. [' + f.level + '] ' + f.account + ' · ' + f.item, ' ' + f.message];
|
|
378
|
+
if (f.hint)
|
|
379
|
+
lines.push(' ' + words.hint + f.hint);
|
|
380
|
+
return lines.join('\n');
|
|
381
|
+
});
|
|
382
|
+
const tail = manual.length < findings.length ? [words.fixFirst, words.check] : [words.check];
|
|
383
|
+
return [words.lead, items.join('\n\n'), ...tail].join('\n\n');
|
|
384
|
+
}
|
|
339
385
|
/**
|
|
340
386
|
* A short command to offer for a new Account `name` of a Family, from the config aliases of its existing Accounts:
|
|
341
387
|
* an alias that is a prefix plus its Account's name (`cc001` for `claude:001`) gives the prefix, the most common
|