tensorgrid-ui 1.1.4 → 1.2.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 (2) hide show
  1. package/lib/client.js +45 -8
  2. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -177,7 +177,9 @@ window.__ModuleLoader__.load({
177
177
  'intensity.vivid': 'Vivid',
178
178
  'accent.title': 'Obsidian / Ion accent',
179
179
  'accent.hint': 'Leading tone of the interface and the glow',
180
+ 'auth.nav': 'Subscriptions',
180
181
  'auth.title': 'Provider sign-in',
182
+ 'auth.others': 'Only providers offering a subscription sign-in are listed. The rest — Z.AI among them — offer an API key only; configure those under Models.',
181
183
  'auth.hint': 'Sign in with a subscription instead of an API key. The account stays on this computer.',
182
184
  'auth.signIn': 'Sign in',
183
185
  'auth.again': 'Sign in again',
@@ -222,7 +224,9 @@ window.__ModuleLoader__.load({
222
224
  'intensity.vivid': '强烈',
223
225
  'accent.title': 'Obsidian / Ion 主色',
224
226
  'accent.hint': '界面与光晕的主色调',
227
+ 'auth.nav': '订阅',
225
228
  'auth.title': '登录服务商',
229
+ 'auth.others': '这里只列出提供订阅登录的服务商。其余(包括 Z.AI)只提供 API 密钥,请在「模型」中配置。',
226
230
  'auth.hint': '使用订阅登录,而非 API 密钥。账号仅保存在本机。',
227
231
  'auth.signIn': '登录',
228
232
  'auth.again': '重新登录',
@@ -1564,7 +1568,9 @@ window.__ModuleLoader__.load({
1564
1568
  'intensity.vivid': 'Ярко',
1565
1569
  'accent.title': 'Акцент Obsidian / Ion',
1566
1570
  'accent.hint': 'Ведущий тон интерфейса и свечения',
1571
+ 'auth.nav': 'Подписки',
1567
1572
  'auth.title': 'Вход к провайдерам',
1573
+ 'auth.others': 'Здесь только провайдеры, у которых есть вход по подписке. Остальные — в том числе Z.AI — предлагают лишь ключ API; их место в разделе «Модели».',
1568
1574
  'auth.hint': 'Войти по подписке вместо ключа API. Учётная запись остаётся на этом компьютере.',
1569
1575
  'auth.signIn': 'Войти',
1570
1576
  'auth.again': 'Войти заново',
@@ -1710,7 +1716,7 @@ window.__ModuleLoader__.load({
1710
1716
  // поэтому строка остаётся согласованной при любой палитре.
1711
1717
  '.dsx-setting{display:flex;align-items:center;justify-content:space-between;gap:16px;width:100%;}',
1712
1718
  '.dsx-setting__title{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500;}',
1713
- '.dsx-setting--stack{flex-direction:column;align-items:stretch;gap:10px}.dsx-auth__list{display:flex;flex-direction:column;gap:6px}.dsx-auth__row{display:flex;align-items:center;justify-content:space-between;gap:12px}.dsx-auth__name{color:var(--dsw-alias-label-primary)}.dsx-auth__badge{margin-left:8px;padding:1px 6px;border-radius:999px;font-size:11px;color:var(--dsw-alias-state-success-primary);border:1px solid var(--dsw-alias-border-l2)}.dsx-auth__panel{display:flex;flex-direction:column;gap:8px;padding:10px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1)}.dsx-auth__notice,.dsx-auth__prompt{display:flex;flex-direction:column;gap:6px;color:var(--dsw-alias-label-secondary)}.dsx-auth__link{color:var(--dsw-alias-brand-primary);word-break:break-all}.dsx-auth__code{font-family:ui-monospace,monospace;letter-spacing:.08em;color:var(--dsw-alias-label-primary)}.dsx-auth__input{flex:1;min-width:0;padding:4px 8px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.dsx-setting__hint--strong{color:var(--dsw-alias-label-primary)}.dsx-setting__hint--warn{color:var(--dsw-alias-state-warn-primary)}.dsx-setting__hint{color:var(--dsw-alias-label-secondary);font-size:12px;margin-top:2px;}',
1719
+ '.dsx-subs{display:flex;flex-direction:column;gap:14px;padding:4px 0}.dsx-subs__head{display:flex;flex-direction:column;gap:4px}.dsx-subs__title{font-weight:600;font-size:15px;color:var(--dsw-alias-label-primary)}.dsx-subs__note{padding-top:6px;border-top:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5}.dsx-setting--stack{flex-direction:column;align-items:stretch;gap:10px}.dsx-auth__list{display:flex;flex-direction:column;gap:6px}.dsx-auth__row{display:flex;align-items:center;justify-content:space-between;gap:12px}.dsx-auth__name{color:var(--dsw-alias-label-primary)}.dsx-auth__badge{margin-left:8px;padding:1px 6px;border-radius:999px;font-size:11px;color:var(--dsw-alias-state-success-primary);border:1px solid var(--dsw-alias-border-l2)}.dsx-auth__panel{display:flex;flex-direction:column;gap:8px;padding:10px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1)}.dsx-auth__notice,.dsx-auth__prompt{display:flex;flex-direction:column;gap:6px;color:var(--dsw-alias-label-secondary)}.dsx-auth__link{color:var(--dsw-alias-brand-primary);word-break:break-all}.dsx-auth__code{font-family:ui-monospace,monospace;letter-spacing:.08em;color:var(--dsw-alias-label-primary)}.dsx-auth__input{flex:1;min-width:0;padding:4px 8px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.dsx-setting__hint--strong{color:var(--dsw-alias-label-primary)}.dsx-setting__hint--warn{color:var(--dsw-alias-state-warn-primary)}.dsx-setting__hint{color:var(--dsw-alias-label-secondary);font-size:12px;margin-top:2px;}',
1714
1720
  '.dsx-setting__control{display:inline-flex;padding:2px;gap:2px;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;background:var(--dsw-alias-bg-layer-2);flex:none;}',
1715
1721
  '.dsx-seg{appearance:none;border:0;cursor:pointer;padding:4px 10px;border-radius:6px;font-size:12px;line-height:18px;background:transparent;color:var(--dsw-alias-label-secondary);transition:background .16s ease,color .16s ease;}',
1716
1722
  '.dsx-seg:hover{color:var(--dsw-alias-label-primary);}',
@@ -1946,6 +1952,18 @@ window.__ModuleLoader__.load({
1946
1952
  const [busy, setBusy] = React.useState(false)
1947
1953
  const [draft, setDraft] = React.useState('')
1948
1954
 
1955
+ // Функция перевода приходит от рантайма НОВОЙ при каждом рендере —
1956
+ // в поставочном коде это обычная стрелка, не мемоизированная. Если
1957
+ // поставить её в зависимости запроса, цепочка t → send → refresh
1958
+ // пересоздаётся каждый раз, эффект с [refresh] срабатывает снова, и
1959
+ // строка уходит в бесконечный цикл рендеров и обращений к Host.
1960
+ // Такой цикл подвешивает всю вкладку, а не только настройки.
1961
+ //
1962
+ // Поэтому перевод берётся через ссылку: она всегда указывает на
1963
+ // свежую функцию, но сама себя не меняет.
1964
+ const translate = React.useRef(t)
1965
+ translate.current = t
1966
+
1949
1967
  const send = React.useCallback(async (body) => {
1950
1968
  const response = body === undefined
1951
1969
  ? await fetch(AUTH_PATH)
@@ -1961,16 +1979,17 @@ window.__ModuleLoader__.load({
1961
1979
  // не JSON. Без этой проверки строка молча показывала пустоту.
1962
1980
  const type = response.headers.get('content-type') || ''
1963
1981
  if (!type.includes('application/json')) {
1982
+ const say = translate.current
1964
1983
  return {
1965
1984
  available: true,
1966
1985
  providers: [],
1967
1986
  problem: response.status === 401 || response.status === 404
1968
- ? t('auth.needsRestart')
1969
- : t('auth.badResponse').replace('{status}', String(response.status)),
1987
+ ? say('auth.needsRestart')
1988
+ : say('auth.badResponse').replace('{status}', String(response.status)),
1970
1989
  }
1971
1990
  }
1972
1991
  return response.json()
1973
- }, [t])
1992
+ }, [])
1974
1993
 
1975
1994
  const refresh = React.useCallback(async (body) => {
1976
1995
  setBusy(true)
@@ -2085,11 +2104,12 @@ window.__ModuleLoader__.load({
2085
2104
  }
2086
2105
 
2087
2106
  return jsxs('div', {
2088
- className: 'dsx-setting dsx-setting--stack',
2107
+ className: 'dsx-subs',
2089
2108
  children: [
2090
2109
  jsxs('div', {
2110
+ className: 'dsx-subs__head',
2091
2111
  children: [
2092
- jsx('div', { className: 'dsx-setting__title', children: t('auth.title') }),
2112
+ jsx('div', { className: 'dsx-subs__title', children: t('auth.title') }),
2093
2113
  jsx('div', { className: 'dsx-setting__hint', children: t('auth.hint') }),
2094
2114
  ],
2095
2115
  }),
@@ -2136,6 +2156,11 @@ window.__ModuleLoader__.load({
2136
2156
  }),
2137
2157
  })
2138
2158
  : null,
2159
+ // Здесь только провайдеры, у которых есть вход по подписке. У
2160
+ // остальных — включая Z.AI — поставщик предлагает единственный
2161
+ // способ, ключ API, и его место в разделе «Модели». Без этой
2162
+ // строки отсутствие знакомого имени выглядит как недоработка.
2163
+ jsx('div', { className: 'dsx-subs__note', children: t('auth.others') }),
2139
2164
  ],
2140
2165
  })
2141
2166
  }
@@ -2348,9 +2373,21 @@ window.__ModuleLoader__.load({
2348
2373
  ),
2349
2374
  )
2350
2375
 
2351
- ctx.slots.inject('settings.general.item', () =>
2376
+ // Подписки — собственный раздел настроек, а не строка среди прочих.
2377
+ //
2378
+ // `settings.section` — аддитивный список: своя запись добавляет свою
2379
+ // вкладку и ничего не замещает. Порядок 12 ставит её между «Моделями»
2380
+ // (10) и «Плагинами» (15): вход к провайдерам — сосед моделей, а не
2381
+ // оформления.
2382
+ ctx.slots.inject('settings.section', () =>
2352
2383
  ctx.slots.register(
2353
- { name: 'settings.general.item', id: 'tensorgrid-auth', order: 10, locale: LOCALE_NS },
2384
+ {
2385
+ name: 'settings.section',
2386
+ id: 'tensorgrid-subscriptions',
2387
+ order: 12,
2388
+ locale: LOCALE_NS,
2389
+ label: () => ctx.locale.translate(LOCALE_NS, 'auth.nav'),
2390
+ },
2354
2391
  AuthRow,
2355
2392
  ),
2356
2393
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tensorgrid-ui",
3
- "version": "1.1.4",
3
+ "version": "1.2.0",
4
4
  "description": "TENSOR GRID — фирменный интерфейс поверх DeepSeek Harness: палитра, живой ambient-слой, айдентика и русский язык-пакет",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",