@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
@@ -3,7 +3,7 @@ import type { QaAccountsController } from "../QaAccountsController.js";
3
3
  * The signed-in QA account, as a client service.
4
4
  *
5
5
  * A QA panel plugin receives the account token through its panel props. A card
6
- * mounted in the host's own settings (`settings.plugin.item`) has no panel to
6
+ * seated on the Host's Plugins panel (`plugins.row.config`) has no panel to
7
7
  * read it from, so this service is the one place such a surface asks whether a
8
8
  * QA account is signed in and obtains the bearer credential the
9
9
  * principal-scoped QA remotes authorize with.
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The palette the surface paints with. The Host owns the same three
3
+ * preferences and applies the one it stores; its settings surface is not
4
+ * reachable from `/qa` — the overlay suppresses the native shell, and the
5
+ * kiosk never mounts it — so the QA page carries its own choice.
6
+ *
7
+ * The choice is browser-local on purpose: it is written to this deployment's
8
+ * localStorage namespace, never to the Host user-settings document, because a
9
+ * stand is shared by everyone who opens it and one visitor's eyes are not a
10
+ * deployment setting.
11
+ */
12
+ /** The preferences the control offers — the same vocabulary the Host uses. */
13
+ export declare const QA_THEME_PREFERENCES: readonly ["light", "dark", "system"];
14
+ export type QaThemePreference = (typeof QA_THEME_PREFERENCES)[number];
15
+ /** Body attribute that selects the dark palette in the Host token sheet. */
16
+ export declare const QA_DARK_THEME_ATTRIBUTE = "data-ds-dark-theme";
17
+ /** `light`/`dark` are themselves; `system` is whatever the OS asks for. */
18
+ export declare function resolveQaThemeScheme(preference: QaThemePreference, systemDark: boolean): "light" | "dark";
19
+ /** The stored choice, or null when this browser never picked one. */
20
+ export declare function readQaThemePreference(storage: Pick<Storage, "getItem">, key: string): QaThemePreference | null;
21
+ export declare function writeQaThemePreference(storage: Pick<Storage, "setItem">, key: string, preference: QaThemePreference): void;
22
+ /**
23
+ * What the control shows while this browser has no choice of its own: the
24
+ * palette the document is already painted with, read through the Host's own
25
+ * contract. The Host publishes its *preference* nowhere in the DOM — only the
26
+ * resolved palette — so an untouched stand is reported as the palette it
27
+ * shows, never as a preference this browser did not pick.
28
+ */
29
+ export declare function readQaThemeScheme(target: Pick<QaThemeDocument, "body">): Exclude<QaThemePreference, "system">;
30
+ /** The two document nodes the palette hangs on, injectable for tests. */
31
+ export interface QaThemeDocument {
32
+ readonly documentElement: {
33
+ style: {
34
+ colorScheme: string;
35
+ };
36
+ };
37
+ readonly body: {
38
+ hasAttribute: (name: string) => boolean;
39
+ setAttribute: (name: string, value: string) => void;
40
+ removeAttribute: (name: string) => void;
41
+ };
42
+ }
43
+ /**
44
+ * Project one preference onto the document, writing exactly the two fields the
45
+ * Host's own presenter owns for the same choice: the native-chrome scheme on
46
+ * the root and the palette attribute on the body. Nothing else — the font-size
47
+ * axis and the theme token overrides stay the Host's.
48
+ */
49
+ export declare function applyQaThemePreference(target: QaThemeDocument, preference: QaThemePreference, systemDark: boolean): void;
50
+ export interface QaThemePreferenceState {
51
+ /** The choice this browser owns, or the palette it is looking at. */
52
+ readonly preference: QaThemePreference;
53
+ readonly select: (preference: QaThemePreference) => void;
54
+ }
55
+ export interface UseQaThemePreferenceOptions {
56
+ /** Whether the surface is what the visitor is looking at right now. */
57
+ readonly active: boolean;
58
+ readonly storage: Pick<Storage, "getItem" | "setItem">;
59
+ readonly storageKey: string;
60
+ }
61
+ /**
62
+ * Own the palette for as long as the surface is what the visitor sees, and only
63
+ * for as long as this browser actually asked for one: an explicit choice is
64
+ * written to storage and projected onto the document, `system` keeps answering
65
+ * the OS, and a visitor who never touches the control leaves the Host's own
66
+ * palette in force — the surface writes nothing at all in that case.
67
+ */
68
+ export declare function useQaThemePreference({ active, storage, storageKey, }: UseQaThemePreferenceOptions): QaThemePreferenceState;
69
+ //# sourceMappingURL=theme-preference.d.ts.map
@@ -1,7 +1,7 @@
1
1
  import type { ClientRemote } from "@deepseek-ai/dsh-api-gateway/client";
2
2
  import type { ISessions, SessionFace } from "@deepseek-ai/dsh-api-session-controller/client";
3
3
  import type { UiConversation } from "@deepseek-ai/dsh-client-ui-conversation/client";
4
- import type { QaAccountProfileInput, QaAccountSession, QaAccountStartersInput, QaAccountStarter, QaAccountUserPublic, QaAccessAdminSnapshot, QaApprovalDecision, QaClaimResult, QaLockdownProof, QaOwnershipEntry, QaPasswordResetRequest, QaPendingApproval, QaPendingQuestion, QaQuestionAnswerItem, QaIssuedServiceToken, QaServiceTokenCreateInput, QaServiceTokenSummary, QaSessionState, QaSkillDocument, QaSkillDraftInput, QaSkillRemoval, QaSkillSummary, QaSkillToolDescriptor, QaSkillValidation, QaSourceFilePreview, QaTurnSources, QaWhoamiResult, QaDocumentPreview, QaWorkspaceFile, QaWorkspaceListing, QaCapabilitySelection, QaCurrentAccess, QaSessionAccess, QaSkillActivationRecord, QaSkillAssignmentOverride, QaSubrole, QaUserAccess, QaAdminAuditEvent, QaAdminOverview, QaAdminPage, QaAdminSkillScope, QaAdminSkillsView, QaAdminUserDetail, QaAdminUserRow, QaAdminUserUpdate, QaAuditQuery, QaConversationDetail, QaConversationDeletion, QaConversationQuery, QaConversationReview, QaConversationReviewInput, QaConversationSummary, QaFeedbackQuery, QaFeedbackRow, QaMessageFeedback, QaMessageFeedbackInput, QaQualityMetrics, QaReviewQueueItem, QaReviewQueueRow, QaSlashCatalog, QaSlashExecution, QaSlashSubmitAttachment, QaUserQuery } from "../types.js";
4
+ import type { QaAccountNotificationsInput, QaAccountProfileInput, QaAccountSession, QaAccountStartersInput, QaAccountStarter, QaAccountUserPublic, QaAccessAdminSnapshot, QaApprovalDecision, QaClaimResult, QaLockdownProof, QaOwnershipEntry, QaPasswordResetRequest, QaPendingApproval, QaPendingQuestion, QaQuestionAnswerItem, QaQueueStatus, QaIssuedServiceToken, QaServiceTokenCreateInput, QaServiceTokenSummary, QaSessionState, QaSkillDocument, QaSkillDraftInput, QaSkillRemoval, QaSkillSummary, QaSkillToolDescriptor, QaSkillValidation, QaSourceFilePreview, QaTurnSources, QaWhoamiResult, QaDocumentPreview, QaWorkspaceFile, QaWorkspaceListing, QaCapabilitySelection, QaCurrentAccess, QaSessionAccess, QaSkillActivationRecord, QaSkillAssignmentOverride, QaSubrole, QaUserAccess, QaAdminAuditEvent, QaAdminOverview, QaAdminPage, QaAdminSkillScope, QaAdminSkillsView, QaAdminUserDetail, QaAdminUserRow, QaAdminUserUpdate, QaAuditQuery, QaConversationDetail, QaConversationDeletion, QaConversationQuery, QaConversationReview, QaConversationReviewInput, QaConversationSummary, QaExpertMemoryDraft, QaExpertMemoryPage, QaExpertMemoryRecord, QaExpertMemoryScope, QaFeedbackQuery, QaFeedbackRow, QaMessageFeedback, QaMessageFeedbackInput, QaQualityMetrics, QaReviewQueueItem, QaReviewQueueRow, QaSlashCatalog, QaSlashExecution, QaSlashSubmitAttachment, QaUserQuery } from "../types.js";
5
5
  /** Wire content one prompt carries: text plus base64 image uploads. */
6
6
  export type QaPromptContent = Parameters<SessionFace["prompt"]>[0];
7
7
  /** DSH session runtime surface the QA controller is allowed to touch. */
@@ -30,6 +30,12 @@ export type QaSecureSession = (token: string, sessionId: string) => Promise<{
30
30
  }>;
31
31
  /** Host-authoritative creation: identity, cwd and policy never come from the browser. */
32
32
  export type QaCreateSession = (token: string, subroleId: string | null, adminPreview: boolean) => Promise<RemoteResult<string>>;
33
+ /**
34
+ * The Host's live read of the request ceiling (`qaSurface/queueStatus`), asked
35
+ * per send: how many questions the stand is answering and whether one more
36
+ * fits.
37
+ */
38
+ export type QaQueueStatusRemote = () => Promise<RemoteResult<QaQueueStatus>>;
33
39
  /** Role selector plus administrator mutation channel. */
34
40
  export interface QaAccessApi {
35
41
  current(token: string): Promise<RemoteResult<QaCurrentAccess>>;
@@ -100,6 +106,18 @@ export interface QaAdminApi {
100
106
  deleteSkill(token: string, scope: QaAdminSkillScope, name: string, expectedRevision: string | null): Promise<RemoteResult<QaSkillRemoval>>;
101
107
  validateSkill(token: string, scope: QaAdminSkillScope, name: string | null, input: QaSkillDraftInput): Promise<RemoteResult<QaSkillValidation>>;
102
108
  skillTools(token: string, scope: QaAdminSkillScope): Promise<RemoteResult<readonly QaSkillToolDescriptor[]>>;
109
+ /**
110
+ * What the domain experts remembered.
111
+ *
112
+ * The namespaces come from the experts' own definitions, so a namespace the
113
+ * console can list is one an expert claims; `memory.read` opens the list and
114
+ * `memory.manage` the corrections.
115
+ */
116
+ memoryScopes(token: string): Promise<RemoteResult<readonly QaExpertMemoryScope[]>>;
117
+ memoryRecords(token: string, namespace: string, query: string, limit: number | null, offset: number): Promise<RemoteResult<QaExpertMemoryPage>>;
118
+ correctMemory(token: string, namespace: string, key: string, draft: QaExpertMemoryDraft): Promise<RemoteResult<QaExpertMemoryRecord>>;
119
+ forgetMemory(token: string, namespace: string, keys: readonly string[]): Promise<RemoteResult<number>>;
120
+ wipeMemory(token: string, namespace: string, expectedRecords: number | null): Promise<RemoteResult<number>>;
103
121
  }
104
122
  /**
105
123
  * Browser file-upload service (`ctx.fileUpload`), described structurally on
@@ -333,6 +351,12 @@ export interface QaAccountsApi {
333
351
  accountsUpdateProfile(token: string, input: QaAccountProfileInput): Promise<RemoteResult<QaAccountUserPublic>>;
334
352
  /** Replace the caller's own starter buttons; the token is the identity. */
335
353
  accountsUpdateStarters(token: string, input: QaAccountStartersInput): Promise<RemoteResult<QaAccountUserPublic>>;
354
+ /**
355
+ * Replace the caller's own notification channels; the token is the identity.
356
+ * The stand's switches are applied when a notice is planned, not here, so
357
+ * this write can only ever narrow what the deployment allows.
358
+ */
359
+ accountsUpdateNotifications(token: string, input: QaAccountNotificationsInput): Promise<RemoteResult<QaAccountUserPublic>>;
336
360
  /**
337
361
  * Replace the caller's own password. The answer carries a fresh token: the
338
362
  * write bumps the account's token version, so without it the browser that
@@ -33,9 +33,11 @@ export interface QaSessionUiState {
33
33
  }
34
34
  /**
35
35
  * Per-chat UI state: composer attachments, variant offsets, the rail mark and
36
- * the drawers. Everything here describes the chat it was made in, so a
37
- * session change clears it instead of leaking a draft, an attachment or a
38
- * drawer from one conversation into the next.
36
+ * the drawers. Everything here describes the chat it was made in, so a chat
37
+ * change clears it instead of leaking a draft, an attachment or a drawer from
38
+ * one conversation into the next. The key is the surface's chat identity, not
39
+ * the session id: a new chat only creates its session on the first prompt, and
40
+ * the attachments of that prompt must survive the hand-off.
39
41
  */
40
- export declare function useSessionUiState(sessionId: string | null): QaSessionUiState;
42
+ export declare function useSessionUiState(chatKey: number): QaSessionUiState;
41
43
  //# sourceMappingURL=use-session-ui-state.d.ts.map
@@ -5,11 +5,11 @@ export interface QaGeneralSettingsPageProps {
5
5
  }
6
6
  /**
7
7
  * Placeholder with a purpose: the section exists so the dialog has a home for
8
- * the user-scoped preferences that follow (notifications, privacy), and so the
9
- * thing it must not become is written down — deployment and chat policy live in
10
- * the Host settings, not here. It shows the account facts a user can act on
11
- * today and nothing invented, and it names only what is still missing: a
12
- * preference that already has its own tab does not belong on this list.
8
+ * the user-scoped preferences that follow (privacy), and so the thing it must
9
+ * not become is written down — deployment and chat policy live in the Host
10
+ * settings, not here. It shows the account facts a user can act on today and
11
+ * nothing invented, and it names only what is still missing: a preference that
12
+ * already has its own tab does not belong on this list.
13
13
  */
14
14
  export declare function QaGeneralSettingsPage(props: QaGeneralSettingsPageProps): import("react/jsx-runtime").JSX.Element;
15
15
  //# sourceMappingURL=GeneralSettingsPage.d.ts.map
@@ -0,0 +1,40 @@
1
+ import type { QaAccountNotifications, QaAccountNotificationsInput, ResolvedQaSurfaceConfig } from "../../types.js";
2
+ export interface QaNotificationSettingsPageProps {
3
+ /** The channels this account has chosen. */
4
+ readonly notifications: QaAccountNotifications;
5
+ /** `config.notifications`: what the stand allows whatever the reader picks. */
6
+ readonly switches: ResolvedQaSurfaceConfig["notifications"];
7
+ /** Persist the edited pair; resolves to refusal copy, or null. */
8
+ readonly onSave: (input: QaAccountNotificationsInput) => Promise<string | null>;
9
+ }
10
+ export declare const QA_NOTIFICATION_SETTINGS_COPY: Readonly<{
11
+ title: "Уведомления";
12
+ lead: "Напоминание о завершённом ходе доходит до вас, даже когда вы читаете другой чат.";
13
+ inApp: "Строка «Ход завершён» на странице";
14
+ inAppHint: "Появляется, когда ход закончился в чате, который вы сейчас не читаете; клик открывает его.";
15
+ desktop: "Системные уведомления";
16
+ desktopHint: "Приходят, когда эта вкладка свёрнута или закрыта другим окном. В самом чате, который открыт перед вами, ничего не появляется.";
17
+ offOnStand: "Уведомления о завершённых ходах выключены на этом стенде администратором.";
18
+ desktopOffOnStand: "Системные уведомления выключены на этом стенде: строка на странице остаётся.";
19
+ unsupported: "Браузер этого устройства не умеет системные уведомления: напоминание останется на странице.";
20
+ denied: "Браузер запретил уведомления для этого адреса. Разрешите их в его собственных настройках — до этого напоминание останется только на странице.";
21
+ askAction: "Разрешить в браузере";
22
+ askHint: "Браузер спросит разрешение один раз, по этому нажатию; больше вопрос не вернётся.";
23
+ granted: "Браузер разрешил уведомления для этого адреса.";
24
+ saved: "Настройки уведомлений сохранены.";
25
+ }>;
26
+ /**
27
+ * The signed-in reader's own answer about the channels a finished turn may use.
28
+ *
29
+ * Two switches, because that is how many the feature has: the line inside the
30
+ * page and the notice the page hands to the operating system. What the stand
31
+ * allows is a third voice over each of them and is shown rather than hidden —
32
+ * a control that silently does nothing reads as a bug, and the reader is the
33
+ * one person who should not have to guess whose decision it was.
34
+ *
35
+ * Same full-replace contract as the starters form: the pair is seeded from the
36
+ * stored record whenever that record changes, so a write from another tab never
37
+ * leaves a stale edit on screen.
38
+ */
39
+ export declare function QaNotificationSettingsPage(props: QaNotificationSettingsPageProps): import("react/jsx-runtime").JSX.Element;
40
+ //# sourceMappingURL=NotificationSettingsPage.d.ts.map
@@ -1,8 +1,8 @@
1
- import type { QaAccountIdentityField, QaAccountProfile, QaAccountProfileInput, QaAccountStarters, QaAccountStartersInput } from "../../types.js";
1
+ import type { QaAccountIdentityField, QaAccountNotifications, QaAccountNotificationsInput, QaAccountProfile, QaAccountProfileInput, QaAccountStarters, QaAccountStartersInput, ResolvedQaSurfaceConfig } from "../../types.js";
2
2
  import type { QaBoundSkillApi, QaIntegrationTokenApi } from "../types.js";
3
3
  import type { QaUserSettingsSections } from "../settings-extensions/index.js";
4
4
  /** Sections of the user-facing settings dialog. */
5
- export type QaSettingsSectionId = "profile" | "password" | "starters" | "tokens" | "general" | "skills" | (string & {});
5
+ export type QaSettingsSectionId = "profile" | "password" | "starters" | "notifications" | "tokens" | "general" | "skills" | (string & {});
6
6
  export interface QaUserSettingsDialogProps {
7
7
  readonly open: boolean;
8
8
  /** Section to show when the dialog opens. */
@@ -30,6 +30,16 @@ export interface QaUserSettingsDialogProps {
30
30
  readonly starters: QaAccountStarters;
31
31
  readonly onSave: (input: QaAccountStartersInput) => Promise<string | null>;
32
32
  };
33
+ /**
34
+ * Self-service notification channels. Absent only where there is no account
35
+ * to hold the choice: an anonymous stand keeps its mute switch in the
36
+ * browser, and the notices read it from there.
37
+ */
38
+ readonly notifications?: {
39
+ readonly notifications: QaAccountNotifications;
40
+ readonly switches: ResolvedQaSurfaceConfig["notifications"];
41
+ readonly onSave: (input: QaAccountNotificationsInput) => Promise<string | null>;
42
+ };
33
43
  /** Integration tokens; absent when accounts are off altogether. */
34
44
  readonly integrationTokens?: QaIntegrationTokenApi;
35
45
  /** Personal skills; absent when the deployment cannot host them. */
@@ -38,7 +38,10 @@ export interface QaSkillDraftDiagnostics {
38
38
  export declare function draftDiagnostics(draft: QaSkillDraft, options: QaSkillDraftDiagnostics): readonly QaSkillDiagnostic[];
39
39
  /** Whether the draft is complete enough to send. */
40
40
  export declare function draftIsSavable(draft: QaSkillDraft): boolean;
41
- export declare function draftInput(draft: QaSkillDraft, revision: string | null): QaSkillDraftInput;
41
+ export declare function draftInput(draft: QaSkillDraft, revision: string | null, options?: {
42
+ /** Say so when saving over a file the Host could not read whole. */
43
+ readonly confirmPartialOverwrite?: boolean;
44
+ }): QaSkillDraftInput;
42
45
  /** The terse line under a catalog row: invocation, command, tool count. */
43
46
  export declare function skillMetaLine(skill: QaSkillSummary): string;
44
47
  /** Tools the catalog cannot use right now, as the row's warning text. */
@@ -7,6 +7,8 @@ import type { ReactNode } from "react";
7
7
  * the deployment settings.
8
8
  */
9
9
  export interface QaSettingsFieldProps {
10
+ /** Handle this instance is addressed by from a browser run. */
11
+ readonly testId: string;
10
12
  readonly label: string;
11
13
  /** Secondary line under the control; not part of the field's name. */
12
14
  readonly hint?: string;
@@ -14,11 +16,13 @@ export interface QaSettingsFieldProps {
14
16
  }
15
17
  export declare function QaSettingsField(props: QaSettingsFieldProps): import("react/jsx-runtime").JSX.Element;
16
18
  export declare function QaSettingsSection(props: {
19
+ readonly testId: string;
17
20
  readonly title: string;
18
21
  readonly aside?: ReactNode;
19
22
  readonly children: ReactNode;
20
23
  }): import("react/jsx-runtime").JSX.Element;
21
24
  export declare function QaSettingsToggle(props: {
25
+ readonly testId: string;
22
26
  readonly label: string;
23
27
  readonly checked: boolean;
24
28
  readonly disabled?: boolean;
@@ -26,6 +30,7 @@ export declare function QaSettingsToggle(props: {
26
30
  readonly onChange: (checked: boolean) => void;
27
31
  }): import("react/jsx-runtime").JSX.Element;
28
32
  export declare function QaSettingsNotice(props: {
33
+ readonly testId: string;
29
34
  readonly tone: "info" | "warn" | "error";
30
35
  readonly children: ReactNode;
31
36
  }): import("react/jsx-runtime").JSX.Element;
@@ -33,6 +38,8 @@ export declare function QaSettingsActions(props: {
33
38
  readonly children: ReactNode;
34
39
  }): import("react/jsx-runtime").JSX.Element;
35
40
  export declare function QaSettingsButton(props: {
41
+ /** Omitted for a button the settings dialog does not own, such as the sidebar's. */
42
+ readonly testId?: string;
36
43
  readonly label: string;
37
44
  readonly tone?: "primary" | "plain" | "danger";
38
45
  readonly type?: "button" | "submit";
@@ -0,0 +1,10 @@
1
+ import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "../types.js";
2
+ type NotificationsSlice = ResolvedQaSurfaceConfig["notifications"];
3
+ /**
4
+ * Resolve the notification domain: the deployment's two switches over the
5
+ * notices a finished turn may raise. Which chats a notice is allowed to speak
6
+ * about is not a configuration question — it is the browser's own chat list.
7
+ */
8
+ export declare function resolveNotifications(input: QaSurfaceConfig): NotificationsSlice;
9
+ export {};
10
+ //# sourceMappingURL=notifications.d.ts.map
@@ -1,5 +1,11 @@
1
1
  import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "../types.js";
2
2
  type SessionSlice = ResolvedQaSurfaceConfig["session"];
3
+ /**
4
+ * Ceiling of `session.maxActiveRequests`. The floor is 0 — "no ceiling" — and
5
+ * the cap only keeps a mistyped value from becoming a silently meaningless
6
+ * one: a stand that answers sixty chat turns at once has no queue to configure.
7
+ */
8
+ export declare const QA_MAX_ACTIVE_REQUESTS_MAX = 50;
3
9
  /** Resolve the session domain: policy, pinning, and model selection. */
4
10
  export declare function resolveSession(input: QaSurfaceConfig): SessionSlice;
5
11
  export {};
@@ -1,3 +1,4 @@
1
+ import type { Volatile } from "@deepseek-ai/cordis";
1
2
  import z from "@deepseek-ai/schemastery";
2
3
  import type { QaSurfaceConfig } from "./types.js";
3
4
  /**
@@ -10,6 +11,24 @@ import type { QaSurfaceConfig } from "./types.js";
10
11
  * `../package.json` resolves at.
11
12
  */
12
13
  export declare function qaSurfaceVersion(): string;
13
- export declare const ConfigSchema: z<QaSurfaceConfig>;
14
+ /**
15
+ * Every top-level field of {@link QaSurfaceConfig}, as the Host delivers it.
16
+ *
17
+ * A field whose schema node carries `.volatile()` arrives as a stable reference
18
+ * whose snapshot the Host swaps in place, so a plugin keeps one reference for
19
+ * its whole lifetime and reads the current value through it.
20
+ */
21
+ export type QaSurfaceConfigRefs = {
22
+ readonly [K in keyof Required<QaSurfaceConfig>]: Volatile<NonNullable<QaSurfaceConfig[K]>>;
23
+ };
24
+ /**
25
+ * Fold one Host-delivered Config into the plain data `resolveConfig` reads.
26
+ *
27
+ * The schema mints a volatile reference for every field it declares volatile, so
28
+ * the object the plugin is constructed with carries references and each read
29
+ * here answers with the value the Host currently holds.
30
+ */
31
+ export declare function readConfigRefs(config: Partial<QaSurfaceConfigRefs>): QaSurfaceConfig;
32
+ export declare const ConfigSchema: z<QaSurfaceConfigRefs>;
14
33
  export { DEFAULT_QA_SURFACE_CONFIG, normalizeRoutePath, resolveConfig, } from "./resolve-config.js";
15
34
  //# sourceMappingURL=config.d.ts.map
@@ -1,12 +1,14 @@
1
1
  import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
2
2
  import type { Context } from "@deepseek-ai/cordis";
3
+ import type { QaSurfaceConfigRefs } from "./config.js";
4
+ import type { QaAccountNotificationsInput } from "./types.js";
3
5
  import type { QaTurnSources } from "./provenance/types.js";
4
- import type { QaAccountProfileInput, QaAccountSession, QaAccountStartersInput, QaAccountUserPublic, QaApprovalDecision, QaClaimResult, QaDocumentPreview, QaIssuedServiceToken, QaLockdownProof, QaOwnershipEntry, QaPasswordResetRequest, QaPendingApproval, QaPendingQuestion, QaQuestionAnswerItem, QaServiceTokenCreateInput, QaServiceTokenSummary, QaSurfaceConfig, ResolvedQaSurfaceConfig, QaAdminSkillScope, QaAdminSkillsView, QaSkillDocument, QaSkillDraftInput, QaSkillRemoval, QaSkillSummary, QaSkillToolDescriptor, QaSkillValidation, QaSourceFilePreview, QaWhoamiResult, QaWorkspaceFile, QaWorkspaceListing, QaPrincipal, QaAccessAdminSnapshot, QaAdminAuditEvent, QaAdminOverview, QaAdminPage, QaAdminUserDetail, QaAdminUserRow, QaAdminUserUpdate, QaAuditQuery, QaCapabilitySelection, QaConversationDetail, QaConversationDeletion, QaConversationQuery, QaConversationReview, QaConversationReviewInput, QaConversationSummary, QaCurrentAccess, QaFeedbackHarvestEntry, QaFeedbackHarvestResult, QaFeedbackQuery, QaFeedbackRow, QaMessageFeedback, QaMessageFeedbackInput, QaQualityMetrics, QaReviewQueueItem, QaReviewQueueRow, QaSessionAccess, QaSlashCatalog, QaSlashExecution, QaSlashSubmitAttachment, QaSkillActivationRecord, QaSkillAssignmentOverride, QaSubrole, QaUserAccess, QaUserQuery } from "./types.js";
6
+ import type { QaAccountProfileInput, QaAccountSession, QaAccountStartersInput, QaAccountUserPublic, QaApprovalDecision, QaClaimResult, QaDocumentPreview, QaIssuedServiceToken, QaLockdownProof, QaOwnershipEntry, QaPasswordResetRequest, QaPendingApproval, QaPendingQuestion, QaQuestionAnswerItem, QaQueueStatus, QaServiceTokenCreateInput, QaServiceTokenSummary, ResolvedQaSurfaceConfig, QaAdminSkillScope, QaAdminSkillsView, QaExpertMemoryDraft, QaExpertMemoryPage, QaExpertMemoryRecord, QaExpertMemoryScope, QaSkillDocument, QaSkillDraftInput, QaSkillRemoval, QaSkillSummary, QaSkillToolDescriptor, QaSkillValidation, QaSourceFilePreview, QaWhoamiResult, QaWorkspaceFile, QaWorkspaceListing, QaPrincipal, QaAccessAdminSnapshot, QaAdminAuditEvent, QaAdminOverview, QaAdminPage, QaAdminUserDetail, QaAdminUserRow, QaAdminUserUpdate, QaAuditQuery, QaCapabilitySelection, QaConversationDetail, QaConversationDeletion, QaConversationQuery, QaConversationReview, QaConversationReviewInput, QaConversationSummary, QaCurrentAccess, QaFeedbackHarvestEntry, QaFeedbackHarvestResult, QaFeedbackQuery, QaFeedbackRow, QaMessageFeedback, QaMessageFeedbackInput, QaQualityMetrics, QaReviewQueueItem, QaReviewQueueRow, QaSessionAccess, QaSlashCatalog, QaSlashExecution, QaSlashSubmitAttachment, QaSkillActivationRecord, QaSkillAssignmentOverride, QaSubrole, QaUserAccess, QaUserQuery } from "./types.js";
5
7
  export declare const name = "qa-surface";
6
8
  export declare const inject: string[];
7
9
  import { QA_SURFACE_SETTINGS_NAMESPACE } from "./shared/settings.js";
8
10
  export { QA_SURFACE_SETTINGS_NAMESPACE };
9
- export declare const Config: import("@deepseek-ai/schemastery").default<QaSurfaceConfig>;
11
+ export declare const Config: import("@deepseek-ai/schemastery").default<QaSurfaceConfigRefs>;
10
12
  declare module "@deepseek-ai/cordis" {
11
13
  interface Context {
12
14
  qaSurface: QaSurface;
@@ -15,8 +17,8 @@ declare module "@deepseek-ai/cordis" {
15
17
  /** Host companion: validates config, owns the admission boundary and the route. */
16
18
  export declare class QaSurface extends TypertRemoteService {
17
19
  static inject: string[];
18
- static Config: import("@deepseek-ai/schemastery").default<QaSurfaceConfig>;
19
- private source;
20
+ static Config: import("@deepseek-ai/schemastery").default<QaSurfaceConfigRefs>;
21
+ private readonly source;
20
22
  private readonly logger;
21
23
  private readonly admission;
22
24
  private readonly approvals;
@@ -64,7 +66,7 @@ export declare class QaSurface extends TypertRemoteService {
64
66
  * opens the admin console never grows one.
65
67
  */
66
68
  private qualityStore;
67
- constructor(ctx: Context, entry?: QaSurfaceConfig);
69
+ constructor(ctx: Context, entry?: Partial<QaSurfaceConfigRefs>);
68
70
  /** The quality store, opening its file the first time anyone needs it. */
69
71
  private quality;
70
72
  /**
@@ -75,6 +77,9 @@ export declare class QaSurface extends TypertRemoteService {
75
77
  * the preset composes it but starts no agent, no session and no turn;
76
78
  * without a pinned preset there is nothing to borrow, and the read stays
77
79
  * global.
80
+ *
81
+ * The registry answers with a lease on one preset revision, so the scope is
82
+ * handed to the caller that reads with it and released when that read ends.
78
83
  */
79
84
  private qaPresetScope;
80
85
  /**
@@ -157,6 +162,13 @@ export declare class QaSurface extends TypertRemoteService {
157
162
  * deployment's limits are enforced in the store before anything is written.
158
163
  */
159
164
  accountsUpdateStarters(token: string, input: QaAccountStartersInput): QaAccountUserPublic;
165
+ /**
166
+ * Replace the caller's own notification channels. The account the token
167
+ * authenticates is the only one editable, and the answer is the whole public
168
+ * record, so the settings form re-reads what the stand now holds rather than
169
+ * what it meant to send.
170
+ */
171
+ accountsUpdateNotifications(token: string, input: QaAccountNotificationsInput): QaAccountUserPublic;
160
172
  /**
161
173
  * The caller's own integration tokens. The list is the account's own: the
162
174
  * token names it, and a secret is never part of a summary, so reading this
@@ -188,6 +200,20 @@ export declare class QaSurface extends TypertRemoteService {
188
200
  * boundary stays in {@link secureSession}.
189
201
  */
190
202
  describe(): ResolvedQaSurfaceConfig;
203
+ /**
204
+ * Report how much of the deployment's request ceiling the stand is using, so
205
+ * a browser holds its question back instead of opening another turn on a
206
+ * model that is busy answering the ones it allows.
207
+ *
208
+ * The count is the Host's, not the browser's: a visitor cannot see another
209
+ * account's chats, and the HTTP API's questions are invisible to every chat
210
+ * view. Read-only, and a ceiling rather than a lock — a prompt rides the
211
+ * native session RPC this plugin does not own, so the boundary is the
212
+ * browser's own courtesy, and two questions sent in the same instant can
213
+ * still overshoot by one. What the ceiling buys is that steady state, not a
214
+ * strict bound.
215
+ */
216
+ queueStatus(): QaQueueStatus;
191
217
  /**
192
218
  * Create a QA session from Host-owned inputs. With account workspaces on,
193
219
  * cwd is `<configured workspace>/.qa-users/<account UUID>` and the child is
@@ -232,6 +258,28 @@ export declare class QaSurface extends TypertRemoteService {
232
258
  adminSkillTools(token: string, scope: QaAdminSkillScope): Promise<{
233
259
  readonly tools: readonly QaSkillToolDescriptor[];
234
260
  }>;
261
+ /**
262
+ * Which experts hold memory, and how much.
263
+ *
264
+ * Reads the domain-experts service on the host plane rather than its remotes:
265
+ * those answer a trusted in-Harness caller and check no token, while this
266
+ * console answers a browser, so the permission check lives here.
267
+ */
268
+ adminMemoryScopes(token: string): Promise<readonly QaExpertMemoryScope[]>;
269
+ /** One page of one namespace, newest first, with the filter's match count. */
270
+ adminMemoryRecords(token: string, namespace: string, query: string, limit: number | null, offset: number): Promise<QaExpertMemoryPage>;
271
+ /** Rewrite one remembered line; the audit trail keeps both images. */
272
+ adminMemoryCorrect(token: string, namespace: string, key: string, draft: QaExpertMemoryDraft): Promise<QaExpertMemoryRecord>;
273
+ /** Drop one or several remembered lines of one namespace. */
274
+ adminMemoryForget(token: string, namespace: string, keys: readonly string[]): Promise<number>;
275
+ /**
276
+ * Empty one namespace, confirming the count the operator was shown.
277
+ *
278
+ * The check is the console's, not the store's: what the operator clicked was
279
+ * a number on a screen, and memory an expert wrote in the meantime is not
280
+ * memory they agreed to erase.
281
+ */
282
+ adminMemoryWipe(token: string, namespace: string, expectedRecords: number | null): Promise<number>;
235
283
  /**
236
284
  * Counters, attention lines and the newest quality signals.
237
285
  *
@@ -20,6 +20,15 @@ export interface QaTurnAnswer {
20
20
  /** Durable seq of the message the answer came from, when there was one. */
21
21
  readonly seq: number | null;
22
22
  }
23
+ /** One request's answer, additionally attributed to the turn it came from. */
24
+ export interface QaRequestAnswer extends QaTurnAnswer {
25
+ /**
26
+ * The harness turn number the answer was read out of, or null when the log
27
+ * named no turn for the request's own row. The provenance bundle of a turn is
28
+ * the evidence of its answer, so the caller cites the same number.
29
+ */
30
+ readonly turn: number | null;
31
+ }
23
32
  /** The empty answer: what a turn that committed nothing readable looks like. */
24
33
  export declare const QA_EMPTY_ANSWER: QaTurnAnswer;
25
34
  /**
@@ -35,6 +44,24 @@ export declare const QA_EMPTY_ANSWER: QaTurnAnswer;
35
44
  * @returns the publishable answer and whether the turn was interrupted.
36
45
  */
37
46
  export declare function answerAfter(events: readonly StoredSessionEvent[], afterSeq: number): QaTurnAnswer;
47
+ /**
48
+ * Project the answer of the turn one request's own prompt opened.
49
+ *
50
+ * The harness stamps the prompt's rpc id onto the durable user row it claims,
51
+ * so the row is found by id rather than guessed from the newest human message:
52
+ * two questions in flight on one chat open two turns, and a selection by
53
+ * "latest" answers each caller with the other's turn. The turn that answers a
54
+ * request is the one its row was claimed into — `turn/start` opens a turn and
55
+ * the claimed rows follow it — so the answer is read out of that turn's
56
+ * assistant messages only, and its number travels with it for the citation.
57
+ *
58
+ * @param events - durable events, in any order.
59
+ * @param requestId - the rpc id the prompt was submitted with.
60
+ * @returns the answer of this request's turn, or `undefined` when the log
61
+ * holds no row for the request (an unflushed prompt, or a harness that does not
62
+ * echo the id), which leaves the choice of cursor to the caller.
63
+ */
64
+ export declare function answerForRequest(events: readonly StoredSessionEvent[], requestId: string): QaRequestAnswer | undefined;
38
65
  /**
39
66
  * Cut an answer down to the size the caller publishes.
40
67
  *
@@ -0,0 +1,49 @@
1
+ import type { QaExpertMemoryRecord, QaExpertMemoryScope } from "../types.js";
2
+ /**
3
+ * The slice of `@yadsh/dsh-domain-experts` the QA console uses.
4
+ *
5
+ * Declared structurally instead of imported, for the same reason the audit
6
+ * remote is: the QA surface has to load on a stand where the experts plugin is
7
+ * not composed at all, and a package dependency would turn "not installed" into
8
+ * "does not boot".
9
+ *
10
+ * What is reached is the plugin's `memoryAdmin` seam — not its `@Remote`
11
+ * methods. A domain-experts remote takes no token and checks no permission,
12
+ * because inside the Harness its caller is already a trusted component; the QA
13
+ * console answers a browser on a LAN port, so it carries the identity itself
14
+ * and goes through the host-plane seam instead.
15
+ */
16
+ export interface QaExpertMemoryAdmin {
17
+ scopes(): Promise<readonly QaExpertMemoryScope[]>;
18
+ search(namespace: string, query: string, limit: number, offset: number): Promise<{
19
+ readonly records: readonly QaExpertMemoryRecord[];
20
+ readonly total: number;
21
+ }>;
22
+ correct(input: QaExpertMemoryRecordInput): Promise<QaExpertMemoryRecord>;
23
+ remove(namespace: string, key: string): Promise<boolean>;
24
+ removeMany(namespace: string, keys: readonly string[]): Promise<number>;
25
+ wipe(namespace: string): Promise<number>;
26
+ }
27
+ /** What a correction says one record should hold. The key is the address. */
28
+ export interface QaExpertMemoryRecordInput {
29
+ readonly namespace: string;
30
+ readonly key: string;
31
+ readonly text: string;
32
+ readonly tags?: readonly string[];
33
+ }
34
+ /** The part of the domain-experts service the console addresses. */
35
+ export interface QaDomainExpertsFace {
36
+ readonly memoryAdmin: QaExpertMemoryAdmin;
37
+ }
38
+ /**
39
+ * Why a memory call failed, in the coarse vocabulary the console's copy table
40
+ * speaks.
41
+ *
42
+ * The refusal is read off the plugin's stable `code` field rather than its
43
+ * message: a message is written for a log and gets reworded, and matching one
44
+ * here would mean a rename in another package silently turns a refusal into an
45
+ * unhandled fault. `cause` is checked too, because the storage seam wraps what
46
+ * the backend threw.
47
+ */
48
+ export declare function expertMemoryReasonOf(error: unknown): "forbidden" | "memory-record-unknown" | "memory-unavailable" | "invalid-memory" | undefined;
49
+ //# sourceMappingURL=expert-memory.d.ts.map
@@ -0,0 +1,32 @@
1
+ import type { QaAccountNotifications, QaAccountNotificationsInput } from "./types.js";
2
+ /**
3
+ * What an account that never opened the notifications form gets.
4
+ *
5
+ * The in-page line is the shipped default of the feature itself, so an
6
+ * untouched account keeps behaving as it did before the form existed. The
7
+ * desktop channel stays off until asked for: raising an operating-system notice
8
+ * is the one choice that leaves the page, and a stand where the browser was
9
+ * never asked must not make it on the account's behalf.
10
+ */
11
+ export declare function emptyNotifications(): QaAccountNotifications;
12
+ /**
13
+ * Read one stored (or wire-delivered) notifications record into its public
14
+ * shape. Unknown or hand-edited input degrades to the readable subset rather
15
+ * than throwing, mirroring the starters read path: a malformed record must
16
+ * never cost the account its session.
17
+ */
18
+ export declare function normalizeNotifications(value: unknown): QaAccountNotifications;
19
+ export type QaNotificationsWriteResult = {
20
+ readonly ok: true;
21
+ readonly value: QaAccountNotificationsInput;
22
+ } | {
23
+ readonly ok: false;
24
+ readonly message: string;
25
+ };
26
+ /**
27
+ * Validate one full-replace notifications write. Both channels are required: a
28
+ * payload that names only one would silently reset the other, and the form
29
+ * always sends the pair it was rendered with.
30
+ */
31
+ export declare function validateNotificationsWrite(input: unknown): QaNotificationsWriteResult;
32
+ //# sourceMappingURL=notifications.d.ts.map
@@ -3,7 +3,7 @@
3
3
  * `(reason: <code>)` marker the account remotes established: the browser maps
4
4
  * them to audience-safe copy, while the precise cause stays in the Host log.
5
5
  */
6
- export type QaPersonalSkillErrorReason = "skills-disabled" | "workspace-unavailable" | "skill-not-found" | "skill-exists" | "skill-conflict" | "skill-name-invalid" | "skill-invalid" | "storage-unavailable";
6
+ export type QaPersonalSkillErrorReason = "skills-disabled" | "workspace-unavailable" | "skill-not-found" | "skill-exists" | "skill-conflict" | "skill-truncated" | "skill-name-invalid" | "skill-invalid" | "storage-unavailable";
7
7
  export declare class QaPersonalSkillError extends Error {
8
8
  readonly reason: QaPersonalSkillErrorReason;
9
9
  constructor(reason: QaPersonalSkillErrorReason, message: string);
@@ -55,6 +55,12 @@ export interface QaStoredSkill {
55
55
  readonly contents: QaSkillFileContents | undefined;
56
56
  readonly diagnostics: readonly QaSkillDiagnostic[];
57
57
  readonly resourceCount: number;
58
+ /**
59
+ * True when `raw` is only the head of the file: an oversized `SKILL.md` is
60
+ * read up to the ceiling, and what follows it was never loaded. A write must
61
+ * not overwrite such a document without saying so out loud.
62
+ */
63
+ readonly truncated: boolean;
58
64
  }
59
65
  export interface QaPersonalSkillsOptions {
60
66
  readonly getConfig: () => ResolvedQaSurfaceConfig;