@yadsh/dsh-qa-surface 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -22
- package/compatibility.json +7 -3
- package/lib/access/capability-catalog.js +22 -6
- package/lib/access/capability-catalog.js.map +1 -1
- package/lib/access/model.js +36 -2
- package/lib/access/model.js.map +1 -1
- package/lib/access/service.js +19 -4
- package/lib/access/service.js.map +1 -1
- package/lib/account-remotes.js +4 -0
- package/lib/account-remotes.js.map +1 -1
- package/lib/accounts/database.js +49 -9
- package/lib/accounts/database.js.map +1 -1
- package/lib/accounts/errors.js.map +1 -1
- package/lib/accounts/file.js.map +1 -1
- package/lib/accounts/store.js +53 -8
- package/lib/accounts/store.js.map +1 -1
- package/lib/admin/permissions.js +6 -0
- package/lib/admin/permissions.js.map +1 -1
- package/lib/admin/quality-store.js +95 -19
- package/lib/admin/quality-store.js.map +1 -1
- package/lib/admin/service.js +432 -52
- package/lib/admin/service.js.map +1 -1
- package/lib/cli.js +24 -4
- package/lib/cli.js.map +1 -1
- package/lib/client/QaAccountsController.js +70 -5
- package/lib/client/QaAccountsController.js.map +1 -1
- package/lib/client/QaConfigController.js.map +1 -1
- package/lib/client/QaSessionController.js +626 -63
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +279 -43
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaSurfaceGuard.js +2 -2
- package/lib/client/QaSurfaceGuard.js.map +1 -1
- package/lib/client/QaTranscriptAdapter.js +4 -2
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/admin/QaAdmin.js +59 -34
- package/lib/client/admin/QaAdmin.js.map +1 -1
- package/lib/client/admin/pages/Conversations.js +21 -14
- package/lib/client/admin/pages/Conversations.js.map +1 -1
- package/lib/client/admin/pages/ExpertMemory.js +210 -0
- package/lib/client/admin/pages/ExpertMemory.js.map +1 -0
- package/lib/client/admin/pages/Overview.js +5 -5
- package/lib/client/admin/pages/Overview.js.map +1 -1
- package/lib/client/admin/pages/Quality.js +6 -6
- package/lib/client/admin/pages/Quality.js.map +1 -1
- package/lib/client/admin/pages/Review.js +13 -9
- package/lib/client/admin/pages/Review.js.map +1 -1
- package/lib/client/admin/pages/SkillFiles.js +3 -3
- package/lib/client/admin/pages/SkillFiles.js.map +1 -1
- package/lib/client/admin/pages/Users.js +12 -12
- package/lib/client/admin/pages/Users.js.map +1 -1
- package/lib/client/admin/routes.js +4 -0
- package/lib/client/admin/routes.js.map +1 -1
- package/lib/client/admin/shared.js +57 -10
- package/lib/client/admin/shared.js.map +1 -1
- package/lib/client/admin/styles.js +3 -0
- package/lib/client/admin/styles.js.map +1 -1
- package/lib/client/attestation.js +11 -2
- package/lib/client/attestation.js.map +1 -1
- package/lib/client/audit/QaAuditDialog.js +2 -2
- package/lib/client/audit/QaAuditDialog.js.map +1 -1
- package/lib/client/audit/QaAuditRowBadge.js +1 -1
- package/lib/client/audit/QaAuditRowBadge.js.map +1 -1
- package/lib/client/components/Markdown.js +7 -2
- package/lib/client/components/Markdown.js.map +1 -1
- package/lib/client/components/QaAgentsDrawer.js +7 -5
- package/lib/client/components/QaAgentsDrawer.js.map +1 -1
- package/lib/client/components/QaApproval.js +2 -2
- package/lib/client/components/QaApproval.js.map +1 -1
- package/lib/client/components/QaAuthGate.js +6 -6
- package/lib/client/components/QaAuthGate.js.map +1 -1
- package/lib/client/components/QaChangelog.js +87 -0
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/components/QaComposer.js +9 -6
- package/lib/client/components/QaComposer.js.map +1 -1
- package/lib/client/components/QaFileAttachment.js +1 -1
- package/lib/client/components/QaFileAttachment.js.map +1 -1
- package/lib/client/components/QaFilesPanel.js +7 -7
- package/lib/client/components/QaFilesPanel.js.map +1 -1
- package/lib/client/components/QaHeader.js +4 -4
- package/lib/client/components/QaHeader.js.map +1 -1
- package/lib/client/components/QaMessage.js +12 -12
- package/lib/client/components/QaMessage.js.map +1 -1
- package/lib/client/components/QaModal.js +11 -2
- package/lib/client/components/QaModal.js.map +1 -1
- package/lib/client/components/QaQuestions.js +4 -4
- package/lib/client/components/QaQuestions.js.map +1 -1
- package/lib/client/components/QaQueueDock.js +137 -0
- package/lib/client/components/QaQueueDock.js.map +1 -0
- package/lib/client/components/QaRequestQueue.js +22 -0
- package/lib/client/components/QaRequestQueue.js.map +1 -0
- package/lib/client/components/QaRightRail.js +2 -2
- package/lib/client/components/QaRightRail.js.map +1 -1
- package/lib/client/components/QaSidebar.js +66 -6
- package/lib/client/components/QaSidebar.js.map +1 -1
- package/lib/client/components/QaSourcesPanel.js +10 -8
- package/lib/client/components/QaSourcesPanel.js.map +1 -1
- package/lib/client/components/QaThemeSwitcher.js +19 -0
- package/lib/client/components/QaThemeSwitcher.js.map +1 -0
- package/lib/client/components/QaTurnNotice.js +40 -0
- package/lib/client/components/QaTurnNotice.js.map +1 -0
- package/lib/client/components/QaTurnRail.js +3 -3
- package/lib/client/components/QaTurnRail.js.map +1 -1
- package/lib/client/components/QaWelcomeNotice.js +2 -6
- package/lib/client/components/QaWelcomeNotice.js.map +1 -1
- package/lib/client/components/QaWidthHandle.js +2 -2
- package/lib/client/components/QaWidthHandle.js.map +1 -1
- package/lib/client/components/QaWorkGroup.js +5 -5
- package/lib/client/components/QaWorkGroup.js.map +1 -1
- package/lib/client/components/QaWorkspaceBrowser.js +10 -10
- package/lib/client/components/QaWorkspaceBrowser.js.map +1 -1
- package/lib/client/components/VariantSwitcher.js +1 -1
- package/lib/client/components/VariantSwitcher.js.map +1 -1
- package/lib/client/failure-copy.js +26 -8
- package/lib/client/failure-copy.js.map +1 -1
- package/lib/client/focus-ring.js +193 -0
- package/lib/client/focus-ring.js.map +1 -0
- package/lib/client/index.js +58 -24
- package/lib/client/index.js.map +1 -1
- package/lib/client/lineage.js +3 -16
- package/lib/client/lineage.js.map +1 -1
- package/lib/client/markdown/CodeBlock.js +2 -2
- package/lib/client/markdown/CodeBlock.js.map +1 -1
- package/lib/client/markdown/blocks.js +118 -31
- package/lib/client/markdown/blocks.js.map +1 -1
- package/lib/client/markdown/math.js +1 -1
- package/lib/client/markdown/math.js.map +1 -1
- package/lib/client/markdown/render.js +32 -12
- package/lib/client/markdown/render.js.map +1 -1
- package/lib/client/markdown/source-chip.js +3 -3
- package/lib/client/markdown/source-chip.js.map +1 -1
- package/lib/client/notifications/notification-dispatcher.js +90 -0
- package/lib/client/notifications/notification-dispatcher.js.map +1 -0
- package/lib/client/notifications/preferences.js +61 -0
- package/lib/client/notifications/preferences.js.map +1 -0
- package/lib/client/notifications/turn-completion-source.js +82 -0
- package/lib/client/notifications/turn-completion-source.js.map +1 -0
- package/lib/client/notifications/use-turn-notifications.js +108 -0
- package/lib/client/notifications/use-turn-notifications.js.map +1 -0
- package/lib/client/panels/PanelHost.js +5 -5
- package/lib/client/panels/PanelHost.js.map +1 -1
- package/lib/client/panels/PanelLauncher.js +2 -2
- package/lib/client/panels/PanelLauncher.js.map +1 -1
- package/lib/client/project-session-state.js +156 -4
- package/lib/client/project-session-state.js.map +1 -1
- package/lib/client/rating-harvest.js +138 -0
- package/lib/client/rating-harvest.js.map +1 -0
- package/lib/client/role/RoleSelector.js +9 -4
- package/lib/client/role/RoleSelector.js.map +1 -1
- package/lib/client/settings/card.js +58 -17
- package/lib/client/settings/card.js.map +1 -1
- package/lib/client/settings/fields.js +11 -10
- package/lib/client/settings/fields.js.map +1 -1
- package/lib/client/settings/format.js +0 -9
- package/lib/client/settings/format.js.map +1 -1
- package/lib/client/settings/sections/access.js +5 -5
- package/lib/client/settings/sections/access.js.map +1 -1
- package/lib/client/settings/sections/accounts.js +10 -10
- package/lib/client/settings/sections/accounts.js.map +1 -1
- package/lib/client/settings/sections/attachments.js +6 -6
- package/lib/client/settings/sections/attachments.js.map +1 -1
- package/lib/client/settings/sections/branding.js +7 -7
- package/lib/client/settings/sections/branding.js.map +1 -1
- package/lib/client/settings/sections/common.js +4 -2
- package/lib/client/settings/sections/common.js.map +1 -1
- package/lib/client/settings/sections/docs.js +4 -3
- package/lib/client/settings/sections/docs.js.map +1 -1
- package/lib/client/settings/sections/embedding.js +2 -2
- package/lib/client/settings/sections/embedding.js.map +1 -1
- package/lib/client/settings/sections/interface.js +12 -12
- package/lib/client/settings/sections/interface.js.map +1 -1
- package/lib/client/settings/sections/lockdown.js +9 -9
- package/lib/client/settings/sections/lockdown.js.map +1 -1
- package/lib/client/settings/sections/notes.js +12 -12
- package/lib/client/settings/sections/notes.js.map +1 -1
- package/lib/client/settings/sections/session.js +15 -12
- package/lib/client/settings/sections/session.js.map +1 -1
- package/lib/client/settings/sections/slash.js +9 -9
- package/lib/client/settings/sections/slash.js.map +1 -1
- package/lib/client/settings/sections/sources.js +26 -26
- package/lib/client/settings/sections/sources.js.map +1 -1
- package/lib/client/settings/sections/status.js +2 -2
- package/lib/client/settings/sections/status.js.map +1 -1
- package/lib/client/settings/styles.js +15 -9
- package/lib/client/settings/styles.js.map +1 -1
- package/lib/client/slash/SlashPalette.js +4 -4
- package/lib/client/slash/SlashPalette.js.map +1 -1
- package/lib/client/styles.js +139 -66
- package/lib/client/styles.js.map +1 -1
- package/lib/client/theme-preference.js +162 -0
- package/lib/client/theme-preference.js.map +1 -0
- package/lib/client/types.js +8 -0
- package/lib/client/types.js.map +1 -1
- package/lib/client/use-session-ui-state.js +7 -5
- package/lib/client/use-session-ui-state.js.map +1 -1
- package/lib/client/user-settings/GeneralSettingsPage.js +6 -6
- package/lib/client/user-settings/GeneralSettingsPage.js.map +1 -1
- package/lib/client/user-settings/IntegrationTokensPage.js +6 -6
- package/lib/client/user-settings/IntegrationTokensPage.js.map +1 -1
- package/lib/client/user-settings/NotificationSettingsPage.js +107 -0
- package/lib/client/user-settings/NotificationSettingsPage.js.map +1 -0
- package/lib/client/user-settings/PasswordSettingsPage.js +1 -1
- package/lib/client/user-settings/PasswordSettingsPage.js.map +1 -1
- package/lib/client/user-settings/ProfileSettingsPage.js +2 -2
- package/lib/client/user-settings/ProfileSettingsPage.js.map +1 -1
- package/lib/client/user-settings/SkillCatalog.js +3 -3
- package/lib/client/user-settings/SkillCatalog.js.map +1 -1
- package/lib/client/user-settings/SkillEditor.js +26 -8
- package/lib/client/user-settings/SkillEditor.js.map +1 -1
- package/lib/client/user-settings/SkillToolPicker.js +3 -3
- package/lib/client/user-settings/SkillToolPicker.js.map +1 -1
- package/lib/client/user-settings/SkillsSettingsPage.js +1 -1
- package/lib/client/user-settings/SkillsSettingsPage.js.map +1 -1
- package/lib/client/user-settings/StartersSettingsPage.js +6 -6
- package/lib/client/user-settings/StartersSettingsPage.js.map +1 -1
- package/lib/client/user-settings/UserSettingsDialog.js +7 -2
- package/lib/client/user-settings/UserSettingsDialog.js.map +1 -1
- package/lib/client/user-settings/copy.js +2 -0
- package/lib/client/user-settings/copy.js.map +1 -1
- package/lib/client/user-settings/draft.js +4 -1
- package/lib/client/user-settings/draft.js.map +1 -1
- package/lib/client/user-settings/fields.js +5 -5
- package/lib/client/user-settings/fields.js.map +1 -1
- package/lib/client.js +7483 -2075
- package/lib/client.js.map +1 -1
- package/lib/config-resolvers/defaults.js +7 -0
- package/lib/config-resolvers/defaults.js.map +1 -1
- package/lib/config-resolvers/lockdown.js +7 -0
- package/lib/config-resolvers/lockdown.js.map +1 -1
- package/lib/config-resolvers/notifications.js +15 -0
- package/lib/config-resolvers/notifications.js.map +1 -0
- package/lib/config-resolvers/session.js +11 -1
- package/lib/config-resolvers/session.js.map +1 -1
- package/lib/config.js +67 -18
- package/lib/config.js.map +1 -1
- package/lib/enforcement/tool-grants.js +6 -6
- package/lib/enforcement/tool-grants.js.map +1 -1
- package/lib/index.js +171 -39
- package/lib/index.js.map +1 -1
- package/lib/integration/answer.js +74 -8
- package/lib/integration/answer.js.map +1 -1
- package/lib/integration/expert-memory.js +39 -0
- package/lib/integration/expert-memory.js.map +1 -0
- package/lib/integration/host-runner.js +26 -14
- package/lib/integration/host-runner.js.map +1 -1
- package/lib/notifications.js +66 -0
- package/lib/notifications.js.map +1 -0
- package/lib/personal-skills/errors.js.map +1 -1
- package/lib/personal-skills/service.js +81 -7
- package/lib/personal-skills/service.js.map +1 -1
- package/lib/prompt-notes.js +2 -10
- package/lib/prompt-notes.js.map +1 -1
- package/lib/provenance/extractors.js +1 -1
- package/lib/provenance/extractors.js.map +1 -1
- package/lib/provenance/host-store.js +5 -1
- package/lib/provenance/host-store.js.map +1 -1
- package/lib/qa-tools/docs-tools.js +64 -11
- package/lib/qa-tools/docs-tools.js.map +1 -1
- package/lib/qa-tools/lifecycle.js +6 -3
- package/lib/qa-tools/lifecycle.js.map +1 -1
- package/lib/request-queue.js +32 -0
- package/lib/request-queue.js.map +1 -0
- package/lib/resolve-config.js +2 -0
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +7 -2
- package/lib/secure-session.js.map +1 -1
- package/lib/shared/settings.js +19 -2
- package/lib/shared/settings.js.map +1 -1
- package/lib/turn-failure-log.js +67 -0
- package/lib/turn-failure-log.js.map +1 -0
- package/lib/typert.host.js +1459 -647
- package/lib/typert.remote-client.d.ts +25 -9
- package/lib/typert.remote-client.js +1356 -636
- package/lib/types/access/capability-catalog.d.ts +20 -4
- package/lib/types/access/model.d.ts +23 -0
- package/lib/types/access/service.d.ts +2 -3
- package/lib/types/account-remotes.d.ts +8 -1
- package/lib/types/accounts/database.d.ts +13 -3
- package/lib/types/accounts/errors.d.ts +9 -1
- package/lib/types/accounts/file.d.ts +12 -0
- package/lib/types/accounts/store.d.ts +30 -2
- package/lib/types/admin/quality-store.d.ts +33 -0
- package/lib/types/admin/service.d.ts +119 -9
- package/lib/types/client/QaAccountsController.d.ts +37 -3
- package/lib/types/client/QaConfigController.d.ts +2 -2
- package/lib/types/client/QaSessionController.d.ts +199 -6
- package/lib/types/client/QaSurface.d.ts +6 -1
- package/lib/types/client/admin/pages/ExpertMemory.d.ts +19 -0
- package/lib/types/client/admin/routes.d.ts +3 -1
- package/lib/types/client/admin/shared.d.ts +20 -1
- package/lib/types/client/components/Markdown.d.ts +8 -1
- package/lib/types/client/components/QaHeader.d.ts +3 -1
- package/lib/types/client/components/QaModal.d.ts +7 -0
- package/lib/types/client/components/QaQueueDock.d.ts +27 -0
- package/lib/types/client/components/QaRequestQueue.d.ts +20 -0
- package/lib/types/client/components/QaThemeSwitcher.d.ts +14 -0
- package/lib/types/client/components/QaTurnNotice.d.ts +55 -0
- package/lib/types/client/focus-ring.d.ts +65 -0
- package/lib/types/client/lineage.d.ts +3 -13
- package/lib/types/client/markdown/blocks.d.ts +30 -2
- package/lib/types/client/markdown/render.d.ts +4 -1
- package/lib/types/client/notifications/notification-dispatcher.d.ts +68 -0
- package/lib/types/client/notifications/preferences.d.ts +44 -0
- package/lib/types/client/notifications/turn-completion-source.d.ts +114 -0
- package/lib/types/client/notifications/use-turn-notifications.d.ts +51 -0
- package/lib/types/client/project-session-state.d.ts +35 -1
- package/lib/types/client/rating-harvest.d.ts +49 -0
- package/lib/types/client/role/RoleSelector.d.ts +7 -1
- package/lib/types/client/settings/card.d.ts +36 -5
- package/lib/types/client/settings/fields.d.ts +24 -0
- package/lib/types/client/settings/format.d.ts +0 -5
- package/lib/types/client/settings/sections/common.d.ts +3 -1
- package/lib/types/client/settings/sections/session.d.ts +2 -1
- package/lib/types/client/settings/styles.d.ts +9 -4
- package/lib/types/client/settings-extensions/user-session.d.ts +1 -1
- package/lib/types/client/theme-preference.d.ts +69 -0
- package/lib/types/client/types.d.ts +36 -5
- package/lib/types/client/use-session-ui-state.d.ts +6 -4
- package/lib/types/client/user-settings/GeneralSettingsPage.d.ts +5 -5
- package/lib/types/client/user-settings/NotificationSettingsPage.d.ts +40 -0
- package/lib/types/client/user-settings/UserSettingsDialog.d.ts +12 -2
- package/lib/types/client/user-settings/draft.d.ts +4 -1
- package/lib/types/client/user-settings/fields.d.ts +7 -0
- package/lib/types/config-resolvers/notifications.d.ts +10 -0
- package/lib/types/config-resolvers/session.d.ts +6 -0
- package/lib/types/config.d.ts +20 -1
- package/lib/types/index.d.ts +70 -10
- package/lib/types/integration/answer.d.ts +27 -0
- package/lib/types/integration/expert-memory.d.ts +49 -0
- package/lib/types/notifications.d.ts +32 -0
- package/lib/types/personal-skills/errors.d.ts +1 -1
- package/lib/types/personal-skills/service.d.ts +6 -0
- package/lib/types/prompt-notes.d.ts +17 -4
- package/lib/types/qa-tools/docs-tools.d.ts +2 -2
- package/lib/types/request-queue.d.ts +32 -0
- package/lib/types/shared/settings.d.ts +19 -2
- package/lib/types/turn-failure-log.d.ts +18 -0
- package/lib/types/types.d.ts +200 -4
- package/package.json +64 -62
- package/scripts/attach-workspace-sessions.mjs +24 -5
- package/scripts/repair-session-events.mjs +25 -5
|
@@ -1,4 +1,143 @@
|
|
|
1
1
|
import { projectTranscript } from "./QaTranscriptAdapter.js";
|
|
2
|
+
import { chatLegacyOf } from "./turn-sources.js";
|
|
3
|
+
/** Matches the Host queue strip, which folds a long row into one line. */
|
|
4
|
+
const QUEUE_PREVIEW_CHARS = 200;
|
|
5
|
+
function queuePreview(text) {
|
|
6
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
7
|
+
const chars = Array.from(flat);
|
|
8
|
+
return chars.length > QUEUE_PREVIEW_CHARS
|
|
9
|
+
? `${chars.slice(0, QUEUE_PREVIEW_CHARS).join("")}…`
|
|
10
|
+
: flat;
|
|
11
|
+
}
|
|
12
|
+
/** The `source.rpcId` of one Host row, when the Host named the send it carries. */
|
|
13
|
+
function rpcIdOf(source) {
|
|
14
|
+
const rpcId = source?.rpcId;
|
|
15
|
+
return rpcId === undefined || rpcId === null ? null : String(rpcId);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Request ids the Host's queue carries. A queued message lists the submission it
|
|
19
|
+
* answers for, which is what keeps one send from reading as two rows while it is
|
|
20
|
+
* both in transport and admitted.
|
|
21
|
+
*/
|
|
22
|
+
function queueNamedIds(queued) {
|
|
23
|
+
const ids = new Set();
|
|
24
|
+
for (const message of queued) {
|
|
25
|
+
const id = rpcIdOf(message.source);
|
|
26
|
+
if (id !== null)
|
|
27
|
+
ids.add(id);
|
|
28
|
+
}
|
|
29
|
+
return ids;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The request ids the Host has itself named for a send, out of the two lists it
|
|
33
|
+
* publishes: the messages waiting in its Inbox and the durable input rows of its
|
|
34
|
+
* transcript (`user` opens the turn that took the message, `steering` is one
|
|
35
|
+
* injected into the turn already running). Either is the server's own receipt
|
|
36
|
+
* that the message crossed, and reading both is what makes the receipt
|
|
37
|
+
* independent of which frame carried the news: a message the turn has claimed is
|
|
38
|
+
* gone from the Inbox yet stays in the transcript, so a send admitted and claimed
|
|
39
|
+
* between two notifications is still named by the next transcript frame.
|
|
40
|
+
*/
|
|
41
|
+
export function hostNamedSubmissionIds(queued, conversationSnapshot) {
|
|
42
|
+
const ids = queueNamedIds(queued);
|
|
43
|
+
for (const node of chatLegacyOf(conversationSnapshot).nodes) {
|
|
44
|
+
if (node.kind !== "user" && node.kind !== "steering")
|
|
45
|
+
continue;
|
|
46
|
+
const id = rpcIdOf(node.source);
|
|
47
|
+
if (id !== null)
|
|
48
|
+
ids.add(id);
|
|
49
|
+
}
|
|
50
|
+
return ids;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Messages waiting for the agent's next turn, in the order the Host will claim
|
|
54
|
+
* them. An admitted row comes from the Host's Inbox projection; a row still
|
|
55
|
+
* crossing the transport comes from the submission echo registered for it, so
|
|
56
|
+
* one queued send reads as one row at every moment.
|
|
57
|
+
*
|
|
58
|
+
* That echo is the browser's own, and retiring it is the session library's job.
|
|
59
|
+
* `@deepseek-ai/dsh-api-session-controller` — the harness's
|
|
60
|
+
* `packages/api/session-controller`, pinned here at 0.1.7-rc.2 — documents
|
|
61
|
+
* `SessionSnapshot.pendingSubmissions` as "Local prompt-submission echoes not
|
|
62
|
+
* yet observed as durable events or queue occurrences" and `beginSubmission` as
|
|
63
|
+
* "Queued echoes retire on queue acceptance", that retirement being the
|
|
64
|
+
* `observed` branch of `PendingSubmissionRetirement`. It does not complete the
|
|
65
|
+
* removal at acceptance: the settlement is latched and the removal deferred one
|
|
66
|
+
* animation frame (`scheduleObservedRetirement` hands `finishSubmission` to
|
|
67
|
+
* `scheduleFrame`; in the pinned bundle, `lib/client.js:2233` and `:2309`), and
|
|
68
|
+
* `scheduleFrame` falls back to a macrotask only where `requestAnimationFrame`
|
|
69
|
+
* does not exist at all. A surface whose frame clock has stopped therefore never
|
|
70
|
+
* runs the removal while its snapshot notifications keep arriving on microtasks —
|
|
71
|
+
* the card measured exactly that with the browser panel collapsed
|
|
72
|
+
* (`viewport=0x0`): the question and its answer in the feed, and the survivor
|
|
73
|
+
* drawn below it as a buttonless «отправляется…» row that a page reload cleared.
|
|
74
|
+
*
|
|
75
|
+
* So while that removal waits on a clock the surface may not have, a submission
|
|
76
|
+
* the Host has once named is never drawn as crossing. The follow-up belongs to
|
|
77
|
+
* `scheduleObservedRetirement` / `scheduleFrame` in that package: retire a
|
|
78
|
+
* settlement a delivered notification already proved without a frame.
|
|
79
|
+
*
|
|
80
|
+
* The substitute costs no row the contract would have drawn, because the library
|
|
81
|
+
* has already committed to the removal by the time either Host list can name the
|
|
82
|
+
* send: an Inbox frame that lists a queued echo latches the retirement there and
|
|
83
|
+
* then, and so does the durable row that opens the turn (`observeSubmissionMessage`
|
|
84
|
+
* hands the request to `scheduleObservedRetirement`, `lib/client.js:2201` and
|
|
85
|
+
* `:2213`, both landing at `:2233`). A message the Host takes out of its queue
|
|
86
|
+
* without handing it to the turn is therefore not a case this record swallows — its
|
|
87
|
+
* removal was latched the moment the Inbox listed it, and only the frame is
|
|
88
|
+
* missing. The retirements the library runs without a frame are the ones for a send
|
|
89
|
+
* the Host never named at all: the abandon path and a failed prompt
|
|
90
|
+
* (`lib/client.js:1704`, `:1753`), and the splice reporting `outcome === "canceled"`
|
|
91
|
+
* for a settlement it tracked by insertion receipt, which a queued echo never is
|
|
92
|
+
* (`lib/client.js:2164`, `:2186`, `:2245`). So the mask differs from the contract
|
|
93
|
+
* by the clock, never by the outcome.
|
|
94
|
+
*
|
|
95
|
+
* What it costs is the binding rather than a row. `unbind()` drops the record —
|
|
96
|
+
* leaving a chat, opening a subagent view, a policy re-bind and entering a draft
|
|
97
|
+
* all run it — and only a rebind of the same Session object could draw a survivor
|
|
98
|
+
* again. This surface retains under one source, so releasing its reference makes
|
|
99
|
+
* the manager withdraw the instance and dispose it (`lib/client.js:2413`), and the
|
|
100
|
+
* next binding holds a session with no echoes at all; where another holder keeps
|
|
101
|
+
* that object alive, the next Host frame names the send again and re-earns the
|
|
102
|
+
* record, so the row returns for a frame rather than for good.
|
|
103
|
+
*
|
|
104
|
+
* Where the frame clock does run, the library retires the echo on the frame after
|
|
105
|
+
* the claim, so this filter has nothing left to hide; a release that retired at
|
|
106
|
+
* acceptance rather than on a frame would leave it hiding nothing at all, and the
|
|
107
|
+
* filter becomes dead code to delete.
|
|
108
|
+
*/
|
|
109
|
+
function projectQueue(snapshot, queued, admitted) {
|
|
110
|
+
const echoed = queueNamedIds(queued);
|
|
111
|
+
const sending = snapshot.pendingSubmissions
|
|
112
|
+
.filter((item) => item.placement === "queued" &&
|
|
113
|
+
!echoed.has(String(item.requestId)) &&
|
|
114
|
+
!admitted.has(String(item.requestId)))
|
|
115
|
+
.map((item) => ({
|
|
116
|
+
id: String(item.requestId),
|
|
117
|
+
preview: queuePreview(item.text),
|
|
118
|
+
text: item.text,
|
|
119
|
+
attachments: item.attachments.length,
|
|
120
|
+
sending: true,
|
|
121
|
+
}));
|
|
122
|
+
return [
|
|
123
|
+
...queued.map((message) => {
|
|
124
|
+
const texts = message.content.flatMap((block) => block.type === "text" ? [block.text] : []);
|
|
125
|
+
const plainText = texts.join("\n\n");
|
|
126
|
+
return {
|
|
127
|
+
id: String(message.id),
|
|
128
|
+
preview: queuePreview(plainText),
|
|
129
|
+
// A row that mixes in non-text content cannot be re-sent as plain text,
|
|
130
|
+
// so it is previewed but not editable, exactly as the Host docks it.
|
|
131
|
+
text: message.content.every((block) => block.type === "text")
|
|
132
|
+
? plainText
|
|
133
|
+
: null,
|
|
134
|
+
attachments: message.content.filter((block) => block.type === "image" || block.type === "file").length,
|
|
135
|
+
sending: false,
|
|
136
|
+
};
|
|
137
|
+
}),
|
|
138
|
+
...sending,
|
|
139
|
+
];
|
|
140
|
+
}
|
|
2
141
|
/**
|
|
3
142
|
* Project one bound chat into the observable surface state: phase, transcript
|
|
4
143
|
* with per-turn sources, footer sources, and the composer's capabilities.
|
|
@@ -62,21 +201,33 @@ export function projectBoundSessionState(input) {
|
|
|
62
201
|
// the operator is answering a tool call that is already waiting, and text
|
|
63
202
|
// sent beside it would open a second turn instead.
|
|
64
203
|
const questionPending = questions.length > 0;
|
|
204
|
+
// Every Host operation the binding may still issue: a read-only historical
|
|
205
|
+
// chat issues none, and a parked question owns the composer until it is
|
|
206
|
+
// answered, because text sent beside it would open a second turn.
|
|
207
|
+
const canOperate = input.connected &&
|
|
208
|
+
input.policyReady &&
|
|
209
|
+
!questionPending &&
|
|
210
|
+
input.compatibilityReadOnly !== true;
|
|
65
211
|
return {
|
|
66
212
|
phase,
|
|
67
213
|
sessionId: input.sessionId,
|
|
214
|
+
chatKey: input.chatKey,
|
|
68
215
|
messages,
|
|
69
216
|
pendingMessage: null,
|
|
70
217
|
error,
|
|
71
218
|
compatibilityReadOnly: input.compatibilityReadOnly === true,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
219
|
+
// A running turn has nowhere for a new question to land except its queue,
|
|
220
|
+
// so the composer stays live beside it and the message is admitted as the
|
|
221
|
+
// next turn. A send whose admission has not returned yet stays a lock.
|
|
222
|
+
canSend: canOperate &&
|
|
223
|
+
!input.admissionPending &&
|
|
224
|
+
(phase === "ready" || snapshot.running),
|
|
76
225
|
canStop: input.connected &&
|
|
77
226
|
snapshot.running &&
|
|
78
227
|
config.ui.showStop &&
|
|
79
228
|
input.compatibilityReadOnly !== true,
|
|
229
|
+
queue: projectQueue(snapshot, input.queuedMessages, input.admittedSubmissions),
|
|
230
|
+
canEditQueue: canOperate,
|
|
80
231
|
chatsRevision: input.chatsRevision,
|
|
81
232
|
sources: latest === undefined
|
|
82
233
|
? []
|
|
@@ -91,6 +242,7 @@ export function projectBoundSessionState(input) {
|
|
|
91
242
|
viewingSubagent: input.viewingSubagent,
|
|
92
243
|
approvals: input.compatibilityReadOnly === true ? [] : input.approvals,
|
|
93
244
|
questions,
|
|
245
|
+
requestQueue: input.requestQueue,
|
|
94
246
|
// A read-only binding issues no Host operation at all, and running a
|
|
95
247
|
// command is one — the policy gate closes the palette with everything else.
|
|
96
248
|
slash: input.compatibilityReadOnly === true
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-session-state.js","sourceRoot":"","sources":["../../src/client/project-session-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"project-session-state.js","sourceRoot":"","sources":["../../src/client/project-session-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-shot replay of the ratings this browser still holds locally.
|
|
3
|
+
*
|
|
4
|
+
* A thumbs given before the surface could file it lives in the chat's ratings
|
|
5
|
+
* map and nowhere else. That map carries no timestamp and no reasons, so it
|
|
6
|
+
* cannot tell a lost rating from one the Host already holds a fuller version
|
|
7
|
+
* of — which is why the harvest writes through an insert-only call, offers only
|
|
8
|
+
* the ratings of the chats the signing-in account owns, and marks an account as
|
|
9
|
+
* read rather than re-offering its verdicts on every login.
|
|
10
|
+
*/
|
|
11
|
+
/** Chat-scoped ratings keys sit under this marker: `<ns>:chat:<id>:ratings`. */
|
|
12
|
+
const CHAT_MARKER = ":chat:";
|
|
13
|
+
/** The suffix the message row writes its ratings map under. */
|
|
14
|
+
const RATINGS_SUFFIX = ":ratings";
|
|
15
|
+
/** Prefix of the per-account marker: `<ns>:ratings-harvested:<account>`. */
|
|
16
|
+
const HARVESTED_MARKER = ":ratings-harvested:";
|
|
17
|
+
/** How many ratings one request carries. */
|
|
18
|
+
const BATCH_SIZE = 100;
|
|
19
|
+
/** The durable log position an answer row's browser id carries. */
|
|
20
|
+
const RATED_ANSWER = /^assistant:(\d+)$/u;
|
|
21
|
+
const ALREADY_HARVESTED = Object.freeze({
|
|
22
|
+
status: "already-harvested",
|
|
23
|
+
entries: 0,
|
|
24
|
+
recorded: 0,
|
|
25
|
+
});
|
|
26
|
+
function harvestedKey(namespace, accountId) {
|
|
27
|
+
return `${namespace}${HARVESTED_MARKER}${accountId}`;
|
|
28
|
+
}
|
|
29
|
+
/** Whether this browser has already been read out for that account. */
|
|
30
|
+
export function ratingsHarvested(storage, namespace, accountId) {
|
|
31
|
+
try {
|
|
32
|
+
return storage.getItem(harvestedKey(namespace, accountId)) === "1";
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// A store that will not answer has not been read out.
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function markRatingsHarvested(storage, namespace, accountId) {
|
|
40
|
+
try {
|
|
41
|
+
storage.setItem(harvestedKey(namespace, accountId), "1");
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// A denied write costs a replay at the next login, which the Host answers
|
|
45
|
+
// as already recorded. It must not fail the harvest that just succeeded.
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function readKeys(storage) {
|
|
49
|
+
const keys = [];
|
|
50
|
+
try {
|
|
51
|
+
for (let index = 0; index < storage.length; index += 1) {
|
|
52
|
+
const key = storage.key(index);
|
|
53
|
+
if (typeof key === "string")
|
|
54
|
+
keys.push(key);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// A store that refuses enumeration yields what it yielded until then.
|
|
59
|
+
}
|
|
60
|
+
return keys;
|
|
61
|
+
}
|
|
62
|
+
function parseRatings(raw) {
|
|
63
|
+
if (raw === null)
|
|
64
|
+
return {};
|
|
65
|
+
try {
|
|
66
|
+
const parsed = JSON.parse(raw);
|
|
67
|
+
return typeof parsed === "object" &&
|
|
68
|
+
parsed !== null &&
|
|
69
|
+
!Array.isArray(parsed)
|
|
70
|
+
? parsed
|
|
71
|
+
: {};
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return {};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function ratingOf(thumbs) {
|
|
78
|
+
if (thumbs === "up")
|
|
79
|
+
return "positive";
|
|
80
|
+
return thumbs === "down" ? "negative" : undefined;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Every rating this browser holds for that namespace, addressed by the
|
|
84
|
+
* conversation and by the durable log position the Host files a verdict under.
|
|
85
|
+
*
|
|
86
|
+
* An answer row's browser id is `assistant:<position>`, so those keys are
|
|
87
|
+
* addressable. Anything else — a work row, a half-streamed answer, an id the
|
|
88
|
+
* Host named rather than numbered — cannot be traced back to a log position,
|
|
89
|
+
* and is left where it is instead of guessed at.
|
|
90
|
+
*/
|
|
91
|
+
export function collectLocalRatings(storage, namespace) {
|
|
92
|
+
const prefix = `${namespace}${CHAT_MARKER}`;
|
|
93
|
+
const entries = [];
|
|
94
|
+
for (const key of readKeys(storage)) {
|
|
95
|
+
if (!key.startsWith(prefix) || !key.endsWith(RATINGS_SUFFIX))
|
|
96
|
+
continue;
|
|
97
|
+
const conversationId = key.slice(prefix.length, -RATINGS_SUFFIX.length);
|
|
98
|
+
if (conversationId === "")
|
|
99
|
+
continue;
|
|
100
|
+
for (const [messageId, thumbs] of Object.entries(parseRatings(storage.getItem(key)))) {
|
|
101
|
+
const position = RATED_ANSWER.exec(messageId)?.[1];
|
|
102
|
+
const rating = ratingOf(thumbs);
|
|
103
|
+
if (position === undefined || rating === undefined)
|
|
104
|
+
continue;
|
|
105
|
+
entries.push({ conversationId, messageId: position, rating });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return entries;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Read this browser's ratings out through `send`, once per account.
|
|
112
|
+
*
|
|
113
|
+
* `send` is the Host call; the caller chooses the token and the remote it
|
|
114
|
+
* travels on. The marker is written only after every batch landed, so a
|
|
115
|
+
* half-failed harvest is retried by the next login rather than lost.
|
|
116
|
+
*/
|
|
117
|
+
export async function harvestLocalRatings(options) {
|
|
118
|
+
const { storage, namespace, accountId, ownedIds, send } = options;
|
|
119
|
+
if (ratingsHarvested(storage, namespace, accountId))
|
|
120
|
+
return ALREADY_HARVESTED;
|
|
121
|
+
const owned = new Set(ownedIds);
|
|
122
|
+
const entries = collectLocalRatings(storage, namespace).filter((entry) => owned.has(entry.conversationId));
|
|
123
|
+
if (entries.length === 0) {
|
|
124
|
+
markRatingsHarvested(storage, namespace, accountId);
|
|
125
|
+
return { status: "nothing-to-harvest", entries: 0, recorded: 0 };
|
|
126
|
+
}
|
|
127
|
+
let recorded = 0;
|
|
128
|
+
for (let offset = 0; offset < entries.length; offset += BATCH_SIZE) {
|
|
129
|
+
const result = await send(entries.slice(offset, offset + BATCH_SIZE));
|
|
130
|
+
if (!result.ok) {
|
|
131
|
+
return { status: "failed", entries: entries.length, recorded };
|
|
132
|
+
}
|
|
133
|
+
recorded += result.value.recorded;
|
|
134
|
+
}
|
|
135
|
+
markRatingsHarvested(storage, namespace, accountId);
|
|
136
|
+
return { status: "harvested", entries: entries.length, recorded };
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=rating-harvest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rating-harvest.js","sourceRoot":"","sources":["../../src/client/rating-harvest.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,11 +19,11 @@ export function QaRoleSelector(props) {
|
|
|
19
19
|
props.onSelect(role.id);
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
|
-
return (_jsxs(_Fragment, { children: [_jsxs("label", { className: "dsh-qa-role-selector", children: [_jsx("span", { className: "dsh-qa-sr-only", children: "\u0420\u043E\u043B\u044C \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442\u0430" }), _jsx("select", { value: props.selected, disabled: props.disabled, "aria-label": "\u0420\u043E\u043B\u044C \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442\u0430", onChange: (event) => select(event.currentTarget.value), children: props.roles.map((role) => (_jsx("option", { value: role.id, children: role.name }, role.id))) })] }), _jsx(QaModal, { open: pending !== undefined, title: "\u041D\u0430\u0447\u0430\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u0447\u0430\u0442?", closeLabel: "\u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C \u0441\u043C\u0435\u043D\u0443 \u0440\u043E\u043B\u0438", onClose: () => setPending(undefined), footer: _jsxs(_Fragment, { children: [_jsx("button", { type: "button", onClick: () => setPending(undefined), children: "\u041E\u0442\u043C\u0435\u043D\u0430" }), _jsxs("button", { type: "button", className: "dsh-qa-modal__primary", onClick: () => {
|
|
22
|
+
return (_jsxs(_Fragment, { children: [_jsxs("label", { className: "dsh-qa-role-selector", "data-testid": "qa-role-selector", children: [_jsx("span", { className: "dsh-qa-sr-only", children: "\u0420\u043E\u043B\u044C \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442\u0430" }), _jsx("select", { "data-testid": "qa-role-selector-input", value: props.selected, disabled: props.disabled, "aria-label": "\u0420\u043E\u043B\u044C \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442\u0430", onChange: (event) => select(event.currentTarget.value), children: props.roles.map((role) => (_jsx("option", { value: role.id, "data-testid": "qa-role-selector-option", children: role.name }, role.id))) })] }), _jsx(QaModal, { open: pending !== undefined, title: "\u041D\u0430\u0447\u0430\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u0447\u0430\u0442?", closeLabel: "\u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C \u0441\u043C\u0435\u043D\u0443 \u0440\u043E\u043B\u0438", onClose: () => setPending(undefined), footer: _jsxs(_Fragment, { children: [_jsx("button", { type: "button", "data-testid": "qa-role-change-cancel", onClick: () => setPending(undefined), children: "\u041E\u0442\u043C\u0435\u043D\u0430" }), _jsxs("button", { type: "button", className: "dsh-qa-modal__primary", "data-testid": "qa-role-change-confirm", onClick: () => {
|
|
23
23
|
if (pending !== undefined)
|
|
24
24
|
props.onSelect(pending.id);
|
|
25
25
|
setPending(undefined);
|
|
26
|
-
}, children: ["\u041D\u0430\u0447\u0430\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u0447\u0430\u0442 \u043A\u0430\u043A ", pending?.name ?? ""] })] }), children: _jsx("p", { className: "dsh-qa-role-selector__notice", children: "\u0421\u043C\u0435\u043D\u0430 \u0440\u043E\u043B\u0438 \u043D\u0430\u0447\u0438\u043D\u0430\u0435\u0442 \u043D\u043E\u0432\u044B\u0439 \u0440\u0430\u0437\u0433\u043E\u0432\u043E\u0440: \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435 \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442\u0443 \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u044B \u0438 \u043D\u0430\u0432\u044B\u043A\u0438 \u0438\u0437\u043C\u0435\u043D\u044F\u0442\u0441\u044F. \u0422\u0435\u043A\u0443\u0449\u0438\u0439 \u0447\u0430\u0442 \u043E\u0441\u0442\u0430\u043D\u0435\u0442\u0441\u044F \u0432 \u0438\u0441\u0442\u043E\u0440\u0438\u0438 \u0431\u0435\u0437 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439." }) })] }));
|
|
26
|
+
}, children: ["\u041D\u0430\u0447\u0430\u0442\u044C \u043D\u043E\u0432\u044B\u0439 \u0447\u0430\u0442 \u043A\u0430\u043A ", pending?.name ?? ""] })] }), children: _jsx("p", { className: "dsh-qa-role-selector__notice", "data-testid": "qa-role-change-notice", children: "\u0421\u043C\u0435\u043D\u0430 \u0440\u043E\u043B\u0438 \u043D\u0430\u0447\u0438\u043D\u0430\u0435\u0442 \u043D\u043E\u0432\u044B\u0439 \u0440\u0430\u0437\u0433\u043E\u0432\u043E\u0440: \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0435 \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442\u0443 \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u044B \u0438 \u043D\u0430\u0432\u044B\u043A\u0438 \u0438\u0437\u043C\u0435\u043D\u044F\u0442\u0441\u044F. \u0422\u0435\u043A\u0443\u0449\u0438\u0439 \u0447\u0430\u0442 \u043E\u0441\u0442\u0430\u043D\u0435\u0442\u0441\u044F \u0432 \u0438\u0441\u0442\u043E\u0440\u0438\u0438 \u0431\u0435\u0437 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439." }) })] }));
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* The banner that keeps a preview from being mistaken for an ordinary chat.
|
|
@@ -32,9 +32,14 @@ export function QaRoleSelector(props) {
|
|
|
32
32
|
* is hidden — the previewed profile need not be one the account holds — so
|
|
33
33
|
* without a control here the only exit was the browser's Back button, and a new
|
|
34
34
|
* chat meanwhile ran as the previewed profile instead of the account's default.
|
|
35
|
-
*
|
|
35
|
+
*
|
|
36
|
+
* Leaving is a new chat, so the way out waits for the same moments the header's
|
|
37
|
+
* "Новый чат" and the role selector wait for: while a chat is still being
|
|
38
|
+
* created, this click would take the screen from the question on its way in.
|
|
39
|
+
* @param props - the previewed role's name, how to leave the preview, and whether
|
|
40
|
+
* that way is currently blocked by a chat being created.
|
|
36
41
|
*/
|
|
37
42
|
export function QaAdminPreviewBanner(props) {
|
|
38
|
-
return (_jsxs("div", { className: "dsh-qa-admin-preview", role: "status", children: [_jsxs("span", { children: ["\u041F\u0420\u041E\u0421\u041C\u041E\u0422\u0420 \u0410\u0414\u041C\u0418\u041D\u0418\u0421\u0422\u0420\u0410\u0422\u041E\u0420\u0410: ", props.role] }), props.onExit === undefined ? null : (_jsx("button", { type: "button", className: "dsh-qa-admin-preview__exit", onClick: props.onExit, title: "\u0412\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F \u043A \u0441\u0432\u043E\u0435\u043C\u0443 \u043F\u0440\u043E\u0444\u0438\u043B\u044E \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E: \u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440 \u0437\u0430\u043A\u043E\u043D\u0447\u0438\u0442\u0441\u044F, \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0447\u0430\u0442 \u043D\u0430\u0447\u043D\u0451\u0442\u0441\u044F \u0437\u0430\u043D\u043E\u0432\u043E", children: "\u0412\u044B\u0439\u0442\u0438 \u0438\u0437 \u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440\u0430" }))] }));
|
|
43
|
+
return (_jsxs("div", { className: "dsh-qa-admin-preview", "data-testid": "qa-admin-preview", role: "status", children: [_jsxs("span", { "data-testid": "qa-admin-preview-role", children: ["\u041F\u0420\u041E\u0421\u041C\u041E\u0422\u0420 \u0410\u0414\u041C\u0418\u041D\u0418\u0421\u0422\u0420\u0410\u0422\u041E\u0420\u0410: ", props.role] }), props.onExit === undefined ? null : (_jsx("button", { type: "button", className: "dsh-qa-admin-preview__exit", "data-testid": "qa-admin-preview-exit", onClick: props.onExit, disabled: props.disabled === true, title: "\u0412\u0435\u0440\u043D\u0443\u0442\u044C\u0441\u044F \u043A \u0441\u0432\u043E\u0435\u043C\u0443 \u043F\u0440\u043E\u0444\u0438\u043B\u044E \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E: \u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440 \u0437\u0430\u043A\u043E\u043D\u0447\u0438\u0442\u0441\u044F, \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0447\u0430\u0442 \u043D\u0430\u0447\u043D\u0451\u0442\u0441\u044F \u0437\u0430\u043D\u043E\u0432\u043E", children: "\u0412\u044B\u0439\u0442\u0438 \u0438\u0437 \u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440\u0430" }))] }));
|
|
39
44
|
}
|
|
40
45
|
//# sourceMappingURL=RoleSelector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RoleSelector.js","sourceRoot":"","sources":["../../../src/client/role/RoleSelector.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAUnD,0EAA0E;AAC1E,MAAM,UAAU,cAAc,CAAC,KAA0B;IACvD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,EAAa,CAAC;IACpD,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,MAAM,MAAM,GAAG,CAAC,EAAU,EAAE,EAAE;QAC5B,IAAI,EAAE,KAAK,KAAK,CAAC,QAAQ;YAAE,OAAO;QAClC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAClE,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO;QAC/B,IAAI,KAAK,CAAC,mBAAmB,EAAE,CAAC;YAC9B,UAAU,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CAAC;IACF,OAAO,CACL,8BACE,iBAAO,SAAS,EAAC,sBAAsB,
|
|
1
|
+
{"version":3,"file":"RoleSelector.js","sourceRoot":"","sources":["../../../src/client/role/RoleSelector.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { bindSettingsExternalStore, startVisibilityAwarePolling, } from "@yadsh/dsh-plugin-kit/client";
|
|
3
3
|
import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore, } from "react";
|
|
4
|
-
import {
|
|
4
|
+
import { isOverridden, mutationLanded, overriddenKeys, pluralRu, } from "./format.js";
|
|
5
5
|
import { AccessSection, AttachmentsSection, AccountsSection, BrandingSection, DocsSection, EmbeddingSection, InterfaceSection, LockdownSection, NotesSection, SessionSection, SlashSection, SourcesSection, StatusSection, } from "./sections.js";
|
|
6
6
|
const REFRESH_INTERVAL_MS = 5_000;
|
|
7
7
|
/** Shown when a settled mutation left the configuration unchanged. */
|
|
8
8
|
const REFUSED_MESSAGE = "Хост отклонил изменение: значение не сохранилось. Обычно так отвечает несовместимая комбинация полей — проверьте связанные значения этого раздела. Точную причину хост пишет в свой журнал.";
|
|
9
|
+
/**
|
|
10
|
+
* The one-liner of this row, carried by the `summary` view the Plugins page asks
|
|
11
|
+
* this seat for. Kept equal to the `description` field of `package.json`, which
|
|
12
|
+
* is where the host reads the row's sentence from: the two answers reach the same
|
|
13
|
+
* paragraph, so a drift makes one row read two ways. Pinned by a test that reads
|
|
14
|
+
* the manifest rather than repeating this literal (AGENTS.md card-shell contract,
|
|
15
|
+
* `docs/DSH-0.1.7-MIGRATION.md` §4.2).
|
|
16
|
+
*/
|
|
17
|
+
const ROW_SUMMARY = "A focused end-user QA surface backed by native DeepSeek Harness sessions";
|
|
9
18
|
function displayError(error) {
|
|
10
19
|
if (error instanceof Error)
|
|
11
20
|
return error.message;
|
|
@@ -18,8 +27,8 @@ function displayError(error) {
|
|
|
18
27
|
}
|
|
19
28
|
return "Хост отклонил изменение настроек помощника.";
|
|
20
29
|
}
|
|
21
|
-
export function QaSettingsCard({
|
|
22
|
-
const store = useMemo(() => bindSettingsExternalStore(
|
|
30
|
+
export function QaSettingsCard({ settingsForm, describe }) {
|
|
31
|
+
const store = useMemo(() => bindSettingsExternalStore(settingsForm), [settingsForm]);
|
|
23
32
|
const settings = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
24
33
|
const config = settings.value;
|
|
25
34
|
const writable = settings.status === "ready" && settings.writable;
|
|
@@ -64,18 +73,22 @@ export function QaSettingsCard({ scope, describe }) {
|
|
|
64
73
|
}
|
|
65
74
|
}, [describe]);
|
|
66
75
|
useEffect(() => {
|
|
76
|
+
// An unreachable namespace has no status section to feed, so the poll stays
|
|
77
|
+
// off until a snapshot serves values again.
|
|
78
|
+
if (settings.status === "unavailable")
|
|
79
|
+
return;
|
|
67
80
|
const stopPolling = startVisibilityAwarePolling(refresh, REFRESH_INTERVAL_MS);
|
|
68
81
|
return () => {
|
|
69
82
|
stopPolling();
|
|
70
83
|
activeRequest.current += 1;
|
|
71
84
|
};
|
|
72
|
-
}, [refresh]);
|
|
85
|
+
}, [refresh, settings.status]);
|
|
73
86
|
/**
|
|
74
|
-
* Path-addressed writes into the namespace. The
|
|
87
|
+
* Path-addressed writes into the namespace. The form's mutation operations
|
|
75
88
|
* are typed for the wire's JSON values, which a control's value satisfies by
|
|
76
89
|
* construction; the cast keeps that boundary in one place.
|
|
77
90
|
*
|
|
78
|
-
* A write the Host refuses does not reject the
|
|
91
|
+
* A write the Host refuses does not reject the form's promise: the form
|
|
79
92
|
* reloads Host state and settles normally. Acceptance is therefore confirmed
|
|
80
93
|
* against the namespace — the revision advances on every committed change,
|
|
81
94
|
* and a write that changed nothing is answered by the section itself —
|
|
@@ -83,7 +96,7 @@ export function QaSettingsCard({ scope, describe }) {
|
|
|
83
96
|
* nothing.
|
|
84
97
|
*/
|
|
85
98
|
const applyMutation = useCallback(async (entries, cleared) => {
|
|
86
|
-
const before =
|
|
99
|
+
const before = settingsForm.getSnapshot().revision;
|
|
87
100
|
const ops = [
|
|
88
101
|
...entries.map((entry) => ({
|
|
89
102
|
op: "set",
|
|
@@ -93,18 +106,18 @@ export function QaSettingsCard({ scope, describe }) {
|
|
|
93
106
|
...cleared.map((path) => ({ op: "unset", path: [...path] })),
|
|
94
107
|
];
|
|
95
108
|
try {
|
|
96
|
-
await
|
|
109
|
+
await settingsForm.mutate(ops);
|
|
97
110
|
}
|
|
98
111
|
catch (cause) {
|
|
99
112
|
setWriteError(displayError(cause));
|
|
100
113
|
return;
|
|
101
114
|
}
|
|
102
|
-
const after =
|
|
115
|
+
const after = settingsForm.getSnapshot();
|
|
103
116
|
const landed = after.revision !== before || mutationLanded(entries, cleared, after);
|
|
104
117
|
// Held until a later write lands: the message names what to look at, and
|
|
105
118
|
// a timer that clears it would only hide the problem.
|
|
106
119
|
setWriteError(landed ? null : REFUSED_MESSAGE);
|
|
107
|
-
}, [
|
|
120
|
+
}, [settingsForm]);
|
|
108
121
|
const write = useCallback((path, value) => {
|
|
109
122
|
void applyMutation([{ path, value }], []);
|
|
110
123
|
}, [applyMutation]);
|
|
@@ -119,10 +132,16 @@ export function QaSettingsCard({ scope, describe }) {
|
|
|
119
132
|
const resetAll = useCallback(() => {
|
|
120
133
|
void applyMutation([], overrides.map((key) => [key]));
|
|
121
134
|
}, [applyMutation, overrides]);
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
135
|
+
// The row's page draws its heading and its expand control whatever the
|
|
136
|
+
// namespace answers, so an unavailable one says why rather than leaving the
|
|
137
|
+
// column the operator just opened empty. The Plugins panel is not the settings
|
|
138
|
+
// directory: a browser on another machine sees the namespace as unavailable
|
|
139
|
+
// and still has the row, so hiding the body would hide the reason (AGENTS.md).
|
|
140
|
+
// A namespace that serves values but refuses writes is the other case: the
|
|
141
|
+
// body renders and disables its controls on `writable` instead of hiding.
|
|
142
|
+
if (settings.status === "unavailable") {
|
|
143
|
+
return (_jsx("p", { className: "qa-card-muted", "data-testid": "qa-settings-unavailable", children: "\u0425\u043E\u0441\u0442 \u043D\u0435 \u043E\u0442\u0434\u0430\u0451\u0442 \u044D\u0442\u043E\u043C\u0443 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u043F\u0440\u043E\u0441\u0442\u0440\u0430\u043D\u0441\u0442\u0432\u043E \u043D\u0430\u0441\u0442\u0440\u043E\u0435\u043A \u043F\u043B\u0430\u0433\u0438\u043D\u0430 \u2014 \u043E\u043D\u0438 \u0447\u0438\u0442\u0430\u044E\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \u0441 \u043C\u0430\u0448\u0438\u043D\u044B, \u0433\u0434\u0435 \u043F\u043E\u0434\u043D\u044F\u0442 \u0441\u0442\u0435\u043D\u0434. \u0420\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0437\u0434\u0435\u0441\u044C \u043D\u0435\u0447\u0435\u0433\u043E, \u0440\u0430\u0431\u043E\u0442\u0430 \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043D\u0442\u0430 \u043F\u0440\u0438 \u044D\u0442\u043E\u043C \u0438\u0434\u0451\u0442 \u043F\u043E \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u043C \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F\u043C." }));
|
|
144
|
+
}
|
|
126
145
|
const sectionProps = {
|
|
127
146
|
config,
|
|
128
147
|
effective,
|
|
@@ -132,12 +151,34 @@ export function QaSettingsCard({ scope, describe }) {
|
|
|
132
151
|
unset,
|
|
133
152
|
overridden,
|
|
134
153
|
};
|
|
135
|
-
return (_jsx(
|
|
154
|
+
return (_jsx("div", { className: "qa-card-body", children: settings.status === "loading" ? (_jsx("p", { className: "qa-card-muted", "data-testid": "qa-settings-loading", children: "\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u044E \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u043F\u043E\u043C\u043E\u0449\u043D\u0438\u043A\u0430\u2026" })) : (_jsxs(_Fragment, { children: [writeError !== null ? (_jsx("div", { className: "qa-card-error", "data-testid": "qa-settings-write-error", children: writeError })) : null, hostError !== null ? (_jsx("div", { className: "qa-card-error", "data-testid": "qa-settings-host-error", children: hostError })) : null, _jsx(StatusSection, { effective: effective, config: config, refreshing: refreshing, refreshedAt: refreshedAt, overrides: overrides.length, onRefresh: () => {
|
|
136
155
|
void refresh();
|
|
137
|
-
} }), _jsx(AccessSection, { ...sectionProps }), _jsx(BrandingSection, { ...sectionProps }), _jsx(SessionSection, { ...sectionProps }), _jsx(InterfaceSection, { ...sectionProps }), _jsx(LockdownSection, { ...sectionProps }), _jsx(SlashSection, { ...sectionProps }), _jsx(AccountsSection, { ...sectionProps }), _jsx(SourcesSection, { ...sectionProps }), _jsx(DocsSection, { ...sectionProps }), _jsx(NotesSection, { ...sectionProps }), _jsx(AttachmentsSection, { ...sectionProps }), _jsx(EmbeddingSection, { ...sectionProps }), _jsxs("div", { className: "qa-card-footer", children: [_jsx("p", { className: "qa-card-footer-note", children: "\u0418\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0443\u0445\u043E\u0434\u044F\u0442 \u043D\u0430 \u0440\u0430\u0431\u043E\u0442\u0430\u044E\u0449\u0438\u0439 Host \u0441\u0440\u0430\u0437\u0443: \u043C\u0430\u0440\u0448\u0440\u0443\u0442 \u043F\u0435\u0440\u0435\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044F, \u043F\u043E\u043B\u0438\u0442\u0438\u043A\u0430 \u043F\u0440\u0438\u043C\u0435\u043D\u044F\u0435\u0442\u0441\u044F \u043F\u0440\u0438 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u043C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u0438 \u0441\u0435\u0441\u0441\u0438\u0438. \u041F\u0440\u0430\u0432\u043A\u0438 \u043B\u043E\u0436\u0430\u0442\u0441\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u043C \u0441\u043B\u043E\u0435\u043C \u043F\u043E\u0432\u0435\u0440\u0445 \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044B\u0432\u0430\u043D\u0438\u044F, \u043F\u043E\u044D\u0442\u043E\u043C\u0443 \u0438\u0445 \u043C\u043E\u0436\u043D\u043E \u0441\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u2014 \u043D\u043E \u043D\u0435 \u043E\u0442\u043C\u0435\u043D\u0438\u0442\u044C \u043F\u043E\u0432\u0435\u0434\u0435\u043D\u0438\u0435, \u0437\u0430\u0448\u0438\u0442\u043E\u0435 \u0432 \u0441\u0430\u043C\u043E\u043C \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044B\u0432\u0430\u043D\u0438\u0438." }), overrides.length > 0 ? (_jsxs("button", { type: "button", className: "qa-card-btn", disabled: !writable, onClick: resetAll, children: ["\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C", " ", pluralRu(overrides.length, [
|
|
156
|
+
} }), _jsx(AccessSection, { ...sectionProps }), _jsx(BrandingSection, { ...sectionProps }), _jsx(SessionSection, { ...sectionProps }), _jsx(InterfaceSection, { ...sectionProps }), _jsx(LockdownSection, { ...sectionProps }), _jsx(SlashSection, { ...sectionProps }), _jsx(AccountsSection, { ...sectionProps }), _jsx(SourcesSection, { ...sectionProps }), _jsx(DocsSection, { ...sectionProps }), _jsx(NotesSection, { ...sectionProps }), _jsx(AttachmentsSection, { ...sectionProps }), _jsx(EmbeddingSection, { ...sectionProps }), _jsxs("div", { className: "qa-card-footer", children: [_jsx("p", { className: "qa-card-footer-note", children: "\u0418\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0443\u0445\u043E\u0434\u044F\u0442 \u043D\u0430 \u0440\u0430\u0431\u043E\u0442\u0430\u044E\u0449\u0438\u0439 Host \u0441\u0440\u0430\u0437\u0443: \u043C\u0430\u0440\u0448\u0440\u0443\u0442 \u043F\u0435\u0440\u0435\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044F, \u043F\u043E\u043B\u0438\u0442\u0438\u043A\u0430 \u043F\u0440\u0438\u043C\u0435\u043D\u044F\u0435\u0442\u0441\u044F \u043F\u0440\u0438 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u043C \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043D\u0438\u0438 \u0441\u0435\u0441\u0441\u0438\u0438. \u041F\u0440\u0430\u0432\u043A\u0438 \u043B\u043E\u0436\u0430\u0442\u0441\u044F \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u043C \u0441\u043B\u043E\u0435\u043C \u043F\u043E\u0432\u0435\u0440\u0445 \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044B\u0432\u0430\u043D\u0438\u044F, \u043F\u043E\u044D\u0442\u043E\u043C\u0443 \u0438\u0445 \u043C\u043E\u0436\u043D\u043E \u0441\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u2014 \u043D\u043E \u043D\u0435 \u043E\u0442\u043C\u0435\u043D\u0438\u0442\u044C \u043F\u043E\u0432\u0435\u0434\u0435\u043D\u0438\u0435, \u0437\u0430\u0448\u0438\u0442\u043E\u0435 \u0432 \u0441\u0430\u043C\u043E\u043C \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044B\u0432\u0430\u043D\u0438\u0438." }), overrides.length > 0 ? (_jsxs("button", { type: "button", className: "qa-card-btn", "data-testid": "qa-settings-reset-all", disabled: !writable, onClick: resetAll, children: ["\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C", " ", pluralRu(overrides.length, [
|
|
138
157
|
"переопределение",
|
|
139
158
|
"переопределения",
|
|
140
159
|
"переопределений",
|
|
141
160
|
])] })) : null] })] })) }));
|
|
142
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* The entry this plugin registers in the row's configuration seat.
|
|
164
|
+
*
|
|
165
|
+
* `RowDetail` in `@deepseek-ai/dsh-client-ui-plugin-manager/lib/client.js` can
|
|
166
|
+
* ask this seat for two shapes of the same entry: `view: 'summary'` as the row's
|
|
167
|
+
* one-liner and `view: 'page'` in the configuration column under the row's
|
|
168
|
+
* heading. Which of the two it asks for is the page's decision and §4.2 of
|
|
169
|
+
* `docs/DSH-0.1.7-MIGRATION.md` is where that is measured and stated — the row's
|
|
170
|
+
* description comes from the installed manifest, and the summary seat is the
|
|
171
|
+
* fallback for a row that declares none — so this bundle answers both without
|
|
172
|
+
* claiming either call is its own. The summary lands inside a line of the page's
|
|
173
|
+
* text, so it stays a sentence: a card seated there would draw a page within a
|
|
174
|
+
* line and start a second poll of the `qaSurface/describe` Remote. The page view
|
|
175
|
+
* is the body alone — the row's page already draws the card surface, the heading
|
|
176
|
+
* and the expand control, so a shell of ours would be a second frame inside the
|
|
177
|
+
* first (AGENTS.md, card-shell contract).
|
|
178
|
+
*/
|
|
179
|
+
export function QaSettingsCardEntry(props) {
|
|
180
|
+
if (props.view === "summary")
|
|
181
|
+
return ROW_SUMMARY;
|
|
182
|
+
return _jsx(QaSettingsCard, { ...props });
|
|
183
|
+
}
|
|
143
184
|
//# sourceMappingURL=card.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.js","sourceRoot":"","sources":["../../../src/client/settings/card.tsx"],"names":[],"mappings":";AAoBA,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"card.js","sourceRoot":"","sources":["../../../src/client/settings/card.tsx"],"names":[],"mappings":"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"}
|