@goodandready/dsh-russian-lang 0.1.14 → 0.1.16
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/lib/client.js +122 -33
- package/lib/index.js +21 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -431,7 +431,7 @@ window.__ModuleLoader__.load({
|
|
|
431
431
|
"cd.shadowed": "{n} навыков скрыты записью с таким же названием",
|
|
432
432
|
"cd.skills": "Каталог скиллов",
|
|
433
433
|
"cd.skills.sub": "{n} навыков",
|
|
434
|
-
"cd.subtitle": "Аудит контекста
|
|
434
|
+
"cd.subtitle": "Аудит контекста",
|
|
435
435
|
"cd.suggestions": "Рекомендации",
|
|
436
436
|
"cd.suggestions.few": "{n} рекомендации",
|
|
437
437
|
"cd.suggestions.many": "{n} рекомендаций",
|
|
@@ -442,7 +442,7 @@ window.__ModuleLoader__.load({
|
|
|
442
442
|
"cd.tools.sub": "{n} встроенных инструментов",
|
|
443
443
|
"cd.toolsCount": "инструментов",
|
|
444
444
|
"cd.topSchemas": "Самые большие схемы",
|
|
445
|
-
"cd.total": "Общее количество
|
|
445
|
+
"cd.total": "Общее количество",
|
|
446
446
|
"cd.updated": "Обновлено {when}"
|
|
447
447
|
},
|
|
448
448
|
"conversation": {
|
|
@@ -745,13 +745,13 @@ window.__ModuleLoader__.load({
|
|
|
745
745
|
"form.notice": "Уведомление",
|
|
746
746
|
"form.recall": "Напомнить",
|
|
747
747
|
"form.relay": "Агентский ретранслятор",
|
|
748
|
-
"form.snapshot": "Снимок состояния
|
|
748
|
+
"form.snapshot": "Снимок состояния",
|
|
749
749
|
"gran.step": "Шаг",
|
|
750
750
|
"gran.turn": "Повернуть",
|
|
751
751
|
"kind.compaction": "Компактный",
|
|
752
|
-
"kind.inject": "Внедрить
|
|
752
|
+
"kind.inject": "Внедрить",
|
|
753
753
|
"kind.model": "Переключить",
|
|
754
|
-
"kind.prune": "Обрезать
|
|
754
|
+
"kind.prune": "Обрезать",
|
|
755
755
|
"loading": "Чтение журнала сессии…",
|
|
756
756
|
"node.calls": "Звонки",
|
|
757
757
|
"node.empty": "(пустой ответ)",
|
|
@@ -767,7 +767,7 @@ window.__ModuleLoader__.load({
|
|
|
767
767
|
"overview.free": "Бесплатное окно",
|
|
768
768
|
"overview.ofUsed": "из использованного контекста",
|
|
769
769
|
"overview.title": "Текущий контекст",
|
|
770
|
-
"overview.used": "использовано
|
|
770
|
+
"overview.used": "использовано контекста",
|
|
771
771
|
"plugin.github": "GitHub",
|
|
772
772
|
"plugin.hint": "Лучший плагин контекста для DSH ⭐",
|
|
773
773
|
"plugin.name": "Плагин",
|
|
@@ -776,7 +776,7 @@ window.__ModuleLoader__.load({
|
|
|
776
776
|
"rich.raw": "Сырьё",
|
|
777
777
|
"rich.toMd": "Просмотреть как Markdown",
|
|
778
778
|
"rich.toRaw": "Просмотреть исходный текст",
|
|
779
|
-
"stats.cacheHit": "Кэш-попадания
|
|
779
|
+
"stats.cacheHit": "Кэш-попадания",
|
|
780
780
|
"stats.compactions": "Компактизации",
|
|
781
781
|
"stats.cost": "Расч. стоимость",
|
|
782
782
|
"stats.costHit": "попадание",
|
|
@@ -1855,9 +1855,9 @@ window.__ModuleLoader__.load({
|
|
|
1855
1855
|
"loginOpenLink": "Откройте страницу авторизации ↗",
|
|
1856
1856
|
"loginStarting": "Запуск локального серверного обработчика callback…",
|
|
1857
1857
|
"loginStoreFailed": "Не удалось сохранить ключ в локальной службе учетных данных; вставьте его вручную.",
|
|
1858
|
-
"loginSuccess": "Вошли как
|
|
1858
|
+
"loginSuccess": "Вошли как",
|
|
1859
1859
|
"loginTimeout": "Истекло время ожидания ответа авторизации; попробуйте снова.",
|
|
1860
|
-
"loginTitle": "
|
|
1860
|
+
"loginTitle": "Войти, чтобы получить ключ",
|
|
1861
1861
|
"loginUnavailable": "Вход в систему недоступен в этой среде; вставьте {API key} вместо этого.",
|
|
1862
1862
|
"loginWaiting": "Ожидание авторизации в вашем браузере…",
|
|
1863
1863
|
"nav": "Код команды",
|
|
@@ -1882,7 +1882,7 @@ window.__ModuleLoader__.load({
|
|
|
1882
1882
|
"usageActive": "Активно",
|
|
1883
1883
|
"usageCooldown": "Охлаждение",
|
|
1884
1884
|
"usageCost": "Потратить",
|
|
1885
|
-
"usageError": "Не удалось получить данные об использовании
|
|
1885
|
+
"usageError": "Не удалось получить данные об использовании",
|
|
1886
1886
|
"usageExceeded": "Превышено",
|
|
1887
1887
|
"usageFailed": "не удалось",
|
|
1888
1888
|
"usageFiveHour": "5-часовое окно",
|
|
@@ -1895,7 +1895,7 @@ window.__ModuleLoader__.load({
|
|
|
1895
1895
|
"usageLoading": "Получение данных об использовании аккаунта…",
|
|
1896
1896
|
"usageMonthly": "Ежемесячно",
|
|
1897
1897
|
"usageNetworkError": "Не удалось подключиться к сервису Command Code",
|
|
1898
|
-
"usageNetworkHint": "На сервер не поступило ни одного запроса. Проверьте подключение к сети или настройку базового API
|
|
1898
|
+
"usageNetworkHint": "На сервер не поступило ни одного запроса. Проверьте подключение к сети или настройку базового API.",
|
|
1899
1899
|
"usageNoKey": "Настройте API-ключ, чтобы увидеть здесь данные об использовании и состоянии кредитов этого аккаунта.",
|
|
1900
1900
|
"usagePartial": "Некоторые данные конечной точки недоступны",
|
|
1901
1901
|
"usagePeriodEnd": "Период заканчивается",
|
|
@@ -2497,10 +2497,10 @@ window.__ModuleLoader__.load({
|
|
|
2497
2497
|
"col.default": "Стандартная ставка",
|
|
2498
2498
|
"col.hour": "Время",
|
|
2499
2499
|
"col.input": "Ввод",
|
|
2500
|
-
"col.model": "Модель
|
|
2500
|
+
"col.model": "Модель",
|
|
2501
2501
|
"col.models": "Модели",
|
|
2502
2502
|
"col.output": "Вывод",
|
|
2503
|
-
"col.price": "
|
|
2503
|
+
"col.price": "Тариф",
|
|
2504
2504
|
"col.provider": "Провайдер",
|
|
2505
2505
|
"col.session": "Сессия",
|
|
2506
2506
|
"col.sessions": "Сессии",
|
|
@@ -2531,7 +2531,7 @@ window.__ModuleLoader__.load({
|
|
|
2531
2531
|
"heatmap.fri": "Пт",
|
|
2532
2532
|
"heatmap.less": "Меньше",
|
|
2533
2533
|
"heatmap.mon": "Пн",
|
|
2534
|
-
"heatmap.month": "{
|
|
2534
|
+
"heatmap.month": "{m}",
|
|
2535
2535
|
"heatmap.more": "Ещё",
|
|
2536
2536
|
"heatmap.title": "Тепловая карта активности (52 недели)",
|
|
2537
2537
|
"heatmap.wed": "Ср",
|
|
@@ -2702,7 +2702,7 @@ window.__ModuleLoader__.load({
|
|
|
2702
2702
|
}
|
|
2703
2703
|
|
|
2704
2704
|
// Подписи собственной карточки настроек (namespace russian-lang).
|
|
2705
|
-
RU['russian-lang'] = {"cardTitle": "Русская локализация", "cardSub": "Язык интерфейса, типографика, раскладка", "enabled": "Русский язык включён", "typography": "Типографика вывода", "yo": "Буква ё", "overridesCount": "Своих переопределений", "statusLoading": "Настройки загружаются…", "statusUnavailable": "Настройки недоступны на этом хосте", "hint": "Машинные переводы помечены в очереди выверки; ручная правка словарей приоритетна.", "altL": "Alt+L — конвертировать раскладку текущего поля"}
|
|
2705
|
+
RU['russian-lang'] = {"cardTitle": "Русская локализация", "cardSub": "Язык интерфейса, типографика, раскладка", "enabled": "Русский язык включён", "typography": "Типографика вывода", "typographyDesc": "Исправляет типографику в тексте ответов: кавычки-«ёлочки», тире вместо дефисов, неразрывные пробелы после коротких предлогов. Код и ссылки не трогаются.", "yo": "Буква ё", "yoDesc": "Восстанавливать «ё» в частых словах (ещё, чёрный, идёт и др.), написанных через «е». Неоднозначные слова (например «все/всё») не трогаются.", "agentPrompt": "Русский промпт агента", "agentPromptDesc": "Добавляет в системный промпт инструкцию отвечать по-русски. Не по умолчанию.", "overridesCount": "Своих переопределений", "statusLoading": "Настройки загружаются…", "statusUnavailable": "Настройки недоступны на этом хосте", "hint": "Машинные переводы помечены в очереди выверки; ручная правка словарей приоритетна.", "altL": "Alt+L — конвертировать раскладку текущего поля"}
|
|
2706
2706
|
|
|
2707
2707
|
const SETTINGS_NS_NAME = 'russian-lang'
|
|
2708
2708
|
|
|
@@ -3056,12 +3056,20 @@ window.__ModuleLoader__.load({
|
|
|
3056
3056
|
return out
|
|
3057
3057
|
}
|
|
3058
3058
|
const ruWordFraction = (text) => {
|
|
3059
|
-
// доля слов текста, присутствующих в частотном словаре
|
|
3059
|
+
// доля слов текста, присутствующих в частотном словаре или локальном
|
|
3060
3060
|
const words = text.toLowerCase().split(/[^а-яё]+/).filter(Boolean)
|
|
3061
3061
|
if (!words.length) return 0
|
|
3062
|
-
const hit = words.filter((w) => FREQ.has(w)).length
|
|
3062
|
+
const hit = words.filter((w) => FREQ.has(w) || localDict.has(w)).length
|
|
3063
3063
|
return hit / words.length
|
|
3064
3064
|
}
|
|
3065
|
+
// Локальный словарь обучения (#67): слова, которые пользователь принял
|
|
3066
|
+
// через «Исправить». Живёт в памяти сессии, в настройки/бандл не пишется.
|
|
3067
|
+
const localDict = new Set()
|
|
3068
|
+
const learnWords = (text) => {
|
|
3069
|
+
for (const w of text.toLowerCase().split(/[^а-яё]+/).filter(Boolean)) {
|
|
3070
|
+
if (w.length >= 3) localDict.add(w)
|
|
3071
|
+
}
|
|
3072
|
+
}
|
|
3065
3073
|
const layoutFixCandidate = (value, direction) => {
|
|
3066
3074
|
// direction: 'lat2cyr' | 'cyr2lat'. Возвращает {converted} если подозрительно.
|
|
3067
3075
|
if (direction === 'lat2cyr') {
|
|
@@ -3103,6 +3111,7 @@ window.__ModuleLoader__.load({
|
|
|
3103
3111
|
ev.preventDefault()
|
|
3104
3112
|
inputEl.value = converted
|
|
3105
3113
|
inputEl.dispatchEvent(new Event('input', { bubbles: true }))
|
|
3114
|
+
learnWords(converted) // #67: запомнить принятые слова
|
|
3106
3115
|
layoutDismiss()
|
|
3107
3116
|
})
|
|
3108
3117
|
document.body.appendChild(layoutHintEl)
|
|
@@ -3111,11 +3120,50 @@ window.__ModuleLoader__.load({
|
|
|
3111
3120
|
layoutHintEl.style.left = (r.left + 8) + 'px'
|
|
3112
3121
|
layoutHintEl.style.bottom = (window.innerHeight - r.top + 6) + 'px'
|
|
3113
3122
|
}
|
|
3123
|
+
|
|
3124
|
+
// #66: индикатор активной раскладки у чат-инпута. Определяем по последнему
|
|
3125
|
+
// введённому символу (кириллица → RU, латиница → EN); клик — Alt+L-конверт.
|
|
3126
|
+
let layoutBadgeEl = null
|
|
3127
|
+
const layoutBadge = (el) => {
|
|
3128
|
+
const value = el.value || ''
|
|
3129
|
+
const last = value.trim().slice(-1)
|
|
3130
|
+
const isCyr = /[\u0430-\u044f\u0451]/.test(last)
|
|
3131
|
+
const isLat = /[a-z]/i.test(last)
|
|
3132
|
+
const label = isCyr ? 'RU' : (isLat ? 'EN' : '')
|
|
3133
|
+
if (!label) { layoutBadgeHide(); return }
|
|
3134
|
+
if (!layoutBadgeEl) {
|
|
3135
|
+
layoutBadgeEl = document.createElement('button')
|
|
3136
|
+
layoutBadgeEl.type = 'button'
|
|
3137
|
+
layoutBadgeEl.dataset.russianLangLayoutBadge = '1'
|
|
3138
|
+
Object.assign(layoutBadgeEl.style, {
|
|
3139
|
+
position: 'fixed', zIndex: '99998', background: 'var(--dsw-alias-bg-layer-3, #fff)',
|
|
3140
|
+
color: 'var(--dsw-alias-label-secondary, #666)', border: '1px solid var(--dsw-alias-border-l2, #888)',
|
|
3141
|
+
borderRadius: '6px', padding: '1px 6px', fontSize: '11px', cursor: 'pointer',
|
|
3142
|
+
fontFamily: 'monospace', lineHeight: '1.4',
|
|
3143
|
+
})
|
|
3144
|
+
layoutBadgeEl.title = 'Раскладка — клик: конвертировать (Alt+L)'
|
|
3145
|
+
layoutBadgeEl.addEventListener('mousedown', (ev) => {
|
|
3146
|
+
ev.preventDefault()
|
|
3147
|
+
const v = el.value || ''
|
|
3148
|
+
const c = layoutFixCandidate(v, 'lat2cyr') || layoutFixCandidate(v, 'cyr2lat')
|
|
3149
|
+
if (c) { el.value = c.converted; el.dispatchEvent(new Event('input', { bubbles: true })) }
|
|
3150
|
+
})
|
|
3151
|
+
document.body.appendChild(layoutBadgeEl)
|
|
3152
|
+
}
|
|
3153
|
+
layoutBadgeEl.textContent = label
|
|
3154
|
+
const r = el.getBoundingClientRect()
|
|
3155
|
+
layoutBadgeEl.style.left = (r.right - 24) + 'px'
|
|
3156
|
+
layoutBadgeEl.style.top = (r.top - 20) + 'px'
|
|
3157
|
+
}
|
|
3158
|
+
const layoutBadgeHide = () => {
|
|
3159
|
+
if (layoutBadgeEl) { layoutBadgeEl.remove(); layoutBadgeEl = null }
|
|
3160
|
+
}
|
|
3114
3161
|
const layoutOnInput = () => {
|
|
3115
3162
|
try {
|
|
3116
|
-
if (runtime.getLocale().active !== 'ru') { layoutDismiss(); return }
|
|
3163
|
+
if (runtime.getLocale().active !== 'ru') { layoutDismiss(); layoutBadgeHide(); return }
|
|
3117
3164
|
const el = layoutCurrentInput()
|
|
3118
|
-
if (!el) { layoutDismiss(); return }
|
|
3165
|
+
if (!el) { layoutDismiss(); layoutBadgeHide(); return }
|
|
3166
|
+
layoutBadge(el) // #66: метка раскладки
|
|
3119
3167
|
const value = el.value || ''
|
|
3120
3168
|
if (value.trim().length < 4) { layoutDismiss(); return }
|
|
3121
3169
|
// lat2cyr: если есть латиница и почти нет кириллицы
|
|
@@ -3146,6 +3194,7 @@ window.__ModuleLoader__.load({
|
|
|
3146
3194
|
ev.preventDefault()
|
|
3147
3195
|
el.value = c.converted
|
|
3148
3196
|
el.dispatchEvent(new Event('input', { bubbles: true }))
|
|
3197
|
+
learnWords(c.converted) // #67
|
|
3149
3198
|
}
|
|
3150
3199
|
}
|
|
3151
3200
|
}
|
|
@@ -3154,6 +3203,7 @@ window.__ModuleLoader__.load({
|
|
|
3154
3203
|
unsubscribeLayout()
|
|
3155
3204
|
document.removeEventListener('input', layoutOnInput, true)
|
|
3156
3205
|
layoutDismiss()
|
|
3206
|
+
layoutBadgeHide()
|
|
3157
3207
|
}, 'dsh-russian-lang: layout')
|
|
3158
3208
|
|
|
3159
3209
|
// 8. Карточка настроек («Настройки → Плагины → Настройки плагинов»).
|
|
@@ -3189,31 +3239,49 @@ window.__ModuleLoader__.load({
|
|
|
3189
3239
|
const [open, setOpen] = React.useState(false)
|
|
3190
3240
|
const [snap, setSnap] = React.useState(
|
|
3191
3241
|
() => (scope && scope.getSnapshot ? scope.getSnapshot() : { status: 'loading', value: {} }))
|
|
3242
|
+
const [ruActive, setRuActive] = React.useState(
|
|
3243
|
+
() => { try { return runtime.getLocale().active === 'ru' } catch (e) { return false } })
|
|
3244
|
+
// Оптимистичное состояние типографики: галочка переключается сразу,
|
|
3245
|
+
// а host-подтверждение (scope.subscribe) лишь синхронизирует его позже.
|
|
3246
|
+
const [typo, setTypoState] = React.useState(() =>
|
|
3247
|
+
(snap.value && snap.value.typography) || {})
|
|
3248
|
+
|
|
3192
3249
|
React.useEffect(() => {
|
|
3193
3250
|
if (!scope || !scope.subscribe) return undefined
|
|
3194
|
-
const un = scope.subscribe(() =>
|
|
3251
|
+
const un = scope.subscribe(() => {
|
|
3252
|
+
const s = scope.getSnapshot()
|
|
3253
|
+
setSnap(s)
|
|
3254
|
+
if (s.value && s.value.typography) setTypoState(s.value.typography)
|
|
3255
|
+
})
|
|
3195
3256
|
setSnap(scope.getSnapshot())
|
|
3196
3257
|
return un
|
|
3197
3258
|
}, [])
|
|
3259
|
+
React.useEffect(() => {
|
|
3260
|
+
try {
|
|
3261
|
+
const un = runtime.subscribe(() => {
|
|
3262
|
+
try { setRuActive(runtime.getLocale().active === 'ru') } catch (e) { /* ignore */ }
|
|
3263
|
+
})
|
|
3264
|
+
return un
|
|
3265
|
+
} catch (e) { return undefined }
|
|
3266
|
+
}, [])
|
|
3198
3267
|
|
|
3199
3268
|
const status = snap.status || 'loading'
|
|
3200
3269
|
const value = snap.value || {}
|
|
3201
|
-
const typography =
|
|
3270
|
+
const typography = typo
|
|
3202
3271
|
const overridesCount = Object.keys(value.overrides || {}).length
|
|
3203
3272
|
|
|
3204
|
-
const ruActive = (() => {
|
|
3205
|
-
try { return runtime.getLocale().active === 'ru' } catch (err) { return false }
|
|
3206
|
-
})()
|
|
3207
|
-
|
|
3208
3273
|
const setTypo = (patch) => {
|
|
3209
|
-
const next = Object.assign({},
|
|
3274
|
+
const next = Object.assign({}, typo, patch)
|
|
3275
|
+
setTypoState(next) // мгновенно
|
|
3210
3276
|
try { scope.set('typography', next) } catch (err) { /* ignore */ }
|
|
3211
3277
|
}
|
|
3212
3278
|
const onEnabled = (ev) => { if (toggleRu) toggleRu(ev.target.checked) }
|
|
3213
3279
|
|
|
3214
|
-
const row = (label, control) =>
|
|
3280
|
+
const row = (label, control, desc) =>
|
|
3215
3281
|
React.createElement('div', { className: 'rl-field' },
|
|
3216
|
-
React.createElement('span', { className: 'rl-label' }, label),
|
|
3282
|
+
React.createElement('span', { className: 'rl-label' }, label),
|
|
3283
|
+
control,
|
|
3284
|
+
desc ? React.createElement('div', { className: 'rl-desc' }, desc) : null)
|
|
3217
3285
|
|
|
3218
3286
|
const checkbox = (checked, onChange, disabled) =>
|
|
3219
3287
|
React.createElement('input', {
|
|
@@ -3226,6 +3294,21 @@ window.__ModuleLoader__.load({
|
|
|
3226
3294
|
: (status === 'unavailable' ? t('statusUnavailable') : t('statusLoading'))
|
|
3227
3295
|
const disabled = status !== 'ready'
|
|
3228
3296
|
|
|
3297
|
+
// Ядровый шеврон раскрытия; в урезанной сборке — запасной SVG той же формы.
|
|
3298
|
+
const Chevron = (() => {
|
|
3299
|
+
try {
|
|
3300
|
+
const primitives = require('@deepseek-ai/dsh-client-ui-primitives')
|
|
3301
|
+
if (primitives && primitives.IconChevronDownOutline14) return primitives.IconChevronDownOutline14
|
|
3302
|
+
} catch (e) { /* нет набора */ }
|
|
3303
|
+
return () => React.createElement('svg', {
|
|
3304
|
+
width: 14, height: 14, viewBox: '0 0 14 14', fill: 'none',
|
|
3305
|
+
'aria-hidden': 'true',
|
|
3306
|
+
}, React.createElement('path', {
|
|
3307
|
+
d: 'M3.5 5.25 7 8.75l3.5-3.5', stroke: 'currentColor',
|
|
3308
|
+
'stroke-width': 1.5, 'stroke-linecap': 'round', 'stroke-linejoin': 'round',
|
|
3309
|
+
}))
|
|
3310
|
+
})()
|
|
3311
|
+
|
|
3229
3312
|
return React.createElement('div', { className: 'rl-card' },
|
|
3230
3313
|
React.createElement('button', {
|
|
3231
3314
|
type: 'button',
|
|
@@ -3237,13 +3320,17 @@ window.__ModuleLoader__.load({
|
|
|
3237
3320
|
React.createElement('div', { className: 'rl-title' }, t('cardTitle')),
|
|
3238
3321
|
React.createElement('div', { className: 'rl-sub' },
|
|
3239
3322
|
statusLine || t('cardSub'))),
|
|
3240
|
-
React.createElement('span', {
|
|
3323
|
+
React.createElement('span', {
|
|
3324
|
+
className: 'rl-chev' + (open ? ' rl-chev-open' : ''),
|
|
3325
|
+
}, React.createElement(Chevron, null))),
|
|
3241
3326
|
open && React.createElement('div', { className: 'rl-body' },
|
|
3242
|
-
row(t('enabled'), checkbox(ruActive, onEnabled, false)),
|
|
3327
|
+
row(t('enabled'), checkbox(ruActive, onEnabled, false), null),
|
|
3243
3328
|
row(t('typography'), checkbox(typography.enabled !== false && ruActive,
|
|
3244
|
-
(ev) => setTypo({ enabled: ev.target.checked }), !ruActive)),
|
|
3329
|
+
(ev) => setTypo({ enabled: ev.target.checked }), !ruActive), t('typographyDesc')),
|
|
3245
3330
|
row(t('yo'), checkbox(typography.yo === true,
|
|
3246
|
-
(ev) => setTypo({ yo: ev.target.checked }), !ruActive)),
|
|
3331
|
+
(ev) => setTypo({ yo: ev.target.checked }), !ruActive), t('yoDesc')),
|
|
3332
|
+
row(t('agentPrompt'), checkbox(value.agentPrompt === true,
|
|
3333
|
+
(ev) => { try { scope.set('agentPrompt', ev.target.checked) } catch (e) { /* ignore */ } }, false), t('agentPromptDesc')),
|
|
3247
3334
|
React.createElement('div', { className: 'rl-note' },
|
|
3248
3335
|
t('overridesCount') + ': ' + overridesCount),
|
|
3249
3336
|
React.createElement('div', { className: 'rl-hint' }, t('altL')),
|
|
@@ -3257,10 +3344,12 @@ window.__ModuleLoader__.load({
|
|
|
3257
3344
|
'.rl-head{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;display:flex;align-items:center;gap:12px;padding:14px 16px}',
|
|
3258
3345
|
'.rl-title{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}',
|
|
3259
3346
|
'.rl-sub{color:var(--dsw-alias-label-secondary);font-size:13px}',
|
|
3260
|
-
'.rl-chev{color:var(--dsw-alias-label-
|
|
3347
|
+
'.rl-chev{margin-left:auto;flex:none;color:var(--dsw-alias-label-tertiary);display:inline-flex;transition:transform .16s}',
|
|
3348
|
+
'.rl-chev-open{transform:rotate(180deg)}',
|
|
3261
3349
|
'.rl-body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}',
|
|
3262
3350
|
'.rl-field{display:flex;flex-direction:column;gap:6px;padding:12px 0}',
|
|
3263
3351
|
'.rl-label{color:var(--dsw-alias-label-primary);font-size:13px}',
|
|
3352
|
+
'.rl-desc{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.4}',
|
|
3264
3353
|
'.rl-check{width:16px;height:16px;accent-color:var(--dsw-alias-label-primary)}',
|
|
3265
3354
|
'.rl-note{color:var(--dsw-alias-label-secondary);font-size:12px;padding:8px 0 4px}',
|
|
3266
3355
|
'.rl-hint{color:var(--dsw-alias-label-secondary);font-size:12px;padding:4px 0 8px}',
|
package/lib/index.js
CHANGED
|
@@ -15,11 +15,31 @@ const RussianLangSettingsSchema = z.object({
|
|
|
15
15
|
typography: z.object({
|
|
16
16
|
enabled: z.boolean().required(false),
|
|
17
17
|
yo: z.boolean().required(false)
|
|
18
|
-
}).required(false)
|
|
18
|
+
}).required(false),
|
|
19
|
+
agentPrompt: z.boolean().required(false)
|
|
19
20
|
})
|
|
20
21
|
|
|
21
22
|
export function apply(ctx) {
|
|
22
23
|
ctx.inject(['settings'], (settingsCtx) => {
|
|
23
24
|
settingsCtx.settings.register(settingsNamespace('russian-lang'), RussianLangSettingsSchema)
|
|
24
25
|
})
|
|
26
|
+
|
|
27
|
+
// #68: русский системный промпт агента (опционально). Регистрируем секцию
|
|
28
|
+
// промпта, которая просит отвечать по-русски, когда включён флаг
|
|
29
|
+
// russian-lang.agentPrompt. Секция — официальная точка расширения ядра.
|
|
30
|
+
ctx.inject(['settings', 'systemPrompt'], (settingsCtx, prompt) => {
|
|
31
|
+
const NS = settingsNamespace('russian-lang')
|
|
32
|
+
const RU_SECTION = 'dsh-russian-lang-agent-prompt'
|
|
33
|
+
const RU_TEXT = 'Отвечай пользователю на русском языке. Если пользователь пишет на другом языке, отвечай на его языке.'
|
|
34
|
+
let current = false
|
|
35
|
+
const sync = () => {
|
|
36
|
+
const value = settingsCtx.settings.get(NS)
|
|
37
|
+
const want = !!(value && value.agentPrompt)
|
|
38
|
+
if (want === current) return
|
|
39
|
+
current = want
|
|
40
|
+
prompt.section({ name: RU_SECTION, order: 1000, text: want ? RU_TEXT : '' })
|
|
41
|
+
}
|
|
42
|
+
ctx.on('settings/updated', (ns) => { if (ns === NS) sync() })
|
|
43
|
+
sync()
|
|
44
|
+
})
|
|
25
45
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-russian-lang",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Russian localization for the DeepSeek Harness web UI: adds Русский as the third option in the native Settings - General - Language menu. Translates the full core surface (100% coverage of DSH 0.1.1-rc.2) plus 16 community plugin namespaces - 52 namespaces, 2795 strings (many machine-drafted, queued for manual review), with Russian plural forms, count-key plurals, a typography pass (guillemets, em dash, nbsp), a wrong-layout input hint and browser spellcheck. The locale runtime snapshot is extended at runtime on unpatched cores; no files in the DSH installation are modified. The choice is persisted through the plugin-owned russian-lang namespace.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|