@yadsh/dsh-qa-surface 0.13.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.
Files changed (336) hide show
  1. package/README.md +148 -22
  2. package/compatibility.json +7 -3
  3. package/lib/access/capability-catalog.js +22 -6
  4. package/lib/access/capability-catalog.js.map +1 -1
  5. package/lib/access/model.js +36 -2
  6. package/lib/access/model.js.map +1 -1
  7. package/lib/access/service.js +19 -4
  8. package/lib/access/service.js.map +1 -1
  9. package/lib/account-remotes.js +4 -0
  10. package/lib/account-remotes.js.map +1 -1
  11. package/lib/accounts/database.js +49 -9
  12. package/lib/accounts/database.js.map +1 -1
  13. package/lib/accounts/errors.js.map +1 -1
  14. package/lib/accounts/file.js.map +1 -1
  15. package/lib/accounts/store.js +53 -8
  16. package/lib/accounts/store.js.map +1 -1
  17. package/lib/admin/permissions.js +6 -0
  18. package/lib/admin/permissions.js.map +1 -1
  19. package/lib/admin/quality-store.js +95 -19
  20. package/lib/admin/quality-store.js.map +1 -1
  21. package/lib/admin/service.js +178 -0
  22. package/lib/admin/service.js.map +1 -1
  23. package/lib/cli.js +24 -4
  24. package/lib/cli.js.map +1 -1
  25. package/lib/client/QaAccountsController.js +52 -5
  26. package/lib/client/QaAccountsController.js.map +1 -1
  27. package/lib/client/QaConfigController.js.map +1 -1
  28. package/lib/client/QaSessionController.js +626 -63
  29. package/lib/client/QaSessionController.js.map +1 -1
  30. package/lib/client/QaSurface.js +279 -43
  31. package/lib/client/QaSurface.js.map +1 -1
  32. package/lib/client/QaSurfaceGuard.js +2 -2
  33. package/lib/client/QaSurfaceGuard.js.map +1 -1
  34. package/lib/client/QaTranscriptAdapter.js +4 -2
  35. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  36. package/lib/client/admin/QaAdmin.js +59 -34
  37. package/lib/client/admin/QaAdmin.js.map +1 -1
  38. package/lib/client/admin/pages/Conversations.js +12 -12
  39. package/lib/client/admin/pages/Conversations.js.map +1 -1
  40. package/lib/client/admin/pages/ExpertMemory.js +210 -0
  41. package/lib/client/admin/pages/ExpertMemory.js.map +1 -0
  42. package/lib/client/admin/pages/Overview.js +4 -4
  43. package/lib/client/admin/pages/Overview.js.map +1 -1
  44. package/lib/client/admin/pages/Quality.js +5 -5
  45. package/lib/client/admin/pages/Quality.js.map +1 -1
  46. package/lib/client/admin/pages/Review.js +5 -5
  47. package/lib/client/admin/pages/Review.js.map +1 -1
  48. package/lib/client/admin/pages/SkillFiles.js +3 -3
  49. package/lib/client/admin/pages/SkillFiles.js.map +1 -1
  50. package/lib/client/admin/pages/Users.js +12 -12
  51. package/lib/client/admin/pages/Users.js.map +1 -1
  52. package/lib/client/admin/routes.js +4 -0
  53. package/lib/client/admin/routes.js.map +1 -1
  54. package/lib/client/admin/shared.js +15 -6
  55. package/lib/client/admin/shared.js.map +1 -1
  56. package/lib/client/admin/styles.js +3 -0
  57. package/lib/client/admin/styles.js.map +1 -1
  58. package/lib/client/attestation.js +11 -2
  59. package/lib/client/attestation.js.map +1 -1
  60. package/lib/client/audit/QaAuditDialog.js +2 -2
  61. package/lib/client/audit/QaAuditDialog.js.map +1 -1
  62. package/lib/client/audit/QaAuditRowBadge.js +1 -1
  63. package/lib/client/audit/QaAuditRowBadge.js.map +1 -1
  64. package/lib/client/components/Markdown.js +7 -2
  65. package/lib/client/components/Markdown.js.map +1 -1
  66. package/lib/client/components/QaAgentsDrawer.js +7 -5
  67. package/lib/client/components/QaAgentsDrawer.js.map +1 -1
  68. package/lib/client/components/QaApproval.js +2 -2
  69. package/lib/client/components/QaApproval.js.map +1 -1
  70. package/lib/client/components/QaAuthGate.js +6 -6
  71. package/lib/client/components/QaAuthGate.js.map +1 -1
  72. package/lib/client/components/QaChangelog.js +64 -0
  73. package/lib/client/components/QaChangelog.js.map +1 -1
  74. package/lib/client/components/QaComposer.js +9 -6
  75. package/lib/client/components/QaComposer.js.map +1 -1
  76. package/lib/client/components/QaFileAttachment.js +1 -1
  77. package/lib/client/components/QaFileAttachment.js.map +1 -1
  78. package/lib/client/components/QaFilesPanel.js +7 -7
  79. package/lib/client/components/QaFilesPanel.js.map +1 -1
  80. package/lib/client/components/QaHeader.js +4 -4
  81. package/lib/client/components/QaHeader.js.map +1 -1
  82. package/lib/client/components/QaMessage.js +12 -12
  83. package/lib/client/components/QaMessage.js.map +1 -1
  84. package/lib/client/components/QaModal.js +11 -2
  85. package/lib/client/components/QaModal.js.map +1 -1
  86. package/lib/client/components/QaQuestions.js +4 -4
  87. package/lib/client/components/QaQuestions.js.map +1 -1
  88. package/lib/client/components/QaQueueDock.js +137 -0
  89. package/lib/client/components/QaQueueDock.js.map +1 -0
  90. package/lib/client/components/QaRequestQueue.js +22 -0
  91. package/lib/client/components/QaRequestQueue.js.map +1 -0
  92. package/lib/client/components/QaRightRail.js +2 -2
  93. package/lib/client/components/QaRightRail.js.map +1 -1
  94. package/lib/client/components/QaSidebar.js +66 -6
  95. package/lib/client/components/QaSidebar.js.map +1 -1
  96. package/lib/client/components/QaSourcesPanel.js +10 -8
  97. package/lib/client/components/QaSourcesPanel.js.map +1 -1
  98. package/lib/client/components/QaThemeSwitcher.js +19 -0
  99. package/lib/client/components/QaThemeSwitcher.js.map +1 -0
  100. package/lib/client/components/QaTurnNotice.js +40 -0
  101. package/lib/client/components/QaTurnNotice.js.map +1 -0
  102. package/lib/client/components/QaTurnRail.js +3 -3
  103. package/lib/client/components/QaTurnRail.js.map +1 -1
  104. package/lib/client/components/QaWelcomeNotice.js +2 -6
  105. package/lib/client/components/QaWelcomeNotice.js.map +1 -1
  106. package/lib/client/components/QaWidthHandle.js +2 -2
  107. package/lib/client/components/QaWidthHandle.js.map +1 -1
  108. package/lib/client/components/QaWorkGroup.js +5 -5
  109. package/lib/client/components/QaWorkGroup.js.map +1 -1
  110. package/lib/client/components/QaWorkspaceBrowser.js +10 -10
  111. package/lib/client/components/QaWorkspaceBrowser.js.map +1 -1
  112. package/lib/client/components/VariantSwitcher.js +1 -1
  113. package/lib/client/components/VariantSwitcher.js.map +1 -1
  114. package/lib/client/failure-copy.js +26 -8
  115. package/lib/client/failure-copy.js.map +1 -1
  116. package/lib/client/focus-ring.js +193 -0
  117. package/lib/client/focus-ring.js.map +1 -0
  118. package/lib/client/index.js +40 -20
  119. package/lib/client/index.js.map +1 -1
  120. package/lib/client/lineage.js +3 -16
  121. package/lib/client/lineage.js.map +1 -1
  122. package/lib/client/markdown/CodeBlock.js +2 -2
  123. package/lib/client/markdown/CodeBlock.js.map +1 -1
  124. package/lib/client/markdown/blocks.js +118 -31
  125. package/lib/client/markdown/blocks.js.map +1 -1
  126. package/lib/client/markdown/math.js +1 -1
  127. package/lib/client/markdown/math.js.map +1 -1
  128. package/lib/client/markdown/render.js +32 -16
  129. package/lib/client/markdown/render.js.map +1 -1
  130. package/lib/client/markdown/source-chip.js +3 -3
  131. package/lib/client/markdown/source-chip.js.map +1 -1
  132. package/lib/client/notifications/notification-dispatcher.js +90 -0
  133. package/lib/client/notifications/notification-dispatcher.js.map +1 -0
  134. package/lib/client/notifications/preferences.js +61 -0
  135. package/lib/client/notifications/preferences.js.map +1 -0
  136. package/lib/client/notifications/turn-completion-source.js +82 -0
  137. package/lib/client/notifications/turn-completion-source.js.map +1 -0
  138. package/lib/client/notifications/use-turn-notifications.js +108 -0
  139. package/lib/client/notifications/use-turn-notifications.js.map +1 -0
  140. package/lib/client/panels/PanelHost.js +5 -5
  141. package/lib/client/panels/PanelHost.js.map +1 -1
  142. package/lib/client/panels/PanelLauncher.js +2 -2
  143. package/lib/client/panels/PanelLauncher.js.map +1 -1
  144. package/lib/client/project-session-state.js +156 -4
  145. package/lib/client/project-session-state.js.map +1 -1
  146. package/lib/client/role/RoleSelector.js +9 -4
  147. package/lib/client/role/RoleSelector.js.map +1 -1
  148. package/lib/client/settings/card.js +58 -17
  149. package/lib/client/settings/card.js.map +1 -1
  150. package/lib/client/settings/fields.js +11 -10
  151. package/lib/client/settings/fields.js.map +1 -1
  152. package/lib/client/settings/format.js +0 -9
  153. package/lib/client/settings/format.js.map +1 -1
  154. package/lib/client/settings/sections/access.js +5 -5
  155. package/lib/client/settings/sections/access.js.map +1 -1
  156. package/lib/client/settings/sections/accounts.js +10 -10
  157. package/lib/client/settings/sections/accounts.js.map +1 -1
  158. package/lib/client/settings/sections/attachments.js +6 -6
  159. package/lib/client/settings/sections/attachments.js.map +1 -1
  160. package/lib/client/settings/sections/branding.js +7 -7
  161. package/lib/client/settings/sections/branding.js.map +1 -1
  162. package/lib/client/settings/sections/common.js +4 -2
  163. package/lib/client/settings/sections/common.js.map +1 -1
  164. package/lib/client/settings/sections/docs.js +4 -3
  165. package/lib/client/settings/sections/docs.js.map +1 -1
  166. package/lib/client/settings/sections/embedding.js +2 -2
  167. package/lib/client/settings/sections/embedding.js.map +1 -1
  168. package/lib/client/settings/sections/interface.js +12 -12
  169. package/lib/client/settings/sections/interface.js.map +1 -1
  170. package/lib/client/settings/sections/lockdown.js +9 -9
  171. package/lib/client/settings/sections/lockdown.js.map +1 -1
  172. package/lib/client/settings/sections/notes.js +12 -12
  173. package/lib/client/settings/sections/notes.js.map +1 -1
  174. package/lib/client/settings/sections/session.js +15 -12
  175. package/lib/client/settings/sections/session.js.map +1 -1
  176. package/lib/client/settings/sections/slash.js +9 -9
  177. package/lib/client/settings/sections/slash.js.map +1 -1
  178. package/lib/client/settings/sections/sources.js +26 -26
  179. package/lib/client/settings/sections/sources.js.map +1 -1
  180. package/lib/client/settings/sections/status.js +2 -2
  181. package/lib/client/settings/sections/status.js.map +1 -1
  182. package/lib/client/settings/styles.js +15 -9
  183. package/lib/client/settings/styles.js.map +1 -1
  184. package/lib/client/slash/SlashPalette.js +4 -4
  185. package/lib/client/slash/SlashPalette.js.map +1 -1
  186. package/lib/client/styles.js +133 -83
  187. package/lib/client/styles.js.map +1 -1
  188. package/lib/client/theme-preference.js +162 -0
  189. package/lib/client/theme-preference.js.map +1 -0
  190. package/lib/client/types.js +8 -0
  191. package/lib/client/types.js.map +1 -1
  192. package/lib/client/use-session-ui-state.js +7 -5
  193. package/lib/client/use-session-ui-state.js.map +1 -1
  194. package/lib/client/user-settings/GeneralSettingsPage.js +6 -6
  195. package/lib/client/user-settings/GeneralSettingsPage.js.map +1 -1
  196. package/lib/client/user-settings/IntegrationTokensPage.js +6 -6
  197. package/lib/client/user-settings/IntegrationTokensPage.js.map +1 -1
  198. package/lib/client/user-settings/NotificationSettingsPage.js +107 -0
  199. package/lib/client/user-settings/NotificationSettingsPage.js.map +1 -0
  200. package/lib/client/user-settings/PasswordSettingsPage.js +1 -1
  201. package/lib/client/user-settings/PasswordSettingsPage.js.map +1 -1
  202. package/lib/client/user-settings/ProfileSettingsPage.js +2 -2
  203. package/lib/client/user-settings/ProfileSettingsPage.js.map +1 -1
  204. package/lib/client/user-settings/SkillCatalog.js +3 -3
  205. package/lib/client/user-settings/SkillCatalog.js.map +1 -1
  206. package/lib/client/user-settings/SkillEditor.js +26 -8
  207. package/lib/client/user-settings/SkillEditor.js.map +1 -1
  208. package/lib/client/user-settings/SkillToolPicker.js +3 -3
  209. package/lib/client/user-settings/SkillToolPicker.js.map +1 -1
  210. package/lib/client/user-settings/SkillsSettingsPage.js +1 -1
  211. package/lib/client/user-settings/SkillsSettingsPage.js.map +1 -1
  212. package/lib/client/user-settings/StartersSettingsPage.js +6 -6
  213. package/lib/client/user-settings/StartersSettingsPage.js.map +1 -1
  214. package/lib/client/user-settings/UserSettingsDialog.js +7 -2
  215. package/lib/client/user-settings/UserSettingsDialog.js.map +1 -1
  216. package/lib/client/user-settings/copy.js +2 -0
  217. package/lib/client/user-settings/copy.js.map +1 -1
  218. package/lib/client/user-settings/draft.js +4 -1
  219. package/lib/client/user-settings/draft.js.map +1 -1
  220. package/lib/client/user-settings/fields.js +5 -5
  221. package/lib/client/user-settings/fields.js.map +1 -1
  222. package/lib/client.js +7228 -4002
  223. package/lib/client.js.map +1 -1
  224. package/lib/config-resolvers/defaults.js +7 -0
  225. package/lib/config-resolvers/defaults.js.map +1 -1
  226. package/lib/config-resolvers/lockdown.js +7 -0
  227. package/lib/config-resolvers/lockdown.js.map +1 -1
  228. package/lib/config-resolvers/notifications.js +15 -0
  229. package/lib/config-resolvers/notifications.js.map +1 -0
  230. package/lib/config-resolvers/session.js +11 -1
  231. package/lib/config-resolvers/session.js.map +1 -1
  232. package/lib/config.js +67 -18
  233. package/lib/config.js.map +1 -1
  234. package/lib/enforcement/tool-grants.js +6 -6
  235. package/lib/enforcement/tool-grants.js.map +1 -1
  236. package/lib/index.js +145 -30
  237. package/lib/index.js.map +1 -1
  238. package/lib/integration/answer.js +74 -8
  239. package/lib/integration/answer.js.map +1 -1
  240. package/lib/integration/expert-memory.js +39 -0
  241. package/lib/integration/expert-memory.js.map +1 -0
  242. package/lib/integration/host-runner.js +26 -14
  243. package/lib/integration/host-runner.js.map +1 -1
  244. package/lib/notifications.js +66 -0
  245. package/lib/notifications.js.map +1 -0
  246. package/lib/personal-skills/errors.js.map +1 -1
  247. package/lib/personal-skills/service.js +81 -7
  248. package/lib/personal-skills/service.js.map +1 -1
  249. package/lib/prompt-notes.js +2 -10
  250. package/lib/prompt-notes.js.map +1 -1
  251. package/lib/qa-tools/docs-tools.js +1 -1
  252. package/lib/qa-tools/docs-tools.js.map +1 -1
  253. package/lib/qa-tools/lifecycle.js +6 -3
  254. package/lib/qa-tools/lifecycle.js.map +1 -1
  255. package/lib/request-queue.js +32 -0
  256. package/lib/request-queue.js.map +1 -0
  257. package/lib/resolve-config.js +2 -0
  258. package/lib/resolve-config.js.map +1 -1
  259. package/lib/secure-session.js +7 -2
  260. package/lib/secure-session.js.map +1 -1
  261. package/lib/shared/settings.js +19 -2
  262. package/lib/shared/settings.js.map +1 -1
  263. package/lib/turn-failure-log.js +67 -0
  264. package/lib/turn-failure-log.js.map +1 -0
  265. package/lib/typert.host.js +1398 -651
  266. package/lib/typert.remote-client.d.ts +15 -1
  267. package/lib/typert.remote-client.js +1315 -645
  268. package/lib/types/access/capability-catalog.d.ts +20 -4
  269. package/lib/types/access/model.d.ts +23 -0
  270. package/lib/types/access/service.d.ts +2 -3
  271. package/lib/types/account-remotes.d.ts +8 -1
  272. package/lib/types/accounts/database.d.ts +13 -3
  273. package/lib/types/accounts/errors.d.ts +9 -1
  274. package/lib/types/accounts/file.d.ts +12 -0
  275. package/lib/types/accounts/store.d.ts +30 -2
  276. package/lib/types/admin/quality-store.d.ts +33 -0
  277. package/lib/types/admin/service.d.ts +60 -1
  278. package/lib/types/client/QaAccountsController.d.ts +25 -2
  279. package/lib/types/client/QaConfigController.d.ts +2 -2
  280. package/lib/types/client/QaSessionController.d.ts +199 -6
  281. package/lib/types/client/QaSurface.d.ts +6 -1
  282. package/lib/types/client/admin/pages/ExpertMemory.d.ts +19 -0
  283. package/lib/types/client/admin/routes.d.ts +3 -1
  284. package/lib/types/client/admin/shared.d.ts +4 -0
  285. package/lib/types/client/components/Markdown.d.ts +8 -1
  286. package/lib/types/client/components/QaHeader.d.ts +3 -1
  287. package/lib/types/client/components/QaModal.d.ts +7 -0
  288. package/lib/types/client/components/QaQueueDock.d.ts +27 -0
  289. package/lib/types/client/components/QaRequestQueue.d.ts +20 -0
  290. package/lib/types/client/components/QaThemeSwitcher.d.ts +14 -0
  291. package/lib/types/client/components/QaTurnNotice.d.ts +55 -0
  292. package/lib/types/client/focus-ring.d.ts +65 -0
  293. package/lib/types/client/lineage.d.ts +3 -13
  294. package/lib/types/client/markdown/blocks.d.ts +30 -2
  295. package/lib/types/client/markdown/render.d.ts +4 -1
  296. package/lib/types/client/notifications/notification-dispatcher.d.ts +68 -0
  297. package/lib/types/client/notifications/preferences.d.ts +44 -0
  298. package/lib/types/client/notifications/turn-completion-source.d.ts +114 -0
  299. package/lib/types/client/notifications/use-turn-notifications.d.ts +51 -0
  300. package/lib/types/client/project-session-state.d.ts +35 -1
  301. package/lib/types/client/role/RoleSelector.d.ts +7 -1
  302. package/lib/types/client/settings/card.d.ts +36 -5
  303. package/lib/types/client/settings/fields.d.ts +24 -0
  304. package/lib/types/client/settings/format.d.ts +0 -5
  305. package/lib/types/client/settings/sections/common.d.ts +3 -1
  306. package/lib/types/client/settings/sections/session.d.ts +2 -1
  307. package/lib/types/client/settings/styles.d.ts +9 -4
  308. package/lib/types/client/settings-extensions/user-session.d.ts +1 -1
  309. package/lib/types/client/theme-preference.d.ts +69 -0
  310. package/lib/types/client/types.d.ts +25 -1
  311. package/lib/types/client/use-session-ui-state.d.ts +6 -4
  312. package/lib/types/client/user-settings/GeneralSettingsPage.d.ts +5 -5
  313. package/lib/types/client/user-settings/NotificationSettingsPage.d.ts +40 -0
  314. package/lib/types/client/user-settings/UserSettingsDialog.d.ts +12 -2
  315. package/lib/types/client/user-settings/draft.d.ts +4 -1
  316. package/lib/types/client/user-settings/fields.d.ts +7 -0
  317. package/lib/types/config-resolvers/notifications.d.ts +10 -0
  318. package/lib/types/config-resolvers/session.d.ts +6 -0
  319. package/lib/types/config.d.ts +20 -1
  320. package/lib/types/index.d.ts +53 -5
  321. package/lib/types/integration/answer.d.ts +27 -0
  322. package/lib/types/integration/expert-memory.d.ts +49 -0
  323. package/lib/types/notifications.d.ts +32 -0
  324. package/lib/types/personal-skills/errors.d.ts +1 -1
  325. package/lib/types/personal-skills/service.d.ts +6 -0
  326. package/lib/types/prompt-notes.d.ts +17 -4
  327. package/lib/types/request-queue.d.ts +32 -0
  328. package/lib/types/shared/settings.d.ts +19 -2
  329. package/lib/types/turn-failure-log.d.ts +18 -0
  330. package/lib/types/types.d.ts +180 -4
  331. package/package.json +64 -63
  332. package/scripts/attach-workspace-sessions.mjs +24 -5
  333. package/scripts/repair-session-events.mjs +25 -5
  334. package/lib/client/markdown/MermaidBlock.js +0 -80
  335. package/lib/client/markdown/MermaidBlock.js.map +0 -1
  336. package/lib/types/client/markdown/MermaidBlock.d.ts +0 -6
@@ -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<ScopeKey | undefined>);
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 pins
49
- * QA chats to an agent preset gets that preset's standing scope; without a
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<ScopeKey | undefined>;
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
- /** Take the current data version as the baseline a caller's model reflects. */
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
- /** The account behind a token, or an auth-required refusal. */
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,8 +2,9 @@ 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, QaFeedbackHarvestEntry, QaFeedbackHarvestResult, 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 { QaDomainExpertsFace } from "../integration/expert-memory.js";
7
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";
@@ -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;
@@ -230,6 +239,56 @@ export declare class QaAdminService {
230
239
  removeSkill(token: string, scope: QaAdminSkillScope, name: string, expectedRevision: string | null): Promise<QaSkillRemoval>;
231
240
  /** One skill as it exists now; a missing one is the service's refusal. */
232
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>;
233
292
  /**
234
293
  * The audit trail as one table. Two writers keep records — the capability
235
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
  /**
@@ -82,6 +89,12 @@ export declare class QaAccountsController {
82
89
  token(): string | null;
83
90
  /** Server-owned chat ids (empty until authed); falls back to nothing. */
84
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[];
85
98
  /** Boot probe: restore the stored token and ask the Host who it is. */
86
99
  start(): Promise<void>;
87
100
  login(email: string, password: string): Promise<void>;
@@ -123,6 +136,9 @@ export declare class QaAccountsController {
123
136
  * created or opened after login enters it here — the next login is not a
124
137
  * reasonable price for a chat the visitor is looking at. Ids already known,
125
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.
126
142
  */
127
143
  private noteOwnedSession;
128
144
  /**
@@ -138,6 +154,13 @@ export declare class QaAccountsController {
138
154
  * carries the stored record, so the composer picks the new buttons up.
139
155
  */
140
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>;
141
164
  /**
142
165
  * The signed-in user's integration tokens. Resolves to the list, or to the
143
166
  * copy the page renders when the Host refused the read; the tokens are not
@@ -1,4 +1,4 @@
1
- import type { SettingsScope } from "@deepseek-ai/dsh-client-ui-settings/client";
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: SettingsScope<QaSurfaceConfig>, fallback?: QaConfigFallback);
29
+ constructor(scope: ConfigForm<QaSurfaceConfig>, fallback?: QaConfigFallback);
30
30
  getSnapshot: () => QaConfigSnapshot;
31
31
  subscribe: (listener: () => void) => (() => void);
32
32
  dispose(): void;