@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
|
@@ -10,10 +10,25 @@ export interface CapabilityCatalogSnapshot {
|
|
|
10
10
|
readonly skillIds: ReadonlySet<string>;
|
|
11
11
|
/** Installed skills a person may invoke, including model-hidden ones. */
|
|
12
12
|
readonly userSkillIds: ReadonlySet<string>;
|
|
13
|
+
/**
|
|
14
|
+
* The subset {@link userSkillIds} this account owns: what its own skills root
|
|
15
|
+
* contributes, never the deployment's shared root. The access model hands
|
|
16
|
+
* these to their owner without a role grant.
|
|
17
|
+
*/
|
|
18
|
+
readonly ownUserSkillIds: ReadonlySet<string>;
|
|
13
19
|
readonly skills: ReadonlyMap<string, SkillSummary>;
|
|
14
20
|
/** Normalized `metadata.qa-surface` of every discovered skill. */
|
|
15
21
|
readonly skillMetadata: ReadonlyMap<string, QaSkillDescriptor>;
|
|
16
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* The viewing scope of one preset read, plus the release of the revision lease
|
|
25
|
+
* the preset registry hands it out with. The caller owns the lease for exactly
|
|
26
|
+
* as long as the read it borrowed the scope for.
|
|
27
|
+
*/
|
|
28
|
+
export interface QaPresetScopeLease {
|
|
29
|
+
readonly key: ScopeKey;
|
|
30
|
+
release(): Promise<void>;
|
|
31
|
+
}
|
|
17
32
|
/** Read-only adapter over the current DSH registries. */
|
|
18
33
|
export declare class QaCapabilityCatalog {
|
|
19
34
|
private readonly ctx;
|
|
@@ -42,12 +57,13 @@ export declare class QaCapabilityCatalog {
|
|
|
42
57
|
* Resolving the scope may compose the preset; a failure degrades to the
|
|
43
58
|
* global view instead of failing the page.
|
|
44
59
|
*/
|
|
45
|
-
presetScope?: () => Promise<
|
|
60
|
+
presetScope?: () => Promise<QaPresetScopeLease | undefined>);
|
|
46
61
|
snapshot(agent?: Agent): Promise<CapabilityCatalogSnapshot>;
|
|
62
|
+
private readCatalog;
|
|
47
63
|
/**
|
|
48
|
-
* The scope an administrator's catalog is read with. A deployment that
|
|
49
|
-
* QA chats to an agent preset gets that preset's standing scope; without
|
|
50
|
-
* pinned preset there is no scope to borrow, and the read stays global.
|
|
64
|
+
* The scope lease an administrator's catalog is read with. A deployment that
|
|
65
|
+
* pins QA chats to an agent preset gets that preset's standing scope; without
|
|
66
|
+
* a pinned preset there is no scope to borrow, and the read stays global.
|
|
51
67
|
*/
|
|
52
68
|
private resolvePresetScope;
|
|
53
69
|
/**
|
|
@@ -28,6 +28,12 @@ export interface CapabilityAvailability {
|
|
|
28
28
|
readonly skills: ReadonlySet<string>;
|
|
29
29
|
/** Installed skills a person may invoke; defaults to the model-facing set. */
|
|
30
30
|
readonly userSkills?: ReadonlySet<string>;
|
|
31
|
+
/**
|
|
32
|
+
* User-invocable skills the account of this session owns. They join
|
|
33
|
+
* `userSkills` for their owner whatever the role lists, because a personal
|
|
34
|
+
* skill belongs to one account and cannot be named in a shared role at all.
|
|
35
|
+
*/
|
|
36
|
+
readonly ownSkills?: ReadonlySet<string>;
|
|
31
37
|
}
|
|
32
38
|
export interface ResolveCapabilityPolicyInput {
|
|
33
39
|
readonly config: QaCapabilityConfig;
|
|
@@ -40,6 +46,23 @@ export interface ResolveCapabilityPolicyInput {
|
|
|
40
46
|
/** Revision recorded with the session snapshot; opaque to enforcement. */
|
|
41
47
|
readonly revision?: string;
|
|
42
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Names an administrator withdrew outright, which is every account at once,
|
|
51
|
+
* its owner included.
|
|
52
|
+
* @param config - the role configuration the withdrawal was recorded in.
|
|
53
|
+
*/
|
|
54
|
+
export declare function withdrawnSkillNames(config: QaCapabilityConfig): ReadonlySet<string>;
|
|
55
|
+
/**
|
|
56
|
+
* The personal layer of one session's user-invoke list.
|
|
57
|
+
*
|
|
58
|
+
* Only an outright administrator withdrawal reaches a skill the account owns:
|
|
59
|
+
* the role overlay edits per-role audiences, and a personal skill is not a role
|
|
60
|
+
* grant, while `disabled` withdraws the name from the deployment for everyone,
|
|
61
|
+
* its owner included.
|
|
62
|
+
* @param config - the role configuration the policy is resolved against.
|
|
63
|
+
* @param ownSkills - the account's own user-invocable skills, if any.
|
|
64
|
+
*/
|
|
65
|
+
export declare function personalUserSkillNames(config: QaCapabilityConfig, ownSkills: ReadonlySet<string> | undefined): readonly string[];
|
|
43
66
|
export declare function resolveCapabilityPolicy({ config, subroleId, systemTools, systemSkills, available: installed, skillMetadata, revision, }: ResolveCapabilityPolicyInput): QaEffectiveCapabilityPolicy;
|
|
44
67
|
export interface ResolveSkillAccessInput {
|
|
45
68
|
readonly config: QaCapabilityConfig;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type { Agent } from "@deepseek-ai/dsh-agent";
|
|
2
2
|
import type { Context } from "@deepseek-ai/cordis";
|
|
3
|
-
import type { ScopeKey } from "@deepseek-ai/dsh-scope";
|
|
4
3
|
import type { PluginLogger } from "@yadsh/dsh-plugin-log";
|
|
5
4
|
import type { QaAccounts } from "../accounts/store.js";
|
|
6
5
|
import type { QaAgentToolGrants } from "../enforcement/tool-grants.js";
|
|
7
6
|
import type { QaAccessAdminSnapshot, QaAccountUserPublic, QaCapabilityConfig, QaCapabilityDescriptor, QaCapabilitySelection, QaClaimResult, QaCurrentAccess, QaEffectiveCapabilityPolicy, QaSessionAccess, QaSkillActivationRecord, QaSkillAssignmentOverride, QaSubrole, QaUserAccess, ResolvedQaSurfaceConfig } from "../types.js";
|
|
8
7
|
import type { QaSessionLogReader } from "../admin/session-log.js";
|
|
9
|
-
import { QaCapabilityCatalog, type CapabilityCatalogSnapshot } from "./capability-catalog.js";
|
|
8
|
+
import { QaCapabilityCatalog, type CapabilityCatalogSnapshot, type QaPresetScopeLease } from "./capability-catalog.js";
|
|
10
9
|
import { QaRoleRepository } from "./role-repository.js";
|
|
11
10
|
export interface QaResolvedSessionPolicy {
|
|
12
11
|
readonly policy: QaEffectiveCapabilityPolicy;
|
|
@@ -51,7 +50,7 @@ export declare class QaAccessService {
|
|
|
51
50
|
* preset's scope, so a global-only catalog left the operator unable to
|
|
52
51
|
* see — or grant — what every QA chat actually mounts.
|
|
53
52
|
*/
|
|
54
|
-
readonly presetScope?: () => Promise<
|
|
53
|
+
readonly presetScope?: () => Promise<QaPresetScopeLease | undefined>;
|
|
55
54
|
/**
|
|
56
55
|
* Durable session listing, used to tell a chat from a delegated child
|
|
57
56
|
* across Host runs. Without it the lineage answer degrades to the live
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PluginLogger } from "@yadsh/dsh-plugin-log";
|
|
2
2
|
import { QaAccounts } from "./accounts/store.js";
|
|
3
|
-
import type { QaAccountProfileInput, QaAccountSession, QaAccountStartersInput, QaAccountUserPublic, QaIssuedServiceToken, QaOwnershipEntry, QaServiceTokenCreateInput, QaServiceTokenSummary, QaWhoamiResult, ResolvedQaSurfaceConfig } from "./types.js";
|
|
3
|
+
import type { QaAccountNotificationsInput, QaAccountProfileInput, QaAccountSession, QaAccountStartersInput, QaAccountUserPublic, QaIssuedServiceToken, QaOwnershipEntry, QaServiceTokenCreateInput, QaServiceTokenSummary, QaWhoamiResult, ResolvedQaSurfaceConfig } from "./types.js";
|
|
4
4
|
/**
|
|
5
5
|
* Host-side bodies of the account remotes the `QaSurface` service exposes.
|
|
6
6
|
* The `@Remote`-decorated signatures stay on the service class (typert code
|
|
@@ -57,6 +57,13 @@ export interface QaAccountRemotes {
|
|
|
57
57
|
updateProfile(token: string, input: QaAccountProfileInput): QaAccountUserPublic;
|
|
58
58
|
/** Replace the caller's own starter buttons; the token is the identity. */
|
|
59
59
|
updateStarters(token: string, input: QaAccountStartersInput): QaAccountUserPublic;
|
|
60
|
+
/**
|
|
61
|
+
* Replace the caller's own notification channels; the token is the identity.
|
|
62
|
+
* The deployment's own switches are not this write's business: they gate the
|
|
63
|
+
* channels at read time, so an account can only ever narrow what a stand
|
|
64
|
+
* allows, never widen it.
|
|
65
|
+
*/
|
|
66
|
+
updateNotifications(token: string, input: QaAccountNotificationsInput): QaAccountUserPublic;
|
|
60
67
|
/**
|
|
61
68
|
* The caller's own integration tokens, newest last. Never a secret: the
|
|
62
69
|
* plaintext exists only in the answer that minted it.
|
|
@@ -55,10 +55,20 @@ export declare class QaAccountsDatabase {
|
|
|
55
55
|
get secret(): string;
|
|
56
56
|
/** True while the in-memory model a caller holds is still current. */
|
|
57
57
|
get unchangedSinceLoad(): boolean;
|
|
58
|
-
/**
|
|
59
|
-
markLoaded(): void;
|
|
60
|
-
/** Every account, ownership record and skill activation, in one read. */
|
|
58
|
+
/** Every account, ownership record and skill activation, as one snapshot. */
|
|
61
59
|
loadAll(): AccountsFile;
|
|
60
|
+
/**
|
|
61
|
+
* The accounts model, read as the rows stand right now.
|
|
62
|
+
*
|
|
63
|
+
* Read through {@link loadAll}, never on its own: in autocommit every
|
|
64
|
+
* statement is a snapshot of its own, so these SELECTs are only one state
|
|
65
|
+
* when no other connection committed while they ran — which is exactly what
|
|
66
|
+
* the surrounding `PRAGMA data_version` check proves. The baseline used to be
|
|
67
|
+
* taken *after* the reads, which labeled a model of two states, and the token
|
|
68
|
+
* versions in it, as current: a token revoked by the `qa-accounts` CLI into
|
|
69
|
+
* this window kept working until some later write moved the version again.
|
|
70
|
+
*/
|
|
71
|
+
private readModel;
|
|
62
72
|
/** Append one account, preserving the order accounts are listed in. */
|
|
63
73
|
insertUser(user: StoredUser): void;
|
|
64
74
|
/** Replace one account's row in place. */
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
export type QaAccountsErrorReason = "auth-required" | "admin-required" | "forbidden" | "invalid-credentials"
|
|
7
7
|
/** The signed-in user typed a current password that does not match. */
|
|
8
8
|
| "invalid-current-password" | "account-disabled" | "email-taken" | "invalid-email" | "invalid-display-name" | "invalid-profile" | "profile-disabled" | "invalid-starters" | "starters-disabled"
|
|
9
|
+
/** The notifications payload named a channel that is not a yes or a no. */
|
|
10
|
+
| "invalid-notifications"
|
|
9
11
|
/** The endpoint this credential is for is switched off on this deployment. */
|
|
10
12
|
| "integration-disabled" | "invalid-role" | "weak-password" | "registration-disabled" | "rate-limited" | "session-owned-elsewhere"
|
|
11
13
|
/** The conversation a deletion names is not one this deployment knows. */
|
|
@@ -13,7 +15,13 @@ export type QaAccountsErrorReason = "auth-required" | "admin-required" | "forbid
|
|
|
13
15
|
/** The Harness still holds the conversation open, so its log would come back. */
|
|
14
16
|
| "conversation-live"
|
|
15
17
|
/** This deployment cannot remove stored conversations at all. */
|
|
16
|
-
| "conversation-not-removable"
|
|
18
|
+
| "conversation-not-removable"
|
|
19
|
+
/** The record an operator edited is no longer the one stored. */
|
|
20
|
+
| "memory-record-unknown"
|
|
21
|
+
/** Expert memory is not reachable: no plugin composed it, or its store is down. */
|
|
22
|
+
| "memory-unavailable"
|
|
23
|
+
/** The Host refused the memory edit itself, not who asked for it. */
|
|
24
|
+
| "invalid-memory";
|
|
17
25
|
export declare class QaAccountsError extends Error {
|
|
18
26
|
readonly reason: QaAccountsErrorReason;
|
|
19
27
|
constructor(reason: QaAccountsErrorReason, message: string);
|
|
@@ -14,6 +14,16 @@ export interface StoredStarters {
|
|
|
14
14
|
}[];
|
|
15
15
|
hideDefaults?: boolean;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* One account's notification channels as they rest in the accounts store. Every
|
|
19
|
+
* field is optional because the record is read, not parsed: an account created
|
|
20
|
+
* before the settings form existed has none of it, and a hand-edited row must
|
|
21
|
+
* not decide anything the reader never chose.
|
|
22
|
+
*/
|
|
23
|
+
export interface StoredNotifications {
|
|
24
|
+
inApp?: boolean;
|
|
25
|
+
desktop?: boolean;
|
|
26
|
+
}
|
|
17
27
|
export interface StoredUser {
|
|
18
28
|
readonly id: string;
|
|
19
29
|
readonly email: string;
|
|
@@ -37,6 +47,8 @@ export interface StoredUser {
|
|
|
37
47
|
profile?: StoredProfile;
|
|
38
48
|
/** Absent until the owner customizes the starter buttons. */
|
|
39
49
|
starters?: StoredStarters;
|
|
50
|
+
/** Absent until the owner opens the notifications form for the first time. */
|
|
51
|
+
notifications?: StoredNotifications;
|
|
40
52
|
/** Agent capability profiles assigned by an administrator. */
|
|
41
53
|
qaAccess?: QaUserAccess;
|
|
42
54
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { QaAccountIdentityField, QaAccountProfile, QaAccountProfileInput, QaAccountRole, QaAccountSession, QaAccountStartersInput, QaAccountUserPublic, QaAccessUser, QaAdminAccountRow, QaClaimResult, QaEffectiveCapabilityPolicy, QaOwnershipEntry, QaIssuedServiceToken, QaPasswordResetRequest, QaServiceTokenSummary, QaSkillActivationRecord, QaUserAccess, QaWhoamiResult } from "../types.js";
|
|
1
|
+
import type { QaAccountIdentityField, QaAccountNotificationsInput, QaAccountProfile, QaAccountProfileInput, QaAccountRole, QaAccountSession, QaAccountStartersInput, QaAccountUserPublic, QaAccessUser, QaAdminAccountRow, QaClaimResult, QaEffectiveCapabilityPolicy, QaOwnershipEntry, QaIssuedServiceToken, QaPasswordResetRequest, QaServiceTokenSummary, QaSkillActivationRecord, QaUserAccess, QaWhoamiResult } from "../types.js";
|
|
2
2
|
import { type StoredOwnership, type StoredUser } from "./file.js";
|
|
3
3
|
import { type QaServiceTokenScope } from "./service-token.js";
|
|
4
4
|
export { QaAccountsError } from "./errors.js";
|
|
@@ -105,6 +105,16 @@ export declare class QaAccounts {
|
|
|
105
105
|
* mtime-and-size stamp of the JSON file used to provide.
|
|
106
106
|
*/
|
|
107
107
|
private reloadIfChanged;
|
|
108
|
+
/**
|
|
109
|
+
* The authorization state as the database holds it right now.
|
|
110
|
+
*
|
|
111
|
+
* Every credential check reads through here, because what decides one — the
|
|
112
|
+
* token version and the disabled flag — is a row another process may have
|
|
113
|
+
* changed since this store last read. Refreshing inside the check rather than
|
|
114
|
+
* in whichever method the caller happened to invoke first is what keeps a
|
|
115
|
+
* revoked token from surviving in the in-memory model.
|
|
116
|
+
*/
|
|
117
|
+
private authState;
|
|
108
118
|
private pruneAuthAttempts;
|
|
109
119
|
private assertAuthBudget;
|
|
110
120
|
private userByEmail;
|
|
@@ -114,7 +124,14 @@ export declare class QaAccounts {
|
|
|
114
124
|
/** Resolve a token to its user, or null for absent/invalid/expired ones. */
|
|
115
125
|
verifyToken(token: string): string | null;
|
|
116
126
|
private mintToken;
|
|
117
|
-
/**
|
|
127
|
+
/**
|
|
128
|
+
* The account behind a token, or an auth-required refusal.
|
|
129
|
+
*
|
|
130
|
+
* The check reads the current authorization state, so the refusal lands on the
|
|
131
|
+
* call that presents a revoked token rather than on whichever method reloaded
|
|
132
|
+
* first. The personal-skill remotes gate on this call alone, which is what
|
|
133
|
+
* made the difference a security one.
|
|
134
|
+
*/
|
|
118
135
|
requireUser(token: string): StoredUser;
|
|
119
136
|
/** Public identity behind a token; used by server-side access services. */
|
|
120
137
|
currentUser(token: string): QaAccountUserPublic;
|
|
@@ -449,6 +466,17 @@ export declare class QaAccounts {
|
|
|
449
466
|
* write leaves the stored record untouched.
|
|
450
467
|
*/
|
|
451
468
|
updateOwnStarters(token: string, input: QaAccountStartersInput): QaAccountUserPublic;
|
|
469
|
+
/**
|
|
470
|
+
* Replace the token account's notification channels. Same self-service shape
|
|
471
|
+
* as {@link updateOwnStarters}: the token is the only identity, the write is
|
|
472
|
+
* full-replace, and a rejected payload leaves the stored record alone.
|
|
473
|
+
*
|
|
474
|
+
* Deliberately not gated by a config key the way profiles and starters are —
|
|
475
|
+
* a stand that wanted this switched off already has `notifications.enabled`,
|
|
476
|
+
* and two switches for one decision is how a deployment ends up with an
|
|
477
|
+
* answer nobody can find.
|
|
478
|
+
*/
|
|
479
|
+
updateOwnNotifications(token: string, input: QaAccountNotificationsInput): QaAccountUserPublic;
|
|
452
480
|
/**
|
|
453
481
|
* Validate one profile write and stamp it onto the account. Throws before
|
|
454
482
|
* anything is mutated, so a rejected write leaves the stored profile, and
|
|
@@ -19,6 +19,21 @@ export interface QaManualQueueEntry {
|
|
|
19
19
|
readonly userId: string;
|
|
20
20
|
readonly createdAt: string;
|
|
21
21
|
}
|
|
22
|
+
/** The four record families the store keeps, one row each. */
|
|
23
|
+
export type QualityRowKind = "feedback" | "review" | "queue" | "audit";
|
|
24
|
+
/** How many rows of each family survive; the oldest fall off first. */
|
|
25
|
+
export declare const QA_ROW_CAPS: Readonly<Record<QualityRowKind, number>>;
|
|
26
|
+
/** Give up everything older in rank than the row at the cap, whose position the
|
|
27
|
+
* caller binds as `QA_ROW_CAPS[kind] - 1`. */
|
|
28
|
+
export declare const OVERFLOW_CUT_SQL = "\n DELETE FROM quality_rows\n WHERE kind = ?\n AND seq < (\n SELECT seq FROM quality_rows\n WHERE kind = ?\n ORDER BY seq DESC\n LIMIT 1 OFFSET ?\n )";
|
|
29
|
+
/** Read a whole family back in the order its records arrived. */
|
|
30
|
+
export declare const FAMILY_REPLAY_SQL = "\n SELECT json FROM quality_rows WHERE kind = ? ORDER BY seq";
|
|
31
|
+
/** Write one record at the end of its family's order, taking that end from the
|
|
32
|
+
* family's `MAX(seq)` whether the record is new or being re-judged. */
|
|
33
|
+
export declare const ROW_PLACEMENT_SQL = "\n INSERT INTO quality_rows (kind, key, seq, json)\n VALUES (?, ?, (SELECT COALESCE(MAX(seq), 0) + 1 FROM quality_rows WHERE kind = ?), ?)\n ON CONFLICT(kind, key) DO UPDATE SET\n seq = (SELECT COALESCE(MAX(seq), 0) + 1 FROM quality_rows WHERE kind = excluded.kind),\n json = excluded.json";
|
|
34
|
+
/** Read a whole family with each record's identity, the way the ownership sweep
|
|
35
|
+
* finds the rows of a conversation it is forgetting. */
|
|
36
|
+
export declare const FAMILY_MEMBERSHIP_SQL = "\n SELECT key, json FROM quality_rows WHERE kind = ?";
|
|
22
37
|
export declare function defaultQualityFilePath(): string;
|
|
23
38
|
/** The pre-SQLite quality file, imported once on first use. */
|
|
24
39
|
export declare function defaultLegacyQualityFilePath(): string;
|
|
@@ -102,6 +117,24 @@ export declare class QaQualityStore {
|
|
|
102
117
|
/** Append a record whose identity the store mints itself. */
|
|
103
118
|
private appendRow;
|
|
104
119
|
private deleteRow;
|
|
120
|
+
/**
|
|
121
|
+
* Drop the rows that overflow their family's cap.
|
|
122
|
+
*
|
|
123
|
+
* The rows to give up are the oldest by rank, not everything below
|
|
124
|
+
* `MAX(seq) - cap`. That range only equals the overflow while every sequence
|
|
125
|
+
* value is taken, and the store itself vacates values: an updated record
|
|
126
|
+
* moves to the end of the order and leaves its old value behind, and a
|
|
127
|
+
* dropped record leaves a hole. A range cut pays for each of those gaps with
|
|
128
|
+
* a real record, so a family at its cap loses one every time a record it
|
|
129
|
+
* already holds is re-rated — feedback disappears without anything new
|
|
130
|
+
* arriving to displace it.
|
|
131
|
+
*
|
|
132
|
+
* Reading that rank is not a seek: it walks cap entries of the family's own
|
|
133
|
+
* slice of the (kind, seq) index, so the cap bounds the cost of every write,
|
|
134
|
+
* while the delete reaches only the rows it removes and a write that does not
|
|
135
|
+
* overflow pays the read alone. Without the index the same read sorts the
|
|
136
|
+
* whole family into a temp B-tree.
|
|
137
|
+
*/
|
|
105
138
|
private applyCap;
|
|
106
139
|
private rowsOf;
|
|
107
140
|
private readDataVersion;
|
|
@@ -2,9 +2,10 @@ import type { PluginLogger } from "@yadsh/dsh-plugin-log";
|
|
|
2
2
|
import type { QaAccounts } from "../accounts/store.js";
|
|
3
3
|
import type { QaAccessService } from "../access/service.js";
|
|
4
4
|
import type { QaRoleRepository } from "../access/role-repository.js";
|
|
5
|
-
import type { QaAdminAuditEvent, QaAdminOverview, QaAdminPage, QaAdminSkillScope, QaAdminSkillsView, QaAdminUserDetail, QaAdminUserRow, QaAdminUserUpdate, QaAuditQuery, QaConversationDetail, QaConversationDeletion, QaConversationQuery, QaConversationReview, QaConversationReviewInput, QaConversationSummary, QaFeedbackQuery, QaFeedbackRow, QaMessageFeedback, QaMessageFeedbackInput, QaPasswordResetRequest, QaQualityMetrics, QaReviewQueueItem, QaReviewQueueRow, QaSkillDocument, QaSkillDraftInput, QaSkillRemoval, QaSkillToolDescriptor, QaSkillValidation, QaUserQuery } from "../types.js";
|
|
5
|
+
import type { QaAdminAuditEvent, QaAdminOverview, QaAdminPage, QaAdminSkillScope, QaAdminSkillsView, QaAdminUserDetail, QaAdminUserRow, QaAdminUserUpdate, QaAuditQuery, QaConversationDetail, QaConversationDeletion, QaConversationQuery, QaConversationReview, QaConversationReviewInput, QaConversationSummary, QaExpertMemoryDraft, QaExpertMemoryPage, QaExpertMemoryRecord, QaExpertMemoryScope, QaFeedbackHarvestEntry, QaFeedbackHarvestResult, QaFeedbackQuery, QaFeedbackRow, QaMessageFeedback, QaMessageFeedbackInput, QaPasswordResetRequest, QaQualityMetrics, QaReviewQueueItem, QaReviewQueueRow, QaSkillDocument, QaSkillDraftInput, QaSkillRemoval, QaSkillToolDescriptor, QaSkillValidation, QaUserQuery } from "../types.js";
|
|
6
6
|
import type { QaPersonalSkills } from "../personal-skills/index.js";
|
|
7
|
-
import type {
|
|
7
|
+
import type { QaDomainExpertsFace } from "../integration/expert-memory.js";
|
|
8
|
+
import { type QaQualityStore } from "./quality-store.js";
|
|
8
9
|
import type { QaAdminRedactor } from "./redaction.js";
|
|
9
10
|
import type { QaSessionLogReader, QaStoredSessionEraser } from "./session-log.js";
|
|
10
11
|
/**
|
|
@@ -43,6 +44,14 @@ export interface QaAdminServiceOptions {
|
|
|
43
44
|
* never constructs storage before someone opens its skills page.
|
|
44
45
|
*/
|
|
45
46
|
readonly skills: () => QaPersonalSkills;
|
|
47
|
+
/**
|
|
48
|
+
* The domain-experts service, if this deployment composed one. Resolved
|
|
49
|
+
* lazily for the same reason `skills` is, and for one more: a stand without
|
|
50
|
+
* experts must still open its console, so the memory page learns "there is
|
|
51
|
+
* nothing here to maintain" from this returning `undefined` rather than from a
|
|
52
|
+
* missing import at boot.
|
|
53
|
+
*/
|
|
54
|
+
readonly domainExperts?: () => QaDomainExpertsFace | undefined;
|
|
46
55
|
/** Drops the sources a conversation collected, when the deployment keeps any. */
|
|
47
56
|
readonly dropSources?: (sessionId: string) => void;
|
|
48
57
|
readonly logger: PluginLogger;
|
|
@@ -52,6 +61,8 @@ export interface QaAdminServiceOptions {
|
|
|
52
61
|
export declare class QaAdminService {
|
|
53
62
|
private readonly options;
|
|
54
63
|
private readonly redactor;
|
|
64
|
+
/** The aggregate pass running now, shared by the callers waiting for it. */
|
|
65
|
+
private scanning;
|
|
55
66
|
private readonly transcripts;
|
|
56
67
|
constructor(options: QaAdminServiceOptions);
|
|
57
68
|
private requireAccounts;
|
|
@@ -74,11 +85,46 @@ export declare class QaAdminService {
|
|
|
74
85
|
* costs a listing per interval at most.
|
|
75
86
|
*/
|
|
76
87
|
private index;
|
|
77
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* One conversation's projected log, held across calls.
|
|
90
|
+
*
|
|
91
|
+
* A log the Harness no longer holds is finished — nothing can append to it —
|
|
92
|
+
* so its projection stays valid until the cache evicts it or the conversation
|
|
93
|
+
* is deleted. Only a log this process is still writing is re-read once the TTL
|
|
94
|
+
* expires. A cache hit counts as a use: an aggregate pass walks the whole
|
|
95
|
+
* window, and evicting by read time would drop the conversations the pages ask
|
|
96
|
+
* for most often and then read them again.
|
|
97
|
+
*
|
|
98
|
+
* The one answer this can hold back is a conversation resumed and finished
|
|
99
|
+
* between two page loads: its counters lag until the log is read for another
|
|
100
|
+
* reason. The conversation itself is never affected — the detail view always
|
|
101
|
+
* reads the log — and what the aggregate pages show instead is the newest
|
|
102
|
+
* projection of every finished conversation, which is the cheaper lie.
|
|
103
|
+
*/
|
|
78
104
|
private transcript;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
105
|
+
/** Insert or re-touch one projection, keeping the cache inside its budget. */
|
|
106
|
+
private retain;
|
|
107
|
+
/**
|
|
108
|
+
* The aggregate rows of the newest scan window, read in one pass.
|
|
109
|
+
*
|
|
110
|
+
* The message counts and the tool failures come from the same projections, so
|
|
111
|
+
* one walk fills both. While a walk runs, a caller that wants the same window
|
|
112
|
+
* joins it rather than starting a second scan of the deployment's logs, and the
|
|
113
|
+
* walk stops once no caller waits for it: a scan nobody is reading is only ever
|
|
114
|
+
* a load on the store.
|
|
115
|
+
*/
|
|
116
|
+
private scanOf;
|
|
117
|
+
/**
|
|
118
|
+
* Walk one scan window, filling the counts and the failure signals as it goes.
|
|
119
|
+
*
|
|
120
|
+
* `waiting` is the caller set of the pass this walk belongs to: the walk gives
|
|
121
|
+
* up between two reads once every caller has left, so a reviewer who abandons a
|
|
122
|
+
* page that has not answered does not keep the deployment reading logs for an
|
|
123
|
+
* answer nobody will see.
|
|
124
|
+
*/
|
|
125
|
+
private walk;
|
|
126
|
+
overview(token: string, signal?: AbortSignal): Promise<QaAdminOverview>;
|
|
127
|
+
metrics(token: string, signal?: AbortSignal): Promise<QaQualityMetrics>;
|
|
82
128
|
private metricsOf;
|
|
83
129
|
/** One attention line per condition worth an administrator's time. */
|
|
84
130
|
private alertsOf;
|
|
@@ -108,7 +154,7 @@ export declare class QaAdminService {
|
|
|
108
154
|
private assertAdminSurvives;
|
|
109
155
|
/** Validate an assignment against the enabled roles before storing it. */
|
|
110
156
|
private exactAssignment;
|
|
111
|
-
conversations(token: string, query: QaConversationQuery, cursor: string | undefined, limit: number | undefined): Promise<QaAdminPage<QaConversationSummary>>;
|
|
157
|
+
conversations(token: string, query: QaConversationQuery, cursor: string | undefined, limit: number | undefined, signal?: AbortSignal): Promise<QaAdminPage<QaConversationSummary>>;
|
|
112
158
|
private summaryOf;
|
|
113
159
|
conversation(token: string, conversationId: string): Promise<QaConversationDetail>;
|
|
114
160
|
/**
|
|
@@ -130,17 +176,31 @@ export declare class QaAdminService {
|
|
|
130
176
|
*/
|
|
131
177
|
deleteConversation(token: string, conversationId: string): Promise<QaConversationDeletion>;
|
|
132
178
|
private failuresOf;
|
|
133
|
-
private failureSignals;
|
|
134
179
|
/**
|
|
135
180
|
* Record the caller's verdict on one assistant message. The conversation must
|
|
136
181
|
* be the caller's own: a rating is the user's own signal, and nobody rates
|
|
137
182
|
* someone else's answer on their behalf.
|
|
138
183
|
*/
|
|
139
184
|
rateMessage(token: string, conversationId: string, messageId: string, input: QaMessageFeedbackInput): QaMessageFeedback;
|
|
185
|
+
/**
|
|
186
|
+
* Replay the ratings a browser still holds from the window in which a thumbs
|
|
187
|
+
* never reached the Host.
|
|
188
|
+
*
|
|
189
|
+
* A harvest never overwrites. The browser's map stores no timestamp, so an
|
|
190
|
+
* entry may well be a rating the same user has since filed together with a
|
|
191
|
+
* reason and a comment; replacing that record with the bare thumbs would
|
|
192
|
+
* delete exactly what a reviewer reads. An entry the Host already answers for
|
|
193
|
+
* is counted as present and left alone.
|
|
194
|
+
*
|
|
195
|
+
* One unusable or foreign entry costs that entry alone: a browser keeps
|
|
196
|
+
* ratings of chats it no longer owns, and the rest of the replay must not be
|
|
197
|
+
* lost because of them.
|
|
198
|
+
*/
|
|
199
|
+
harvestFeedback(token: string, entries: readonly QaFeedbackHarvestEntry[]): QaFeedbackHarvestResult;
|
|
140
200
|
feedback(token: string, query: QaFeedbackQuery, cursor: string | undefined, limit: number | undefined): Promise<QaAdminPage<QaFeedbackRow>>;
|
|
141
201
|
private feedbackRows;
|
|
142
202
|
private queueRows;
|
|
143
|
-
reviewQueue(token: string, cursor: string | undefined, limit: number | undefined): Promise<QaAdminPage<QaReviewQueueRow>>;
|
|
203
|
+
reviewQueue(token: string, cursor: string | undefined, limit: number | undefined, signal?: AbortSignal): Promise<QaAdminPage<QaReviewQueueRow>>;
|
|
144
204
|
/** Park a conversation for review without rating it. */
|
|
145
205
|
queueConversation(token: string, conversationId: string, messageId: string | undefined): QaReviewQueueItem;
|
|
146
206
|
/** Save a reviewer's verdict, and take the item out of the queue when done. */
|
|
@@ -179,6 +239,56 @@ export declare class QaAdminService {
|
|
|
179
239
|
removeSkill(token: string, scope: QaAdminSkillScope, name: string, expectedRevision: string | null): Promise<QaSkillRemoval>;
|
|
180
240
|
/** One skill as it exists now; a missing one is the service's refusal. */
|
|
181
241
|
private existingSkill;
|
|
242
|
+
/**
|
|
243
|
+
* The domain-experts maintenance seam, or the refusal that says this stand
|
|
244
|
+
* runs no experts.
|
|
245
|
+
*
|
|
246
|
+
* Reach is host-plane on purpose: the sibling plugin's remotes carry no token
|
|
247
|
+
* and check no permission, because inside the Harness their caller is already
|
|
248
|
+
* a trusted component. This console answers a browser on a LAN port, so it
|
|
249
|
+
* calls the service directly and gates every call with its own `require`.
|
|
250
|
+
*/
|
|
251
|
+
private expertMemory;
|
|
252
|
+
/**
|
|
253
|
+
* Run one memory call, translating the sibling plugin's refusal.
|
|
254
|
+
*
|
|
255
|
+
* The reason crosses the wire, never the message: a memory refusal names
|
|
256
|
+
* namespaces, and a storage failure names the database file behind them.
|
|
257
|
+
*/
|
|
258
|
+
private memoryCall;
|
|
259
|
+
/**
|
|
260
|
+
* What an audit row keeps about one record.
|
|
261
|
+
*
|
|
262
|
+
* A remembered line runs to a few pages, and the trail holds a capped JSON
|
|
263
|
+
* snapshot; the identity of the record and the head of its text is what an
|
|
264
|
+
* operator reads back to decide whether the deletion was wrong.
|
|
265
|
+
*/
|
|
266
|
+
private memoryImage;
|
|
267
|
+
/** The record one key holds now, if it still holds one. */
|
|
268
|
+
private rememberedRecord;
|
|
269
|
+
/** Every expert memory namespace on the stand, with its owner and size. */
|
|
270
|
+
memoryScopes(token: string): Promise<readonly QaExpertMemoryScope[]>;
|
|
271
|
+
/** One page of one namespace, newest first, with the filter's match count. */
|
|
272
|
+
memoryRecords(token: string, namespace: string, query: string, limit: number | null, offset: number): Promise<QaExpertMemoryPage>;
|
|
273
|
+
/**
|
|
274
|
+
* Rewrite one remembered line.
|
|
275
|
+
*
|
|
276
|
+
* The key is not editable: it is what the expert's own notes and the audit
|
|
277
|
+
* trail point at, and a console that renamed it would orphan both. The write
|
|
278
|
+
* refuses a record that vanished meanwhile rather than re-creating it — an
|
|
279
|
+
* operator editing a stale row should reload, not resurrect.
|
|
280
|
+
*/
|
|
281
|
+
correctMemory(token: string, namespace: string, key: string, draft: QaExpertMemoryDraft): Promise<QaExpertMemoryRecord>;
|
|
282
|
+
/**
|
|
283
|
+
* Drop one or several remembered lines.
|
|
284
|
+
*
|
|
285
|
+
* A single deletion keeps the text it removed; a bulk one keeps only the
|
|
286
|
+
* count and the keys, because an audit trail that copies every page of memory
|
|
287
|
+
* it deletes becomes the thing an operator has to clean up.
|
|
288
|
+
*/
|
|
289
|
+
forgetMemory(token: string, namespace: string, keys: readonly string[]): Promise<number>;
|
|
290
|
+
/** Empty one expert's private namespace. */
|
|
291
|
+
wipeMemory(token: string, namespace: string, expectedRecords: number | null): Promise<number>;
|
|
182
292
|
/**
|
|
183
293
|
* The audit trail as one table. Two writers keep records — the capability
|
|
184
294
|
* service, whose repository predates the console, and the quality store —
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { QaAccountProfileInput, QaAccountStartersInput, QaAccountUserPublic, QaIssuedServiceToken, QaOwnershipEntry, QaServiceTokenCreateInput, QaServiceTokenSummary, ResolvedQaSurfaceConfig } from "../types.js";
|
|
1
|
+
import type { QaAccountNotificationsInput, QaAccountProfileInput, QaAccountStartersInput, QaAccountUserPublic, QaIssuedServiceToken, QaOwnershipEntry, QaServiceTokenCreateInput, QaServiceTokenSummary, ResolvedQaSurfaceConfig } from "../types.js";
|
|
2
2
|
import type { QaAccountsApi, QaIntegrationTokenResult, StorageLike } from "./types.js";
|
|
3
3
|
/**
|
|
4
4
|
* What the sign-in card says after a forgotten-password request. It names the
|
|
@@ -23,12 +23,19 @@ export type QaAccountsSnapshot = {
|
|
|
23
23
|
* plus every mapped chat for an admin (the cross-user grouping view).
|
|
24
24
|
*/
|
|
25
25
|
readonly ownedIds: readonly string[];
|
|
26
|
+
/**
|
|
27
|
+
* The account's own chats alone — {@link ownedIds} without the
|
|
28
|
+
* cross-user view. Reading another account's chat is not a claim on its
|
|
29
|
+
* activity, so a surface that reports a chat's state outward is bounded
|
|
30
|
+
* by this list rather than by the sidebar's.
|
|
31
|
+
*/
|
|
32
|
+
readonly ownIds: readonly string[];
|
|
26
33
|
/**
|
|
27
34
|
* The full ownership map; admins only, empty for ordinary accounts and
|
|
28
35
|
* whenever the admin listing was refused or unavailable.
|
|
29
36
|
*/
|
|
30
37
|
readonly ownership: readonly QaOwnershipEntry[];
|
|
31
|
-
/** Bumped whenever ownedIds or ownership changes; re-projects lists. */
|
|
38
|
+
/** Bumped whenever ownedIds, ownIds or ownership changes; re-projects lists. */
|
|
32
39
|
readonly ownedRevision: number;
|
|
33
40
|
};
|
|
34
41
|
/**
|
|
@@ -49,6 +56,17 @@ export interface QaAccountsControllerOptions {
|
|
|
49
56
|
*/
|
|
50
57
|
readonly legacyChatIds?: () => readonly string[];
|
|
51
58
|
readonly forgetChat?: (sessionId: string) => void;
|
|
59
|
+
/**
|
|
60
|
+
* Replay this browser's locally held ratings onto the account it just signed
|
|
61
|
+
* in as, for the chats that account owns. Runs once per account: the surface
|
|
62
|
+
* is usable while it is in flight, and a failure costs only the retry the
|
|
63
|
+
* next login performs.
|
|
64
|
+
*/
|
|
65
|
+
readonly harvestRatings?: (context: {
|
|
66
|
+
readonly token: string;
|
|
67
|
+
readonly accountId: string;
|
|
68
|
+
readonly ownedIds: readonly string[];
|
|
69
|
+
}) => Promise<void>;
|
|
52
70
|
}
|
|
53
71
|
/**
|
|
54
72
|
* Browser-side account lifecycle: token persistence, the checking → gate →
|
|
@@ -71,6 +89,12 @@ export declare class QaAccountsController {
|
|
|
71
89
|
token(): string | null;
|
|
72
90
|
/** Server-owned chat ids (empty until authed); falls back to nothing. */
|
|
73
91
|
ownedIds(): readonly string[];
|
|
92
|
+
/**
|
|
93
|
+
* The chat ids this account owns outright (empty until authed): the set the
|
|
94
|
+
* admin's cross-user view may be wider than, and the scope a turn notice
|
|
95
|
+
* speaks within.
|
|
96
|
+
*/
|
|
97
|
+
ownIds(): readonly string[];
|
|
74
98
|
/** Boot probe: restore the stored token and ask the Host who it is. */
|
|
75
99
|
start(): Promise<void>;
|
|
76
100
|
login(email: string, password: string): Promise<void>;
|
|
@@ -112,6 +136,9 @@ export declare class QaAccountsController {
|
|
|
112
136
|
* created or opened after login enters it here — the next login is not a
|
|
113
137
|
* reasonable price for a chat the visitor is looking at. Ids already known,
|
|
114
138
|
* and the ones an admin's cross-user view contributed, are left as they are.
|
|
139
|
+
*
|
|
140
|
+
* A chat this page claimed is owned outright, so both lists gain it: the
|
|
141
|
+
* sidebar's wider read is not what decides that.
|
|
115
142
|
*/
|
|
116
143
|
private noteOwnedSession;
|
|
117
144
|
/**
|
|
@@ -127,6 +154,13 @@ export declare class QaAccountsController {
|
|
|
127
154
|
* carries the stored record, so the composer picks the new buttons up.
|
|
128
155
|
*/
|
|
129
156
|
updateStarters(input: QaAccountStartersInput): Promise<string | null>;
|
|
157
|
+
/**
|
|
158
|
+
* Replace the signed-in user's own notification channels, mirroring
|
|
159
|
+
* {@link updateStarters}: refusal copy on rejection, null once the snapshot
|
|
160
|
+
* carries the stored record — which is also how the page learns the choice
|
|
161
|
+
* took effect, since it reads the same snapshot the notices plan with.
|
|
162
|
+
*/
|
|
163
|
+
updateNotifications(input: QaAccountNotificationsInput): Promise<string | null>;
|
|
130
164
|
/**
|
|
131
165
|
* The signed-in user's integration tokens. Resolves to the list, or to the
|
|
132
166
|
* copy the page renders when the Host refused the read; the tokens are not
|
|
@@ -145,7 +179,7 @@ export declare class QaAccountsController {
|
|
|
145
179
|
*/
|
|
146
180
|
revokeServiceToken(tokenId: string): Promise<QaIntegrationTokenResult<null>>;
|
|
147
181
|
private authenticate;
|
|
148
|
-
/** Own the account, migrate the legacy index, then
|
|
182
|
+
/** Own the account, migrate the legacy index, replay held ratings, then auth. */
|
|
149
183
|
private enterSession;
|
|
150
184
|
/** Refresh the owned list after index changes; cheap enough to re-pull. */
|
|
151
185
|
refreshOwned(): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ConfigForm } from "@deepseek-ai/dsh-client-ui-settings/client";
|
|
2
2
|
import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "../types.js";
|
|
3
3
|
export interface QaConfigSnapshot {
|
|
4
4
|
readonly status: "loading" | "ready" | "unavailable" | "error";
|
|
@@ -26,7 +26,7 @@ export declare class QaConfigController {
|
|
|
26
26
|
private fallbackState;
|
|
27
27
|
private fallbackConfig;
|
|
28
28
|
private disposed;
|
|
29
|
-
constructor(scope:
|
|
29
|
+
constructor(scope: ConfigForm<QaSurfaceConfig>, fallback?: QaConfigFallback);
|
|
30
30
|
getSnapshot: () => QaConfigSnapshot;
|
|
31
31
|
subscribe: (listener: () => void) => (() => void);
|
|
32
32
|
dispose(): void;
|