@yadsh/dsh-qa-surface 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) 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 +432 -52
  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 +70 -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 +21 -14
  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 +5 -5
  43. package/lib/client/admin/pages/Overview.js.map +1 -1
  44. package/lib/client/admin/pages/Quality.js +6 -6
  45. package/lib/client/admin/pages/Quality.js.map +1 -1
  46. package/lib/client/admin/pages/Review.js +13 -9
  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 +57 -10
  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 +87 -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 +58 -24
  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 -12
  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/rating-harvest.js +138 -0
  147. package/lib/client/rating-harvest.js.map +1 -0
  148. package/lib/client/role/RoleSelector.js +9 -4
  149. package/lib/client/role/RoleSelector.js.map +1 -1
  150. package/lib/client/settings/card.js +58 -17
  151. package/lib/client/settings/card.js.map +1 -1
  152. package/lib/client/settings/fields.js +11 -10
  153. package/lib/client/settings/fields.js.map +1 -1
  154. package/lib/client/settings/format.js +0 -9
  155. package/lib/client/settings/format.js.map +1 -1
  156. package/lib/client/settings/sections/access.js +5 -5
  157. package/lib/client/settings/sections/access.js.map +1 -1
  158. package/lib/client/settings/sections/accounts.js +10 -10
  159. package/lib/client/settings/sections/accounts.js.map +1 -1
  160. package/lib/client/settings/sections/attachments.js +6 -6
  161. package/lib/client/settings/sections/attachments.js.map +1 -1
  162. package/lib/client/settings/sections/branding.js +7 -7
  163. package/lib/client/settings/sections/branding.js.map +1 -1
  164. package/lib/client/settings/sections/common.js +4 -2
  165. package/lib/client/settings/sections/common.js.map +1 -1
  166. package/lib/client/settings/sections/docs.js +4 -3
  167. package/lib/client/settings/sections/docs.js.map +1 -1
  168. package/lib/client/settings/sections/embedding.js +2 -2
  169. package/lib/client/settings/sections/embedding.js.map +1 -1
  170. package/lib/client/settings/sections/interface.js +12 -12
  171. package/lib/client/settings/sections/interface.js.map +1 -1
  172. package/lib/client/settings/sections/lockdown.js +9 -9
  173. package/lib/client/settings/sections/lockdown.js.map +1 -1
  174. package/lib/client/settings/sections/notes.js +12 -12
  175. package/lib/client/settings/sections/notes.js.map +1 -1
  176. package/lib/client/settings/sections/session.js +15 -12
  177. package/lib/client/settings/sections/session.js.map +1 -1
  178. package/lib/client/settings/sections/slash.js +9 -9
  179. package/lib/client/settings/sections/slash.js.map +1 -1
  180. package/lib/client/settings/sections/sources.js +26 -26
  181. package/lib/client/settings/sections/sources.js.map +1 -1
  182. package/lib/client/settings/sections/status.js +2 -2
  183. package/lib/client/settings/sections/status.js.map +1 -1
  184. package/lib/client/settings/styles.js +15 -9
  185. package/lib/client/settings/styles.js.map +1 -1
  186. package/lib/client/slash/SlashPalette.js +4 -4
  187. package/lib/client/slash/SlashPalette.js.map +1 -1
  188. package/lib/client/styles.js +139 -66
  189. package/lib/client/styles.js.map +1 -1
  190. package/lib/client/theme-preference.js +162 -0
  191. package/lib/client/theme-preference.js.map +1 -0
  192. package/lib/client/types.js +8 -0
  193. package/lib/client/types.js.map +1 -1
  194. package/lib/client/use-session-ui-state.js +7 -5
  195. package/lib/client/use-session-ui-state.js.map +1 -1
  196. package/lib/client/user-settings/GeneralSettingsPage.js +6 -6
  197. package/lib/client/user-settings/GeneralSettingsPage.js.map +1 -1
  198. package/lib/client/user-settings/IntegrationTokensPage.js +6 -6
  199. package/lib/client/user-settings/IntegrationTokensPage.js.map +1 -1
  200. package/lib/client/user-settings/NotificationSettingsPage.js +107 -0
  201. package/lib/client/user-settings/NotificationSettingsPage.js.map +1 -0
  202. package/lib/client/user-settings/PasswordSettingsPage.js +1 -1
  203. package/lib/client/user-settings/PasswordSettingsPage.js.map +1 -1
  204. package/lib/client/user-settings/ProfileSettingsPage.js +2 -2
  205. package/lib/client/user-settings/ProfileSettingsPage.js.map +1 -1
  206. package/lib/client/user-settings/SkillCatalog.js +3 -3
  207. package/lib/client/user-settings/SkillCatalog.js.map +1 -1
  208. package/lib/client/user-settings/SkillEditor.js +26 -8
  209. package/lib/client/user-settings/SkillEditor.js.map +1 -1
  210. package/lib/client/user-settings/SkillToolPicker.js +3 -3
  211. package/lib/client/user-settings/SkillToolPicker.js.map +1 -1
  212. package/lib/client/user-settings/SkillsSettingsPage.js +1 -1
  213. package/lib/client/user-settings/SkillsSettingsPage.js.map +1 -1
  214. package/lib/client/user-settings/StartersSettingsPage.js +6 -6
  215. package/lib/client/user-settings/StartersSettingsPage.js.map +1 -1
  216. package/lib/client/user-settings/UserSettingsDialog.js +7 -2
  217. package/lib/client/user-settings/UserSettingsDialog.js.map +1 -1
  218. package/lib/client/user-settings/copy.js +2 -0
  219. package/lib/client/user-settings/copy.js.map +1 -1
  220. package/lib/client/user-settings/draft.js +4 -1
  221. package/lib/client/user-settings/draft.js.map +1 -1
  222. package/lib/client/user-settings/fields.js +5 -5
  223. package/lib/client/user-settings/fields.js.map +1 -1
  224. package/lib/client.js +7483 -2075
  225. package/lib/client.js.map +1 -1
  226. package/lib/config-resolvers/defaults.js +7 -0
  227. package/lib/config-resolvers/defaults.js.map +1 -1
  228. package/lib/config-resolvers/lockdown.js +7 -0
  229. package/lib/config-resolvers/lockdown.js.map +1 -1
  230. package/lib/config-resolvers/notifications.js +15 -0
  231. package/lib/config-resolvers/notifications.js.map +1 -0
  232. package/lib/config-resolvers/session.js +11 -1
  233. package/lib/config-resolvers/session.js.map +1 -1
  234. package/lib/config.js +67 -18
  235. package/lib/config.js.map +1 -1
  236. package/lib/enforcement/tool-grants.js +6 -6
  237. package/lib/enforcement/tool-grants.js.map +1 -1
  238. package/lib/index.js +171 -39
  239. package/lib/index.js.map +1 -1
  240. package/lib/integration/answer.js +74 -8
  241. package/lib/integration/answer.js.map +1 -1
  242. package/lib/integration/expert-memory.js +39 -0
  243. package/lib/integration/expert-memory.js.map +1 -0
  244. package/lib/integration/host-runner.js +26 -14
  245. package/lib/integration/host-runner.js.map +1 -1
  246. package/lib/notifications.js +66 -0
  247. package/lib/notifications.js.map +1 -0
  248. package/lib/personal-skills/errors.js.map +1 -1
  249. package/lib/personal-skills/service.js +81 -7
  250. package/lib/personal-skills/service.js.map +1 -1
  251. package/lib/prompt-notes.js +2 -10
  252. package/lib/prompt-notes.js.map +1 -1
  253. package/lib/provenance/extractors.js +1 -1
  254. package/lib/provenance/extractors.js.map +1 -1
  255. package/lib/provenance/host-store.js +5 -1
  256. package/lib/provenance/host-store.js.map +1 -1
  257. package/lib/qa-tools/docs-tools.js +64 -11
  258. package/lib/qa-tools/docs-tools.js.map +1 -1
  259. package/lib/qa-tools/lifecycle.js +6 -3
  260. package/lib/qa-tools/lifecycle.js.map +1 -1
  261. package/lib/request-queue.js +32 -0
  262. package/lib/request-queue.js.map +1 -0
  263. package/lib/resolve-config.js +2 -0
  264. package/lib/resolve-config.js.map +1 -1
  265. package/lib/secure-session.js +7 -2
  266. package/lib/secure-session.js.map +1 -1
  267. package/lib/shared/settings.js +19 -2
  268. package/lib/shared/settings.js.map +1 -1
  269. package/lib/turn-failure-log.js +67 -0
  270. package/lib/turn-failure-log.js.map +1 -0
  271. package/lib/typert.host.js +1459 -647
  272. package/lib/typert.remote-client.d.ts +25 -9
  273. package/lib/typert.remote-client.js +1356 -636
  274. package/lib/types/access/capability-catalog.d.ts +20 -4
  275. package/lib/types/access/model.d.ts +23 -0
  276. package/lib/types/access/service.d.ts +2 -3
  277. package/lib/types/account-remotes.d.ts +8 -1
  278. package/lib/types/accounts/database.d.ts +13 -3
  279. package/lib/types/accounts/errors.d.ts +9 -1
  280. package/lib/types/accounts/file.d.ts +12 -0
  281. package/lib/types/accounts/store.d.ts +30 -2
  282. package/lib/types/admin/quality-store.d.ts +33 -0
  283. package/lib/types/admin/service.d.ts +119 -9
  284. package/lib/types/client/QaAccountsController.d.ts +37 -3
  285. package/lib/types/client/QaConfigController.d.ts +2 -2
  286. package/lib/types/client/QaSessionController.d.ts +199 -6
  287. package/lib/types/client/QaSurface.d.ts +6 -1
  288. package/lib/types/client/admin/pages/ExpertMemory.d.ts +19 -0
  289. package/lib/types/client/admin/routes.d.ts +3 -1
  290. package/lib/types/client/admin/shared.d.ts +20 -1
  291. package/lib/types/client/components/Markdown.d.ts +8 -1
  292. package/lib/types/client/components/QaHeader.d.ts +3 -1
  293. package/lib/types/client/components/QaModal.d.ts +7 -0
  294. package/lib/types/client/components/QaQueueDock.d.ts +27 -0
  295. package/lib/types/client/components/QaRequestQueue.d.ts +20 -0
  296. package/lib/types/client/components/QaThemeSwitcher.d.ts +14 -0
  297. package/lib/types/client/components/QaTurnNotice.d.ts +55 -0
  298. package/lib/types/client/focus-ring.d.ts +65 -0
  299. package/lib/types/client/lineage.d.ts +3 -13
  300. package/lib/types/client/markdown/blocks.d.ts +30 -2
  301. package/lib/types/client/markdown/render.d.ts +4 -1
  302. package/lib/types/client/notifications/notification-dispatcher.d.ts +68 -0
  303. package/lib/types/client/notifications/preferences.d.ts +44 -0
  304. package/lib/types/client/notifications/turn-completion-source.d.ts +114 -0
  305. package/lib/types/client/notifications/use-turn-notifications.d.ts +51 -0
  306. package/lib/types/client/project-session-state.d.ts +35 -1
  307. package/lib/types/client/rating-harvest.d.ts +49 -0
  308. package/lib/types/client/role/RoleSelector.d.ts +7 -1
  309. package/lib/types/client/settings/card.d.ts +36 -5
  310. package/lib/types/client/settings/fields.d.ts +24 -0
  311. package/lib/types/client/settings/format.d.ts +0 -5
  312. package/lib/types/client/settings/sections/common.d.ts +3 -1
  313. package/lib/types/client/settings/sections/session.d.ts +2 -1
  314. package/lib/types/client/settings/styles.d.ts +9 -4
  315. package/lib/types/client/settings-extensions/user-session.d.ts +1 -1
  316. package/lib/types/client/theme-preference.d.ts +69 -0
  317. package/lib/types/client/types.d.ts +36 -5
  318. package/lib/types/client/use-session-ui-state.d.ts +6 -4
  319. package/lib/types/client/user-settings/GeneralSettingsPage.d.ts +5 -5
  320. package/lib/types/client/user-settings/NotificationSettingsPage.d.ts +40 -0
  321. package/lib/types/client/user-settings/UserSettingsDialog.d.ts +12 -2
  322. package/lib/types/client/user-settings/draft.d.ts +4 -1
  323. package/lib/types/client/user-settings/fields.d.ts +7 -0
  324. package/lib/types/config-resolvers/notifications.d.ts +10 -0
  325. package/lib/types/config-resolvers/session.d.ts +6 -0
  326. package/lib/types/config.d.ts +20 -1
  327. package/lib/types/index.d.ts +70 -10
  328. package/lib/types/integration/answer.d.ts +27 -0
  329. package/lib/types/integration/expert-memory.d.ts +49 -0
  330. package/lib/types/notifications.d.ts +32 -0
  331. package/lib/types/personal-skills/errors.d.ts +1 -1
  332. package/lib/types/personal-skills/service.d.ts +6 -0
  333. package/lib/types/prompt-notes.d.ts +17 -4
  334. package/lib/types/qa-tools/docs-tools.d.ts +2 -2
  335. package/lib/types/request-queue.d.ts +32 -0
  336. package/lib/types/shared/settings.d.ts +19 -2
  337. package/lib/types/turn-failure-log.d.ts +18 -0
  338. package/lib/types/types.d.ts +200 -4
  339. package/package.json +64 -62
  340. package/scripts/attach-workspace-sessions.mjs +24 -5
  341. package/scripts/repair-session-events.mjs +25 -5
@@ -31,19 +31,9 @@ export interface SubagentNameCandidate {
31
31
  /** The Host's own wording for the delegation; empty when it listed none. */
32
32
  readonly label: string;
33
33
  }
34
- /** One durable delegation catalog entry, as the Host lists it. */
35
- export interface SubagentCatalogEntry {
36
- readonly kind?: string;
37
- readonly id?: string;
38
- readonly label?: string;
39
- }
40
- /** Direct delegation catalogs keyed by their parent chat. */
41
- export type SubagentCatalogs = Readonly<Record<string, {
42
- readonly entries?: readonly SubagentCatalogEntry[];
43
- } | undefined>>;
44
34
  /**
45
- * Delegated sessions whose names a page may sign its notices with: the
46
- * children of the chats it lists, catalog labels first and list titles after.
35
+ * Delegated sessions whose names a page may sign its notices with: the children
36
+ * of the chats it lists, named by the row title the Host's session list carries.
47
37
  *
48
38
  * `chats` is the visible chat set — the account's own chats while accounts are
49
39
  * on, and `undefined` for a deployment without accounts, where every chat on
@@ -53,5 +43,5 @@ export type SubagentCatalogs = Readonly<Record<string, {
53
43
  * therefore contributes no id and no label — a foreign chat can neither sign
54
44
  * a notice nor be named by one.
55
45
  */
56
- export declare function visibleSubagentCandidates(byId: Readonly<Record<string, SessionSummary>>, catalogs: SubagentCatalogs, chats: ReadonlySet<string> | undefined): readonly SubagentNameCandidate[];
46
+ export declare function visibleSubagentCandidates(byId: Readonly<Record<string, SessionSummary>>, chats: ReadonlySet<string> | undefined): readonly SubagentNameCandidate[];
57
47
  //# sourceMappingURL=lineage.d.ts.map
@@ -16,6 +16,15 @@
16
16
  * delimiters stay literal text, exactly as the Host renders them. Footnote
17
17
  * definitions (`[^id]: …`) are collected the way GitHub's dialect does, with
18
18
  * lazy and indented continuation lines.
19
+ *
20
+ * A frame of a live stream is parsed with `streaming: true`, which says one
21
+ * thing only: the text may still grow. Block boundaries stay the business of
22
+ * this module — a caller that knows the answer is being written passes the
23
+ * flag, and nothing here is re-detected elsewhere. Two readings change with
24
+ * it: a block whose region runs to the end of the text has not met its
25
+ * terminator, so a fence or a `$$` block reports `pending`, and a table treats
26
+ * its live last line as still written (a delimiter row being typed opens the
27
+ * header, a row being typed stays out of the cells).
19
28
  */
20
29
  /** `#`-through-`######` heading levels. */
21
30
  export type HeadingDepth = 1 | 2 | 3 | 4 | 5 | 6;
@@ -39,6 +48,8 @@ export type MarkdownBlock = {
39
48
  readonly kind: "code";
40
49
  readonly text: string;
41
50
  readonly lang?: string;
51
+ /** The fence has not met its closing marker: the stream is inside it. */
52
+ readonly pending?: true;
42
53
  } | {
43
54
  readonly kind: "quote";
44
55
  readonly blocks: readonly MarkdownBlock[];
@@ -56,6 +67,8 @@ export type MarkdownBlock = {
56
67
  } | {
57
68
  readonly kind: "math";
58
69
  readonly text: string;
70
+ /** The `$$` fence has not closed: the stream is still typing the TeX. */
71
+ readonly pending?: true;
59
72
  } | {
60
73
  readonly kind: "rule";
61
74
  };
@@ -67,21 +80,36 @@ export interface ParsedMarkdown {
67
80
  /** Footnote bodies by upper-cased identifier; first definition wins. */
68
81
  readonly footnotes: ReadonlyMap<string, readonly MarkdownBlock[]>;
69
82
  }
83
+ /** How to read the end of the text being parsed. */
84
+ export interface MarkdownParseOptions {
85
+ /**
86
+ * The text is a frame of a live stream, so its last content line may be
87
+ * half-typed: a block that reaches the end of the text is reported as
88
+ * `pending` instead of being treated as settled, and a table leaves an
89
+ * unfinished last row out of its cells. Omitted for a settled answer, which
90
+ * is where the two readings must not drift apart.
91
+ */
92
+ readonly streaming?: boolean;
93
+ }
70
94
  /** Split one table row into trimmed cells, honoring escaped pipes. */
71
95
  export declare function splitTableRow(line: string): string[];
72
96
  /**
73
97
  * Parse a whole document.
74
98
  * @param text - Markdown source with any line endings.
99
+ * @param options - How to read the end of the text; a live stream frame marks
100
+ * the block it stopped inside as pending.
75
101
  * @returns Blocks plus the definitions the inline pass resolves against.
76
102
  */
77
- export declare function parseMarkdown(text: string): ParsedMarkdown;
103
+ export declare function parseMarkdown(text: string, options?: MarkdownParseOptions): ParsedMarkdown;
78
104
  /**
79
105
  * Parse the blocks of one container (document, quote, or list item).
80
106
  * @param lines - Container lines, already de-indented by the caller.
81
107
  * @param definitions - Document-wide definition accumulator.
82
108
  * @param footnotes - Document-wide footnote accumulator.
83
109
  * @param depth - Container nesting depth.
110
+ * @param streaming - Whether the text is a live frame, so the container's last
111
+ * line may still be typed.
84
112
  * @returns The container's blocks.
85
113
  */
86
- export declare function parseBlocks(lines: readonly string[], definitions: Map<string, string>, footnotes: Map<string, readonly MarkdownBlock[]>, depth: number): MarkdownBlock[];
114
+ export declare function parseBlocks(lines: readonly string[], definitions: Map<string, string>, footnotes: Map<string, readonly MarkdownBlock[]>, depth: number, streaming?: boolean): MarkdownBlock[];
87
115
  //# sourceMappingURL=blocks.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import type { ReactNode } from "react";
2
+ import type { MarkdownParseOptions } from "./blocks.js";
2
3
  import { type MarkdownSourceContext } from "./source-chip.js";
3
4
  /**
4
5
  * Render markdown source as semantic React elements. Raw HTML never enters the
@@ -7,8 +8,10 @@ import { type MarkdownSourceContext } from "./source-chip.js";
7
8
  * instead of a plain link or code token.
8
9
  * @param text - Assistant-authored markdown.
9
10
  * @param context - Source resolution handed down by the owning message.
11
+ * @param options - How to read the end of the text; a live stream frame holds
12
+ * the block it stopped inside instead of rendering it as settled.
10
13
  * @returns The document's blocks, plus the footnote section when the document
11
14
  * references a defined footnote.
12
15
  */
13
- export declare function renderMarkdown(text: string, context: MarkdownSourceContext): ReactNode[];
16
+ export declare function renderMarkdown(text: string, context: MarkdownSourceContext, options?: MarkdownParseOptions): ReactNode[];
14
17
  //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1,68 @@
1
+ import type { QaTurnCompletion } from "./turn-completion-source.js";
2
+ import type { QaNoticeChannels } from "./preferences.js";
3
+ /** What the browser exposes of the desktop notification API. */
4
+ export type QaNotificationPermission = NotificationPermission | "unsupported";
5
+ /** One entry of the in-app stack. */
6
+ export interface QaTurnNoticeItem {
7
+ readonly key: string;
8
+ readonly sessionId: string;
9
+ readonly title: string;
10
+ }
11
+ /** A finished turn and the channels it takes. */
12
+ export interface PlannedTurnNotice {
13
+ readonly item: QaTurnNoticeItem;
14
+ /** Keep the line in this page, or send the fact to the desktop alone. */
15
+ readonly inApp: boolean;
16
+ /** Raise the desktop notice as well, or keep this one inside the page. */
17
+ readonly desktop: boolean;
18
+ }
19
+ export interface QaNoticeContext {
20
+ /** `config.notifications`: the deployment's switches over both channels. */
21
+ readonly switches: {
22
+ readonly enabled: boolean;
23
+ readonly allowOs: boolean;
24
+ };
25
+ /** The reader's own choice, from their account or from this browser. */
26
+ readonly channels: QaNoticeChannels;
27
+ readonly permission: QaNotificationPermission;
28
+ /** Whether this page is the one the person is looking at right now. */
29
+ readonly focused: boolean;
30
+ /** The chat the composer is showing. */
31
+ readonly activeSessionId: string | null;
32
+ }
33
+ /** Body text of every desktop notice: the fact, never the content. */
34
+ export declare const QA_TURN_NOTICE_BODY = "\u0425\u043E\u0434 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D";
35
+ /**
36
+ * Decide what one finished turn is worth, if anything.
37
+ *
38
+ * A notice exists to say "this happened where you were not looking". The chat
39
+ * on screen answers itself — the reply arrives in front of the reader — so it
40
+ * gets nothing, while a background chat that settles under their eyes still
41
+ * gets the in-app line. Each channel then needs its own two answers: the
42
+ * deployment's and the reader's. The desktop additionally needs the browser's
43
+ * permission, which neither of those can grant on its behalf.
44
+ */
45
+ export declare function planTurnNotice(completion: QaTurnCompletion, context: QaNoticeContext): PlannedTurnNotice | null;
46
+ /**
47
+ * Whether the person is looking at this page. A hidden tab and a visible tab
48
+ * behind another window both count as away: the notice is for the difference
49
+ * between "watching" and "not watching", not for the tab's own state.
50
+ */
51
+ export declare function isPageFocused(documentState?: {
52
+ visibilityState: DocumentVisibilityState;
53
+ }, hasFocus?: () => boolean): boolean;
54
+ /** The desktop channel's current answer, or `unsupported` off a secure context. */
55
+ export declare function readNotificationPermission(): QaNotificationPermission;
56
+ /**
57
+ * Ask the browser for the desktop channel. Only ever called from a click: the
58
+ * permission prompt is the user's decision about this origin, and a page that
59
+ * asks on load — or once per finished turn — spends it on the wrong moment.
60
+ */
61
+ export declare function requestNotificationPermission(): Promise<QaNotificationPermission>;
62
+ /**
63
+ * Hand one finished turn to the desktop. Returns false when the platform
64
+ * refuses: a notification that cannot be raised costs the reader nothing, and
65
+ * the in-app line is already on its way.
66
+ */
67
+ export declare function raiseDesktopNotice(completion: QaTurnCompletion): boolean;
68
+ //# sourceMappingURL=notification-dispatcher.d.ts.map
@@ -0,0 +1,44 @@
1
+ import type { QaAccountNotifications } from "../../types.js";
2
+ import type { StorageLike } from "../types.js";
3
+ /** One reader's choice about the desktop channel. */
4
+ export interface QaNotificationPrefs {
5
+ /** Raise a desktop notice for a finished turn while this page is in the background. */
6
+ readonly osEnabled: boolean;
7
+ /** The offer was answered or waved off: a notice never asks a second time. */
8
+ readonly osOffered: boolean;
9
+ }
10
+ /** The channels one finished turn may use, whoever decided them. */
11
+ export interface QaNoticeChannels {
12
+ readonly inApp: boolean;
13
+ readonly desktop: boolean;
14
+ }
15
+ export declare const QA_NOTIFICATION_DEFAULT_PREFS: QaNotificationPrefs;
16
+ /**
17
+ * Read the stored choice; a denied, full or foreign-shaped store falls back to
18
+ * the silent default rather than raising notices nobody asked for.
19
+ *
20
+ * What is left in this browser is what belongs to a browser: the answer to the
21
+ * desktop offer, and the desktop choice itself for as long as there is no
22
+ * account to hold it. Signed in, the account's {@link QaAccountNotifications}
23
+ * wins — see {@link resolveNoticeChannels} — because a preference that follows
24
+ * the person is the point of storing it on the account at all.
25
+ */
26
+ export declare function readNotificationPrefs(storage: StorageLike | undefined, key: string): QaNotificationPrefs;
27
+ /** Persist the choice. A store that refuses only costs it across reloads. */
28
+ export declare function writeNotificationPrefs(storage: StorageLike | undefined, key: string, prefs: QaNotificationPrefs): void;
29
+ /**
30
+ * Which channels this reader may use for a finished turn.
31
+ *
32
+ * The account's answer wins once it exists, so the choice follows the person to
33
+ * another browser or another laptop. Without an account the browser's own
34
+ * answer stands: an anonymous stand is the common shape of a QA deployment, and
35
+ * a mute switch that only appeared once signed in would leave it with no switch
36
+ * at all. The in-page line has no browser-level switch of its own — a stand that
37
+ * wants it gone has `notifications.enabled`, and the offer this page makes is
38
+ * only ever about the desktop channel.
39
+ */
40
+ export declare function resolveNoticeChannels(input: {
41
+ readonly account: QaAccountNotifications | undefined;
42
+ readonly prefs: QaNotificationPrefs;
43
+ }): QaNoticeChannels;
44
+ //# sourceMappingURL=preferences.d.ts.map
@@ -0,0 +1,114 @@
1
+ /** One chat of this browser's own list, as the page currently sees it. */
2
+ export interface QaChatActivity {
3
+ readonly id: string;
4
+ readonly title: string;
5
+ readonly running: boolean;
6
+ }
7
+ /** One turn that ended between two observations of the chat list. */
8
+ export interface QaTurnCompletion {
9
+ readonly sessionId: string;
10
+ /** The chat's own display title: the only text a notice may carry. */
11
+ readonly title: string;
12
+ readonly at: number;
13
+ }
14
+ /**
15
+ * What this page last read about one chat's turn. Four readings, because two
16
+ * facts decide whether the end of a run is this reader's news: whether the chat
17
+ * was running, and whether the frame that said so was one the browser could
18
+ * vouch for. A frame read while the link was down settles neither fact, but the
19
+ * way `running` pointed in it still decides what this page is short of: the
20
+ * start of a run it cannot account for, or an idle reading it cannot yet trust.
21
+ */
22
+ export type QaTurnSighting =
23
+ /**
24
+ * Not running, read while the link held — so a run seen next is one this
25
+ * page watches begin.
26
+ */
27
+ "idle"
28
+ /**
29
+ * Running, and this page saw this very run begin: it held `idle` in the first
30
+ * frame that found the chat running. The frames after that keep the reading —
31
+ * the evidence is the witnessed start, so a run does not lose it by lasting
32
+ * longer than one frame.
33
+ */
34
+ | "watched"
35
+ /**
36
+ * Running, with no evidence of where the run began: the page found the chat
37
+ * running without seeing it start — which is how the page opens, and how a run
38
+ * that outlived the link looks once the link is back. A run ending here is not
39
+ * this reader's news.
40
+ */
41
+ | "unwatched"
42
+ /**
43
+ * Not running, but read only in frames the browser cannot vouch for: the link
44
+ * was down when this was read, or it has returned and the chat's row has not
45
+ * moved since. A row that has not moved is no news about now — it may well be
46
+ * the reading the gap left behind, and this page cannot tell the two apart —
47
+ * so it arms nothing, because a run that began inside the gap would leave it
48
+ * exactly as it is. Only the row moving ends it.
49
+ */
50
+ | "stale";
51
+ export interface QaTurnCompletionOptions {
52
+ /**
53
+ * Re-project the baseline and report nothing. While the browser is
54
+ * reconnecting the list it holds is stale, and the first frame after the
55
+ * link returns would otherwise read as a batch of finished turns. This flag
56
+ * goes back off with the link, which is sooner than the host list is read
57
+ * again: the re-pull belongs to the host store and is not awaited, so a live
58
+ * frame can carry the rows the drop left. What a pause costs this page is
59
+ * therefore carried by the readings rather than by the flag — see `stale`. A
60
+ * gap that left no frame with this flag set is named as a rule of
61
+ * `docs/specs/owner-scoped-notifications.md` §12, not as a detail of this
62
+ * file.
63
+ */
64
+ readonly paused?: boolean;
65
+ readonly now?: number;
66
+ }
67
+ /**
68
+ * Report the turns that ended since the previous observation of `chats`.
69
+ *
70
+ * The input is this reader's own rows — see {@link scopeNoticesToOwnChats},
71
+ * which is what keeps an admin's shared history out of them — because a notice
72
+ * is an outward report about the chat it names. The host list is the whole
73
+ * deployment's, so anything wider than these rows would tell one user that
74
+ * another user's turn had stopped.
75
+ *
76
+ * `seen` is the caller's per-page map of the last reading, and a chat is
77
+ * reported only when a `watched` run is seen ending in a frame the browser
78
+ * could vouch for. So the notice always tells the reader about a turn they were
79
+ * waiting for, and never about one that was already under way when they could
80
+ * not see it: a chat found running on the page's first frame, or in the frames
81
+ * around a reconnect, is `unwatched`, and its end passes in silence. Nor does a
82
+ * gap the page was shown spare a run it lands inside: the paused frame takes
83
+ * back the evidence that this page watched that run begin, because while the
84
+ * link was down the chat may have run another turn and the rows that come back
85
+ * name neither. The first run to end after a gap passes in silence too, in a
86
+ * chat whose row never moved across it — the only idle this page holds for that
87
+ * chat was read through the gap, and a run that began inside the gap would look
88
+ * exactly like it. That reading arms nothing until the chat's own row moves, and
89
+ * the move that arms it is a run ending: the very one this page then keeps
90
+ * silent about. So a turn is reported only when no gap falls between the idle
91
+ * reading that armed this page and the frame that sees the run end, which is why
92
+ * a run begun and finished on the recovered link can still pass unreported, and
93
+ * why a gap the page was shown costs a chat one turn — or two, where a turn
94
+ * ended inside the gap. A gap that reached no committed frame hands this function
95
+ * nothing to go silent about, and §12 of
96
+ * `docs/specs/owner-scoped-notifications.md` owns that case. The turn that a link
97
+ * which held carries from an armed idle to its end is the page's own, so a page
98
+ * that stays open notifies again once the turn paying for the gap has ended —
99
+ * once per turn from there.
100
+ */
101
+ export declare function settleTurnCompletions(seen: Map<string, QaTurnSighting>, chats: readonly QaChatActivity[], options?: QaTurnCompletionOptions): QaTurnCompletion[];
102
+ /**
103
+ * Keep the rows a notice may be raised for: the sidebar's rows down to the
104
+ * chats this account owns outright.
105
+ *
106
+ * The sidebar is a *read* surface, and an admin's shared view is deliberately
107
+ * wider than ownership — the same opt-in that shows another account's chat
108
+ * must not decide whose activity this browser reports outward. A notice is
109
+ * that outward report, and it names a chat by title, so it takes the narrow
110
+ * list. `undefined` is the deployment with no accounts, where the browser's own
111
+ * index already is the owned set and there is nothing narrower to ask for.
112
+ */
113
+ export declare function scopeNoticesToOwnChats(chats: readonly QaChatActivity[], ownIds: readonly string[] | undefined): readonly QaChatActivity[];
114
+ //# sourceMappingURL=turn-completion-source.d.ts.map
@@ -0,0 +1,51 @@
1
+ import type { QaAccountNotifications, QaAccountNotificationsInput, ResolvedQaSurfaceConfig } from "../../types.js";
2
+ import type { StorageLike } from "../types.js";
3
+ import { type QaTurnNoticeItem } from "./notification-dispatcher.js";
4
+ import { type QaChatActivity } from "./turn-completion-source.js";
5
+ export interface QaTurnNotificationsInput {
6
+ /** The sidebar's rows: this browser's chats with their running state. */
7
+ readonly chats: readonly QaChatActivity[];
8
+ /**
9
+ * The chats this account owns outright, which is narrower than the rows: an
10
+ * admin's shared history lists chats it only reads, and the turn of such a
11
+ * chat is that other account's business. Absent where there is no account to
12
+ * be narrower than — a stand without accounts, whose rows are the browser's
13
+ * own index.
14
+ */
15
+ readonly ownChatIds?: readonly string[];
16
+ readonly notifications: ResolvedQaSurfaceConfig["notifications"];
17
+ readonly storage: StorageLike | undefined;
18
+ readonly storageKey: string;
19
+ /**
20
+ * The signed-in reader's own channels and the write that changes them.
21
+ * Absent on a stand without accounts, where the browser's own answer is the
22
+ * only one there is to ask.
23
+ */
24
+ readonly account?: {
25
+ readonly notifications: QaAccountNotifications;
26
+ readonly onSave: (input: QaAccountNotificationsInput) => Promise<string | null>;
27
+ };
28
+ /**
29
+ * The link is down, so no run read among these rows is this reader's news. The
30
+ * flag says nothing about the rows: it goes back off with the link, while the
31
+ * host list is re-read after it and unawaited, so the reading named `stale` is
32
+ * what carries the gap over a live frame whose row has not moved since.
33
+ */
34
+ readonly paused: boolean;
35
+ readonly activeSessionId: string | null;
36
+ readonly onSwitch: (sessionId: string) => void;
37
+ }
38
+ export interface QaTurnNotifications {
39
+ readonly items: readonly QaTurnNoticeItem[];
40
+ readonly onOpen: (sessionId: string) => void;
41
+ readonly onDismiss: (key: string) => void;
42
+ readonly onEnableDesktop?: () => void;
43
+ }
44
+ /**
45
+ * Turn-completion notices for the chats this reader owns. Of the rows the
46
+ * sidebar shows, only the ones this account owns outright are watched, and when
47
+ * one of them stops running after this page watched that run begin, the reader
48
+ * is told in the channels they and the deployment allow.
49
+ */
50
+ export declare function useQaTurnNotifications(input: QaTurnNotificationsInput): QaTurnNotifications;
51
+ //# sourceMappingURL=use-turn-notifications.d.ts.map
@@ -1,11 +1,27 @@
1
1
  import type { SessionFace } from "@deepseek-ai/dsh-api-session-controller/client";
2
+ import type { UserMessage } from "@deepseek-ai/dsh-llm";
2
3
  import type { ConversationSnapshot } from "@deepseek-ai/dsh-client-ui-conversation/client";
3
- import type { QaPendingApproval, QaPendingQuestion, QaSessionState, QaSlashView, QaSubagentView, QaTurnSources, ResolvedQaSurfaceConfig } from "../types.js";
4
+ import type { QaPendingApproval, QaPendingQuestion, QaQueueStatus, QaSessionState, QaSlashView, QaSubagentView, QaTurnSources, ResolvedQaSurfaceConfig } from "../types.js";
4
5
  /** Everything the bound-chat projection reads; the computation is pure. */
5
6
  export interface QaBoundProjectionInput {
6
7
  readonly connected: boolean;
7
8
  readonly sessionId: string;
9
+ /** Chat identity from the controller; see `QaSessionState.chatKey`. */
10
+ readonly chatKey: number;
8
11
  readonly sessionSnapshot: ReturnType<SessionFace["getSnapshot"]>;
12
+ /**
13
+ * The Host's Inbox projection for this session: the messages waiting for the
14
+ * agent's next turn. A projection key the Host has not published reads as an
15
+ * empty list, which is what a session with no queued work shows anyway.
16
+ */
17
+ readonly queuedMessages: readonly UserMessage[];
18
+ /**
19
+ * Request ids this binding has already seen the Host name, out of
20
+ * {@link queuedMessages} and the transcript. The mask {@link projectQueue}
21
+ * draws with while the session library's echo retirement waits on a frame the
22
+ * surface may never get.
23
+ */
24
+ readonly admittedSubmissions: ReadonlySet<string>;
9
25
  readonly conversationSnapshot: ConversationSnapshot | undefined;
10
26
  /** Turn bundles with the Host provenance already merged in (Host wins). */
11
27
  readonly sourceBundles: readonly QaTurnSources[];
@@ -17,6 +33,13 @@ export interface QaBoundProjectionInput {
17
33
  readonly approvals: readonly QaPendingApproval[];
18
34
  readonly questions: readonly QaPendingQuestion[];
19
35
  readonly operationError: string | null;
36
+ /**
37
+ * A send the stand had no room for. The dialog is the whole of what the
38
+ * visitor learns: the question never reached the Host, so the transcript has
39
+ * no row to carry the refusal on. Distinct from `queue`, the waiting rows of
40
+ * this chat.
41
+ */
42
+ readonly requestQueue: QaQueueStatus | null;
20
43
  readonly policyReady: boolean;
21
44
  /** Historical binding retained for transcript access after policy drift. */
22
45
  readonly compatibilityReadOnly?: boolean;
@@ -37,6 +60,17 @@ export interface QaBoundProjectionInput {
37
60
  */
38
61
  readonly author?: string;
39
62
  }
63
+ /**
64
+ * The request ids the Host has itself named for a send, out of the two lists it
65
+ * publishes: the messages waiting in its Inbox and the durable input rows of its
66
+ * transcript (`user` opens the turn that took the message, `steering` is one
67
+ * injected into the turn already running). Either is the server's own receipt
68
+ * that the message crossed, and reading both is what makes the receipt
69
+ * independent of which frame carried the news: a message the turn has claimed is
70
+ * gone from the Inbox yet stays in the transcript, so a send admitted and claimed
71
+ * between two notifications is still named by the next transcript frame.
72
+ */
73
+ export declare function hostNamedSubmissionIds(queued: readonly UserMessage[], conversationSnapshot: ConversationSnapshot | undefined): Set<string>;
40
74
  /**
41
75
  * Project one bound chat into the observable surface state: phase, transcript
42
76
  * with per-turn sources, footer sources, and the composer's capabilities.
@@ -0,0 +1,49 @@
1
+ import type { QaFeedbackHarvestEntry, QaFeedbackHarvestResult } from "../types.js";
2
+ import type { RemoteResult, StorageLike } from "./types.js";
3
+ /** `StorageLike` plus the enumeration a browser's `localStorage` offers. */
4
+ export interface HarvestStorage extends StorageLike {
5
+ readonly length: number;
6
+ key(index: number): string | null;
7
+ }
8
+ export type QaRatingHarvestStatus =
9
+ /** This account was already read out; nothing is offered again. */
10
+ "already-harvested"
11
+ /** Nothing addressable was found, so the account is marked as read. */
12
+ | "nothing-to-harvest" | "harvested"
13
+ /** A request failed; the marker stays unset and the next login retries. */
14
+ | "failed";
15
+ export interface QaRatingHarvestReport {
16
+ readonly status: QaRatingHarvestStatus;
17
+ /** Ratings this browser offered for that account. */
18
+ readonly entries: number;
19
+ /** Ratings the Host stored. What it already held counts as nothing. */
20
+ readonly recorded: number;
21
+ }
22
+ /** Whether this browser has already been read out for that account. */
23
+ export declare function ratingsHarvested(storage: HarvestStorage, namespace: string, accountId: string): boolean;
24
+ /**
25
+ * Every rating this browser holds for that namespace, addressed by the
26
+ * conversation and by the durable log position the Host files a verdict under.
27
+ *
28
+ * An answer row's browser id is `assistant:<position>`, so those keys are
29
+ * addressable. Anything else — a work row, a half-streamed answer, an id the
30
+ * Host named rather than numbered — cannot be traced back to a log position,
31
+ * and is left where it is instead of guessed at.
32
+ */
33
+ export declare function collectLocalRatings(storage: HarvestStorage, namespace: string): readonly QaFeedbackHarvestEntry[];
34
+ /**
35
+ * Read this browser's ratings out through `send`, once per account.
36
+ *
37
+ * `send` is the Host call; the caller chooses the token and the remote it
38
+ * travels on. The marker is written only after every batch landed, so a
39
+ * half-failed harvest is retried by the next login rather than lost.
40
+ */
41
+ export declare function harvestLocalRatings(options: {
42
+ readonly storage: HarvestStorage;
43
+ readonly namespace: string;
44
+ readonly accountId: string;
45
+ /** The chats the account owns; a rating of anyone else's chat is not offered. */
46
+ readonly ownedIds: readonly string[];
47
+ readonly send: (batch: readonly QaFeedbackHarvestEntry[]) => Promise<RemoteResult<QaFeedbackHarvestResult>>;
48
+ }): Promise<QaRatingHarvestReport>;
49
+ //# sourceMappingURL=rating-harvest.d.ts.map
@@ -15,10 +15,16 @@ export declare function QaRoleSelector(props: QaRoleSelectorProps): import("reac
15
15
  * is hidden — the previewed profile need not be one the account holds — so
16
16
  * without a control here the only exit was the browser's Back button, and a new
17
17
  * chat meanwhile ran as the previewed profile instead of the account's default.
18
- * @param props - the previewed role's name, and how to leave the preview.
18
+ *
19
+ * Leaving is a new chat, so the way out waits for the same moments the header's
20
+ * "Новый чат" and the role selector wait for: while a chat is still being
21
+ * created, this click would take the screen from the question on its way in.
22
+ * @param props - the previewed role's name, how to leave the preview, and whether
23
+ * that way is currently blocked by a chat being created.
19
24
  */
20
25
  export declare function QaAdminPreviewBanner(props: {
21
26
  readonly role: string;
22
27
  readonly onExit?: () => void;
28
+ readonly disabled?: boolean;
23
29
  }): import("react/jsx-runtime").JSX.Element;
24
30
  //# sourceMappingURL=RoleSelector.d.ts.map
@@ -8,16 +8,47 @@
8
8
  * mutation; the status view re-reads the Remote while the card is visible, so
9
9
  * a saved change is confirmed against the Host rather than against the form.
10
10
  */
11
- import type { SettingsScope } from "@deepseek-ai/dsh-client-ui-settings/client";
11
+ import type { ConfigForm } from "@deepseek-ai/dsh-client-ui-settings/client";
12
12
  import type { InjectFace, PropsRuntime } from "@deepseek-ai/dsh-client-ui-slots";
13
13
  import type { RemoteResult } from "@deepseek-ai/dsh-typert-protocol";
14
14
  import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "../../types.js";
15
- /** The face the slot entry injects into this card. */
15
+ /**
16
+ * The face the row seat injects into this card.
17
+ *
18
+ * The live form is named `settingsForm`, not `form`: the seat hands its
19
+ * registrant a `form` of its own — the page's `ConfigPageForm`, which is only
20
+ * `{ state, mutate }` (`formFor` in
21
+ * `@deepseek-ai/dsh-client-ui-plugin-manager/lib/client.js` snapshots the same
22
+ * namespace's form and forwards `mutate` and nothing else), so it can neither be
23
+ * subscribed to nor written field by field, and which the page leaves
24
+ * `undefined` for a Config declaring no volatile field — and the renderer
25
+ * spreads that owner prop after this face. The card therefore keeps resolving
26
+ * the full `ConfigForm` of its own namespace through `ctx.configForms` and takes
27
+ * no copy of the page's view.
28
+ */
16
29
  export interface QaSettingsCardFace {
17
- readonly scope: SettingsScope<QaSurfaceConfig>;
30
+ readonly settingsForm: ConfigForm<QaSurfaceConfig>;
18
31
  describe(): Promise<RemoteResult<ResolvedQaSurfaceConfig>>;
19
32
  }
20
- type CardProps = PropsRuntime<"settings.plugin.item"> & InjectFace<QaSettingsCardFace>;
21
- export declare function QaSettingsCard({ scope, describe }: CardProps): import("react/jsx-runtime").JSX.Element | null;
33
+ type CardProps = PropsRuntime<"plugins.row.config"> & InjectFace<QaSettingsCardFace>;
34
+ export declare function QaSettingsCard({ settingsForm, describe }: CardProps): import("react/jsx-runtime").JSX.Element;
35
+ /**
36
+ * The entry this plugin registers in the row's configuration seat.
37
+ *
38
+ * `RowDetail` in `@deepseek-ai/dsh-client-ui-plugin-manager/lib/client.js` can
39
+ * ask this seat for two shapes of the same entry: `view: 'summary'` as the row's
40
+ * one-liner and `view: 'page'` in the configuration column under the row's
41
+ * heading. Which of the two it asks for is the page's decision and §4.2 of
42
+ * `docs/DSH-0.1.7-MIGRATION.md` is where that is measured and stated — the row's
43
+ * description comes from the installed manifest, and the summary seat is the
44
+ * fallback for a row that declares none — so this bundle answers both without
45
+ * claiming either call is its own. The summary lands inside a line of the page's
46
+ * text, so it stays a sentence: a card seated there would draw a page within a
47
+ * line and start a second poll of the `qaSurface/describe` Remote. The page view
48
+ * is the body alone — the row's page already draws the card surface, the heading
49
+ * and the expand control, so a shell of ours would be a second frame inside the
50
+ * first (AGENTS.md, card-shell contract).
51
+ */
52
+ export declare function QaSettingsCardEntry(props: CardProps): "A focused end-user QA surface backed by native DeepSeek Harness sessions" | import("react/jsx-runtime").JSX.Element;
22
53
  export {};
23
54
  //# sourceMappingURL=card.d.ts.map