@cortexkit/opencode-anthropic-auth 1.23.0 → 2.0.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.
Files changed (82) hide show
  1. package/README.md +239 -195
  2. package/dist/cli-failure.d.ts +69 -0
  3. package/dist/cli.d.ts +14 -9
  4. package/dist/cli.js +98 -76
  5. package/dist/custody-dimensions.d.ts +7 -24
  6. package/dist/custody-mode.d.ts +29 -169
  7. package/dist/effort-history.d.ts +6 -1
  8. package/dist/index-1jkyhgyr.js +2 -0
  9. package/dist/{index-8y2t4mwz.js → index-2arfb1y3.js} +1 -1
  10. package/dist/{index-0jfsxyn9.js → index-4ya27n12.js} +1 -1
  11. package/dist/index-aaajxwzd.js +2 -0
  12. package/dist/index-ae3fq4n6.js +42 -0
  13. package/dist/{index-xzbhzz0a.js → index-fds0s2j4.js} +2 -2
  14. package/dist/index-nngmvczq.js +450 -0
  15. package/dist/index-pn597b6f.js +2 -0
  16. package/dist/{index-1gr8v4fn.js → index-rqync0pc.js} +1 -1
  17. package/dist/index.js +1 -38
  18. package/dist/native-command.d.ts +19 -0
  19. package/dist/rpc/notifications.d.ts +2 -1
  20. package/dist/rpc/port-file.js +1 -1
  21. package/dist/rpc/protocol.d.ts +8 -4
  22. package/dist/rpc/protocol.js +1 -1
  23. package/dist/rpc/rpc-client.d.ts +2 -0
  24. package/dist/rpc/rpc-client.js +1 -1
  25. package/dist/rpc/rpc-dir.js +1 -1
  26. package/dist/rpc/rpc-server.d.ts +5 -1
  27. package/dist/setup/command.d.ts +12 -0
  28. package/dist/setup/command.test.d.ts +1 -0
  29. package/dist/setup/native-activation.d.ts +29 -0
  30. package/dist/setup/native-enrollment.d.ts +26 -0
  31. package/dist/setup/native-enrollment.test.d.ts +1 -0
  32. package/dist/setup/native-local.d.ts +20 -0
  33. package/dist/setup/native-login.d.ts +3 -0
  34. package/dist/setup/native-paths.d.ts +15 -0
  35. package/dist/setup/native-paths.test.d.ts +1 -0
  36. package/dist/setup/pi.d.ts +13 -3
  37. package/dist/setup/process-fence.d.ts +7 -1
  38. package/dist/setup/process-fence.test.d.ts +1 -0
  39. package/dist/sidebar-state.js +1 -1
  40. package/dist/tui/command-dialogs.d.ts +5 -0
  41. package/dist/tui-preferences.js +2 -2
  42. package/dist/v2/activation.d.ts +7 -0
  43. package/dist/v2/adapter.d.ts +276 -0
  44. package/dist/v2/install.d.ts +13 -0
  45. package/dist/v2/lifecycle.d.ts +8 -0
  46. package/dist/v2/menu-contract.d.ts +8 -0
  47. package/dist/v2/menu.d.ts +10 -0
  48. package/dist/v2/models.d.ts +6 -0
  49. package/dist/v2/ownership.d.ts +11 -0
  50. package/dist/v2/prime.d.ts +12 -0
  51. package/dist/v2/rpc.d.ts +50 -0
  52. package/dist/v2/server.d.ts +8 -0
  53. package/dist/v2/server.js +4 -0
  54. package/dist/v2/setup.d.ts +58 -0
  55. package/dist/v2/source.d.ts +41 -0
  56. package/dist/v2/tui.d.ts +13 -0
  57. package/dist/v2/tui.js +2 -0
  58. package/dist/v2/wire.d.ts +36 -0
  59. package/package.json +20 -5
  60. package/src/rpc/notifications.ts +9 -2
  61. package/src/rpc/protocol.ts +8 -7
  62. package/src/rpc/rpc-client.ts +17 -0
  63. package/src/rpc/rpc-server.ts +20 -3
  64. package/src/tui/command-dialogs.tsx +264 -0
  65. package/src/tui/entry.mjs +44 -18
  66. package/src/tui-compiled/rpc/protocol.ts +8 -7
  67. package/src/tui-compiled/rpc/rpc-client.ts +17 -0
  68. package/src/tui-compiled/tui/command-dialogs.tsx +315 -76
  69. package/src/tui-compiled/tui.tsx +24 -7
  70. package/src/tui.tsx +37 -9
  71. package/dist/claustrum-enrollment-registry.d.ts +0 -4
  72. package/dist/custody-enrollment.d.ts +0 -14
  73. package/dist/custody-live.d.ts +0 -111
  74. package/dist/custody-manifest-watcher.d.ts +0 -16
  75. package/dist/index-1fq7h6yd.js +0 -430
  76. package/dist/index-797pmamn.js +0 -2
  77. package/dist/index-a5d6v3ba.js +0 -5
  78. package/dist/index-n96q8pks.js +0 -2
  79. package/dist/index-xxhyhp98.js +0 -2
  80. package/dist/index-z7gfdyv3.js +0 -1
  81. package/dist/local-login.d.ts +0 -64
  82. package/dist/logger-kk9vyem9.js +0 -1
@@ -1,14 +1,253 @@
1
1
  import { createTextNode as _$createTextNode } from "opentui:runtime-module:%40opentui%2Fsolid";
2
2
  import { effect as _$effect } from "opentui:runtime-module:%40opentui%2Fsolid";
3
3
  import { memo as _$memo } from "opentui:runtime-module:%40opentui%2Fsolid";
4
- import { createComponent as _$createComponent } from "opentui:runtime-module:%40opentui%2Fsolid";
5
4
  import { insertNode as _$insertNode } from "opentui:runtime-module:%40opentui%2Fsolid";
6
5
  import { insert as _$insert } from "opentui:runtime-module:%40opentui%2Fsolid";
7
6
  import { setProp as _$setProp } from "opentui:runtime-module:%40opentui%2Fsolid";
8
7
  import { createElement as _$createElement } from "opentui:runtime-module:%40opentui%2Fsolid";
8
+ import { createComponent as _$createComponent } from "opentui:runtime-module:%40opentui%2Fsolid";
9
9
  /** @jsxImportSource @opentui/solid */
10
+
10
11
  import { custodyStatusLabel } from "@cortexkit/anthropic-auth-core";
11
12
  import { formatPrimeCost, formatPrimeTime } from "../sidebar-state.js";
13
+
14
+ /** Render menu sections, accounts and action inputs; send changes to the host instead of writing credentials here. */
15
+ export function openNativeMenuDialog(api, payload, apply, isCurrentSession) {
16
+ let menu = payload.menu;
17
+ let inFlight = false;
18
+ const DialogSelect = api.ui.DialogSelect;
19
+ const DialogPrompt = api.ui.DialogPrompt;
20
+ const DialogConfirm = api.ui.DialogConfirm;
21
+ const active = () => isCurrentSession() && !inFlight;
22
+ const root = () => {
23
+ if (!active()) return;
24
+ api.ui.dialog.setSize('xlarge');
25
+ api.ui.dialog.replace(() => _$createComponent(DialogSelect, {
26
+ get title() {
27
+ return menu.title;
28
+ },
29
+ get options() {
30
+ return [...menu.sections.map(section => ({
31
+ title: section.title,
32
+ value: section.id
33
+ })), {
34
+ title: 'Close',
35
+ value: '__close'
36
+ }];
37
+ },
38
+ onSelect: option => {
39
+ if (!active()) return;
40
+ const section = menu.sections.find(entry => entry.id === option.value);
41
+ if (section) showSection(section);else if (option.value === '__close') api.ui.dialog.clear();
42
+ }
43
+ }));
44
+ };
45
+ const showSection = section => {
46
+ if (!active()) return;
47
+ api.ui.dialog.replace(() => (() => {
48
+ var _el$ = _$createElement("box"),
49
+ _el$2 = _$createElement("text");
50
+ _$insertNode(_el$, _el$2);
51
+ _$setProp(_el$, "flexDirection", 'column');
52
+ _$setProp(_el$, "padding", 1);
53
+ _$insert(_el$2, () => section.lines.join('\n'));
54
+ _$insert(_el$, _$createComponent(DialogSelect, {
55
+ get title() {
56
+ return section.title;
57
+ },
58
+ get options() {
59
+ return [...section.items.map(item => ({
60
+ title: item.label,
61
+ value: `item:${item.id}`,
62
+ description: item.detail
63
+ })), ...section.actions.map(action => ({
64
+ title: action.label,
65
+ value: `action:${action.id}`,
66
+ description: action.description
67
+ })), {
68
+ title: 'Back',
69
+ value: '__back'
70
+ }];
71
+ },
72
+ onSelect: option => {
73
+ if (!active()) return;
74
+ if (option.value === '__back') return root();
75
+ const action = section.actions.find(entry => `action:${entry.id}` === option.value);
76
+ if (action) return collect(section, action);
77
+ const item = section.items.find(entry => `item:${entry.id}` === option.value);
78
+ if (item) showItem(section, item);
79
+ }
80
+ }), null);
81
+ return _el$;
82
+ })());
83
+ };
84
+ const showItem = (section, item) => {
85
+ if (!active()) return;
86
+ api.ui.dialog.replace(() => (() => {
87
+ var _el$3 = _$createElement("box"),
88
+ _el$4 = _$createElement("text");
89
+ _$insertNode(_el$3, _el$4);
90
+ _$setProp(_el$3, "flexDirection", 'column');
91
+ _$setProp(_el$3, "padding", 1);
92
+ _$insert(_el$4, () => item.detail ?? '');
93
+ _$insert(_el$3, _$createComponent(DialogSelect, {
94
+ get title() {
95
+ return item.label;
96
+ },
97
+ get options() {
98
+ return [...item.actions.map(action => ({
99
+ title: action.label,
100
+ value: action.id,
101
+ description: action.description
102
+ })), {
103
+ title: 'Back',
104
+ value: '__back'
105
+ }];
106
+ },
107
+ onSelect: option => {
108
+ if (!active()) return;
109
+ const action = item.actions.find(entry => entry.id === option.value);
110
+ if (action) collect(section, action, item);else if (option.value === '__back') showSection(section);
111
+ }
112
+ }), null);
113
+ return _el$3;
114
+ })());
115
+ };
116
+ const collect = (section, action, item) => {
117
+ const values = {};
118
+ const back = () => {
119
+ for (const key of Object.keys(values)) delete values[key];
120
+ if (item) showItem(section, item);else showSection(section);
121
+ };
122
+ const submit = async () => {
123
+ if (!active()) return;
124
+ inFlight = true;
125
+ try {
126
+ const result = await apply({
127
+ command: menu.command,
128
+ sectionId: section.id,
129
+ actionId: action.id,
130
+ ...(item ? {
131
+ itemId: item.id
132
+ } : {}),
133
+ values: {
134
+ ...values
135
+ },
136
+ ...(action.confirm ? {
137
+ confirmed: true
138
+ } : {})
139
+ });
140
+ if (!isCurrentSession()) return;
141
+ menu = result.menu;
142
+ api.ui.toast({
143
+ message: result.text
144
+ });
145
+ } catch {
146
+ if (isCurrentSession()) api.ui.toast({
147
+ message: 'Menu apply unavailable; outcome unknown.'
148
+ });
149
+ } finally {
150
+ for (const key of Object.keys(values)) delete values[key];
151
+ inFlight = false;
152
+ if (isCurrentSession()) {
153
+ const refreshed = menu.sections.find(entry => entry.id === section.id);
154
+ if (refreshed) showSection(refreshed);else root();
155
+ }
156
+ }
157
+ };
158
+ const next = index => {
159
+ if (!active()) return;
160
+ const knob = action.knobs[index];
161
+ if (!knob) {
162
+ if (!action.confirm) return void submit();
163
+ api.ui.dialog.replace(() => _$createComponent(DialogConfirm, {
164
+ get title() {
165
+ return action.label;
166
+ },
167
+ get message() {
168
+ return action.confirm?.message ?? '';
169
+ },
170
+ onConfirm: () => void submit(),
171
+ onCancel: back
172
+ }));
173
+ return;
174
+ }
175
+ if (knob.kind === 'choice' || knob.kind === 'toggle') {
176
+ const choices = knob.kind === 'choice' ? knob.choices : [{
177
+ value: 'on',
178
+ label: 'On'
179
+ }, {
180
+ value: 'off',
181
+ label: 'Off'
182
+ }];
183
+ api.ui.dialog.replace(() => _$createComponent(DialogSelect, {
184
+ get title() {
185
+ return knob.label;
186
+ },
187
+ get options() {
188
+ return [...choices.map(choice => ({
189
+ title: choice.label,
190
+ value: choice.value
191
+ })), {
192
+ title: 'Cancel',
193
+ value: '__cancel'
194
+ }];
195
+ },
196
+ onSelect: option => {
197
+ if (!active()) return;
198
+ if (option.value === '__cancel') return back();
199
+ values[knob.id] = knob.kind === 'toggle' ? option.value === 'on' : option.value;
200
+ next(index + 1);
201
+ }
202
+ }));
203
+ return;
204
+ }
205
+ // DialogPrompt has no masking capability in the host API. Never seed a
206
+ // protected input or claim it is hidden; warn before collecting it.
207
+ api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
208
+ get title() {
209
+ return knob.label;
210
+ },
211
+ description: () => (() => {
212
+ var _el$5 = _$createElement("text");
213
+ _$insert(_el$5, (() => {
214
+ var _c$ = _$memo(() => !!(knob.kind === 'text' && knob.masked));
215
+ return () => _c$() ? 'This host prompt displays input. Avoid screen sharing; the value is not echoed in menu results.' : knob.required ? 'Required input' : 'Optional; leave empty for the default';
216
+ })());
217
+ return _el$5;
218
+ })(),
219
+ get value() {
220
+ return _$memo(() => !!(knob.kind === 'text' && knob.masked))() ? '' : _$memo(() => knob.value === undefined)() ? '' : String(knob.value);
221
+ },
222
+ get placeholder() {
223
+ return _$memo(() => knob.kind === 'text')() ? knob.placeholder : `${knob.min ?? ''}-${knob.max ?? ''}`;
224
+ },
225
+ onCancel: back,
226
+ onConfirm: typed => {
227
+ if (!active()) return;
228
+ const text = typed.trim();
229
+ if (!text && knob.required) {
230
+ api.ui.toast({
231
+ message: `${knob.label} is required.`
232
+ });
233
+ return;
234
+ }
235
+ const value = text === '' ? null : knob.kind === 'number' ? Number(text) : text;
236
+ if (knob.kind === 'number' && typeof value === 'number' && (!Number.isFinite(value) || knob.min !== undefined && value < knob.min || knob.max !== undefined && value > knob.max)) {
237
+ api.ui.toast({
238
+ message: `${knob.label} needs a number in range.`
239
+ });
240
+ return;
241
+ }
242
+ values[knob.id] = value;
243
+ next(index + 1);
244
+ }
245
+ }));
246
+ };
247
+ next(0);
248
+ };
249
+ root();
250
+ }
12
251
  export const PRIME_DIALOG_OPTIONS = [{
13
252
  title: 'Enable',
14
253
  value: 'on'
@@ -162,14 +401,14 @@ export function retainAccountDialogProjection(current, incoming) {
162
401
  function showText(api, text) {
163
402
  api.ui.dialog.setSize('xlarge');
164
403
  api.ui.dialog.replace(() => (() => {
165
- var _el$ = _$createElement("box"),
166
- _el$2 = _$createElement("text");
167
- _$insertNode(_el$, _el$2);
168
- _$setProp(_el$, "flexDirection", 'column');
169
- _$setProp(_el$, "padding", 1);
170
- _$setProp(_el$, "width", '100%');
171
- _$insert(_el$2, text);
172
- return _el$;
404
+ var _el$6 = _$createElement("box"),
405
+ _el$7 = _$createElement("text");
406
+ _$insertNode(_el$6, _el$7);
407
+ _$setProp(_el$6, "flexDirection", 'column');
408
+ _$setProp(_el$6, "padding", 1);
409
+ _$setProp(_el$6, "width", '100%');
410
+ _$insert(_el$7, text);
411
+ return _el$6;
173
412
  })());
174
413
  }
175
414
 
@@ -317,9 +556,9 @@ export function openCommandDialog(api, payload, apply) {
317
556
  api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
318
557
  title: "Claude cachekeep schedule",
319
558
  description: () => (() => {
320
- var _el$3 = _$createElement("text");
321
- _$insert(_el$3, () => payload.text);
322
- return _el$3;
559
+ var _el$8 = _$createElement("text");
560
+ _$insert(_el$8, () => payload.text);
561
+ return _el$8;
323
562
  })(),
324
563
  placeholder: "'always', HH-HH (e.g. 08-20), or 'off'",
325
564
  value: seed,
@@ -348,17 +587,17 @@ export function openCommandDialog(api, payload, apply) {
348
587
  const statusText = `Claude prime status:\n\n${lines.join('\n')}`;
349
588
  api.ui.dialog.setSize('xlarge');
350
589
  api.ui.dialog.replace(() => (() => {
351
- var _el$4 = _$createElement("box"),
352
- _el$5 = _$createElement("text"),
353
- _el$6 = _$createElement("box");
354
- _$insertNode(_el$4, _el$5);
355
- _$insertNode(_el$4, _el$6);
356
- _$setProp(_el$4, "flexDirection", 'column');
357
- _$setProp(_el$4, "padding", 1);
358
- _$setProp(_el$4, "width", '100%');
359
- _$insert(_el$5, statusText);
360
- _$setProp(_el$6, "marginTop", 1);
361
- _$insert(_el$6, _$createComponent(DialogSelect, {
590
+ var _el$9 = _$createElement("box"),
591
+ _el$0 = _$createElement("text"),
592
+ _el$1 = _$createElement("box");
593
+ _$insertNode(_el$9, _el$0);
594
+ _$insertNode(_el$9, _el$1);
595
+ _$setProp(_el$9, "flexDirection", 'column');
596
+ _$setProp(_el$9, "padding", 1);
597
+ _$setProp(_el$9, "width", '100%');
598
+ _$insert(_el$0, statusText);
599
+ _$setProp(_el$1, "marginTop", 1);
600
+ _$insert(_el$1, _$createComponent(DialogSelect, {
362
601
  title: "Claude prime \u2014 status",
363
602
  current: "back",
364
603
  options: [{
@@ -367,7 +606,7 @@ export function openCommandDialog(api, payload, apply) {
367
606
  }],
368
607
  onSelect: option => handlePrimeStatusOption(option, renderMain)
369
608
  }));
370
- return _el$4;
609
+ return _el$9;
371
610
  })());
372
611
  };
373
612
  const renderMain = () => {
@@ -414,9 +653,9 @@ export function openCommandDialog(api, payload, apply) {
414
653
  api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
415
654
  title: "Killswitch thresholds",
416
655
  description: () => (() => {
417
- var _el$7 = _$createElement("text");
418
- _$insert(_el$7, () => payload.text);
419
- return _el$7;
656
+ var _el$10 = _$createElement("text");
657
+ _$insert(_el$10, () => payload.text);
658
+ return _el$10;
420
659
  })(),
421
660
  placeholder: "main:5,10,0 work-alt:5,10,0",
422
661
  value: seed,
@@ -479,40 +718,40 @@ export function openCommandDialog(api, payload, apply) {
479
718
  });
480
719
  api.ui.dialog.setSize('xlarge');
481
720
  api.ui.dialog.replace(() => (() => {
482
- var _el$8 = _$createElement("box"),
483
- _el$9 = _$createElement("text"),
484
- _el$0 = _$createElement("text"),
485
- _el$1 = _$createElement("box");
486
- _$insertNode(_el$8, _el$9);
487
- _$insertNode(_el$8, _el$0);
488
- _$insertNode(_el$8, _el$1);
489
- _$setProp(_el$8, "flexDirection", 'column');
490
- _$setProp(_el$8, "padding", 1);
491
- _$setProp(_el$8, "width", '100%');
492
- _$insert(_el$9, () => `Claustrum: ${normalizeAccountDialogPayload(accountKnobs).claustrumDetection}`);
493
- _$insert(_el$0, () => l1.header);
494
- _$insert(_el$8, (() => {
495
- var _c$ = _$memo(() => !!l1.enrollmentStatus);
496
- return () => _c$() && (() => {
497
- var _el$10 = _$createElement("box"),
498
- _el$11 = _$createElement("text");
499
- _$insertNode(_el$10, _el$11);
500
- _$setProp(_el$10, "marginTop", 1);
501
- _$insert(_el$11, () => l1.enrollmentStatus);
502
- return _el$10;
721
+ var _el$11 = _$createElement("box"),
722
+ _el$12 = _$createElement("text"),
723
+ _el$13 = _$createElement("text"),
724
+ _el$14 = _$createElement("box");
725
+ _$insertNode(_el$11, _el$12);
726
+ _$insertNode(_el$11, _el$13);
727
+ _$insertNode(_el$11, _el$14);
728
+ _$setProp(_el$11, "flexDirection", 'column');
729
+ _$setProp(_el$11, "padding", 1);
730
+ _$setProp(_el$11, "width", '100%');
731
+ _$insert(_el$12, () => `Claustrum: ${normalizeAccountDialogPayload(accountKnobs).claustrumDetection}`);
732
+ _$insert(_el$13, () => l1.header);
733
+ _$insert(_el$11, (() => {
734
+ var _c$2 = _$memo(() => !!l1.enrollmentStatus);
735
+ return () => _c$2() && (() => {
736
+ var _el$15 = _$createElement("box"),
737
+ _el$16 = _$createElement("text");
738
+ _$insertNode(_el$15, _el$16);
739
+ _$setProp(_el$15, "marginTop", 1);
740
+ _$insert(_el$16, () => l1.enrollmentStatus);
741
+ return _el$15;
503
742
  })();
504
- })(), _el$1);
505
- _$insert(_el$8, statusMessage && (() => {
506
- var _el$12 = _$createElement("box"),
507
- _el$13 = _$createElement("text");
508
- _$insertNode(_el$12, _el$13);
509
- _$setProp(_el$12, "marginTop", 1);
510
- _$insert(_el$13, () => statusMessage.text);
511
- _$effect(_$p => _$setProp(_el$13, "fg", statusMessage.error ? '#ef4444' : '#22c55e', _$p));
512
- return _el$12;
513
- })(), _el$1);
514
- _$setProp(_el$1, "marginTop", 1);
515
- _$insert(_el$1, _$createComponent(DialogSelect, {
743
+ })(), _el$14);
744
+ _$insert(_el$11, statusMessage && (() => {
745
+ var _el$17 = _$createElement("box"),
746
+ _el$18 = _$createElement("text");
747
+ _$insertNode(_el$17, _el$18);
748
+ _$setProp(_el$17, "marginTop", 1);
749
+ _$insert(_el$18, () => statusMessage.text);
750
+ _$effect(_$p => _$setProp(_el$18, "fg", statusMessage.error ? '#ef4444' : '#22c55e', _$p));
751
+ return _el$17;
752
+ })(), _el$14);
753
+ _$setProp(_el$14, "marginTop", 1);
754
+ _$insert(_el$14, _$createComponent(DialogSelect, {
516
755
  title: "Claude accounts",
517
756
  get options() {
518
757
  return l1.options;
@@ -563,7 +802,7 @@ export function openCommandDialog(api, payload, apply) {
563
802
  openManage(account, false);
564
803
  }
565
804
  }));
566
- return _el$8;
805
+ return _el$11;
567
806
  })());
568
807
  };
569
808
 
@@ -608,9 +847,9 @@ export function openCommandDialog(api, payload, apply) {
608
847
  api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
609
848
  title: "Add API key account \\u2014 API key",
610
849
  description: () => (() => {
611
- var _el$14 = _$createElement("text");
612
- _$insertNode(_el$14, _$createTextNode(`Paste your API key (required).`));
613
- return _el$14;
850
+ var _el$19 = _$createElement("text");
851
+ _$insertNode(_el$19, _$createTextNode(`Paste your API key (required).`));
852
+ return _el$19;
614
853
  })(),
615
854
  placeholder: "sk-ant-...",
616
855
  value: "",
@@ -632,9 +871,9 @@ export function openCommandDialog(api, payload, apply) {
632
871
  api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
633
872
  title: "Add API key account \\u2014 base URL",
634
873
  description: () => (() => {
635
- var _el$16 = _$createElement("text");
636
- _$insertNode(_el$16, _$createTextNode(`Anthropic-compatible API base URL. Default: https://api.kie.ai/claude`));
637
- return _el$16;
874
+ var _el$21 = _$createElement("text");
875
+ _$insertNode(_el$21, _$createTextNode(`Anthropic-compatible API base URL. Default: https://api.kie.ai/claude`));
876
+ return _el$21;
638
877
  })(),
639
878
  placeholder: "https://api.kie.ai/claude",
640
879
  value: "",
@@ -672,9 +911,9 @@ export function openCommandDialog(api, payload, apply) {
672
911
  api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
673
912
  title: "Add API key account \\u2014 label",
674
913
  description: () => (() => {
675
- var _el$18 = _$createElement("text");
676
- _$insertNode(_el$18, _$createTextNode(`A short name for this account (optional).`));
677
- return _el$18;
914
+ var _el$23 = _$createElement("text");
915
+ _$insertNode(_el$23, _$createTextNode(`A short name for this account (optional).`));
916
+ return _el$23;
678
917
  })(),
679
918
  placeholder: "e.g. Work API",
680
919
  value: "",
@@ -768,9 +1007,9 @@ export function openCommandDialog(api, payload, apply) {
768
1007
  api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
769
1008
  title: "OAuth sign-in \\u2014 enter code",
770
1009
  description: () => (() => {
771
- var _el$20 = _$createElement("text");
772
- _$insertNode(_el$20, _$createTextNode(`After signing in you will be redirected. Paste the full callback URL or authorization code below.`));
773
- return _el$20;
1010
+ var _el$25 = _$createElement("text");
1011
+ _$insertNode(_el$25, _$createTextNode(`After signing in you will be redirected. Paste the full callback URL or authorization code below.`));
1012
+ return _el$25;
774
1013
  })(),
775
1014
  placeholder: "Paste callback URL or code here",
776
1015
  value: "",
@@ -791,9 +1030,9 @@ export function openCommandDialog(api, payload, apply) {
791
1030
  api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
792
1031
  title: "OAuth sign-in \\u2014 label",
793
1032
  description: () => (() => {
794
- var _el$22 = _$createElement("text");
795
- _$insertNode(_el$22, _$createTextNode(`A short name for this account (optional).`));
796
- return _el$22;
1033
+ var _el$27 = _$createElement("text");
1034
+ _$insertNode(_el$27, _$createTextNode(`A short name for this account (optional).`));
1035
+ return _el$27;
797
1036
  })(),
798
1037
  placeholder: "e.g. work",
799
1038
  value: "",
@@ -16,7 +16,7 @@ import { createEffect, createSignal, For, onCleanup, Show } from "opentui:runtim
16
16
  import { createRpcClient } from "./rpc/rpc-client.js";
17
17
  import { getRpcDir } from "./rpc/rpc-dir.js";
18
18
  import { computeQuotaPacing, DEFAULT_SIDEBAR_STATE, FIVE_HOUR_MS, formatPrimeAccountValue, formatScopedQuotaLabel, getCollapsedQuotaSummary, getFableRecoverySummary, getSidebarState, resolveActiveAccount, SEVEN_DAY_MS } from "./sidebar-state.js";
19
- import { openCommandDialog } from "./tui/command-dialogs.js";
19
+ import { openCommandDialog, openNativeMenuDialog } from "./tui/command-dialogs.js";
20
20
  import { computeEffectiveOrder, DEFAULT_SLOT_ORDER, PLUGIN_KEY, queueTuiPreferenceUpdate, readTuiPreferencesFile, resolveAnthropicAuthPrefs, watchTuiPreferences } from "./tui-preferences.js";
21
21
  const RPC_POLL_MS = 500;
22
22
  let rpcPollStarted = false;
@@ -1153,18 +1153,35 @@ const tui = async api => {
1153
1153
  if (!rpcPollStarted) {
1154
1154
  rpcPollStarted = true;
1155
1155
  const rpcClient = createRpcClient(getRpcDir(api.state.path.directory ?? ''), process.pid);
1156
- let lastNotificationId = 0;
1156
+ const lastNotificationIdBySession = new Map();
1157
1157
  let rpcInFlight = false;
1158
- setInterval(() => {
1159
- if (rpcInFlight) return;
1158
+ const currentSessionId = () => {
1160
1159
  const current = api.route.current;
1161
1160
  const resolved = typeof current === 'function' ? current() : current;
1162
- const sessionId = resolved?.params?.sessionID;
1161
+ return resolved?.params?.sessionID;
1162
+ };
1163
+ setInterval(() => {
1164
+ if (rpcInFlight) return;
1165
+ const sessionId = currentSessionId();
1163
1166
  if (!sessionId) return;
1164
1167
  rpcInFlight = true;
1165
- void rpcClient.pending(lastNotificationId, sessionId).then(messages => {
1168
+ void rpcClient.pending(lastNotificationIdBySession.get(sessionId) ?? 0, sessionId).then(messages => {
1169
+ // A route change while draining must not open a different session's
1170
+ // dialog or acknowledge notices that were never displayed.
1171
+ if (currentSessionId() !== sessionId) return;
1166
1172
  for (const message of [...messages].sort((a, b) => a.id - b.id)) {
1167
- lastNotificationId = Math.max(lastNotificationId, message.id);
1173
+ if (message.sessionId !== sessionId) continue;
1174
+ lastNotificationIdBySession.set(sessionId, Math.max(lastNotificationIdBySession.get(sessionId) ?? 0, message.id));
1175
+ if (message.type === 'open-menu') {
1176
+ openNativeMenuDialog(api, message.payload, request => {
1177
+ if (currentSessionId() !== sessionId) return Promise.reject(new Error('Menu session changed'));
1178
+ return rpcClient.applyMenu({
1179
+ ...request,
1180
+ sessionId
1181
+ });
1182
+ }, () => currentSessionId() === sessionId);
1183
+ continue;
1184
+ }
1168
1185
  if (message.payload.command === 'claude-quota') {
1169
1186
  api.ui.dialog.setSize('xlarge');
1170
1187
  api.ui.dialog.replace(() => _$createComponent(QuotaDialogContent, {
package/src/tui.tsx CHANGED
@@ -34,7 +34,10 @@ import {
34
34
  SEVEN_DAY_MS,
35
35
  type SidebarState,
36
36
  } from './sidebar-state.js'
37
- import { openCommandDialog } from './tui/command-dialogs.js'
37
+ import {
38
+ openCommandDialog,
39
+ openNativeMenuDialog,
40
+ } from './tui/command-dialogs.js'
38
41
  import {
39
42
  type AnthropicAuthTuiPrefs,
40
43
  type AppearancePrefs,
@@ -920,23 +923,48 @@ const tui: TuiPlugin = async (api) => {
920
923
  getRpcDir(api.state.path.directory ?? ''),
921
924
  process.pid,
922
925
  )
923
- let lastNotificationId = 0
926
+ const lastNotificationIdBySession = new Map<string, number>()
924
927
  let rpcInFlight = false
925
- setInterval(() => {
926
- if (rpcInFlight) return
928
+ const currentSessionId = () => {
927
929
  const current = (api.route as { current?: unknown }).current
928
930
  const resolved =
929
931
  typeof current === 'function' ? (current as () => unknown)() : current
930
- const sessionId = (
931
- resolved as { params?: { sessionID?: string } } | undefined
932
- )?.params?.sessionID
932
+ return (resolved as { params?: { sessionID?: string } } | undefined)
933
+ ?.params?.sessionID
934
+ }
935
+ setInterval(() => {
936
+ if (rpcInFlight) return
937
+ const sessionId = currentSessionId()
933
938
  if (!sessionId) return
934
939
  rpcInFlight = true
935
940
  void rpcClient
936
- .pending(lastNotificationId, sessionId)
941
+ .pending(lastNotificationIdBySession.get(sessionId) ?? 0, sessionId)
937
942
  .then((messages) => {
943
+ // A route change while draining must not open a different session's
944
+ // dialog or acknowledge notices that were never displayed.
945
+ if (currentSessionId() !== sessionId) return
938
946
  for (const message of [...messages].sort((a, b) => a.id - b.id)) {
939
- lastNotificationId = Math.max(lastNotificationId, message.id)
947
+ if (message.sessionId !== sessionId) continue
948
+ lastNotificationIdBySession.set(
949
+ sessionId,
950
+ Math.max(
951
+ lastNotificationIdBySession.get(sessionId) ?? 0,
952
+ message.id,
953
+ ),
954
+ )
955
+ if (message.type === 'open-menu') {
956
+ openNativeMenuDialog(
957
+ api,
958
+ message.payload,
959
+ (request) => {
960
+ if (currentSessionId() !== sessionId)
961
+ return Promise.reject(new Error('Menu session changed'))
962
+ return rpcClient.applyMenu({ ...request, sessionId })
963
+ },
964
+ () => currentSessionId() === sessionId,
965
+ )
966
+ continue
967
+ }
940
968
  if (message.payload.command === 'claude-quota') {
941
969
  api.ui.dialog.setSize('xlarge')
942
970
  api.ui.dialog.replace(() => (
@@ -1,4 +0,0 @@
1
- import { adoptClaustrumEnrollment as adoptSharedEnrollment } from '@cortexkit/anthropic-auth-core';
2
- export type { ClaustrumEnrollmentAdoption } from '@cortexkit/anthropic-auth-core';
3
- export declare function getOpenCodeClaustrumEnrollmentPaths(env?: NodeJS.ProcessEnv, cwd?: string): import("@cortexkit/anthropic-auth-core").ClaustrumEnrollmentPaths;
4
- export declare function adoptClaustrumEnrollment(options: Omit<Parameters<typeof adoptSharedEnrollment>[0], 'proposedName'>): import("@cortexkit/anthropic-auth-core").ClaustrumEnrollmentAdoption;
@@ -1,14 +0,0 @@
1
- import { type AccountStorage, type CustodyHandleAccount, type CustodyHandleManifest, type OAuthAccount } from '@cortexkit/anthropic-auth-core';
2
- /**
3
- * Returns valid manifest bindings that are not yet represented by an OAuth
4
- * routing row. Existing disabled rows are intentionally retained: binding a
5
- * credential must not silently override a user's routing preference.
6
- */
7
- export declare function pendingClaustrumEnrollments(storage: AccountStorage, manifest: CustodyHandleManifest | undefined): CustodyHandleAccount[];
8
- /** Build the secret-free routing row for a provider-verified manifest binding. */
9
- export declare function materializeClaustrumEnrollment(input: {
10
- storage: AccountStorage;
11
- binding: CustodyHandleAccount;
12
- providerAccountUuid: string;
13
- now?: number;
14
- }): OAuthAccount;