dsh-openai-subscription 0.1.6 → 0.1.7
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/dist/client.js +214 -31
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -24,7 +24,12 @@ const ZH = {
|
|
|
24
24
|
'context.model': '模型',
|
|
25
25
|
'context.window': '上下文窗口',
|
|
26
26
|
'context.default': '跟随模型默认',
|
|
27
|
-
'context.million': '1M
|
|
27
|
+
'context.million': '1M 大上下文',
|
|
28
|
+
'context.default.detail': '使用同步的模型配置',
|
|
29
|
+
'context.custom.detail': '手动设置 tokens 数',
|
|
30
|
+
'context.pending': '有未保存的更改',
|
|
31
|
+
'context.applied': '已保存',
|
|
32
|
+
'manage.help': '授权维护与本机连接',
|
|
28
33
|
'context.custom': '自定义',
|
|
29
34
|
'context.tokens': '自定义 tokens 数',
|
|
30
35
|
'context.current': '当前:{count} tokens',
|
|
@@ -155,7 +160,12 @@ const EN = {
|
|
|
155
160
|
'context.model': 'Model',
|
|
156
161
|
'context.window': 'Context window',
|
|
157
162
|
'context.default': 'Use model default',
|
|
158
|
-
'context.million': '1M
|
|
163
|
+
'context.million': '1M context',
|
|
164
|
+
'context.default.detail': 'Use the synced model setting',
|
|
165
|
+
'context.custom.detail': 'Set a token count manually',
|
|
166
|
+
'context.pending': 'Unsaved changes',
|
|
167
|
+
'context.applied': 'Saved',
|
|
168
|
+
'manage.help': 'Authorization and local connection',
|
|
159
169
|
'context.custom': 'Custom',
|
|
160
170
|
'context.tokens': 'Custom token count',
|
|
161
171
|
'context.current': 'Current: {count} tokens',
|
|
@@ -363,16 +373,64 @@ window.__ModuleLoader__.load({
|
|
|
363
373
|
.oasub-model-title { font-size: 13px; font-weight: 500; line-height: 19px; }
|
|
364
374
|
.oasub-model-detail { color: var(--dsw-alias-label-tertiary, #81858c); font-size: 11px; line-height: 17px; }
|
|
365
375
|
.oasub-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
|
|
366
|
-
.oasub-
|
|
367
|
-
.oasub-
|
|
368
|
-
.oasub-
|
|
369
|
-
.oasub-
|
|
370
|
-
.oasub-context { display: flex; flex-direction: column; gap:
|
|
371
|
-
.oasub-
|
|
376
|
+
.oasub-wrap { container-type: inline-size; }
|
|
377
|
+
.oasub-ui-icon { display: block; flex: none; }
|
|
378
|
+
.oasub-section-heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
|
|
379
|
+
.oasub-section-copy { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
|
|
380
|
+
.oasub-context { display: flex; flex-direction: column; gap: 16px; }
|
|
381
|
+
.oasub-context-grid { display: grid; grid-template-columns: 1.1fr 1fr; align-items: start; gap: 12px; }
|
|
382
|
+
.oasub-field { display: flex; flex-direction: column; gap: 8px; min-width: 0; font-size: 12px; font-weight: 500; }
|
|
372
383
|
.oasub-context > .oasub-field { flex: none; }
|
|
373
|
-
.oasub-
|
|
374
|
-
.oasub-
|
|
375
|
-
|
|
384
|
+
.oasub-picker { position: relative; min-width: 0; }
|
|
385
|
+
.oasub-picker-trigger, .oasub-input-shell {
|
|
386
|
+
width: 100%; min-height: 56px; padding: 10px 12px;
|
|
387
|
+
border: 1px solid var(--dsw-alias-border-l1, rgba(15, 17, 21, .2)); border-radius: 12px;
|
|
388
|
+
color: var(--dsw-alias-label-primary, #0f1115); background: var(--dsw-alias-bg-layer-2, #f5f6f7);
|
|
389
|
+
}
|
|
390
|
+
.oasub-picker-trigger { appearance: none; display: flex; align-items: center; justify-content: space-between; gap: 12px; font: inherit; text-align: start; cursor: pointer; transition: border-color .16s, background .16s; }
|
|
391
|
+
.oasub-picker-trigger:hover:not(:disabled), .oasub-picker-trigger[aria-expanded="true"] { border-color: var(--oasub-control-border); background: var(--dsw-alias-bg-layer-1, #fff); }
|
|
392
|
+
.oasub-picker-trigger:focus-visible, .oasub-input-shell:focus-within, .oasub-management-toggle:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary, #4176e6); outline-offset: 3px; }
|
|
393
|
+
.oasub-picker-trigger:disabled { opacity: .5; cursor: default; }
|
|
394
|
+
.oasub-picker-copy { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
|
395
|
+
.oasub-picker-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 500; line-height: 19px; }
|
|
396
|
+
.oasub-picker-detail { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dsw-alias-label-secondary, #61666b); font-size: 11px; font-weight: 400; line-height: 16px; font-variant-numeric: tabular-nums; }
|
|
397
|
+
.oasub-chevron { color: var(--dsw-alias-label-secondary, #61666b); transition: transform .16s; }
|
|
398
|
+
[aria-expanded="true"] > .oasub-chevron { transform: rotate(180deg); }
|
|
399
|
+
.oasub-picker-menu { position: absolute; inset: calc(100% + 6px) 0 auto; z-index: 20; margin: 0; padding: 5px; max-height: 248px; overflow-y: auto; overscroll-behavior: contain; list-style: none; border: 1px solid var(--dsw-alias-border-l1, rgba(15, 17, 21, .2)); border-radius: 14px; background: var(--dsw-alias-bg-layer-1, #fff); box-shadow: 0 8px 28px rgba(0, 0, 0, .14); }
|
|
400
|
+
.oasub-picker-option { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 48px; padding: 8px 10px; border-radius: 9px; cursor: pointer; }
|
|
401
|
+
.oasub-picker-option[data-active="true"] { background: var(--dsw-alias-interactive-bg-hover, rgba(15, 17, 21, .06)); }
|
|
402
|
+
.oasub-picker-option[aria-selected="true"] .oasub-picker-label { font-weight: 600; }
|
|
403
|
+
.oasub-picker-option[aria-disabled="true"] { opacity: .4; cursor: not-allowed; }
|
|
404
|
+
.oasub-input-shell { display: flex; align-items: center; gap: 12px; min-height: 44px; }
|
|
405
|
+
.oasub-input-shell:has(input:disabled) { opacity: .5; }
|
|
406
|
+
.oasub-input-shell:has([aria-invalid="true"]) { border-color: var(--dsw-alias-state-error-primary, #dc2626); }
|
|
407
|
+
.oasub-token-input { appearance: none; width: 100%; min-width: 0; padding: 0; border: 0; outline: none; background: transparent; color: inherit; font: inherit; font-size: 14px; line-height: 22px; font-variant-numeric: tabular-nums; }
|
|
408
|
+
.oasub-token-unit { color: var(--dsw-alias-label-tertiary, #81858c); font-size: 12px; font-weight: 400; }
|
|
409
|
+
.oasub-context-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; color: var(--dsw-alias-label-secondary, #61666b); font-size: 12px; line-height: 18px; font-variant-numeric: tabular-nums; }
|
|
410
|
+
.oasub-context-badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 6px; background: var(--dsw-alias-bg-layer-2, #f5f6f7); font-size: 10px; }
|
|
411
|
+
.oasub-context-note { display: flex; align-items: flex-start; gap: 7px; color: var(--dsw-alias-label-tertiary, #81858c); font-size: 11px; line-height: 17px; }
|
|
412
|
+
.oasub-context-note > svg { margin-top: 2px; }
|
|
413
|
+
.oasub-context-error { color: var(--dsw-alias-state-error-primary, #b91c1c); font-size: 12px; line-height: 18px; }
|
|
414
|
+
.oasub-context-footer { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; padding-top: 14px; border-top: 1px solid var(--dsw-alias-border-l2, rgba(15, 17, 21, .14)); }
|
|
415
|
+
.oasub-management-card { padding: 0; gap: 0; }
|
|
416
|
+
.oasub-management-heading { margin: 0; font: inherit; }
|
|
417
|
+
.oasub-management-toggle { appearance: none; display: flex; align-items: center; gap: 12px; width: 100%; padding: var(--oasub-section-inset); border: 0; border-radius: 16px; color: inherit; background: transparent; font: inherit; text-align: start; cursor: pointer; transition: background .16s; }
|
|
418
|
+
.oasub-management-toggle:hover { background: var(--dsw-alias-interactive-bg-hover, rgba(15, 17, 21, .04)); }
|
|
419
|
+
.oasub-management-toggle > .oasub-section-copy { flex: 1; }
|
|
420
|
+
.oasub-management-symbol { display: grid; place-items: center; width: 34px; height: 34px; flex: none; border-radius: 10px; color: var(--dsw-alias-label-secondary, #61666b); background: var(--dsw-alias-bg-layer-2, #f5f6f7); }
|
|
421
|
+
.oasub-management { display: flex; flex-direction: column; margin-inline: var(--oasub-section-inset); }
|
|
422
|
+
.oasub-management[hidden] { display: none; }
|
|
423
|
+
.oasub-manage-row { display: flex; align-items: center; justify-content: space-between; gap: 24px; padding-block: 16px; border-top: 1px solid var(--dsw-alias-border-l2, rgba(15, 17, 21, .14)); }
|
|
424
|
+
.oasub-manage-row .oasub-status-detail { font-size: 11px; line-height: 17px; }
|
|
425
|
+
.oasub-manage-title { font-size: 13px; font-weight: 500; line-height: 20px; }
|
|
426
|
+
.oasub-manage-row > .oasub-button { flex: 0 0 auto; min-height: 32px; padding: 5px 12px; border-color: var(--dsw-alias-border-l1, rgba(15, 17, 21, .2)); font-size: 12px; }
|
|
427
|
+
.oasub-manage-row > .oasub-button.danger-quiet { color: var(--dsw-alias-state-error-primary, #b91c1c); border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary, #dc2626) 25%, transparent); }
|
|
428
|
+
.oasub-manage-row > .oasub-button.danger-quiet:hover:not(:disabled) { background: color-mix(in srgb, var(--dsw-alias-state-error-primary, #dc2626) 7%, transparent); border-color: var(--dsw-alias-state-error-primary, #dc2626); }
|
|
429
|
+
@container (max-width: 460px) {
|
|
430
|
+
.oasub-context-grid { grid-template-columns: minmax(0, 1fr); }
|
|
431
|
+
.oasub-manage-row { align-items: flex-start; flex-direction: column; gap: 10px; }
|
|
432
|
+
.oasub-manage-row > .oasub-button { align-self: flex-start; }
|
|
433
|
+
}
|
|
376
434
|
.oasub-button {
|
|
377
435
|
appearance: none;
|
|
378
436
|
min-height: 36px;
|
|
@@ -448,6 +506,9 @@ window.__ModuleLoader__.load({
|
|
|
448
506
|
.oasub-manage-row { align-items: flex-start; flex-direction: column; gap: 8px; }
|
|
449
507
|
}
|
|
450
508
|
@media (forced-colors: active) {
|
|
509
|
+
.oasub-picker-trigger, .oasub-input-shell, .oasub-picker-menu { border-color: ButtonText; }
|
|
510
|
+
.oasub-picker-option[data-active="true"] { outline: 1px solid Highlight; outline-offset: -1px; }
|
|
511
|
+
.oasub-picker-option[aria-disabled="true"], .oasub-picker-trigger:disabled { color: GrayText; opacity: 1; }
|
|
451
512
|
.oasub-button { border-color: ButtonText; }
|
|
452
513
|
.oasub-button.primary, .oasub-button.danger { border-color: ButtonText; color: ButtonText; background: ButtonFace; }
|
|
453
514
|
.oasub-button:not(.primary):not(.danger):hover:not(:disabled),
|
|
@@ -456,7 +517,7 @@ window.__ModuleLoader__.load({
|
|
|
456
517
|
.oasub-button:disabled { border-color: GrayText; color: GrayText; opacity: 1; }
|
|
457
518
|
}
|
|
458
519
|
@media (prefers-reduced-motion: reduce) {
|
|
459
|
-
.oasub-button { transition: none; }
|
|
520
|
+
.oasub-button, .oasub-picker-trigger, .oasub-chevron, .oasub-management-toggle { transition: none; }
|
|
460
521
|
.oasub-skeleton::after { animation: none; display: none; }
|
|
461
522
|
}
|
|
462
523
|
`;
|
|
@@ -661,6 +722,17 @@ window.__ModuleLoader__.load({
|
|
|
661
722
|
return null;
|
|
662
723
|
}
|
|
663
724
|
}
|
|
725
|
+
function uiIcon(name, size = 16) {
|
|
726
|
+
const paths = {
|
|
727
|
+
chevron: 'm6 9 6 6 6-6', check: 'm5 12 4 4L19 6',
|
|
728
|
+
info: 'M12 11v6m0-10v.01M22 12a10 10 0 1 1-20 0 10 10 0 0 1 20 0',
|
|
729
|
+
settings: 'M4 7h9m4 0h3M4 17h3m4 0h9M13 4v6M7 14v6',
|
|
730
|
+
};
|
|
731
|
+
return React.createElement('svg', { width: size, height: size, viewBox: '0 0 24 24', fill: 'none',
|
|
732
|
+
stroke: 'currentColor', strokeWidth: 1.6, strokeLinecap: 'round', strokeLinejoin: 'round',
|
|
733
|
+
className: 'oasub-ui-icon' + (name === 'chevron' ? ' oasub-chevron' : ''), 'aria-hidden': true, focusable: false,
|
|
734
|
+
}, React.createElement('path', { d: paths[name] }));
|
|
735
|
+
}
|
|
664
736
|
function Section(props) {
|
|
665
737
|
const el = React.createElement;
|
|
666
738
|
const { connection, timer, t } = props;
|
|
@@ -686,6 +758,10 @@ window.__ModuleLoader__.load({
|
|
|
686
758
|
// null means no pending edit; '' selects the synchronized model default.
|
|
687
759
|
const [contextDraft, setContextDraft] = React.useState(null);
|
|
688
760
|
const [contextChoice, setContextChoice] = React.useState(null);
|
|
761
|
+
const [picker, setPicker] = React.useState(null);
|
|
762
|
+
const pickerRoot = React.useRef(null);
|
|
763
|
+
const activeOption = React.useRef(null);
|
|
764
|
+
const pickerSearch = React.useRef({ text: '', at: 0 });
|
|
689
765
|
const actionLock = React.useRef(false);
|
|
690
766
|
const cancelAcknowledged = React.useRef(false);
|
|
691
767
|
const flowObserved = React.useRef(false);
|
|
@@ -770,6 +846,28 @@ window.__ModuleLoader__.load({
|
|
|
770
846
|
setContextLoading(false); });
|
|
771
847
|
return () => controller.abort();
|
|
772
848
|
}, [connection, configured, statusRevision]);
|
|
849
|
+
const contextDisabled = busy || contextLoading || statusLoading;
|
|
850
|
+
React.useEffect(() => {
|
|
851
|
+
if (contextDisabled || !configured)
|
|
852
|
+
setPicker(null);
|
|
853
|
+
}, [contextDisabled, configured, contexts]);
|
|
854
|
+
React.useEffect(() => {
|
|
855
|
+
if (!picker || typeof document === 'undefined')
|
|
856
|
+
return;
|
|
857
|
+
const dismissOutside = (event) => {
|
|
858
|
+
if (!pickerRoot.current?.contains(event.target))
|
|
859
|
+
setPicker(null);
|
|
860
|
+
};
|
|
861
|
+
document.addEventListener('pointerdown', dismissOutside);
|
|
862
|
+
document.addEventListener('focusin', dismissOutside);
|
|
863
|
+
return () => {
|
|
864
|
+
document.removeEventListener('pointerdown', dismissOutside);
|
|
865
|
+
document.removeEventListener('focusin', dismissOutside);
|
|
866
|
+
};
|
|
867
|
+
}, [picker?.id]);
|
|
868
|
+
React.useEffect(() => {
|
|
869
|
+
activeOption.current?.scrollIntoView?.({ block: 'nearest' });
|
|
870
|
+
}, [picker?.id, picker?.active]);
|
|
773
871
|
React.useEffect(() => {
|
|
774
872
|
if (props.subscribeReset === undefined)
|
|
775
873
|
return;
|
|
@@ -1123,6 +1221,81 @@ window.__ModuleLoader__.load({
|
|
|
1123
1221
|
}
|
|
1124
1222
|
});
|
|
1125
1223
|
};
|
|
1224
|
+
// Select-only combobox: focus stays on the trigger, and navigation never saves a value.
|
|
1225
|
+
const renderPicker = (id, label, value, options, choose, describedBy) => {
|
|
1226
|
+
const open = picker?.id === id && !contextDisabled;
|
|
1227
|
+
const selected = options.find((option) => option.value === value);
|
|
1228
|
+
const enabled = options.map((option, index) => option.disabled ? -1 : index).filter((index) => index >= 0);
|
|
1229
|
+
const selectedIndex = Math.max(0, options.findIndex((option) => option.value === value && !option.disabled));
|
|
1230
|
+
const active = open ? picker.active : selectedIndex;
|
|
1231
|
+
const optionId = (index) => id + '-option-' + index;
|
|
1232
|
+
const commit = (index) => {
|
|
1233
|
+
const option = options[index];
|
|
1234
|
+
if (!option || option.disabled || contextDisabled)
|
|
1235
|
+
return;
|
|
1236
|
+
choose(option.value);
|
|
1237
|
+
setPicker(null);
|
|
1238
|
+
};
|
|
1239
|
+
const onKeyDown = (event) => {
|
|
1240
|
+
if (contextDisabled)
|
|
1241
|
+
return;
|
|
1242
|
+
if (event.key === 'Escape' && open) {
|
|
1243
|
+
event.preventDefault();
|
|
1244
|
+
event.stopPropagation();
|
|
1245
|
+
setPicker(null);
|
|
1246
|
+
return;
|
|
1247
|
+
}
|
|
1248
|
+
if (event.key === 'Tab') {
|
|
1249
|
+
setPicker(null);
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
1253
|
+
event.preventDefault();
|
|
1254
|
+
if (open)
|
|
1255
|
+
commit(active);
|
|
1256
|
+
else {
|
|
1257
|
+
pickerSearch.current.text = '';
|
|
1258
|
+
setPicker({ id, active: selectedIndex });
|
|
1259
|
+
}
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
const direction = event.key === 'ArrowDown' ? 1 : event.key === 'ArrowUp' ? -1 : 0;
|
|
1263
|
+
if (direction || event.key === 'Home' || event.key === 'End') {
|
|
1264
|
+
event.preventDefault();
|
|
1265
|
+
const position = enabled.indexOf(active);
|
|
1266
|
+
const next = event.key === 'Home' ? enabled[0] : event.key === 'End' ? enabled.at(-1)
|
|
1267
|
+
: !open ? selectedIndex : enabled[(position + direction + enabled.length) % enabled.length];
|
|
1268
|
+
setPicker({ id, active: next ?? 0 });
|
|
1269
|
+
return;
|
|
1270
|
+
}
|
|
1271
|
+
if (event.key.length === 1 && !event.altKey && !event.ctrlKey && !event.metaKey) {
|
|
1272
|
+
event.preventDefault();
|
|
1273
|
+
const search = pickerSearch.current;
|
|
1274
|
+
search.text = (Date.now() - search.at > 700 ? '' : search.text) + event.key.toLocaleLowerCase();
|
|
1275
|
+
search.at = Date.now();
|
|
1276
|
+
const text = [...search.text].every((char) => char === search.text[0]) ? search.text[0] : search.text;
|
|
1277
|
+
const order = [...enabled.filter((index) => index > active), ...enabled.filter((index) => index <= active)];
|
|
1278
|
+
const match = order.find((index) => options[index].label.toLocaleLowerCase().startsWith(text) || options[index].value.toLocaleLowerCase().startsWith(text));
|
|
1279
|
+
if (match !== undefined)
|
|
1280
|
+
setPicker({ id, active: match });
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
const copy = (option) => el('span', { className: 'oasub-picker-copy' }, el('span', { className: 'oasub-picker-label' }, option?.label ?? value), option?.detail ? el('span', { className: 'oasub-picker-detail' }, option.detail) : null);
|
|
1284
|
+
return el('div', { className: 'oasub-field' }, el('label', { id: id + '-label', htmlFor: id }, label), el('div', { className: 'oasub-picker', ref: open ? pickerRoot : undefined }, el('button', { id, type: 'button', className: 'oasub-picker-trigger', role: 'combobox',
|
|
1285
|
+
'aria-label': label, 'aria-expanded': open, 'aria-haspopup': 'listbox',
|
|
1286
|
+
'aria-controls': open ? id + '-list' : undefined, 'aria-activedescendant': open ? optionId(active) : undefined,
|
|
1287
|
+
'aria-describedby': describedBy, disabled: contextDisabled, 'data-value': value,
|
|
1288
|
+
onKeyDown, onClick: () => { pickerSearch.current.text = ''; setPicker(open ? null : { id, active: selectedIndex }); },
|
|
1289
|
+
}, copy(selected), uiIcon('chevron')), open ? el('ul', { id: id + '-list', className: 'oasub-picker-menu', role: 'listbox', 'aria-labelledby': id + '-label',
|
|
1290
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
1291
|
+
}, options.map((option, index) => el('li', { key: option.value, id: optionId(index), role: 'option',
|
|
1292
|
+
className: 'oasub-picker-option', 'aria-selected': option.value === value, 'aria-disabled': !!option.disabled,
|
|
1293
|
+
'data-value': option.value, 'data-active': index === active, ref: index === active ? activeOption : undefined,
|
|
1294
|
+
onMouseMove: () => { if (!option.disabled && index !== active)
|
|
1295
|
+
setPicker({ id, active: index }); },
|
|
1296
|
+
onClick: () => commit(index),
|
|
1297
|
+
}, copy(option), option.value === value ? uiIcon('check', 15) : null))) : null));
|
|
1298
|
+
};
|
|
1126
1299
|
const selectCode = () => {
|
|
1127
1300
|
codeRef.current?.focus();
|
|
1128
1301
|
codeRef.current?.select();
|
|
@@ -1185,25 +1358,35 @@ window.__ModuleLoader__.load({
|
|
|
1185
1358
|
onClick: () => startAuthorization(info.refreshable ? 'refresh' : 'device_code'),
|
|
1186
1359
|
}, phase === 'starting' || phase === 'authorizing' ? t('action.refreshing') : t(info.refreshable ? 'action.refresh' : 'action.reconnect'))
|
|
1187
1360
|
: null), configured ? el('div', { id: 'oasub-sync-help', className: 'oasub-status-detail' }, t('model.sync.help')) : null);
|
|
1188
|
-
return el('div', { className: 'oasub-wrap' }, el('header', { className: 'oasub-header' }, el('div', { className: 'oasub-mark', 'aria-hidden': true }, el(OpenAIIcon, { size: 24 })), el('div', { className: 'oasub-heading' }, el('h2', { className: 'oasub-title' }, t('title')), el('p', { className: 'oasub-subtitle' }, t('subtitle')))), statusCard, configured ? el('section', { className: 'oasub-card oasub-context', 'aria-labelledby': 'oasub-context-title' }, el('div', { id: 'oasub-context-title', className: 'oasub-status-title' }, t('context.title')), el('div', { className: 'oasub-status-detail' }, t('context.help')), contextLoading ? el('div', { role: 'status', className: 'oasub-status-detail' }, t('context.loading')) : null, contextError ? el('div', { role: 'alert', className: 'oasub-notice error' }, t(contextError), el('button', { type: 'button', className: 'oasub-button quiet', disabled: contextLoading, onClick: reloadStatus }, t('action.retry'))) : null, !contextLoading && contexts?.models.length === 0 ? el('div', { className: 'oasub-status-detail' }, t('context.empty')) : null, selectedModel ? el('div', { className: 'oasub-context' }, el('div', { className: 'oasub-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
value
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
'aria-
|
|
1202
|
-
|
|
1203
|
-
'
|
|
1204
|
-
onClick:
|
|
1205
|
-
'
|
|
1206
|
-
'aria-
|
|
1361
|
+
return el('div', { className: 'oasub-wrap' }, el('header', { className: 'oasub-header' }, el('div', { className: 'oasub-mark', 'aria-hidden': true }, el(OpenAIIcon, { size: 24 })), el('div', { className: 'oasub-heading' }, el('h2', { className: 'oasub-title' }, t('title')), el('p', { className: 'oasub-subtitle' }, t('subtitle')))), statusCard, configured ? el('section', { className: 'oasub-card oasub-context', 'aria-labelledby': 'oasub-context-title' }, el('div', { className: 'oasub-section-heading' }, el('div', { className: 'oasub-section-copy' }, el('div', { id: 'oasub-context-title', className: 'oasub-status-title' }, t('context.title')), el('div', { className: 'oasub-status-detail' }, t('context.help')))), contextLoading ? el('div', { role: 'status', className: 'oasub-status-detail' }, t('context.loading')) : null, contextError ? el('div', { role: 'alert', className: 'oasub-notice error' }, t(contextError), el('button', { type: 'button', className: 'oasub-button quiet', disabled: contextLoading, onClick: reloadStatus }, t('action.retry'))) : null, !contextLoading && contexts?.models.length === 0 ? el('div', { className: 'oasub-status-detail' }, t('context.empty')) : null, selectedModel ? el('div', { className: 'oasub-context' }, el('div', { className: 'oasub-context-grid' }, renderPicker('oasub-model', t('context.model'), modelId, (contexts?.models ?? []).map((model) => ({
|
|
1362
|
+
value: model.id, label: model.name || model.id,
|
|
1363
|
+
detail: model.name && model.name !== model.id ? model.id : undefined,
|
|
1364
|
+
})), (value) => { setModelId(value); setContextDraft(null); setContextChoice(null); }), renderPicker('oasub-window', t('context.window'), contextMode, [
|
|
1365
|
+
{ value: 'default', label: t('context.default'), detail: selectedModel.defaultContextWindow ? selectedModel.defaultContextWindow.toLocaleString() + ' tokens' : t('context.default.detail') },
|
|
1366
|
+
{ value: 'million', label: t('context.million'), detail: '1,000,000 tokens', disabled: selectedModel.maxContextWindow !== undefined && selectedModel.maxContextWindow < 1_000_000 },
|
|
1367
|
+
{ value: 'custom', label: t('context.custom'), detail: t('context.custom.detail') },
|
|
1368
|
+
], (value) => {
|
|
1369
|
+
const choice = value === 'default' ? 'default' : value === 'million' ? 'million' : 'custom';
|
|
1370
|
+
setContextChoice(choice);
|
|
1371
|
+
setContextDraft(choice === 'default' ? '' : choice === 'million' ? '1000000' : '-');
|
|
1372
|
+
}, 'oasub-context-limit')), contextMode === 'custom' ? el('label', { className: 'oasub-field' }, t('context.tokens'), el('span', { className: 'oasub-input-shell' }, el('input', { className: 'oasub-token-input', type: 'text', inputMode: 'numeric', 'aria-label': t('context.tokens'),
|
|
1373
|
+
value: draft === '-' ? '' : draft, disabled: contextDisabled, placeholder: '1000000',
|
|
1374
|
+
'aria-invalid': contextValidation !== null, 'aria-describedby': 'oasub-context-limit' + (contextDirty && contextValidation ? ' oasub-context-error' : ''),
|
|
1375
|
+
onChange: (event) => setContextDraft(event.currentTarget.value || '-') }), el('span', { className: 'oasub-token-unit', 'aria-hidden': true }, 'tokens'))) : null, el('div', { id: 'oasub-context-limit', className: 'oasub-context-note' }, uiIcon('info', 13), el('span', null, selectedModel.maxContextWindow ? t('context.maximum', { count: selectedModel.maxContextWindow.toLocaleString() }) + ' · ' + t('context.limit.help') : t('context.unknown'))), contextDirty && contextValidation ? el('div', { id: 'oasub-context-error', role: 'alert', className: 'oasub-context-error' }, t(contextValidation)) : null, el('div', { className: 'oasub-context-footer' }, el('div', { className: 'oasub-context-meta' }, selectedModel.contextWindow ? el('span', null, t('context.current', { count: selectedModel.contextWindow.toLocaleString() })) : null, contextDirty ? el('span', { className: 'oasub-context-badge' }, t('context.pending'))
|
|
1376
|
+
: selectedModel.customized ? el('span', { className: 'oasub-context-badge' }, uiIcon('check', 12), t('context.applied')) : null), contextDirty ? el('button', { type: 'button', className: 'oasub-button primary', disabled: contextDisabled || contextValidation !== null,
|
|
1377
|
+
onClick: saveContext }, t(phase === 'saving-context' ? 'context.saving' : 'context.save')) : null)) : null) : null, statusError !== null
|
|
1378
|
+
? el('div', { className: 'oasub-notice error', role: 'alert' }, t(statusError), info !== null ? ' ' + t('status.stale') : null, el('button', { type: 'button', className: 'oasub-button quiet', disabled: statusLoading, onClick: reloadStatus }, t('action.retry'))) : null, el('section', { className: 'oasub-card oasub-management-card', 'aria-label': t('action.more') }, el('h3', { className: 'oasub-management-heading' }, el('button', { ref: reloadRef, type: 'button', className: 'oasub-management-toggle',
|
|
1379
|
+
'aria-label': t(managementOpen ? 'action.less' : 'action.more'),
|
|
1380
|
+
'aria-expanded': managementOpen, 'aria-controls': 'oasub-management',
|
|
1381
|
+
onClick: () => setManagementOpen((open) => !open) }, el('span', { className: 'oasub-management-symbol' }, uiIcon('settings', 18)), el('span', { className: 'oasub-section-copy' }, el('span', { className: 'oasub-status-title' }, t('action.more')), el('span', { className: 'oasub-status-detail' }, t('manage.help'))), uiIcon('chevron'))), el('div', { id: 'oasub-management', className: 'oasub-management', hidden: !managementOpen }, managementOpen ? [
|
|
1382
|
+
configured && info?.credentialState === 'valid' ? el('div', { key: 'refresh', className: 'oasub-manage-row' }, el('div', { className: 'oasub-section-copy' }, el('div', { className: 'oasub-manage-title' }, t(info.refreshable ? 'action.refresh' : 'action.reconnect')), el('div', { className: 'oasub-status-detail', id: 'oasub-refresh-help' }, t(info.refreshable ? 'manage.refresh.help' : 'manage.reconnect.help'))), el('button', { type: 'button', className: 'oasub-button', disabled: busy || !ready,
|
|
1383
|
+
'aria-describedby': 'oasub-refresh-help',
|
|
1384
|
+
onClick: () => startAuthorization(info.refreshable ? 'refresh' : 'device_code') }, phase === 'starting' || phase === 'authorizing' ? t('action.refreshing') : t(info.refreshable ? 'action.refresh' : 'action.reconnect'))) : null,
|
|
1385
|
+
el('div', { key: 'reload', className: 'oasub-manage-row' }, el('div', { className: 'oasub-section-copy' }, el('div', { className: 'oasub-manage-title' }, t('action.reload')), el('div', { className: 'oasub-status-detail', id: 'oasub-reload-help' }, t('manage.reload.help'))), el('button', { type: 'button', className: 'oasub-button', disabled: statusLoading,
|
|
1386
|
+
'aria-describedby': 'oasub-reload-help', onClick: reloadStatus }, t(statusLoading ? 'status.reloading' : 'action.reload'))),
|
|
1387
|
+
info?.cleanupAvailable ? el('div', { key: 'disconnect', className: 'oasub-manage-row' }, el('div', { className: 'oasub-section-copy' }, el('div', { className: 'oasub-manage-title' }, t('action.disconnect')), el('div', { className: 'oasub-status-detail', id: 'oasub-disconnect-help' }, t('manage.disconnect.help'))), el('button', { type: 'button', className: 'oasub-button danger-quiet', disabled: busy,
|
|
1388
|
+
'aria-describedby': 'oasub-disconnect-help', onClick: () => openConfirm('disconnect') }, t(phase === 'disconnecting' ? 'action.disconnecting' : 'action.disconnect'))) : null,
|
|
1389
|
+
] : null)), device !== null
|
|
1207
1390
|
? el('section', { className: 'oasub-card oasub-device', 'aria-label': t('device.title') }, el('div', { className: 'oasub-device-head' }, el('div', { className: 'oasub-status-title' }, t('device.title')), el('div', { className: 'oasub-status-detail' }, t('device.detail'))), el('input', { ref: codeRef, className: 'oasub-code', type: 'text', readOnly: true, value: device.code,
|
|
1208
1391
|
'aria-label': t('device.code'), autoComplete: 'off', spellCheck: false, onFocus: (event) => event.currentTarget.select() }), el('div', { className: 'oasub-actions' }, device.url !== null
|
|
1209
1392
|
? el('a', { className: 'oasub-button primary', href: device.url, target: '_blank', rel: 'noopener noreferrer',
|
package/package.json
CHANGED