@yadsh/dsh-qa-surface 0.15.3 → 0.15.5
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 +49 -8
- package/lib/approvals.js +42 -1
- package/lib/approvals.js.map +1 -1
- package/lib/client/QaSessionController.js +103 -3
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +6 -1
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaTranscriptAdapter.js +33 -3
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/components/QaChangelog.js +38 -1
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/components/QaComposer.js +3 -0
- package/lib/client/components/QaComposer.js.map +1 -1
- package/lib/client/components/QaHeader.js +29 -3
- package/lib/client/components/QaHeader.js.map +1 -1
- package/lib/client/components/QaRightRail.js +20 -1
- package/lib/client/components/QaRightRail.js.map +1 -1
- package/lib/client/components/QaSidebar.js +12 -2
- package/lib/client/components/QaSidebar.js.map +1 -1
- package/lib/client/components/QaSourcesPanel.js +1 -1
- package/lib/client/components/QaSourcesPanel.js.map +1 -1
- package/lib/client/components/QaWorkGroup.js +13 -7
- package/lib/client/components/QaWorkGroup.js.map +1 -1
- package/lib/client/components/QaWorkspaceBrowser.js +5 -1
- package/lib/client/components/QaWorkspaceBrowser.js.map +1 -1
- package/lib/client/settings/styles.js +16 -10
- package/lib/client/settings/styles.js.map +1 -1
- package/lib/client/slash/SlashPalette.js +3 -1
- package/lib/client/slash/SlashPalette.js.map +1 -1
- package/lib/client/styles.js +31 -15
- package/lib/client/styles.js.map +1 -1
- package/lib/client.js +268 -78
- package/lib/client.js.map +1 -1
- package/lib/qa-tools/file-delete-gate.js +35 -10
- package/lib/qa-tools/file-delete-gate.js.map +1 -1
- package/lib/qa-tools/file-delete.js +1 -1
- package/lib/qa-tools/file-delete.js.map +1 -1
- package/lib/types/approvals.d.ts +18 -1
- package/lib/types/client/QaSessionController.d.ts +23 -0
- package/lib/types/client/components/QaHeader.d.ts +10 -1
- package/lib/types/client/components/QaRightRail.d.ts +7 -1
- package/lib/types/client/components/QaSidebar.d.ts +5 -0
- package/lib/types/client/components/QaWorkGroup.d.ts +5 -2
- package/lib/types/client/settings/styles.d.ts +6 -0
- package/lib/types/qa-tools/file-delete-gate.d.ts +24 -7
- package/lib/types/types.d.ts +5 -2
- package/package.json +3 -3
package/lib/client.js
CHANGED
|
@@ -16342,6 +16342,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16342
16342
|
*/
|
|
16343
16343
|
const QA_REGENERATE_MARKER = "Перегенерируй свой предыдущий ответ — дай новый вариант, не повторяя предыдущий.";
|
|
16344
16344
|
/**
|
|
16345
|
+
* Terminal row of a turn a person stopped. "Готово" claims a complete answer,
|
|
16346
|
+
* and a stopped turn commits a prefix instead, so the row says both what
|
|
16347
|
+
* happened and what the reader is holding.
|
|
16348
|
+
*/
|
|
16349
|
+
const QA_TURN_STOPPED_COPY = "Ход остановлен: ответ неполный. Отправь запрос ещё раз, чтобы получить ответ целиком.";
|
|
16350
|
+
/**
|
|
16345
16351
|
* Durable image references carried by user content. The core ContentBlock
|
|
16346
16352
|
* vocabulary is not installed client-side, so the shape is matched
|
|
16347
16353
|
* structurally against the host contract ({type:"image", attachment:{...}}).
|
|
@@ -16431,6 +16437,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16431
16437
|
}
|
|
16432
16438
|
function collectAssistant(node, turns, toolHeads, showReasoning, workspaceRoot) {
|
|
16433
16439
|
const turn = getTurn(turns, node.turn);
|
|
16440
|
+
if (node.interrupted === true) turn.stoppedAt = node.seq;
|
|
16434
16441
|
const text = visibleAssistantText(node.blocks, workspaceRoot);
|
|
16435
16442
|
if (text !== "") turn.text.push({
|
|
16436
16443
|
id: `assistant:${node.messageId ?? node.seq}`,
|
|
@@ -16538,6 +16545,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16538
16545
|
function emitTurn(legacy, running, turn, output, erroredCode) {
|
|
16539
16546
|
const timing = legacy.turnTimings.get(turn.turn);
|
|
16540
16547
|
const completed = timing?.endTime !== void 0 || legacy.turnEnds.has(turn.turn);
|
|
16548
|
+
const stoppedAt = erroredCode === void 0 ? turn.stoppedAt : void 0;
|
|
16541
16549
|
const sortedText = [...turn.text].sort((left, right) => left.order - right.order);
|
|
16542
16550
|
const partial = sortedText.find((message) => message.status === "streaming");
|
|
16543
16551
|
const committed = sortedText.filter((message) => message.status === "committed");
|
|
@@ -16562,7 +16570,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16562
16570
|
id: `work:${turn.turn}`,
|
|
16563
16571
|
role: "work",
|
|
16564
16572
|
turn: turn.turn,
|
|
16565
|
-
status: erroredCode !== void 0 ? "error" : completed || !running ? "complete" : "running",
|
|
16573
|
+
status: erroredCode !== void 0 ? "error" : stoppedAt !== void 0 ? "stopped" : completed || !running ? "complete" : "running",
|
|
16566
16574
|
...timing?.startTime === void 0 ? {} : { startedAt: timing.startTime },
|
|
16567
16575
|
...timing?.endTime === void 0 ? {} : { endedAt: timing.endTime },
|
|
16568
16576
|
items
|
|
@@ -16595,6 +16603,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16595
16603
|
...turn.artifacts.length === 0 ? {} : { artifacts: turn.artifacts }
|
|
16596
16604
|
}
|
|
16597
16605
|
});
|
|
16606
|
+
if (stoppedAt !== void 0) output.push({
|
|
16607
|
+
order: stoppedAt + .5,
|
|
16608
|
+
message: {
|
|
16609
|
+
id: `turn-stopped:${turn.turn}`,
|
|
16610
|
+
role: "system",
|
|
16611
|
+
text: QA_TURN_STOPPED_COPY,
|
|
16612
|
+
status: "info"
|
|
16613
|
+
}
|
|
16614
|
+
});
|
|
16598
16615
|
}
|
|
16599
16616
|
/** Project end-user messages plus optional operator-approved work detail. */
|
|
16600
16617
|
function projectTranscript(snapshot, options = {}) {
|
|
@@ -16926,6 +16943,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16926
16943
|
*/
|
|
16927
16944
|
const SLASH_CATALOG_STALE_MS = 3e3;
|
|
16928
16945
|
/**
|
|
16946
|
+
* How long a refused retain waits for its row to come into this browser's
|
|
16947
|
+
* Session catalog. Short on purpose, and shorter than the adoption timeout: the
|
|
16948
|
+
* row arrives either as a Host push or as the answer of the one pull asked for
|
|
16949
|
+
* here, so it is a round-trip away — while a whole `timeoutMs` of patience
|
|
16950
|
+
* would stack a second window onto the waits that follow and hold a chat that
|
|
16951
|
+
* never opens on screen for two of them. A row that misses this window loses
|
|
16952
|
+
* the chat, and the plate's «Повторить» re-runs the adoption on a catalog that
|
|
16953
|
+
* has had the pull.
|
|
16954
|
+
*/
|
|
16955
|
+
const CATALOG_ROW_PATIENCE_MS = 5e3;
|
|
16956
|
+
/**
|
|
16929
16957
|
* Spacing of the parked-request poll. A request is answered by a person, so a
|
|
16930
16958
|
* second of latency is invisible; the poll only runs while a turn runs.
|
|
16931
16959
|
*/
|
|
@@ -17995,7 +18023,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17995
18023
|
*/
|
|
17996
18024
|
async bind(id, options) {
|
|
17997
18025
|
const { operation, report = true, attest = true, track = true, allowCompatibilityReadOnly = false } = options;
|
|
17998
|
-
const
|
|
18026
|
+
const retainAttemptedAt = Date.now();
|
|
18027
|
+
let reference;
|
|
18028
|
+
try {
|
|
18029
|
+
reference = this.sessions.retain(id, { source: QA_SURFACE_SESSION_SOURCE });
|
|
18030
|
+
} catch (error) {
|
|
18031
|
+
if (this.catalogLists(id)) throw error;
|
|
18032
|
+
if (!await this.awaitCatalogRow(id, retainAttemptedAt, operation, error)) return false;
|
|
18033
|
+
reference = this.sessions.retain(id, { source: QA_SURFACE_SESSION_SOURCE });
|
|
18034
|
+
}
|
|
17999
18035
|
let binding = this.sessions.binding(id);
|
|
18000
18036
|
try {
|
|
18001
18037
|
if (binding === void 0) {
|
|
@@ -18063,6 +18099,53 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18063
18099
|
return true;
|
|
18064
18100
|
}
|
|
18065
18101
|
/**
|
|
18102
|
+
* Whether this browser's Session catalog names one id. The Host answers a
|
|
18103
|
+
* retain from exactly this set, so a refusal of a listed session is a refusal
|
|
18104
|
+
* of a session it knows — never the race this adoption can wait out.
|
|
18105
|
+
*/
|
|
18106
|
+
catalogLists(id) {
|
|
18107
|
+
return Object.hasOwn(this.sessions.list.getSnapshot().byId, id);
|
|
18108
|
+
}
|
|
18109
|
+
/**
|
|
18110
|
+
* Wait for this browser's Session catalog to come to know one id, after
|
|
18111
|
+
* {@link bind} was refused a reference to it, and answer whether the chat on
|
|
18112
|
+
* screen still belongs to the adoption that asked (`false` — it moved on, and
|
|
18113
|
+
* nothing is retained). Only an id the catalog does not name reaches here: a
|
|
18114
|
+
* refusal of a session it already lists is not this race and goes back as it
|
|
18115
|
+
* came, so there is always a row to wait for. A refusal is only final once
|
|
18116
|
+
* that row has had its chance: this is the one window where the race is
|
|
18117
|
+
* repairable rather than reportable, so the failure the caller reads stays the
|
|
18118
|
+
* Host's own refusal, not a timeout nobody asked for.
|
|
18119
|
+
*
|
|
18120
|
+
* Both timestamps are logged because the race is intermittent and the stand
|
|
18121
|
+
* keeps no other trace of it: the server never sees a retain, so its journal
|
|
18122
|
+
* cannot say which chat lost the create, and the next round needs the id and
|
|
18123
|
+
* the two moments to line this up with its own observations.
|
|
18124
|
+
*/
|
|
18125
|
+
async awaitCatalogRow(id, retainAttemptedAt, operation, failure) {
|
|
18126
|
+
if (this.disposed || operation !== this.generation) return false;
|
|
18127
|
+
console.warn("dsh-qa-surface: sessions.retain raced the session catalog", {
|
|
18128
|
+
sessionId: id,
|
|
18129
|
+
retainAttemptedAt: new Date(retainAttemptedAt).toISOString()
|
|
18130
|
+
});
|
|
18131
|
+
this.sessions.refresh().catch((cause) => {
|
|
18132
|
+
console.warn("dsh-qa-surface: session catalog refresh refused", {
|
|
18133
|
+
sessionId: id,
|
|
18134
|
+
cause: cause instanceof Error ? cause.message : String(cause)
|
|
18135
|
+
});
|
|
18136
|
+
});
|
|
18137
|
+
try {
|
|
18138
|
+
await waitFor(this.sessions.list, (snapshot) => Object.hasOwn(snapshot.byId, id), Math.min(this.timeoutMs, CATALOG_ROW_PATIENCE_MS));
|
|
18139
|
+
} catch {
|
|
18140
|
+
throw failure;
|
|
18141
|
+
}
|
|
18142
|
+
console.warn("dsh-qa-surface: session catalog row landed", {
|
|
18143
|
+
sessionId: id,
|
|
18144
|
+
waitedMs: Date.now() - retainAttemptedAt
|
|
18145
|
+
});
|
|
18146
|
+
return !this.disposed && operation === this.generation;
|
|
18147
|
+
}
|
|
18148
|
+
/**
|
|
18066
18149
|
* Give up on an adoption the chat on screen has outgrown, and answer whether
|
|
18067
18150
|
* that is what happened (`true` — the caller has nothing left to publish).
|
|
18068
18151
|
*
|
|
@@ -19524,6 +19607,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19524
19607
|
}
|
|
19525
19608
|
//#endregion
|
|
19526
19609
|
//#region src/client/slash/SlashPalette.tsx
|
|
19610
|
+
/** Whether a Host-supplied description is written in the surface's language. */
|
|
19611
|
+
const isCyrillic = /[А-Яа-яЁё]/u;
|
|
19527
19612
|
const KIND_LABEL = Object.freeze({
|
|
19528
19613
|
skill: "Навык",
|
|
19529
19614
|
command: "Команда"
|
|
@@ -19599,6 +19684,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19599
19684
|
}), props.showDescriptions && entry.description !== "" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
19600
19685
|
className: "dsh-qa-slash__description",
|
|
19601
19686
|
"data-testid": "qa-slash-row-description",
|
|
19687
|
+
lang: isCyrillic.test(entry.description) ? "ru" : "en",
|
|
19602
19688
|
children: entry.description
|
|
19603
19689
|
}) : null]
|
|
19604
19690
|
}, entry.id);
|
|
@@ -19918,6 +20004,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19918
20004
|
if (await props.onSend(text, attachments, pick?.id ?? null)) {
|
|
19919
20005
|
setDraft("");
|
|
19920
20006
|
props.onAttachmentsChange([]);
|
|
20007
|
+
setAttachmentError(null);
|
|
19921
20008
|
}
|
|
19922
20009
|
} finally {
|
|
19923
20010
|
setSubmitting(false);
|
|
@@ -20491,7 +20578,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20491
20578
|
]
|
|
20492
20579
|
});
|
|
20493
20580
|
}
|
|
20494
|
-
function QaHeader({ logoUrl, title, viewingSubagent, onCloseSubagent, roleSelector, themeSwitcher, administration, agentCount, agentsOpen, onToggleAgents, sourcesVisible, sourcesCount, sourcesComplete, sourcesOpen, onOpenSources, fileCount, filesEnabled, filesOpen, onOpenFiles, settings, history, panelLauncher, showReset, resetDisabled, onReset }) {
|
|
20581
|
+
function QaHeader({ logoUrl, title, viewingSubagent, onCloseSubagent, roleSelector, themeSwitcher, administration, agentCount, agentsOpen, onToggleAgents, sourcesVisible, sourcesCount, sourcesComplete, sourcesOpen, onOpenSources, fileCount, filesEnabled, filesOpen, onOpenFiles, settings, history, panelLauncher, showReset, resetDisabled, onReset, onBackToChat }) {
|
|
20495
20582
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
|
|
20496
20583
|
className: "dsh-qa-header",
|
|
20497
20584
|
"data-testid": "qa-surface-header",
|
|
@@ -20548,9 +20635,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20548
20635
|
type: "button",
|
|
20549
20636
|
className: "dsh-qa-header__agents",
|
|
20550
20637
|
"data-testid": "qa-surface-header-agents",
|
|
20551
|
-
disabled: agentCount === 0,
|
|
20638
|
+
"aria-disabled": agentCount === 0 || void 0,
|
|
20552
20639
|
"aria-expanded": agentsOpen,
|
|
20553
|
-
|
|
20640
|
+
...agentCount === 0 ? { "aria-label": "Агенты: субагентов в этом чате пока нет" } : {},
|
|
20641
|
+
title: agentCount === 0 ? "Субагентов в этом чате пока нет" : "Показать субагентов этого чата",
|
|
20642
|
+
onClick: () => {
|
|
20643
|
+
if (agentCount === 0) return;
|
|
20644
|
+
onToggleAgents();
|
|
20645
|
+
},
|
|
20554
20646
|
children: [
|
|
20555
20647
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
20556
20648
|
viewBox: "0 0 16 16",
|
|
@@ -20571,8 +20663,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20571
20663
|
type: "button",
|
|
20572
20664
|
className: "dsh-qa-header__sources",
|
|
20573
20665
|
"data-testid": "qa-surface-header-sources",
|
|
20574
|
-
disabled: sourcesCount === 0 && sourcesComplete,
|
|
20575
20666
|
"aria-expanded": sourcesOpen,
|
|
20667
|
+
...sourcesCount === 0 && sourcesComplete ? { "aria-label": "Источники: этот ответ обошёлся без источников" } : {},
|
|
20668
|
+
title: sourcesCount === 0 && sourcesComplete ? "Этот ответ обошёлся без источников" : "Показать источники этого ответа",
|
|
20576
20669
|
onClick: onOpenSources,
|
|
20577
20670
|
children: [
|
|
20578
20671
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
@@ -20592,9 +20685,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20592
20685
|
type: "button",
|
|
20593
20686
|
className: "dsh-qa-header__files",
|
|
20594
20687
|
"data-testid": "qa-surface-header-files",
|
|
20595
|
-
disabled: !filesEnabled,
|
|
20688
|
+
"aria-disabled": !filesEnabled || void 0,
|
|
20596
20689
|
"aria-expanded": filesOpen,
|
|
20597
|
-
|
|
20690
|
+
...!filesEnabled ? { "aria-label": "Файлы: в этом чате нет ни вложений, ни читаемого рабочего каталога" } : {},
|
|
20691
|
+
title: !filesEnabled ? "В этом чате нет ни вложений, ни читаемого рабочего каталога" : "Показать файлы этого чата",
|
|
20692
|
+
onClick: () => {
|
|
20693
|
+
if (!filesEnabled) return;
|
|
20694
|
+
onOpenFiles();
|
|
20695
|
+
},
|
|
20598
20696
|
children: [
|
|
20599
20697
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
20600
20698
|
viewBox: "0 0 16 16",
|
|
@@ -20647,8 +20745,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20647
20745
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
20648
20746
|
className: "dsh-qa-header__tabs",
|
|
20649
20747
|
"data-testid": "qa-surface-header-tabs",
|
|
20650
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
20748
|
+
children: onBackToChat === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
20749
|
+
"aria-current": "page",
|
|
20750
|
+
children: "Чат"
|
|
20751
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
20752
|
+
type: "button",
|
|
20753
|
+
className: "dsh-qa-header__tab",
|
|
20754
|
+
"data-testid": "qa-surface-header-chat-tab",
|
|
20651
20755
|
"aria-current": "page",
|
|
20756
|
+
"aria-label": "Вернуться к чату",
|
|
20757
|
+
title: "Закрыть панель и вернуться к чату",
|
|
20758
|
+
onClick: onBackToChat,
|
|
20652
20759
|
children: "Чат"
|
|
20653
20760
|
})
|
|
20654
20761
|
})]
|
|
@@ -50182,6 +50289,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
50182
50289
|
}
|
|
50183
50290
|
//#endregion
|
|
50184
50291
|
//#region src/client/components/QaWorkGroup.tsx
|
|
50292
|
+
/** Whether one turn is over: a settled group opens collapsed and stays closed. */
|
|
50293
|
+
function isSettled(status) {
|
|
50294
|
+
return status === "complete" || status === "error" || status === "stopped";
|
|
50295
|
+
}
|
|
50185
50296
|
function Chevron({ open }) {
|
|
50186
50297
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
50187
50298
|
className: "dsh-qa-work__chevron",
|
|
@@ -50356,15 +50467,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
50356
50467
|
const now = useNow(status === "running" && startedAt !== void 0);
|
|
50357
50468
|
const previousStatus = (0, react.useRef)(status);
|
|
50358
50469
|
(0, react.useEffect)(() => {
|
|
50359
|
-
if (previousStatus.current === "running" && (status
|
|
50360
|
-
else if (previousStatus.current
|
|
50470
|
+
if (previousStatus.current === "running" && isSettled(status)) setOpen(false);
|
|
50471
|
+
else if (isSettled(previousStatus.current)) {
|
|
50361
50472
|
if (status === "running") setOpen(true);
|
|
50362
50473
|
}
|
|
50363
50474
|
previousStatus.current = status;
|
|
50364
50475
|
}, [status]);
|
|
50365
50476
|
const elapsed = (endedAt ?? now) - (startedAt ?? now);
|
|
50366
50477
|
const duration = startedAt === void 0 ? null : formatWorkDuration(elapsed);
|
|
50367
|
-
const label = status === "running" ? `${thinkingPhrase(elapsed, thinkingPhrases)}${duration === null ? "" : ` (${duration})`}` : status === "error" ? duration === null ? "Ход прерван" : `Прервано за ${duration}` : duration === null ? "Ход работы" : `Готово за ${duration}`;
|
|
50478
|
+
const label = status === "running" ? `${thinkingPhrase(elapsed, thinkingPhrases)}${duration === null ? "" : ` (${duration})`}` : status === "error" ? duration === null ? "Ход прерван" : `Прервано за ${duration}` : status === "stopped" ? duration === null ? "Ход остановлен" : `Остановлено на ${duration}` : duration === null ? "Ход работы" : `Готово за ${duration}`;
|
|
50368
50479
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
50369
50480
|
className: "dsh-qa-work",
|
|
50370
50481
|
"data-testid": "qa-surface-work-group",
|
|
@@ -52961,8 +53072,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
52961
53072
|
}
|
|
52962
53073
|
//#endregion
|
|
52963
53074
|
//#region src/client/components/QaChangelog.tsx
|
|
52964
|
-
const QA_VERSION = "0.15.
|
|
53075
|
+
const QA_VERSION = "0.15.5";
|
|
52965
53076
|
const QA_CHANGELOG = [
|
|
53077
|
+
{
|
|
53078
|
+
version: "0.15.5",
|
|
53079
|
+
date: "2026-10-08",
|
|
53080
|
+
sections: [{
|
|
53081
|
+
title: "Исправления",
|
|
53082
|
+
items: ["История версий больше не рисует заголовок раздела, под которым нет ни одного пункта. Текст уже выпущенных версий остаётся ровно тем, что было опубликовано: пустой раздел не вычёркивается из данных, а просто не показывается — заголовок без содержимого читался как чейнджлог, у которого потеряли пункты."]
|
|
53083
|
+
}]
|
|
53084
|
+
},
|
|
53085
|
+
{
|
|
53086
|
+
version: "0.15.4",
|
|
53087
|
+
date: "2026-10-08",
|
|
53088
|
+
sections: [{
|
|
53089
|
+
title: "Исправления",
|
|
53090
|
+
items: [
|
|
53091
|
+
"Мелкие контролы поверхности стали объяснять себя, а основной текст — читаться с 16 px. Чипы «Агенты», «Источники» и «Файлы» при пустом списке просто глушились: серая кнопка выпадала из обхода Tab, не отвечала на наведение и не говорила, что именно кончилось; теперь она остаётся доступной, а причина пустоты читается в её имени и подсказке. «Чат» в шапке выглядел выбранной вкладкой, но не нажимался — когда поверх разговора открыта панель, это кнопка, которая закрывает панель и возвращает к чату, а пока ничего не открыто, он остаётся подписью. На телефоне панель, занимающая весь экран, имела один выход — крестик 26 px: у него и зона попадания размером с палец, и имя, называющее закрываемую вкладку, а Escape закрывает панель, где бы ни стоял курсор; действия у сообщения на этой ширине такие же. Ответ ассистента больше не мельчает ни относительно собственного вопроса, ни на узком экране, и карточки входа и настроек переехали на тот же кегль — ниже 16 px остались только служебные подписи. Заголовок беседы в истории, который не влезал целиком, обрывается многоточием, полное имя даёт подсказка, а поиск ищет по всему имени; третий быстрый вопрос на узкой ширине больше не отсекается — чипы переносятся. Красная строка об отказе слишком большого файла уходит вместе с отправленным сообщением, а не висит над пустым полем; «Рабочий каталог» в панели «Файлы» напечатан один раз; карточка «Ожидает одобрения» называет причину по-русски, а описания команд в палитре по `/` объявляют свой язык, чтобы перевод не звучал как ошибка.",
|
|
53092
|
+
"Кнопка «Источники» в шапке больше не блокируется пустым списком, и пустой список объясняет себя сам. Ход, ответивший по памяти или по тому, что уже было в этом разговоре, в список ничего не добавляет: чтения памяти не узнаёт ни один экстрактор, и это замысел, а не поломка. Прежний интерфейс молчал дважды — под ответом не было чипа, а кнопка стояла заблокированной без счётчика и без причины, и вместе с ней закрывалась единственная поверхность, способная объяснить пустоту. Теперь кнопка жива всегда, когда её показывает развёртывание, а панель на пустом завершённом ходе перечисляет, какие материалы в неё попадают, и говорит, что пустой список — не сбой сбора. Пока ход ещё идёт или делегированный запуск остался должен свои источники, объяснение молчит: об этом уже говорит строка о недоступных источниках, и два противоречащих текста на одном экране не встречаются.",
|
|
53093
|
+
"Остановленный ход больше не притворяется завершённым. Кнопка «стоп» обрывала ответ, а под ходом читалось «Готово за 2 с»: «готово» обещает целый ответ, и человек, остановивший ход, чтобы переформулировать вопрос, видел успех вместо того, что сделал сам. Теперь у остановки свой итог — строка «Остановлено на N с» и плашка о том, что ответ неполный и как получить его целиком. Всё, что успело прийти, остаётся обычным сообщением: его можно скопировать и оценить, так что остановка ничего уже написанного не съедает. У сбоя провайдера по-прежнему свой итог — остановка его не подменяет.",
|
|
53094
|
+
"Палитра слэш-команд в чате, который ещё не начался, называет те же навыки, что и в чате, где уже шёл ответ. Пока за разговором не стоял живой агент, список строился по одному общему allow-list'у развёртывания и не сужался ролью: в него попадал навык, который в этом чате вызвать нельзя — имя подсвечивалось, Enter подставлял его в строку, а в ответ приходил отказ, — и наоборот, доступный навык мог не показаться. Теперь роль учитывается при обоих чтениях, а список, который палитра показывает, и список, которым проверяется введённая строка, выводятся из одного правила, поэтому предложение в палитре и возможность его вызвать больше не могут разойтись.",
|
|
53095
|
+
"Делегированный вызов больше не ставит ход на паузу, которую никто не может снять. Проверяющий, вызванный из чата, не умеет спрашивать человека — харнесс отказывает таким запросам, — но заявка на подтверждение вставала карточкой над композером родителя и держала весь ход: на стенде так ждало то двенадцать минут, то больше часа, пока в основном чате шёл только таймер «думаю». Теперь запрос на подтверждение от дочерней сессии отклоняется сразу там, где он поднят, с объяснением, что дочь спрашивать не может, — модель получает это как находку, а оператор не получает зависший ход. Отдельно закрыто то, что привело к заявке: проверяющему ответа выдаются только инструменты чтения и поиска, а имена удаления файла, записи файлов и запуска команд исключены из его набора — и списком по умолчанию, и проверкой на сборке дочерней сессии.",
|
|
53096
|
+
"Запрос на одобрение, который никто не увидел, перестаёт владеть ходом навсегда: карточка, оставшаяся без ответа, гаснет по истечении ожидания и означает отказ, как и явный отказ оператора. Ничего при этом не разрешается автоматически: ни один путь не одобряет вызов без человека.",
|
|
53097
|
+
"Первый вопрос, заданный в новый черновик, больше не открывается плашкой «Не удалось начать чат.» над разговором, который стенд на самом деле создал. Список чатов браузер держит у себя, и право на сессию хост выдаёт по этому списку: идентификатор, которого в нём ещё нет, отвергается строкой `sessions.retain: unknown session`. Разговор же рождается на сервере — через собственный Remote стенда, — и ответ «создано» успевал дойти до браузера раньше, чем строка нового разговора в его список попала. Первая попытка закрепиться за сессией приходилась ровно на это окно, поэтому экран докладывал об отказе и молчал, что чат тем временем уже стоит в боковом списке строкой, в которую никто не вошёл. Теперь поверхность сначала ждёт, пока каталог браузера назовёт этот идентификатор, и сама просит свежий список, а не ждёт, что успеет прийти раньше — собственный кадр сервера или его очередная выгрузка. Ждёт недолго, на одну выгрузку: строка приходит пушем или ответом на этот же запрос, а целый таймаут ожидания лег бы вторым слоем поверх тех, что идут следом, и чат, которому не открыться, держал бы экран вдвое дольше. Если строка так и не пришла, в журнале остаётся отказ самого хоста, а не «истекло ожидание», которого никто не заказывал; отказ хоста для чата, который список уже называет, остаётся самим собой — поверхность не ждёт строку, которая на месте, и не рисует гонку там, где её не было. Отказ самой выгрузки тоже слышен: чат, потерянный в таком виде, читается как медленный каталог, а на деле это нечитаемый каталог. Случается это не на каждом входе, поэтому обе половины гонки пишутся в журнал браузера: отказ удержания — с его моментом, и пришедшая следом строка каталога — с тем, сколько пришлось ждать. Раунд, который чат всё-таки потерял, сможет сказать, на какой стороне создания он его потерял. Тот же порядок и для чата, который поверхность возвращает при открытии: он тоже сначала ждёт, пока список его назовёт, и только потом закрепляется за сессией."
|
|
53098
|
+
]
|
|
53099
|
+
}]
|
|
53100
|
+
},
|
|
52966
53101
|
{
|
|
52967
53102
|
version: "0.15.3",
|
|
52968
53103
|
date: "2026-10-08",
|
|
@@ -53521,12 +53656,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
53521
53656
|
className: "dsh-qa-changelog__date",
|
|
53522
53657
|
children: entry.date
|
|
53523
53658
|
}),
|
|
53524
|
-
entry.version === "0.15.
|
|
53659
|
+
entry.version === "0.15.5" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
53525
53660
|
className: "dsh-qa-changelog__current",
|
|
53526
53661
|
children: "текущая"
|
|
53527
53662
|
}) : null
|
|
53528
53663
|
]
|
|
53529
|
-
}), entry.sections.map((section, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
53664
|
+
}), entry.sections.filter((section) => section.items.some((item) => item.trim() !== "")).map((section, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
53530
53665
|
className: "dsh-qa-changelog__section",
|
|
53531
53666
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
|
|
53532
53667
|
className: "dsh-qa-changelog__section-title",
|
|
@@ -53819,12 +53954,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
53819
53954
|
const summary = byId[id];
|
|
53820
53955
|
if (summary === void 0 || isDelegatedSession(summary)) continue;
|
|
53821
53956
|
const ownerName = ownerNameOf?.(id);
|
|
53957
|
+
const label = summary.blank ? "Новый чат" : summary.displayTitle;
|
|
53958
|
+
const full = summary.title;
|
|
53959
|
+
const clipped = !summary.blank && full !== void 0 && full.length > label.length;
|
|
53822
53960
|
rows.push({
|
|
53823
53961
|
id,
|
|
53824
|
-
title:
|
|
53962
|
+
title: clipped ? `${label.trimEnd()}…` : label,
|
|
53825
53963
|
running: summary.running,
|
|
53826
53964
|
active: id === activeId,
|
|
53827
53965
|
meta: relativeTime(summary.updatedAt, now),
|
|
53966
|
+
...clipped && full !== void 0 ? { fullName: full } : {},
|
|
53828
53967
|
updatedAt: summary.updatedAt,
|
|
53829
53968
|
...ownerName === void 0 ? {} : { ownerName }
|
|
53830
53969
|
});
|
|
@@ -53907,7 +54046,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
53907
54046
|
});
|
|
53908
54047
|
}
|
|
53909
54048
|
function rowMatches(row, query) {
|
|
53910
|
-
return row.title.toLowerCase().includes(query) || row.ownerName?.toLowerCase().includes(query) === true;
|
|
54049
|
+
return row.title.toLowerCase().includes(query) || (row.fullName?.toLowerCase().includes(query) ?? false) || row.ownerName?.toLowerCase().includes(query) === true;
|
|
53911
54050
|
}
|
|
53912
54051
|
/**
|
|
53913
54052
|
* How each chat is named by the controls acting on it, keyed by id. A title is
|
|
@@ -54014,6 +54153,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
54014
54153
|
className: "dsh-qa-sidebar__item-main",
|
|
54015
54154
|
"data-testid": "qa-surface-sidebar-item-open",
|
|
54016
54155
|
"aria-current": row.active ? "true" : void 0,
|
|
54156
|
+
title: row.fullName ?? row.title,
|
|
54017
54157
|
onClick: () => {
|
|
54018
54158
|
props.onSwitch(row.id);
|
|
54019
54159
|
closeDrawer();
|
|
@@ -54811,22 +54951,23 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
54811
54951
|
});
|
|
54812
54952
|
}
|
|
54813
54953
|
const crumbs = crumbsOf(directory);
|
|
54954
|
+
const trail = directory === "" ? crumbs.slice(1) : crumbs;
|
|
54814
54955
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
54815
54956
|
className: "dsh-qa-ws",
|
|
54816
54957
|
"data-testid": "qa-surface-workspace",
|
|
54817
54958
|
children: [
|
|
54818
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
|
|
54959
|
+
trail.length === 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("nav", {
|
|
54819
54960
|
className: "dsh-qa-ws__crumbs",
|
|
54820
54961
|
"data-testid": "qa-surface-workspace-crumbs",
|
|
54821
54962
|
"aria-label": "Путь в рабочем каталоге",
|
|
54822
|
-
children:
|
|
54963
|
+
children: trail.map((crumb, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [index > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
54823
54964
|
"aria-hidden": "true",
|
|
54824
54965
|
children: "/"
|
|
54825
54966
|
}) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
54826
54967
|
type: "button",
|
|
54827
54968
|
className: "dsh-qa-ws__crumb",
|
|
54828
54969
|
"data-testid": "qa-surface-workspace-crumb",
|
|
54829
|
-
"aria-current": index ===
|
|
54970
|
+
"aria-current": index === trail.length - 1 ? "true" : void 0,
|
|
54830
54971
|
onClick: () => setDirectory(crumb.path),
|
|
54831
54972
|
children: crumb.label
|
|
54832
54973
|
})] }, crumb.path))
|
|
@@ -54983,9 +55124,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
54983
55124
|
* The chat's right rail: a fixed column whose top edge is the tab strip,
|
|
54984
55125
|
* mirroring the Harness right Sidebar's chrome. Tabs are plain chips with
|
|
54985
55126
|
* counts; the strip's last control collapses the whole column.
|
|
55127
|
+
*
|
|
55128
|
+
* On the phone layout the column is the whole surface, so the strip's control
|
|
55129
|
+
* is the only way back and Escape has to answer from anywhere on the page —
|
|
55130
|
+
* the focus may well still sit in the composer behind the panel. A dialog above
|
|
55131
|
+
* the rail keeps the key: the innermost thing on the page is what the reader
|
|
55132
|
+
* means to dismiss.
|
|
54986
55133
|
*/
|
|
54987
55134
|
function QaRightRail({ tabs, activeTab, onTabSelect, onClose }) {
|
|
54988
55135
|
const active = tabs.find((tab) => tab.id === activeTab) ?? tabs[0];
|
|
55136
|
+
(0, react.useEffect)(() => {
|
|
55137
|
+
const onKey = (event) => {
|
|
55138
|
+
if (event.key !== "Escape" || event.defaultPrevented) return;
|
|
55139
|
+
if (isQaModalOpen()) return;
|
|
55140
|
+
onClose();
|
|
55141
|
+
};
|
|
55142
|
+
window.addEventListener("keydown", onKey);
|
|
55143
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
55144
|
+
}, [onClose]);
|
|
54989
55145
|
if (active === void 0) return null;
|
|
54990
55146
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
|
|
54991
55147
|
className: "dsh-qa-panel",
|
|
@@ -55011,8 +55167,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
55011
55167
|
type: "button",
|
|
55012
55168
|
className: "dsh-qa-panel__close",
|
|
55013
55169
|
"data-testid": "qa-surface-rail-close",
|
|
55014
|
-
"aria-label":
|
|
55015
|
-
title:
|
|
55170
|
+
"aria-label": `Закрыть панель «${active.title}» и вернуться к чату`,
|
|
55171
|
+
title: `Закрыть панель «${active.title}»`,
|
|
55016
55172
|
onClick: onClose,
|
|
55017
55173
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
55018
55174
|
viewBox: "0 0 16 16",
|
|
@@ -55316,39 +55472,47 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
55316
55472
|
}) : null, detail === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
55317
55473
|
className: "dsh-qa-sources__list",
|
|
55318
55474
|
"data-testid": "qa-sources-list",
|
|
55319
|
-
children: [
|
|
55320
|
-
|
|
55321
|
-
|
|
55322
|
-
|
|
55323
|
-
"Некоторые источники делегированных запусков недоступны (",
|
|
55324
|
-
incompleteOrigins?.length ?? 1,
|
|
55325
|
-
")."
|
|
55326
|
-
]
|
|
55327
|
-
}) : null, groups.map((group) => {
|
|
55328
|
-
const visible = expanded.has(group.key) ? group.sources : group.sources.slice(0, display.maxInitiallyVisiblePerGroup);
|
|
55329
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
55330
|
-
className: "dsh-qa-sources__group",
|
|
55331
|
-
"data-testid": `qa-sources-group-${group.key}`,
|
|
55475
|
+
children: [
|
|
55476
|
+
!complete ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
55477
|
+
className: "dsh-qa-sources__incomplete",
|
|
55478
|
+
"data-testid": "qa-sources-incomplete",
|
|
55332
55479
|
children: [
|
|
55333
|
-
|
|
55334
|
-
|
|
55335
|
-
|
|
55336
|
-
})] }),
|
|
55337
|
-
visible.map((source) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QaSourceCard, {
|
|
55338
|
-
source,
|
|
55339
|
-
showOriginBadges: display.showOriginBadges,
|
|
55340
|
-
onOpen: () => setDetailId(source.id)
|
|
55341
|
-
}, source.id)),
|
|
55342
|
-
visible.length < group.sources.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
55343
|
-
type: "button",
|
|
55344
|
-
className: "dsh-qa-sources__more",
|
|
55345
|
-
"data-testid": "qa-sources-more",
|
|
55346
|
-
onClick: () => setExpanded(/* @__PURE__ */ new Set([...expanded, group.key])),
|
|
55347
|
-
children: ["Показать ещё ", group.sources.length - visible.length]
|
|
55348
|
-
}) : null
|
|
55480
|
+
"Некоторые источники делегированных запусков недоступны (",
|
|
55481
|
+
incompleteOrigins?.length ?? 1,
|
|
55482
|
+
")."
|
|
55349
55483
|
]
|
|
55350
|
-
},
|
|
55351
|
-
|
|
55484
|
+
}) : null,
|
|
55485
|
+
complete && sources.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
55486
|
+
className: "dsh-qa-sources__empty",
|
|
55487
|
+
"data-testid": "qa-sources-empty",
|
|
55488
|
+
children: "Здесь появляются материалы, которые ход читал или открывал сам: файл рабочего каталога, веб-страница, выдача веб-поиска, ответ Jira, Confluence или базы знаний. Ответ, собранный по памяти или по тому, что уже было в этом разговоре, сюда ничего не добавляет — поэтому пустой список после завершённого хода означает именно это, а не сбой сбора."
|
|
55489
|
+
}) : null,
|
|
55490
|
+
groups.map((group) => {
|
|
55491
|
+
const visible = expanded.has(group.key) ? group.sources : group.sources.slice(0, display.maxInitiallyVisiblePerGroup);
|
|
55492
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
55493
|
+
className: "dsh-qa-sources__group",
|
|
55494
|
+
"data-testid": `qa-sources-group-${group.key}`,
|
|
55495
|
+
children: [
|
|
55496
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", { children: [group.label, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
55497
|
+
"data-testid": "qa-sources-group-count",
|
|
55498
|
+
children: group.sources.length
|
|
55499
|
+
})] }),
|
|
55500
|
+
visible.map((source) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QaSourceCard, {
|
|
55501
|
+
source,
|
|
55502
|
+
showOriginBadges: display.showOriginBadges,
|
|
55503
|
+
onOpen: () => setDetailId(source.id)
|
|
55504
|
+
}, source.id)),
|
|
55505
|
+
visible.length < group.sources.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
55506
|
+
type: "button",
|
|
55507
|
+
className: "dsh-qa-sources__more",
|
|
55508
|
+
"data-testid": "qa-sources-more",
|
|
55509
|
+
onClick: () => setExpanded(/* @__PURE__ */ new Set([...expanded, group.key])),
|
|
55510
|
+
children: ["Показать ещё ", group.sources.length - visible.length]
|
|
55511
|
+
}) : null
|
|
55512
|
+
]
|
|
55513
|
+
}, group.key);
|
|
55514
|
+
})
|
|
55515
|
+
]
|
|
55352
55516
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QaSourceDetail, {
|
|
55353
55517
|
source: detail,
|
|
55354
55518
|
sessionId,
|
|
@@ -64658,6 +64822,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
64658
64822
|
config.ui.showHeader ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QaHeader, {
|
|
64659
64823
|
logoUrl: config.branding.logoUrl,
|
|
64660
64824
|
title: conversationTitle,
|
|
64825
|
+
onBackToChat: rail.railOpen || agentsOpen ? () => {
|
|
64826
|
+
rail.close();
|
|
64827
|
+
setAgentsOpen(false);
|
|
64828
|
+
} : void 0,
|
|
64661
64829
|
viewingSubagent: state.viewingSubagent !== null,
|
|
64662
64830
|
onCloseSubagent: handleCloseSubagent,
|
|
64663
64831
|
roleSelector: access === void 0 || selectedSubrole === null || previewing ? void 0 : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QaRoleSelector, {
|
|
@@ -65304,17 +65472,17 @@ body[data-dsh-qa-surface="active"] div:has(>[data-shell-overlay])>:not([data-she
|
|
|
65304
65472
|
.dsh-qa-auth__logo{width:32px;height:32px;fill:none;stroke:var(--dsh-qa-brand);stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}
|
|
65305
65473
|
.dsh-qa-auth__brand h1{margin:0;color:var(--dsw-alias-label-primary);font-size:19px;font-weight:600;line-height:26px}
|
|
65306
65474
|
.dsh-qa-auth__tabs{display:flex;gap:4px;padding:3px;border-radius:9px;background:var(--dsw-alias-bg-module-platform)}
|
|
65307
|
-
.dsh-qa-auth__tab{appearance:none;flex:1;padding:6px 0;border:0;border-radius:7px;background:0 0;color:var(--dsw-alias-label-secondary);font:inherit;font-size:
|
|
65475
|
+
.dsh-qa-auth__tab{appearance:none;flex:1;padding:6px 0;border:0;border-radius:7px;background:0 0;color:var(--dsw-alias-label-secondary);font:inherit;font-size:16px;font-weight:500;line-height:22px;cursor:pointer;transition:background .12s,color .12s}
|
|
65308
65476
|
.dsh-qa-auth__tab:hover{color:var(--dsw-alias-label-primary)}
|
|
65309
65477
|
.dsh-qa-auth__tab--active{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary)}
|
|
65310
65478
|
.dsh-qa-auth__tab:focus-visible{outline:var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsh-qa-accent));outline-offset:-2px}
|
|
65311
65479
|
.dsh-qa-auth__field{display:flex;flex-direction:column;gap:5px}
|
|
65312
|
-
.dsh-qa-auth__field span{color:var(--dsw-alias-label-secondary);font-size:
|
|
65313
|
-
.dsh-qa-auth__field input{appearance:none;width:100%;padding:9px 11px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);font:inherit;font-size:
|
|
65480
|
+
.dsh-qa-auth__field span{color:var(--dsw-alias-label-secondary);font-size:16px;line-height:22px}
|
|
65481
|
+
.dsh-qa-auth__field input{appearance:none;width:100%;padding:9px 11px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);font:inherit;font-size:16px;line-height:22px}
|
|
65314
65482
|
.dsh-qa-auth__field input:focus{outline:none;border-color:var(--dsh-qa-brand)}
|
|
65315
65483
|
.dsh-qa-auth__field input:disabled{opacity:.55}
|
|
65316
|
-
.dsh-qa-auth__error{margin:0;color:var(--dsh-qa-error);font-size:
|
|
65317
|
-
.dsh-qa-auth__submit{appearance:none;margin-top:2px;padding:10px 0;border:0;border-radius:9px;background:var(--dsh-qa-brand);color:var(--dsh-qa-accent-contrast);font:inherit;font-size:
|
|
65484
|
+
.dsh-qa-auth__error{margin:0;color:var(--dsh-qa-error);font-size:16px;line-height:22px}
|
|
65485
|
+
.dsh-qa-auth__submit{appearance:none;margin-top:2px;padding:10px 0;border:0;border-radius:9px;background:var(--dsh-qa-brand);color:var(--dsh-qa-accent-contrast);font:inherit;font-size:16px;font-weight:600;line-height:22px;cursor:pointer;transition:background .12s}
|
|
65318
65486
|
.dsh-qa-auth__submit:hover{background:var(--dsh-qa-accent-hover)}
|
|
65319
65487
|
.dsh-qa-auth__submit:focus-visible{outline:var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsh-qa-accent));outline-offset:2px}
|
|
65320
65488
|
.dsh-qa-auth__submit:disabled{opacity:.6;cursor:default}
|
|
@@ -65476,8 +65644,8 @@ body[data-dsh-qa-surface="active"] div:has(>[data-shell-overlay])>:not([data-she
|
|
|
65476
65644
|
.dsh-qa-header h1{max-width:min(42vw,420px);min-width:0;overflow:hidden;margin:0;color:var(--dsw-alias-label-primary);font-size:14px;font-weight:500;line-height:20px;text-overflow:ellipsis;white-space:nowrap}
|
|
65477
65645
|
.dsh-qa-header__reset{padding:5px 10px;border:0;border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:13px;cursor:pointer}
|
|
65478
65646
|
.dsh-qa-header__agents{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}
|
|
65479
|
-
.dsh-qa-header__agents:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
65480
|
-
.dsh-qa-header__agents:disabled{opacity:.45;cursor:default}
|
|
65647
|
+
.dsh-qa-header__agents:hover:not(:disabled):not([aria-disabled="true"]){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
65648
|
+
.dsh-qa-header__agents:disabled,.dsh-qa-header__agents[aria-disabled="true"]{opacity:.45;cursor:default}
|
|
65481
65649
|
.dsh-qa-header__agents[aria-expanded="true"]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
65482
65650
|
.dsh-qa-header__agents svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round}
|
|
65483
65651
|
.dsh-qa-header__agents:focus-visible{outline:var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsh-qa-accent));outline-offset:2px}
|
|
@@ -65512,13 +65680,12 @@ body[data-dsh-qa-surface="active"] div:has(>[data-shell-overlay])>:not([data-she
|
|
|
65512
65680
|
.dsh-qa-agents__open{flex:none;color:var(--dsh-qa-accent);font-size:12px;font-weight:500;line-height:18px}
|
|
65513
65681
|
.dsh-qa-header__sources{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}
|
|
65514
65682
|
.dsh-qa-header__sources:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
65515
|
-
.dsh-qa-header__sources:disabled{opacity:.45;cursor:default}
|
|
65516
65683
|
.dsh-qa-header__sources[aria-expanded="true"]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
65517
65684
|
.dsh-qa-header__sources svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round}
|
|
65518
65685
|
.dsh-qa-header__sources:focus-visible{outline:var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsh-qa-accent));outline-offset:2px}
|
|
65519
65686
|
.dsh-qa-header__files{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}
|
|
65520
|
-
.dsh-qa-header__files:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
65521
|
-
.dsh-qa-header__files:disabled{opacity:.45;cursor:default}
|
|
65687
|
+
.dsh-qa-header__files:hover:not(:disabled):not([aria-disabled="true"]){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
65688
|
+
.dsh-qa-header__files:disabled,.dsh-qa-header__files[aria-disabled="true"]{opacity:.45;cursor:default}
|
|
65522
65689
|
.dsh-qa-header__files[aria-expanded="true"]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
|
|
65523
65690
|
.dsh-qa-header__files svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round}
|
|
65524
65691
|
.dsh-qa-header__files:focus-visible{outline:var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsh-qa-accent));outline-offset:2px}
|
|
@@ -65589,8 +65756,11 @@ body[data-dsh-qa-surface="active"] div:has(>[data-shell-overlay])>:not([data-she
|
|
|
65589
65756
|
.dsh-qa-header__reset:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
|
|
65590
65757
|
.dsh-qa-header__reset:disabled{opacity:.45;cursor:default}
|
|
65591
65758
|
.dsh-qa-header__tabs{position:relative;z-index:1;display:flex;gap:32px;margin-top:4px}
|
|
65592
|
-
.dsh-qa-header__tabs span{position:relative;padding:0 0 11px;color:var(--dsh-qa-accent);font-size:13px;font-weight:500;line-height:16px}
|
|
65593
|
-
.dsh-qa-
|
|
65759
|
+
.dsh-qa-header__tabs span,.dsh-qa-header__tab{position:relative;padding:0 0 11px;color:var(--dsh-qa-accent);font-size:13px;font-weight:500;line-height:16px}
|
|
65760
|
+
.dsh-qa-header__tab{appearance:none;background:0 0;border:0;cursor:pointer;font-family:inherit}
|
|
65761
|
+
.dsh-qa-header__tab:hover{text-decoration:underline}
|
|
65762
|
+
.dsh-qa-header__tab:focus-visible{outline:var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsh-qa-accent));outline-offset:2px}
|
|
65763
|
+
.dsh-qa-header__tabs span::after,.dsh-qa-header__tab::after{content:"";position:absolute;right:0;bottom:1px;left:0;height:2px;border-radius:2px;background:var(--dsh-qa-accent)}
|
|
65594
65764
|
.dsh-qa-extension-panel__resizer{position:relative;z-index:2;flex:0 0 5px;width:5px;touch-action:none;cursor:col-resize;background:var(--dsw-alias-border-l2)}
|
|
65595
65765
|
.dsh-qa-extension-panel__resizer:hover,.dsh-qa-extension-panel__resizer:focus-visible{background:var(--dsh-qa-accent);outline:0}
|
|
65596
65766
|
.dsh-qa-extension-panel{display:flex;flex-direction:column;min-width:0;min-height:0;background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary)}
|
|
@@ -65695,6 +65865,7 @@ body[data-dsh-qa-surface="active"] div:has(>[data-shell-overlay])>:not([data-she
|
|
|
65695
65865
|
span.dsh-qa-files__thumb{display:inline-block}
|
|
65696
65866
|
img.dsh-qa-files__thumb{object-fit:cover;background:var(--dsw-alias-bg-layer-3)}
|
|
65697
65867
|
.dsh-qa-sources__list{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:0 10px 12px}
|
|
65868
|
+
.dsh-qa-sources__empty{margin:4px 2px 12px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:17px}
|
|
65698
65869
|
.dsh-qa-sources__group{margin:0 0 14px}
|
|
65699
65870
|
.dsh-qa-sources__group h3{display:flex;align-items:center;gap:7px;margin:4px 4px 8px;color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:600;line-height:18px}
|
|
65700
65871
|
.dsh-qa-sources__group h3 span{display:inline-grid;place-items:center;min-width:19px;height:18px;padding:0 5px;border-radius:999px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-tertiary);font-size:10px}
|
|
@@ -65753,7 +65924,20 @@ a.dsh-qa-sources__title:hover{text-decoration:underline}
|
|
|
65753
65924
|
.dsh-qa-message--assistant{align-items:flex-start;margin-right:auto}
|
|
65754
65925
|
.dsh-qa-message--work{align-items:flex-start;margin:-4px 0 14px}
|
|
65755
65926
|
.dsh-qa-message--system{align-items:center;margin:4px auto 20px}
|
|
65756
|
-
|
|
65927
|
+
/*
|
|
65928
|
+
The type scale of this surface: what the reader is asked to read is 16px, and
|
|
65929
|
+
nothing that carries a decision sits below it — the assistant's answer, the
|
|
65930
|
+
operator's own draft and the composer's status line all match the 16px the
|
|
65931
|
+
user bubble is drawn at, so a reply never reads smaller than the question.
|
|
65932
|
+
|
|
65933
|
+
Deliberate exceptions, all of them chrome rather than content: the header row
|
|
65934
|
+
and the tab marker (13px), the panel tab chips and their counts (13px/10px),
|
|
65935
|
+
message meta and timestamps (11-12px), the quick-question chips (13px),
|
|
65936
|
+
system notices and turn lines (13px), code and workspace file names
|
|
65937
|
+
(monospace, 11-13px), the admin console's tables and badges (10-12px), the
|
|
65938
|
+
composer's key hint (11px) and the welcome lede (14px).
|
|
65939
|
+
*/
|
|
65940
|
+
.dsh-qa-message__content{max-width:100%;white-space:pre-wrap;overflow-wrap:anywhere;color:var(--dsw-alias-label-primary);font-size:16px;line-height:1.62}
|
|
65757
65941
|
.dsh-qa-message--user .dsh-qa-message__content{max-width:min(525px,82%);padding:10px 16px;border-radius:22px;background:var(--dsw-specific-bubble);font-size:16px;line-height:24px}
|
|
65758
65942
|
.dsh-qa-message[data-status="pending"] .dsh-qa-message__content{opacity:.78}
|
|
65759
65943
|
.dsh-qa-message__pending{display:flex;align-items:center;gap:6px;margin-top:6px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}
|
|
@@ -65826,7 +66010,7 @@ a.dsh-qa-srcref:hover,button.dsh-qa-srcref:hover{border-color:var(--dsw-alias-la
|
|
|
65826
66010
|
properties, so a font-size preference or a light/dark switch moves both
|
|
65827
66011
|
surfaces together. A container that needs a denser scale (the source
|
|
65828
66012
|
preview, the work-item text) overrides the ladder for its own subtree. */
|
|
65829
|
-
.dsh-qa-md{min-width:0;white-space:normal;overflow-wrap:anywhere;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-markdown-base-font-family,inherit);font-size:var(--dsw-font-markdown-base-font-size,
|
|
66013
|
+
.dsh-qa-md{min-width:0;white-space:normal;overflow-wrap:anywhere;color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-markdown-base-font-family,inherit);font-size:var(--dsw-font-markdown-base-font-size,16px);font-weight:400;line-height:var(--dsw-font-markdown-base-line-height,24px)}
|
|
65830
66014
|
.dsh-qa-md>:first-child{margin-top:0}
|
|
65831
66015
|
.dsh-qa-md>:last-child{margin-bottom:0}
|
|
65832
66016
|
.dsh-qa-md p{margin:16px 0}
|
|
@@ -66115,7 +66299,7 @@ a.dsh-qa-srcref:hover,button.dsh-qa-srcref:hover{border-color:var(--dsw-alias-la
|
|
|
66115
66299
|
row — title, role, palette, action cluster — is wider than the viewport with
|
|
66116
66300
|
every child refusing to shrink, so it wraps instead of pushing «Настройки»
|
|
66117
66301
|
past the clipped edge. */
|
|
66118
|
-
@media (max-width:600px){.dsh-qa-sidebar{display:none}.dsh-qa-sidebar[data-qa-drawer="open"]{display:flex;position:fixed;inset:0 auto 0 0;z-index:24;width:min(320px,86vw);max-width:100%;border-right:1px solid var(--dsw-alias-border-l2);box-shadow:0 18px 44px rgba(0,0,0,.28);padding-bottom:env(safe-area-inset-bottom)}.dsh-qa-sidebar__scrim{display:block;position:fixed;inset:0;z-index:22;background:var(--dsh-qa-overlay)}.dsh-qa-sidebar__resize{display:none}.dsh-qa-sidebar__collapse,.dsh-qa-sidebar__expand{width:44px;height:44px}.dsh-qa-sidebar__new,.dsh-qa-sidebar__item-main{min-height:44px}.dsh-qa-header__history{display:inline-flex}.dsh-qa-panel,.dsh-qa-agents{position:absolute;inset:0;z-index:6;width:100%;border-left:0}.dsh-qa-header__inner{padding-left:16px;padding-right:16px}.dsh-qa-header h1{max-width:48vw}.dsh-qa-header__title-row{flex-wrap:wrap;row-gap:6px}.dsh-qa-width-handle{display:none}.dsh-qa-transcript__inner{--dsh-qa-bleed:0px;max-width:100%;padding:16px 16px 28px}.dsh-qa-footer__inner{max-width:100%}.dsh-qa-message{margin-bottom:16px}.dsh-qa-
|
|
66302
|
+
@media (max-width:600px){.dsh-qa-sidebar{display:none}.dsh-qa-sidebar[data-qa-drawer="open"]{display:flex;position:fixed;inset:0 auto 0 0;z-index:24;width:min(320px,86vw);max-width:100%;border-right:1px solid var(--dsw-alias-border-l2);box-shadow:0 18px 44px rgba(0,0,0,.28);padding-bottom:env(safe-area-inset-bottom)}.dsh-qa-sidebar__scrim{display:block;position:fixed;inset:0;z-index:22;background:var(--dsh-qa-overlay)}.dsh-qa-sidebar__resize{display:none}.dsh-qa-sidebar__collapse,.dsh-qa-sidebar__expand{width:44px;height:44px}.dsh-qa-sidebar__new,.dsh-qa-sidebar__item-main{min-height:44px}.dsh-qa-header__history{display:inline-flex}.dsh-qa-panel,.dsh-qa-agents{position:absolute;inset:0;z-index:6;width:100%;border-left:0}.dsh-qa-panel__close{width:44px;height:44px}.dsh-qa-panel__tab{min-height:44px}.dsh-qa-header__inner{padding-left:16px;padding-right:16px}.dsh-qa-header h1{max-width:48vw}.dsh-qa-header__title-row{flex-wrap:wrap;row-gap:6px}.dsh-qa-width-handle{display:none}.dsh-qa-transcript__inner{--dsh-qa-bleed:0px;max-width:100%;padding:16px 16px 28px}.dsh-qa-footer__inner{max-width:100%}.dsh-qa-message{margin-bottom:16px}.dsh-qa-message__actions{height:44px}.dsh-qa-message__actions button{width:44px;height:44px}.dsh-qa-message--user .dsh-qa-message__content{max-width:88%}.dsh-qa-footer{padding-left:10px;padding-right:10px;padding-bottom:max(8px,env(safe-area-inset-bottom))}.dsh-qa-composer{min-height:84px;padding-top:12px}.dsh-qa-quick-questions{flex-wrap:wrap;overflow-x:visible}.dsh-qa-composer__hint{font-size:0}.dsh-qa-composer__hint::after{content:"Enter: отправить";font-size:11px}}
|
|
66119
66303
|
@media (max-height:480px) and (orientation:landscape){.dsh-qa-header__inner{padding-top:6px}.dsh-qa-header__tabs{display:none}.dsh-qa-transcript__inner{padding-top:12px}.dsh-qa-footer{padding-top:12px}.dsh-qa-composer{min-height:72px;gap:4px;padding-top:8px}}
|
|
66120
66304
|
@media (prefers-reduced-motion:reduce){.dsh-qa-message__cursor,.dsh-qa-message__pending-spinner,.dsh-qa-work__spinner,.dsh-qa-work-item__spinner,.dsh-qa-command__spinner{animation:none}.dsh-qa-work__chevron{transition:none}.dsh-qa-rail__frame,.dsh-qa-rail__pos,.dsh-qa-rail__mark::before,.dsh-qa-rail__mark--busy::before,.dsh-qa-rail__preview{transition:none;animation:none}}
|
|
66121
66305
|
${QA_ADMIN_CONSOLE_STYLES}
|
|
@@ -68892,13 +69076,19 @@ ${QA_ROOT_STYLES}`;
|
|
|
68892
69076
|
* pair rather than a hard-coded outline: the Host's `focus.css` suppresses an
|
|
68893
69077
|
* outline under pointer modality at a specificity our rule cannot win, so a
|
|
68894
69078
|
* hard-coded ring is one that goes missing rather than one that degrades.
|
|
69079
|
+
*
|
|
69080
|
+
* The type scale is the surface's: text the operator reads in order to decide —
|
|
69081
|
+
* section titles, field labels, the values in the controls, the toggle copy —
|
|
69082
|
+
* is 16px, a control's own label and an outcome line are 14px, and only chrome
|
|
69083
|
+
* stays small on purpose: the «Изменено» badge (9px), the status chips (11px),
|
|
69084
|
+
* the monospace data rows (11px) and the footer note (10px).
|
|
68895
69085
|
*/
|
|
68896
69086
|
const QA_SETTINGS_STYLES = `.qa-card-body,.qa-card-body *{box-sizing:border-box}
|
|
68897
69087
|
.qa-card-body{display:grid;gap:18px;color:var(--dsw-alias-label-primary)}
|
|
68898
69088
|
.qa-card-section{display:grid;gap:12px}
|
|
68899
69089
|
.qa-card-section__title{display:flex;justify-content:space-between;align-items:center;gap:12px}
|
|
68900
|
-
.qa-card-section__title h3{font-size:
|
|
68901
|
-
.qa-card-muted{color:var(--dsw-alias-label-tertiary);font-size:
|
|
69090
|
+
.qa-card-section__title h3{font-size:16px;margin:0;display:flex;align-items:center;gap:7px}
|
|
69091
|
+
.qa-card-muted{color:var(--dsw-alias-label-tertiary);font-size:16px;margin:0;line-height:1.5}
|
|
68902
69092
|
.qa-card-modified{font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-module-platform);border-radius:999px;padding:1px 7px}
|
|
68903
69093
|
.qa-card-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:0}
|
|
68904
69094
|
/* One field per row, like the first-party plugin cards: two columns drifted
|
|
@@ -68907,22 +69097,22 @@ ${QA_ROOT_STYLES}`;
|
|
|
68907
69097
|
.qa-card-grid>*,.qa-card-section>.qa-card-field{padding:12px 0}
|
|
68908
69098
|
.qa-card-grid>*+*,.qa-card-section>.qa-card-field:not(:first-child){border-top:.5px solid var(--dsw-alias-border-l2)}
|
|
68909
69099
|
.qa-card-field{display:grid;gap:6px}
|
|
68910
|
-
.qa-card-field>span{font-size:
|
|
68911
|
-
.qa-card-control{width:100%;height:34px;border:.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);padding:0 12px;font:inherit;font-size:
|
|
69100
|
+
.qa-card-field>span{font-size:16px;color:var(--dsw-alias-label-primary);font-weight:500}
|
|
69101
|
+
.qa-card-control{width:100%;height:34px;border:.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);padding:0 12px;font:inherit;font-size:16px;line-height:1.5;outline:none}
|
|
68912
69102
|
textarea.qa-card-control{height:auto;padding:8px 12px;line-height:1.5;resize:vertical}
|
|
68913
69103
|
.qa-card-control:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));outline-offset:-1px}
|
|
68914
69104
|
.qa-card-control:disabled{cursor:default;opacity:.45}
|
|
68915
69105
|
.qa-card-toggle-row{display:flex;align-items:center;justify-content:space-between;gap:12px}
|
|
68916
69106
|
.qa-card-toggle-copy{display:grid;gap:2px;min-width:0}
|
|
68917
|
-
.qa-card-toggle-copy strong{font-size:
|
|
68918
|
-
.qa-card-toggle-copy span{font-size:
|
|
69107
|
+
.qa-card-toggle-copy strong{font-size:16px;font-weight:500;color:var(--dsw-alias-label-primary)}
|
|
69108
|
+
.qa-card-toggle-copy span{font-size:16px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}
|
|
68919
69109
|
.qa-card-toggle{appearance:none;width:34px;height:19px;border-radius:999px;background:var(--dsw-alias-label-dimmed);position:relative;cursor:pointer;transition:.18s;flex:none}
|
|
68920
69110
|
.qa-card-toggle:after{content:'';position:absolute;top:3px;left:3px;width:13px;height:13px;border-radius:50%;background:var(--dsw-alias-bg-layer-3);transition:.18s}
|
|
68921
69111
|
.qa-card-toggle:checked{background:var(--dsw-alias-brand-primary)}
|
|
68922
69112
|
.qa-card-toggle:checked:after{transform:translateX(15px)}
|
|
68923
69113
|
.qa-card-toggle:disabled{cursor:default;opacity:.45}
|
|
68924
69114
|
.qa-card-toggle:focus-visible{outline:var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));outline-offset:2px}
|
|
68925
|
-
.qa-card-btn{height:34px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);padding:0 12px;font:inherit;font-size:
|
|
69115
|
+
.qa-card-btn{height:34px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary);padding:0 12px;font:inherit;font-size:14px;font-weight:600;cursor:pointer;white-space:nowrap}
|
|
68926
69116
|
.qa-card-btn:hover:not(:disabled){border-color:var(--dsw-alias-label-dimmed);background:var(--dsw-alias-interactive-bg-hover)}
|
|
68927
69117
|
.qa-card-btn:focus-visible{outline:var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));outline-offset:-1px}
|
|
68928
69118
|
.qa-card-btn:disabled{cursor:default;opacity:.45}
|
|
@@ -68931,11 +69121,11 @@ textarea.qa-card-control{height:auto;padding:8px 12px;line-height:1.5;resize:ver
|
|
|
68931
69121
|
.qa-card-chip{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--dsw-alias-border-l2);border-radius:999px;padding:3px 10px;font-size:11px;color:var(--dsw-alias-label-secondary)}
|
|
68932
69122
|
.qa-card-chip b{font-weight:600;color:var(--dsw-alias-label-primary)}
|
|
68933
69123
|
.qa-card-chip.off{color:var(--dsw-alias-label-tertiary)}
|
|
68934
|
-
.qa-card-notice{padding:9px 11px;border-radius:8px;background:var(--dsw-alias-bg-module-platform);border:1px solid var(--dsw-alias-border-l2);font-size:
|
|
69124
|
+
.qa-card-notice{padding:9px 11px;border-radius:8px;background:var(--dsw-alias-bg-module-platform);border:1px solid var(--dsw-alias-border-l2);font-size:14px;line-height:1.5;color:var(--dsw-alias-label-secondary)}
|
|
68935
69125
|
.qa-card-notice.warn{border-color:var(--dsw-alias-label-dimmed);color:var(--dsw-alias-label-primary)}
|
|
68936
|
-
.qa-card-error{padding:9px 11px;border-radius:8px;background:color-mix(in srgb, var(--dsw-alias-state-error-primary, #b3261e) 8%, transparent);color:var(--dsw-alias-state-error-primary, #b3261e);font-size:
|
|
69126
|
+
.qa-card-error{padding:9px 11px;border-radius:8px;background:color-mix(in srgb, var(--dsw-alias-state-error-primary, #b3261e) 8%, transparent);color:var(--dsw-alias-state-error-primary, #b3261e);font-size:14px;line-height:1.5}
|
|
68937
69127
|
.qa-card-advanced{border:1px solid var(--dsw-alias-border-l2);border-radius:10px;padding:0 12px}
|
|
68938
|
-
.qa-card-advanced summary{cursor:pointer;padding:11px 0;font-size:
|
|
69128
|
+
.qa-card-advanced summary{cursor:pointer;padding:11px 0;font-size:16px;font-weight:600}
|
|
68939
69129
|
.qa-card-advanced summary:focus-visible{outline:var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));outline-offset:-1px}
|
|
68940
69130
|
.qa-card-advanced-content{padding:2px 0 13px;display:grid;gap:10px}
|
|
68941
69131
|
.qa-card-rows{display:grid;gap:6px}
|