@yadsh/dsh-qa-surface 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/lib/client/QaSurface.js +6 -3
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/admin/routes.js +18 -2
- package/lib/client/admin/routes.js.map +1 -1
- package/lib/client/components/QaChangelog.js +36 -0
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/components/QaHeader.js +2 -2
- package/lib/client/components/QaHeader.js.map +1 -1
- package/lib/client/index.js +15 -0
- package/lib/client/index.js.map +1 -1
- package/lib/client/session-sources.js +20 -1
- package/lib/client/session-sources.js.map +1 -1
- package/lib/client/settings-extensions/index.js +1 -0
- package/lib/client/settings-extensions/index.js.map +1 -1
- package/lib/client/settings-extensions/user-session.js +62 -0
- package/lib/client/settings-extensions/user-session.js.map +1 -0
- package/lib/client/styles.js +10 -7
- package/lib/client/styles.js.map +1 -1
- package/lib/client/user-settings/GeneralSettingsPage.js +6 -5
- package/lib/client/user-settings/GeneralSettingsPage.js.map +1 -1
- package/lib/client/user-settings/SkillToolPicker.js +1 -1
- package/lib/client/user-settings/SkillToolPicker.js.map +1 -1
- package/lib/client/user-settings/StartersSettingsPage.js +10 -10
- package/lib/client/user-settings/StartersSettingsPage.js.map +1 -1
- package/lib/client.js +212 -49
- package/lib/client.js.map +1 -1
- package/lib/enforcement/tool-grants.js +35 -6
- package/lib/enforcement/tool-grants.js.map +1 -1
- package/lib/provenance/extractors.js +26 -1
- package/lib/provenance/extractors.js.map +1 -1
- package/lib/secure-session.js +10 -1
- package/lib/secure-session.js.map +1 -1
- package/lib/types/client/admin/routes.d.ts +10 -0
- package/lib/types/client/components/QaHeader.d.ts +11 -1
- package/lib/types/client/session-sources.d.ts +9 -0
- package/lib/types/client/settings-extensions/index.d.ts +2 -0
- package/lib/types/client/settings-extensions/user-session.d.ts +59 -0
- package/lib/types/client/user-settings/GeneralSettingsPage.d.ts +5 -4
- package/lib/types/enforcement/tool-grants.d.ts +17 -3
- package/package.json +3 -3
package/lib/client.js
CHANGED
|
@@ -11238,10 +11238,23 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11238
11238
|
this.refreshing = false;
|
|
11239
11239
|
this.refusal = "";
|
|
11240
11240
|
}
|
|
11241
|
+
/**
|
|
11242
|
+
* The Host's bundles win the turns they share with the projection, with one
|
|
11243
|
+
* exception: a bundle that collected nothing never erases a turn the
|
|
11244
|
+
* transcript accounts for. Both channels read the same durable tool results,
|
|
11245
|
+
* so a turn the projection filled and the Host reported empty means the
|
|
11246
|
+
* Host's collection missed that turn, not that the answer had no sources —
|
|
11247
|
+
* and without this guard such a turn loses the sources the reader could see
|
|
11248
|
+
* while it ran the moment the Host answers for it.
|
|
11249
|
+
*/
|
|
11241
11250
|
merge(projected) {
|
|
11242
11251
|
const merged = /* @__PURE__ */ new Map();
|
|
11243
11252
|
for (const bundle of projected) merged.set(bundle.turn, bundle);
|
|
11244
|
-
for (const bundle of this.bundles)
|
|
11253
|
+
for (const bundle of this.bundles) {
|
|
11254
|
+
const collected = merged.get(bundle.turn);
|
|
11255
|
+
if (collected !== void 0 && carriesNothing(bundle) && !carriesNothing(collected)) continue;
|
|
11256
|
+
merged.set(bundle.turn, bundle);
|
|
11257
|
+
}
|
|
11245
11258
|
return [...merged.values()].sort((left, right) => left.turn - right.turn);
|
|
11246
11259
|
}
|
|
11247
11260
|
/**
|
|
@@ -11282,6 +11295,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11282
11295
|
}
|
|
11283
11296
|
}
|
|
11284
11297
|
};
|
|
11298
|
+
/** True when a bundle holds no source at all, promoted or discovered. */
|
|
11299
|
+
function carriesNothing(bundle) {
|
|
11300
|
+
return bundle.sources.length === 0 && (bundle.discovered?.length ?? 0) === 0;
|
|
11301
|
+
}
|
|
11285
11302
|
/** Stable text for one refusal, so the same failure is not reported twice. */
|
|
11286
11303
|
function refusalKey(error) {
|
|
11287
11304
|
if (typeof error === "string") return error;
|
|
@@ -12085,6 +12102,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
12085
12102
|
}
|
|
12086
12103
|
};
|
|
12087
12104
|
}
|
|
12105
|
+
/**
|
|
12106
|
+
* The Host's web tool opens its result with an envelope — `Fetched <url>
|
|
12107
|
+
* (HTTP <code>)`, then the untrusted-content notice — before the page itself.
|
|
12108
|
+
* Both lines are dropped here, and so is a first line that is the page's own
|
|
12109
|
+
* address: the card already prints the target URL, so a snippet drawn from
|
|
12110
|
+
* either of them would only repeat what the reader can already see.
|
|
12111
|
+
*/
|
|
12112
|
+
const WEB_FETCH_ENVELOPE = /^(?:Fetched\s+\S+\s+\(HTTP\s+\d+\)|External web content follows\..*)$/u;
|
|
12113
|
+
function fetchedSnippet(value, uri) {
|
|
12114
|
+
if (value === void 0) return void 0;
|
|
12115
|
+
const target = uri.replace(/\/+$/u, "");
|
|
12116
|
+
return snippet(value.split(/\r?\n/u).filter((line) => {
|
|
12117
|
+
const text = line.trim();
|
|
12118
|
+
if (text === "") return true;
|
|
12119
|
+
if (WEB_FETCH_ENVELOPE.test(text)) return false;
|
|
12120
|
+
return text.replace(/\/+$/u, "") !== target;
|
|
12121
|
+
}).join("\n"));
|
|
12122
|
+
}
|
|
12088
12123
|
function createWebFetchExtractor(urlOptions = {}) {
|
|
12089
12124
|
return {
|
|
12090
12125
|
id: "dsh-web-fetch",
|
|
@@ -12100,7 +12135,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
12100
12135
|
if (uri === null) return [];
|
|
12101
12136
|
const explicitTitle = typeof meta?.title === "string" && meta.title.trim() !== "" ? meta.title.trim() : void 0;
|
|
12102
12137
|
const titleExplicit = explicitTitle !== void 0;
|
|
12103
|
-
const sourceSnippet =
|
|
12138
|
+
const sourceSnippet = fetchedSnippet(firstText(context.result), uri);
|
|
12104
12139
|
return [{
|
|
12105
12140
|
id: `web:${uri}`,
|
|
12106
12141
|
kind: "web",
|
|
@@ -14862,7 +14897,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14862
14897
|
]
|
|
14863
14898
|
});
|
|
14864
14899
|
}
|
|
14865
|
-
function QaHeader({ logoUrl, title, viewingSubagent, onCloseSubagent, agentPreset, roleSelector, administration, agentCount, agentsOpen, onToggleAgents, sourcesVisible, sourcesCount, sourcesComplete, sourcesOpen, onOpenSources, fileCount, filesOpen, onOpenFiles, panelLauncher, showReset, resetDisabled, onReset }) {
|
|
14900
|
+
function QaHeader({ logoUrl, title, viewingSubagent, onCloseSubagent, agentPreset, roleSelector, administration, agentCount, agentsOpen, onToggleAgents, sourcesVisible, sourcesCount, sourcesComplete, sourcesOpen, onOpenSources, fileCount, filesOpen, onOpenFiles, settings, panelLauncher, showReset, resetDisabled, onReset }) {
|
|
14866
14901
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
|
|
14867
14902
|
className: "dsh-qa-header",
|
|
14868
14903
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -14988,7 +15023,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14988
15023
|
onClick: administration.onOpen,
|
|
14989
15024
|
children: "Администрирование"
|
|
14990
15025
|
}),
|
|
14991
|
-
panelLauncher
|
|
15026
|
+
panelLauncher,
|
|
15027
|
+
settings === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
15028
|
+
type: "button",
|
|
15029
|
+
className: "dsh-qa-header__settings",
|
|
15030
|
+
title: settings.label,
|
|
15031
|
+
onClick: settings.onOpen,
|
|
15032
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
15033
|
+
viewBox: "0 0 16 16",
|
|
15034
|
+
"aria-hidden": "true",
|
|
15035
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
15036
|
+
cx: "8",
|
|
15037
|
+
cy: "8",
|
|
15038
|
+
r: "2.2"
|
|
15039
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M8 1.8v2M8 12.2v2M1.8 8h2M12.2 8h2M3.6 3.6l1.4 1.4M11 11l1.4 1.4M3.6 12.4 5 11M11 5l1.4-1.4" })]
|
|
15040
|
+
}), "Настройки"]
|
|
15041
|
+
})
|
|
14992
15042
|
]
|
|
14993
15043
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
14994
15044
|
className: "dsh-qa-header__tabs",
|
|
@@ -16572,8 +16622,35 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16572
16622
|
}
|
|
16573
16623
|
//#endregion
|
|
16574
16624
|
//#region src/client/components/QaChangelog.tsx
|
|
16575
|
-
const QA_VERSION = "0.7.
|
|
16625
|
+
const QA_VERSION = "0.7.2";
|
|
16576
16626
|
const QA_CHANGELOG = [
|
|
16627
|
+
{
|
|
16628
|
+
version: "0.7.2",
|
|
16629
|
+
date: "2026-09-16",
|
|
16630
|
+
sections: [{
|
|
16631
|
+
title: "Исправления",
|
|
16632
|
+
items: [
|
|
16633
|
+
"Чаты снова открываются: сервер отказывал в допуске, потому что набор инструментов роли называл служебный инструмент проверки активации, а такой инструмент агент регистрирует у себя сам — в ограничение его подставить нельзя. Теперь ограничение ставится только на наследуемые инструменты, служебный остаётся доступным, и выдача инструментов навыком больше не теряется молча из-за того же имени.",
|
|
16634
|
+
"Источники, появившиеся во время ответа, больше не исчезают после его завершения. Пустой ответ сервера об источниках хода больше не затирает то, что браузер прочитал из самой истории чата: список источников, видимый во время работы агента, остаётся рядом с ответом и после её окончания.",
|
|
16635
|
+
"В карточке скачанной страницы больше не повторяется её адрес: вместо служебной строки веб-инструмента «Fetched … (HTTP 200)» показывается начало текста самой страницы.",
|
|
16636
|
+
"В разделе «Быстрые сообщения» поля «Название» и «Промпт» выровнены по одной правой границе, а кнопка удаления подсказки больше не выглядит пустым полем ввода.",
|
|
16637
|
+
"Список инструментов в редакторе навыка стал компактнее и выше: длинные описания занимают две строки, а полный текст виден во всплывающей подсказке.",
|
|
16638
|
+
"Из раздела «Общие» убран пункт «Персональные интеграции и внешние системы» из списка будущих возможностей: интеграции уже доступны отдельным разделом настроек.",
|
|
16639
|
+
"Настройки пользователя больше не теряются в деплоях без списка чатов: если боковая панель с чатами скрыта (это поведение по умолчанию), кнопка «Настройки» появляется в шапке рядом с «Файлами», а при включённой панели вход остаётся прежним — по своему имени внизу списка чатов."
|
|
16640
|
+
]
|
|
16641
|
+
}]
|
|
16642
|
+
},
|
|
16643
|
+
{
|
|
16644
|
+
version: "0.7.1",
|
|
16645
|
+
date: "2026-09-16",
|
|
16646
|
+
sections: [{
|
|
16647
|
+
title: "Исправления",
|
|
16648
|
+
items: ["В консоли администратора открываются все разделы, а не только «Обзор»: «Пользователи», «Саброли», «Общие возможности», «Навыки», «Разговоры», «Очередь разбора», «Обратная связь», «Аналитика» и «Аудит». Раньше переход в любой раздел закрывал консоль и возвращал в чат, а ссылка на конкретный разговор или сообщение вместо разбора открывала обычный чат. Каждый такой переход ещё и оставлял в стенде пустой чат, попадавший в счётчики разговоров; переходы внутри консоли чатов больше не создают."]
|
|
16649
|
+
}, {
|
|
16650
|
+
title: "Прочее",
|
|
16651
|
+
items: ["Внутренняя доработка для плагинов стенда: карточка плагина в настройках DSH теперь может узнать, вошёл ли пользователь в QA, и работать с его подключениями от его имени — на этом подключения к рабочим сервисам показываются и в списке плагинов. Интерфейс QA это не меняет: вход, чаты и настройки работают как раньше, а без входа карточка подключений ничего не показывает."]
|
|
16652
|
+
}]
|
|
16653
|
+
},
|
|
16577
16654
|
{
|
|
16578
16655
|
version: "0.7.0",
|
|
16579
16656
|
date: "2026-09-16",
|
|
@@ -16779,7 +16856,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16779
16856
|
className: "dsh-qa-changelog__date",
|
|
16780
16857
|
children: entry.date
|
|
16781
16858
|
}),
|
|
16782
|
-
entry.version === "0.7.
|
|
16859
|
+
entry.version === "0.7.2" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16783
16860
|
className: "dsh-qa-changelog__current",
|
|
16784
16861
|
children: "текущая"
|
|
16785
16862
|
}) : null
|
|
@@ -18100,10 +18177,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18100
18177
|
//#region src/client/user-settings/GeneralSettingsPage.tsx
|
|
18101
18178
|
/**
|
|
18102
18179
|
* Placeholder with a purpose: the section exists so the dialog has a home for
|
|
18103
|
-
* the user-scoped preferences that follow (notifications,
|
|
18104
|
-
*
|
|
18105
|
-
*
|
|
18106
|
-
*
|
|
18180
|
+
* the user-scoped preferences that follow (notifications, privacy), and so the
|
|
18181
|
+
* thing it must not become is written down — deployment and chat policy live in
|
|
18182
|
+
* the Host settings, not here. It shows the account facts a user can act on
|
|
18183
|
+
* today and nothing invented, and it names only what is still missing: a
|
|
18184
|
+
* preference that already has its own tab does not belong on this list.
|
|
18107
18185
|
*/
|
|
18108
18186
|
function QaGeneralSettingsPage(props) {
|
|
18109
18187
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -18141,11 +18219,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18141
18219
|
title: "Скоро здесь",
|
|
18142
18220
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
|
|
18143
18221
|
className: "dsh-qa-settings__list",
|
|
18144
|
-
children: [
|
|
18145
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: "Настройки уведомлений" }),
|
|
18146
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: "Персональные интеграции и внешние системы" }),
|
|
18147
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: "Приватность и хранение данных" })
|
|
18148
|
-
]
|
|
18222
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: "Настройки уведомлений" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: "Приватность и хранение данных" })]
|
|
18149
18223
|
})
|
|
18150
18224
|
})
|
|
18151
18225
|
]
|
|
@@ -18645,6 +18719,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18645
18719
|
}),
|
|
18646
18720
|
tool.description === "" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
18647
18721
|
className: "dsh-qa-toolpicker__description",
|
|
18722
|
+
title: tool.description,
|
|
18648
18723
|
children: tool.description
|
|
18649
18724
|
})
|
|
18650
18725
|
]
|
|
@@ -19262,9 +19337,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19262
19337
|
className: "dsh-qa-starters__list",
|
|
19263
19338
|
children: rows.map((row, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
19264
19339
|
className: "dsh-qa-starters__item",
|
|
19265
|
-
children: [
|
|
19266
|
-
|
|
19267
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
19340
|
+
children: [
|
|
19341
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
19268
19342
|
className: "dsh-qa-settings__field",
|
|
19269
19343
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
19270
19344
|
className: "dsh-qa-settings__field-label",
|
|
@@ -19282,7 +19356,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19282
19356
|
}
|
|
19283
19357
|
})]
|
|
19284
19358
|
})
|
|
19285
|
-
}),
|
|
19359
|
+
}),
|
|
19360
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
19286
19361
|
type: "button",
|
|
19287
19362
|
className: "dsh-qa-starters__remove",
|
|
19288
19363
|
"aria-label": `Удалить «${row.label.trim() || "без названия"}»`,
|
|
@@ -19296,27 +19371,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19296
19371
|
"aria-hidden": "true",
|
|
19297
19372
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "m4 4 8 8m0-8-8 8" })
|
|
19298
19373
|
})
|
|
19299
|
-
})
|
|
19300
|
-
|
|
19301
|
-
|
|
19302
|
-
|
|
19303
|
-
|
|
19304
|
-
|
|
19305
|
-
|
|
19306
|
-
|
|
19307
|
-
|
|
19308
|
-
|
|
19309
|
-
|
|
19310
|
-
|
|
19311
|
-
|
|
19312
|
-
|
|
19313
|
-
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
|
|
19374
|
+
}),
|
|
19375
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
19376
|
+
className: "dsh-qa-settings__field",
|
|
19377
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
19378
|
+
className: "dsh-qa-settings__field-label",
|
|
19379
|
+
children: ["Промпт", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
19380
|
+
rows: 2,
|
|
19381
|
+
value: row.prompt,
|
|
19382
|
+
maxLength: QA_STARTERS_MAX_PROMPT,
|
|
19383
|
+
placeholder: "Что уйдёт в чат при нажатии",
|
|
19384
|
+
onChange: (event) => {
|
|
19385
|
+
const value = event.currentTarget.value;
|
|
19386
|
+
setRows((current) => current.map((candidate, at) => at === index ? {
|
|
19387
|
+
...candidate,
|
|
19388
|
+
prompt: value
|
|
19389
|
+
} : candidate));
|
|
19390
|
+
setSaved(false);
|
|
19391
|
+
}
|
|
19392
|
+
})]
|
|
19393
|
+
})
|
|
19318
19394
|
})
|
|
19319
|
-
|
|
19395
|
+
]
|
|
19320
19396
|
}, index))
|
|
19321
19397
|
}),
|
|
19322
19398
|
rows.length >= 12 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
@@ -19967,9 +20043,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19967
20043
|
}
|
|
19968
20044
|
//#endregion
|
|
19969
20045
|
//#region src/client/admin/routes.ts
|
|
20046
|
+
/** The console's own base path under the surface route. */
|
|
20047
|
+
function adminBasePath(routePath) {
|
|
20048
|
+
return `${routePath === "/" ? "" : routePath}/admin`;
|
|
20049
|
+
}
|
|
20050
|
+
/**
|
|
20051
|
+
* Whether a pathname addresses the console at all. Sections and entities each
|
|
20052
|
+
* own a path under the base ({@link adminPath}), and the surface hosting the
|
|
20053
|
+
* console must stay the console while any of them is open, so the test is by
|
|
20054
|
+
* prefix. An equality test against the base alone unmounts the console on the
|
|
20055
|
+
* first navigation inside it, and every deep link lands in the chat instead.
|
|
20056
|
+
*/
|
|
20057
|
+
function isAdminPath(pathname, routePath) {
|
|
20058
|
+
const base = adminBasePath(routePath);
|
|
20059
|
+
const trimmed = pathname.replace(/\/+$/u, "");
|
|
20060
|
+
return trimmed === base || trimmed.startsWith(`${base}/`);
|
|
20061
|
+
}
|
|
19970
20062
|
/** Path segments after `/qa/admin`, without the leading slash. */
|
|
19971
20063
|
function adminSegments(pathname, routePath) {
|
|
19972
|
-
const base =
|
|
20064
|
+
const base = adminBasePath(routePath);
|
|
19973
20065
|
return (pathname.startsWith(base) ? pathname.slice(base.length) : "").split("/").map((segment) => segment.trim()).filter((segment) => segment !== "");
|
|
19974
20066
|
}
|
|
19975
20067
|
/**
|
|
@@ -20009,7 +20101,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20009
20101
|
}
|
|
20010
20102
|
/** The pathname for one console route; the inverse of {@link parseAdminRoute}. */
|
|
20011
20103
|
function adminPath(routePath, route, search = "") {
|
|
20012
|
-
return `${
|
|
20104
|
+
return `${adminBasePath(routePath)}${(() => {
|
|
20013
20105
|
switch (route.page) {
|
|
20014
20106
|
case "overview": return "";
|
|
20015
20107
|
case "users": return "/users";
|
|
@@ -22799,7 +22891,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
22799
22891
|
const accounts = props.accounts;
|
|
22800
22892
|
const accountsSnapshot = (0, react.useSyncExternalStore)(accounts?.subscribe ?? noopSubscribe$1, accounts?.getSnapshot ?? noopAccountsSnapshot, accounts?.getSnapshot ?? noopAccountsSnapshot);
|
|
22801
22893
|
const accountsStage = accountsSnapshot.stage;
|
|
22802
|
-
const adminRoute = route.pathname
|
|
22894
|
+
const adminRoute = isAdminPath(route.pathname, config.route.path);
|
|
22803
22895
|
const [access, setAccess] = (0, react.useState)();
|
|
22804
22896
|
const [selectedSubrole, setSelectedSubrole] = (0, react.useState)(null);
|
|
22805
22897
|
const [adminPreview, setAdminPreview] = (0, react.useState)(false);
|
|
@@ -23277,6 +23369,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
23277
23369
|
filesOpen: rail.railOpen && rail.railTab === "files",
|
|
23278
23370
|
onOpenFiles: () => rail.openTab("files"),
|
|
23279
23371
|
panelLauncher: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QaPanelLauncher, { panels: props.panels }),
|
|
23372
|
+
settings: showSidebar ? void 0 : settingsEntry,
|
|
23280
23373
|
showReset: showResetButton,
|
|
23281
23374
|
resetDisabled: controller === void 0 || state.phase === "creating",
|
|
23282
23375
|
onReset: handleNewChat
|
|
@@ -23898,21 +23991,20 @@ body[data-dsh-qa-surface="active"] div:has(>[data-shell-overlay])>:not([data-she
|
|
|
23898
23991
|
.dsh-qa-settings__list{margin:0;padding-left:18px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}
|
|
23899
23992
|
.dsh-qa-settings__list li{margin:2px 0}
|
|
23900
23993
|
.dsh-qa-starters__list{display:flex;flex-direction:column;gap:10px}
|
|
23901
|
-
.dsh-qa-starters__item{display:
|
|
23902
|
-
.dsh-qa-starters__item-
|
|
23903
|
-
.dsh-qa-
|
|
23904
|
-
.dsh-qa-starters__remove{
|
|
23905
|
-
.dsh-qa-starters__remove:hover{color:var(--dsh-qa-error);border-color:var(--dsh-alias-label-error)}
|
|
23994
|
+
.dsh-qa-starters__item{display:grid;grid-template-columns:minmax(0,1fr) 28px;column-gap:8px;row-gap:8px;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-3)}
|
|
23995
|
+
.dsh-qa-starters__item>.dsh-qa-settings__field{grid-column:1}
|
|
23996
|
+
.dsh-qa-starters__remove{appearance:none;grid-column:2;grid-row:1;align-self:end;flex:none;width:28px;height:28px;margin-bottom:6px;display:flex;align-items:center;justify-content:center;padding:0;border:0;border-radius:8px;background:0 0;color:var(--dsw-alias-label-tertiary);cursor:pointer}
|
|
23997
|
+
.dsh-qa-starters__remove:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsh-qa-error)}
|
|
23906
23998
|
.dsh-qa-starters__remove:focus-visible{outline:2px solid var(--dsh-qa-accent);outline-offset:1px}
|
|
23907
23999
|
.dsh-qa-starters__remove svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}
|
|
23908
|
-
.dsh-qa-toolpicker__list{display:flex;flex-direction:column;gap:2px;max-height:
|
|
24000
|
+
.dsh-qa-toolpicker__list{display:flex;flex-direction:column;gap:2px;max-height:min(52vh,440px);margin:8px 0 0;padding:0;list-style:none;overflow-y:auto}
|
|
23909
24001
|
.dsh-qa-toolpicker__group{padding:8px 0 3px;color:var(--dsw-alias-label-tertiary);font-size:11px;font-weight:600;line-height:16px}
|
|
23910
24002
|
.dsh-qa-toolpicker__row{margin:0}
|
|
23911
24003
|
.dsh-qa-toolpicker__label{display:grid;grid-template-columns:16px minmax(0,auto) minmax(0,1fr);align-items:baseline;gap:9px;padding:6px 8px;border-radius:8px;cursor:pointer}
|
|
23912
24004
|
.dsh-qa-toolpicker__label:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
23913
24005
|
.dsh-qa-toolpicker__label input{width:15px;height:15px;margin:0;accent-color:var(--dsh-qa-brand)}
|
|
23914
24006
|
.dsh-qa-toolpicker__name{color:var(--dsw-alias-label-primary);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;line-height:18px}
|
|
23915
|
-
.dsh-qa-toolpicker__description{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;min-width:0}
|
|
24007
|
+
.dsh-qa-toolpicker__description{display:-webkit-box;overflow:hidden;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;min-width:0;-webkit-box-orient:vertical;-webkit-line-clamp:2}
|
|
23916
24008
|
.dsh-qa-toolpicker__selected{margin-right:auto;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:17px}
|
|
23917
24009
|
@media (max-width:720px){.dsh-qa-modal__panel--settings{height:min(640px,calc(100vh - 48px))}.dsh-qa-settings{grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr)}.dsh-qa-settings__nav{flex-direction:row;gap:4px;padding:8px 10px;border-right:0;border-bottom:1px solid var(--dsw-alias-border-l2);overflow-x:auto;overflow-y:hidden}.dsh-qa-settings__tab{white-space:nowrap}.dsh-qa-settings__content{padding:12px 14px 0}.dsh-qa-settings__page{padding-bottom:18px}.dsh-qa-settings__actions{margin:auto -14px -18px;padding:10px 14px}}
|
|
23918
24010
|
.dsh-qa-surface *{box-sizing:border-box}
|
|
@@ -23974,6 +24066,10 @@ body[data-dsh-qa-surface="active"] div:has(>[data-shell-overlay])>:not([data-she
|
|
|
23974
24066
|
.dsh-qa-header__files[aria-expanded="true"]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
23975
24067
|
.dsh-qa-header__files svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round}
|
|
23976
24068
|
.dsh-qa-header__files:focus-visible{outline:2px solid var(--dsh-qa-accent);outline-offset:2px}
|
|
24069
|
+
.dsh-qa-header__settings{display:inline-flex;align-items:center;gap:6px;flex:none;padding:5px 10px;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:13px;line-height:20px;cursor:pointer}
|
|
24070
|
+
.dsh-qa-header__settings:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
24071
|
+
.dsh-qa-header__settings svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round}
|
|
24072
|
+
.dsh-qa-header__settings:focus-visible{outline:2px solid var(--dsh-qa-accent);outline-offset:2px}
|
|
23977
24073
|
.dsh-qa-role-selector select,.dsh-qa-header__admin{height:30px;padding:4px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;line-height:20px;cursor:pointer}
|
|
23978
24074
|
.dsh-qa-role-selector select:hover,.dsh-qa-header__admin:hover{border-color:var(--dsw-alias-label-dimmed);color:var(--dsw-alias-label-primary)}
|
|
23979
24075
|
.dsh-qa-role-selector select:focus-visible,.dsh-qa-header__admin:focus-visible{outline:2px solid var(--dsh-qa-accent);outline-offset:1px}
|
|
@@ -26590,6 +26686,64 @@ textarea.qa-card-control{height:auto;padding:8px 12px;line-height:1.5;resize:ver
|
|
|
26590
26686
|
}
|
|
26591
26687
|
};
|
|
26592
26688
|
//#endregion
|
|
26689
|
+
//#region src/client/settings-extensions/user-session.ts
|
|
26690
|
+
const CHECKING = Object.freeze({
|
|
26691
|
+
stage: "checking",
|
|
26692
|
+
token: null
|
|
26693
|
+
});
|
|
26694
|
+
const ANONYMOUS = Object.freeze({
|
|
26695
|
+
stage: "anonymous",
|
|
26696
|
+
token: null
|
|
26697
|
+
});
|
|
26698
|
+
/**
|
|
26699
|
+
* Publishes the account state of the controller the QA overlay mounts. The
|
|
26700
|
+
* service lives for the whole host page while the controller is rebuilt
|
|
26701
|
+
* whenever the remote wiring re-injects, so {@link attach} swaps the source and
|
|
26702
|
+
* republishes; an unattached mirror stays in `checking`, which is what a card
|
|
26703
|
+
* that mounts before the accounts subsystem sees.
|
|
26704
|
+
*/
|
|
26705
|
+
var QaUserSessionMirror = class {
|
|
26706
|
+
controller;
|
|
26707
|
+
unsubscribeSource;
|
|
26708
|
+
snapshot = CHECKING;
|
|
26709
|
+
listeners = /* @__PURE__ */ new Set();
|
|
26710
|
+
/** Bind the controller whose account state this view publishes. */
|
|
26711
|
+
attach(controller) {
|
|
26712
|
+
this.unsubscribeSource?.();
|
|
26713
|
+
this.unsubscribeSource = void 0;
|
|
26714
|
+
this.controller = controller;
|
|
26715
|
+
this.unsubscribeSource = controller?.subscribe(() => {
|
|
26716
|
+
this.publish();
|
|
26717
|
+
});
|
|
26718
|
+
this.publish();
|
|
26719
|
+
}
|
|
26720
|
+
dispose() {
|
|
26721
|
+
this.attach(void 0);
|
|
26722
|
+
this.listeners.clear();
|
|
26723
|
+
}
|
|
26724
|
+
getSnapshot = () => this.snapshot;
|
|
26725
|
+
subscribe = (listener) => {
|
|
26726
|
+
this.listeners.add(listener);
|
|
26727
|
+
return () => this.listeners.delete(listener);
|
|
26728
|
+
};
|
|
26729
|
+
publish() {
|
|
26730
|
+
const next = this.derive();
|
|
26731
|
+
if (next.stage === this.snapshot.stage && next.token === this.snapshot.token) return;
|
|
26732
|
+
this.snapshot = next;
|
|
26733
|
+
for (const listener of [...this.listeners]) listener();
|
|
26734
|
+
}
|
|
26735
|
+
derive() {
|
|
26736
|
+
const state = this.controller?.getSnapshot();
|
|
26737
|
+
const token = this.controller?.token() ?? null;
|
|
26738
|
+
if (state?.stage === "authed" && token !== null) return Object.freeze({
|
|
26739
|
+
stage: "authed",
|
|
26740
|
+
token
|
|
26741
|
+
});
|
|
26742
|
+
if (state === void 0 || state.stage === "checking") return CHECKING;
|
|
26743
|
+
return ANONYMOUS;
|
|
26744
|
+
}
|
|
26745
|
+
};
|
|
26746
|
+
//#endregion
|
|
26593
26747
|
//#region src/client/index.tsx
|
|
26594
26748
|
const QA_WELCOME_SLOT_ID = "welcome-notice";
|
|
26595
26749
|
function qaWelcomeStorageKey(config) {
|
|
@@ -26607,6 +26761,7 @@ textarea.qa-card-control{height:auto;padding:8px 12px;line-height:1.5;resize:ver
|
|
|
26607
26761
|
async function apply(ctx) {
|
|
26608
26762
|
const panels = new QaSurfacePanelRegistry();
|
|
26609
26763
|
const settingsSections = new QaUserSettingsSectionRegistry();
|
|
26764
|
+
const userSession = new QaUserSessionMirror();
|
|
26610
26765
|
ctx.effect(() => {
|
|
26611
26766
|
const removeService = ctx.provide("qaSurfacePanels", panels);
|
|
26612
26767
|
return () => {
|
|
@@ -26621,6 +26776,13 @@ textarea.qa-card-control{height:auto;padding:8px 12px;line-height:1.5;resize:ver
|
|
|
26621
26776
|
removeService();
|
|
26622
26777
|
};
|
|
26623
26778
|
}, "dsh-qa-surface: user settings extension service");
|
|
26779
|
+
ctx.effect(() => {
|
|
26780
|
+
const removeService = ctx.provide("qaUserSession", userSession);
|
|
26781
|
+
return () => {
|
|
26782
|
+
userSession.dispose();
|
|
26783
|
+
removeService();
|
|
26784
|
+
};
|
|
26785
|
+
}, "dsh-qa-surface: user session service");
|
|
26624
26786
|
const disposeRemote = await ctx.remote.$mount(TYPERT_REMOTE);
|
|
26625
26787
|
await ctx.inject([
|
|
26626
26788
|
"remote.qaSurface",
|
|
@@ -26700,6 +26862,7 @@ textarea.qa-card-control{height:auto;padding:8px 12px;line-height:1.5;resize:ver
|
|
|
26700
26862
|
new QaChatIndex(window.localStorage, qaStorageNamespace(snapshot)).forgetChat(sessionId);
|
|
26701
26863
|
}
|
|
26702
26864
|
});
|
|
26865
|
+
userSession.attach(accounts);
|
|
26703
26866
|
const route = new QaRouteController();
|
|
26704
26867
|
const settingsScope = ctx.settingsScope.bind({ namespace: QA_SURFACE_SETTINGS_NAMESPACE });
|
|
26705
26868
|
const config = new QaConfigController(settingsScope, async () => {
|