@yadsh/dsh-qa-surface 0.9.0 → 0.11.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 (250) hide show
  1. package/README.md +269 -2
  2. package/lib/access/service.js +49 -10
  3. package/lib/access/service.js.map +1 -1
  4. package/lib/account-remotes.js +41 -0
  5. package/lib/account-remotes.js.map +1 -1
  6. package/lib/accounts/database.js +140 -0
  7. package/lib/accounts/database.js.map +1 -1
  8. package/lib/accounts/errors.js.map +1 -1
  9. package/lib/accounts/service-token.js +103 -0
  10. package/lib/accounts/service-token.js.map +1 -0
  11. package/lib/accounts/store.js +291 -5
  12. package/lib/accounts/store.js.map +1 -1
  13. package/lib/admin/conversation-log.js +14 -8
  14. package/lib/admin/conversation-log.js.map +1 -1
  15. package/lib/admin/permissions.js +5 -0
  16. package/lib/admin/permissions.js.map +1 -1
  17. package/lib/admin/quality-store.js +4 -0
  18. package/lib/admin/quality-store.js.map +1 -1
  19. package/lib/admin/service.js +180 -7
  20. package/lib/admin/service.js.map +1 -1
  21. package/lib/admin/session-log.js +39 -8
  22. package/lib/admin/session-log.js.map +1 -1
  23. package/lib/attachment-rules.js +39 -6
  24. package/lib/attachment-rules.js.map +1 -1
  25. package/lib/cli.js +83 -1
  26. package/lib/cli.js.map +1 -1
  27. package/lib/client/QaAccountsController.js +213 -4
  28. package/lib/client/QaAccountsController.js.map +1 -1
  29. package/lib/client/QaSessionController.js +49 -21
  30. package/lib/client/QaSessionController.js.map +1 -1
  31. package/lib/client/QaSurface.js +51 -9
  32. package/lib/client/QaSurface.js.map +1 -1
  33. package/lib/client/QaSurfaceGuard.js +12 -5
  34. package/lib/client/QaSurfaceGuard.js.map +1 -1
  35. package/lib/client/admin/QaAdmin.js +14 -2
  36. package/lib/client/admin/QaAdmin.js.map +1 -1
  37. package/lib/client/admin/pages/SkillFiles.js +78 -0
  38. package/lib/client/admin/pages/SkillFiles.js.map +1 -0
  39. package/lib/client/admin/pages/Users.js +74 -3
  40. package/lib/client/admin/pages/Users.js.map +1 -1
  41. package/lib/client/admin/routes.js +8 -1
  42. package/lib/client/admin/routes.js.map +1 -1
  43. package/lib/client/admin/shared.js +5 -1
  44. package/lib/client/admin/shared.js.map +1 -1
  45. package/lib/client/admin/styles.js +2 -0
  46. package/lib/client/admin/styles.js.map +1 -1
  47. package/lib/client/attachments.js +41 -11
  48. package/lib/client/attachments.js.map +1 -1
  49. package/lib/client/base64.js +22 -1
  50. package/lib/client/base64.js.map +1 -1
  51. package/lib/client/components/QaAgentsDrawer.js +9 -6
  52. package/lib/client/components/QaAgentsDrawer.js.map +1 -1
  53. package/lib/client/components/QaApproval.js +1 -1
  54. package/lib/client/components/QaApproval.js.map +1 -1
  55. package/lib/client/components/QaAuthGate.js +19 -10
  56. package/lib/client/components/QaAuthGate.js.map +1 -1
  57. package/lib/client/components/QaChangelog.js +56 -0
  58. package/lib/client/components/QaChangelog.js.map +1 -1
  59. package/lib/client/components/QaFilesPanel.js +17 -11
  60. package/lib/client/components/QaFilesPanel.js.map +1 -1
  61. package/lib/client/components/QaHeader.js +3 -11
  62. package/lib/client/components/QaHeader.js.map +1 -1
  63. package/lib/client/components/QaModal.js.map +1 -1
  64. package/lib/client/components/QaQuestions.js +4 -4
  65. package/lib/client/components/QaQuestions.js.map +1 -1
  66. package/lib/client/components/QaSidebar.js +10 -2
  67. package/lib/client/components/QaSidebar.js.map +1 -1
  68. package/lib/client/components/QaWidthHandle.js +111 -5
  69. package/lib/client/components/QaWidthHandle.js.map +1 -1
  70. package/lib/client/components/QaWorkspaceBrowser.js +231 -0
  71. package/lib/client/components/QaWorkspaceBrowser.js.map +1 -0
  72. package/lib/client/index.js +122 -53
  73. package/lib/client/index.js.map +1 -1
  74. package/lib/client/kiosk.js +51 -0
  75. package/lib/client/kiosk.js.map +1 -0
  76. package/lib/client/lineage.js +64 -0
  77. package/lib/client/lineage.js.map +1 -1
  78. package/lib/client/markdown/blocks.js +122 -7
  79. package/lib/client/markdown/blocks.js.map +1 -1
  80. package/lib/client/markdown/inline.js +108 -12
  81. package/lib/client/markdown/inline.js.map +1 -1
  82. package/lib/client/markdown/katex-css.js +12 -0
  83. package/lib/client/markdown/katex-css.js.map +1 -0
  84. package/lib/client/markdown/math.js +84 -0
  85. package/lib/client/markdown/math.js.map +1 -0
  86. package/lib/client/markdown/render.js +74 -5
  87. package/lib/client/markdown/render.js.map +1 -1
  88. package/lib/client/settings/card.js +2 -2
  89. package/lib/client/settings/card.js.map +1 -1
  90. package/lib/client/settings/sections/attachments.js +6 -5
  91. package/lib/client/settings/sections/attachments.js.map +1 -1
  92. package/lib/client/settings/sections/notes.js +64 -0
  93. package/lib/client/settings/sections/notes.js.map +1 -0
  94. package/lib/client/settings/sections/sources.js +4 -1
  95. package/lib/client/settings/sections/sources.js.map +1 -1
  96. package/lib/client/settings/sections.js +1 -0
  97. package/lib/client/settings/sections.js.map +1 -1
  98. package/lib/client/settlement.js +1 -1
  99. package/lib/client/settlement.js.map +1 -1
  100. package/lib/client/source-preview.js +3 -0
  101. package/lib/client/source-preview.js.map +1 -1
  102. package/lib/client/styles.js +106 -18
  103. package/lib/client/styles.js.map +1 -1
  104. package/lib/client/types.js.map +1 -1
  105. package/lib/client/user-settings/IntegrationTokensPage.js +150 -0
  106. package/lib/client/user-settings/IntegrationTokensPage.js.map +1 -0
  107. package/lib/client/user-settings/PasswordSettingsPage.js +48 -0
  108. package/lib/client/user-settings/PasswordSettingsPage.js.map +1 -0
  109. package/lib/client/user-settings/SkillCatalog.js +2 -2
  110. package/lib/client/user-settings/SkillCatalog.js.map +1 -1
  111. package/lib/client/user-settings/UserSettingsDialog.js +17 -2
  112. package/lib/client/user-settings/UserSettingsDialog.js.map +1 -1
  113. package/lib/client/user-settings/copy.js +20 -0
  114. package/lib/client/user-settings/copy.js.map +1 -1
  115. package/lib/client.js +31007 -686
  116. package/lib/client.js.map +1 -1
  117. package/lib/config-resolvers/attachments.js +6 -5
  118. package/lib/config-resolvers/attachments.js.map +1 -1
  119. package/lib/config-resolvers/defaults.js +33 -2
  120. package/lib/config-resolvers/defaults.js.map +1 -1
  121. package/lib/config-resolvers/integration.js +94 -0
  122. package/lib/config-resolvers/integration.js.map +1 -0
  123. package/lib/config-resolvers/notes.js +26 -0
  124. package/lib/config-resolvers/notes.js.map +1 -0
  125. package/lib/config-resolvers/sources.js +4 -0
  126. package/lib/config-resolvers/sources.js.map +1 -1
  127. package/lib/config.js +107 -0
  128. package/lib/config.js.map +1 -1
  129. package/lib/index.js +348 -12
  130. package/lib/index.js.map +1 -1
  131. package/lib/integration/answer.js +100 -0
  132. package/lib/integration/answer.js.map +1 -0
  133. package/lib/integration/attachments.js +231 -0
  134. package/lib/integration/attachments.js.map +1 -0
  135. package/lib/integration/contract.js +53 -0
  136. package/lib/integration/contract.js.map +1 -0
  137. package/lib/integration/host-runner.js +243 -0
  138. package/lib/integration/host-runner.js.map +1 -0
  139. package/lib/integration/http.js +538 -0
  140. package/lib/integration/http.js.map +1 -0
  141. package/lib/integration/service.js +331 -0
  142. package/lib/integration/service.js.map +1 -0
  143. package/lib/integration/transcript-reader.js +202 -0
  144. package/lib/integration/transcript-reader.js.map +1 -0
  145. package/lib/integration/transcript.js +148 -0
  146. package/lib/integration/transcript.js.map +1 -0
  147. package/lib/personal-skills/index.js +2 -2
  148. package/lib/personal-skills/index.js.map +1 -1
  149. package/lib/personal-skills/paths.js +14 -8
  150. package/lib/personal-skills/paths.js.map +1 -1
  151. package/lib/personal-skills/provider.js +16 -4
  152. package/lib/personal-skills/provider.js.map +1 -1
  153. package/lib/personal-skills/service.js +240 -30
  154. package/lib/personal-skills/service.js.map +1 -1
  155. package/lib/prompt-notes.js +103 -6
  156. package/lib/prompt-notes.js.map +1 -1
  157. package/lib/provenance/document-preview.js +60 -0
  158. package/lib/provenance/document-preview.js.map +1 -0
  159. package/lib/provenance/file-preview.js +191 -19
  160. package/lib/provenance/file-preview.js.map +1 -1
  161. package/lib/qa-tools/catalog.js +18 -1
  162. package/lib/qa-tools/catalog.js.map +1 -1
  163. package/lib/qa-tools/docs-tools.js +563 -0
  164. package/lib/qa-tools/docs-tools.js.map +1 -0
  165. package/lib/qa-tools/file-delete-gate.js +60 -0
  166. package/lib/qa-tools/file-delete-gate.js.map +1 -0
  167. package/lib/qa-tools/file-delete.js +156 -0
  168. package/lib/qa-tools/file-delete.js.map +1 -0
  169. package/lib/resolve-config.js +6 -0
  170. package/lib/resolve-config.js.map +1 -1
  171. package/lib/secure-session.js +83 -3
  172. package/lib/secure-session.js.map +1 -1
  173. package/lib/shared/documents.js +22 -0
  174. package/lib/shared/documents.js.map +1 -0
  175. package/lib/shared/integration-tokens.js +23 -0
  176. package/lib/shared/integration-tokens.js.map +1 -0
  177. package/lib/typert.host.js +1320 -134
  178. package/lib/typert.remote-client.d.ts +33 -1
  179. package/lib/typert.remote-client.js +1102 -74
  180. package/lib/types/access/service.d.ts +33 -2
  181. package/lib/types/account-remotes.d.ts +30 -1
  182. package/lib/types/accounts/database.d.ts +53 -0
  183. package/lib/types/accounts/errors.d.ts +5 -1
  184. package/lib/types/accounts/service-token.d.ts +70 -0
  185. package/lib/types/accounts/store.d.ts +131 -1
  186. package/lib/types/admin/conversation-log.d.ts +12 -0
  187. package/lib/types/admin/service.d.ts +56 -1
  188. package/lib/types/admin/session-log.d.ts +21 -0
  189. package/lib/types/attachment-rules.d.ts +26 -3
  190. package/lib/types/client/QaAccountsController.d.ts +64 -5
  191. package/lib/types/client/QaSessionController.d.ts +24 -2
  192. package/lib/types/client/admin/pages/SkillFiles.d.ts +17 -0
  193. package/lib/types/client/admin/routes.d.ts +2 -0
  194. package/lib/types/client/admin/shared.d.ts +2 -0
  195. package/lib/types/client/attachments.d.ts +21 -4
  196. package/lib/types/client/base64.d.ts +13 -1
  197. package/lib/types/client/components/QaAgentsDrawer.d.ts +2 -1
  198. package/lib/types/client/components/QaFilesPanel.d.ts +16 -4
  199. package/lib/types/client/components/QaHeader.d.ts +9 -3
  200. package/lib/types/client/components/QaModal.d.ts +4 -3
  201. package/lib/types/client/components/QaWidthHandle.d.ts +48 -2
  202. package/lib/types/client/components/QaWorkspaceBrowser.d.ts +15 -0
  203. package/lib/types/client/index.d.ts +1 -1
  204. package/lib/types/client/kiosk.d.ts +34 -0
  205. package/lib/types/client/lineage.d.ts +42 -0
  206. package/lib/types/client/markdown/blocks.d.ts +14 -1
  207. package/lib/types/client/markdown/inline.d.ts +23 -7
  208. package/lib/types/client/markdown/katex-css.d.ts +11 -0
  209. package/lib/types/client/markdown/math.d.ts +23 -0
  210. package/lib/types/client/markdown/render.d.ts +2 -1
  211. package/lib/types/client/settings/sections/notes.d.ts +12 -0
  212. package/lib/types/client/settings/sections.d.ts +1 -0
  213. package/lib/types/client/settlement.d.ts +4 -1
  214. package/lib/types/client/styles.d.ts +15 -2
  215. package/lib/types/client/types.d.ts +120 -1
  216. package/lib/types/client/user-settings/IntegrationTokensPage.d.ts +21 -0
  217. package/lib/types/client/user-settings/PasswordSettingsPage.d.ts +19 -0
  218. package/lib/types/client/user-settings/UserSettingsDialog.d.ts +11 -2
  219. package/lib/types/client/user-settings/copy.d.ts +10 -1
  220. package/lib/types/config-resolvers/integration.d.ts +47 -0
  221. package/lib/types/config-resolvers/notes.d.ts +10 -0
  222. package/lib/types/config.d.ts +10 -0
  223. package/lib/types/index.d.ts +111 -1
  224. package/lib/types/integration/answer.d.ts +65 -0
  225. package/lib/types/integration/attachments.d.ts +85 -0
  226. package/lib/types/integration/contract.d.ts +196 -0
  227. package/lib/types/integration/host-runner.d.ts +44 -0
  228. package/lib/types/integration/http.d.ts +79 -0
  229. package/lib/types/integration/service.d.ts +120 -0
  230. package/lib/types/integration/transcript-reader.d.ts +100 -0
  231. package/lib/types/integration/transcript.d.ts +59 -0
  232. package/lib/types/personal-skills/index.d.ts +2 -2
  233. package/lib/types/personal-skills/paths.d.ts +15 -3
  234. package/lib/types/personal-skills/provider.d.ts +14 -2
  235. package/lib/types/personal-skills/service.d.ts +89 -14
  236. package/lib/types/prompt-notes.d.ts +37 -0
  237. package/lib/types/provenance/document-preview.d.ts +28 -0
  238. package/lib/types/provenance/file-preview.d.ts +69 -2
  239. package/lib/types/qa-tools/catalog.d.ts +1 -1
  240. package/lib/types/qa-tools/docs-tools.d.ts +160 -0
  241. package/lib/types/qa-tools/file-delete-gate.d.ts +42 -0
  242. package/lib/types/qa-tools/file-delete.d.ts +32 -0
  243. package/lib/types/secure-session.d.ts +52 -1
  244. package/lib/types/shared/documents.d.ts +20 -0
  245. package/lib/types/shared/integration-tokens.d.ts +24 -0
  246. package/lib/types/types.d.ts +263 -3
  247. package/lib/types/ui-mode.d.ts +18 -0
  248. package/lib/ui-mode.js +22 -0
  249. package/lib/ui-mode.js.map +1 -0
  250. package/package.json +12 -10
@@ -42,7 +42,9 @@ export interface QaQuestionAnswerItem {
42
42
  */
43
43
  export type QaAccountRole = "user" | "reviewer" | "admin";
44
44
  /** Administrative permissions a role grants; see `admin/permissions.ts`. */
45
- export type QaPermission = "users.read" | "users.manage" | "roles.read" | "roles.manage" | "conversations.read.all" | "conversations.read.own" | "conversations.delete" | "reviews.read" | "reviews.write" | "analytics.read" | "audit.read" | "settings.manage";
45
+ export type QaPermission = "users.read" | "users.manage" | "roles.read" | "roles.manage" | "conversations.read.all" | "conversations.read.own" | "conversations.delete" | "reviews.read" | "reviews.write" | "analytics.read" | "audit.read" | "settings.manage"
46
+ /** Write access to skill files, personal and deployment-wide. */
47
+ | "skills.manage";
46
48
  /**
47
49
  * Tools split by how they become available. `always` is visible from the first
48
50
  * model step; `skillGrantable` is a ceiling — the tool only appears once an
@@ -342,6 +344,21 @@ export interface QaAccountSession {
342
344
  readonly token: string;
343
345
  readonly user: QaAccountUserPublic;
344
346
  }
347
+ /**
348
+ * One forgotten-password request waiting for an operator. The address and name
349
+ * travel with it so the console can show who is locked out without a second
350
+ * lookup; the count makes repeated taps visible instead of silent.
351
+ */
352
+ export interface QaPasswordResetRequest {
353
+ readonly userId: string;
354
+ readonly email: string;
355
+ readonly displayName: string;
356
+ readonly requestedAt: string;
357
+ readonly lastRequestedAt: string;
358
+ readonly requestCount: number;
359
+ /** True when the account is disabled: a reset will not let it sign in. */
360
+ readonly disabled: boolean;
361
+ }
345
362
  export type QaWhoamiResult = {
346
363
  readonly authenticated: false;
347
364
  } | {
@@ -354,6 +371,45 @@ export interface QaClaimResult {
354
371
  /** Ids already owned by a different user; the browser drops them. */
355
372
  readonly conflicts: readonly string[];
356
373
  }
374
+ /**
375
+ * What an integration token may do. The credential a non-browser application
376
+ * presents to the QA HTTP API carries its own scopes, so a bridge that asks
377
+ * questions cannot read back conversations it was never given.
378
+ */
379
+ export type QaServiceTokenScope = "ask" | "sessions:read";
380
+ /**
381
+ * What an account asks a new integration token to be. The credential is always
382
+ * issued to the caller: nothing a browser sends may name another account, so
383
+ * this shape has no owner field and the administrative path keeps its own.
384
+ */
385
+ export interface QaServiceTokenCreateInput {
386
+ /** A note the operator's list shows; empty becomes a generic label. */
387
+ readonly label?: string;
388
+ /** Requested scopes; unknown ones are dropped, empty falls back to `ask`. */
389
+ readonly scopes?: readonly string[];
390
+ /** How long the token lives, in days; bounded server-side. */
391
+ readonly ttlDays?: number;
392
+ }
393
+ /**
394
+ * One integration token as a list shows it. The plaintext is deliberately not
395
+ * part of this shape: a secret is shown once, when it is minted, and a list
396
+ * that could repeat it would be a list that leaks it.
397
+ */
398
+ export interface QaServiceTokenSummary {
399
+ readonly id: string;
400
+ readonly label: string;
401
+ readonly scopes: readonly QaServiceTokenScope[];
402
+ readonly createdAt: string;
403
+ readonly expiresAt: string;
404
+ readonly lastUsedAt: string | null;
405
+ readonly revokedAt: string | null;
406
+ readonly useCount: number;
407
+ }
408
+ /** One freshly minted token: the plaintext is here and nowhere else, ever. */
409
+ export interface QaIssuedServiceToken extends QaServiceTokenSummary {
410
+ /** The credential to hand to the integration. Never recoverable later. */
411
+ readonly token: string;
412
+ }
357
413
  /**
358
414
  * One chat-ownership entry as the admin views see it: the session, its owner
359
415
  * and the owner's display name resolved at read time (a disabled account
@@ -388,6 +444,44 @@ export type QaSkillJsonValue = string | number | boolean | null | readonly QaSki
388
444
  readonly [key: string]: QaSkillJsonValue;
389
445
  };
390
446
  /** One personal skill as the catalog list renders it. */
447
+ /**
448
+ * One administrator write to a skill somebody else owns.
449
+ *
450
+ * The record exists so a personal skill cannot be changed behind its owner's
451
+ * back: it is written beside the skill and reported on every read, and the
452
+ * owner sees the badge in their own catalog.
453
+ */
454
+ export interface QaSkillAdminEdit {
455
+ /** Administrator account id; the owner is told a role, not a colleague. */
456
+ readonly actorId: string;
457
+ /** ISO timestamp of that write. */
458
+ readonly at: string;
459
+ }
460
+ /**
461
+ * Which skill store an administrator is editing: the deployment-wide shared
462
+ * root every account may read, or one account's own directory.
463
+ */
464
+ export type QaAdminSkillScope = {
465
+ readonly kind: "shared";
466
+ } | {
467
+ readonly kind: "user";
468
+ readonly userId: string;
469
+ };
470
+ /** The account a personal skill scope belongs to, for the console's header. */
471
+ export interface QaAdminSkillOwner {
472
+ readonly userId: string;
473
+ readonly email: string;
474
+ readonly displayName: string;
475
+ }
476
+ /** One scope's catalog plus the facts the console names it by. */
477
+ export interface QaAdminSkillsView {
478
+ readonly scope: QaAdminSkillScope;
479
+ /** The account of a personal scope; null for the shared root. */
480
+ readonly owner: QaAdminSkillOwner | null;
481
+ readonly skills: readonly QaSkillSummary[];
482
+ /** Absolute directory this scope reads and writes, rendered read-only. */
483
+ readonly rootPath: string;
484
+ }
391
485
  export interface QaSkillSummary {
392
486
  readonly name: string;
393
487
  readonly description: string;
@@ -405,6 +499,13 @@ export interface QaSkillSummary {
405
499
  readonly updatedAt: string | null;
406
500
  /** sha256 of the stored bytes; an update must echo the revision it read. */
407
501
  readonly revision: string;
502
+ /**
503
+ * The administrator write that produced the stored revision, or null. A
504
+ * record whose revision no longer matches is stale and reports as null: the
505
+ * badge answers "did an administrator write what I am looking at", not
506
+ * "was this skill ever touched by an administrator".
507
+ */
508
+ readonly adminEdit: QaSkillAdminEdit | null;
408
509
  }
409
510
  /** One personal skill with everything the editor needs. */
410
511
  export interface QaSkillDocument extends QaSkillSummary {
@@ -489,6 +590,7 @@ export interface QaSourcesConfig {
489
590
  readonly allowRawToggle?: boolean;
490
591
  readonly maxBytes?: number;
491
592
  readonly maxMarkdownRenderBytes?: number;
593
+ readonly maxListingEntries?: number;
492
594
  };
493
595
  readonly subagents?: {
494
596
  readonly inheritSources?: boolean;
@@ -504,6 +606,40 @@ export interface QaSourcesConfig {
504
606
  readonly parseAssistantSourcesBlock?: boolean;
505
607
  };
506
608
  }
609
+ /**
610
+ * The ambient notes the injector writes into a QA chat as plugin-sourced user
611
+ * messages (`prompt-notes.ts`). Each note can be switched off and reworded;
612
+ * an empty template keeps the built-in wording.
613
+ */
614
+ export interface QaNotesConfig {
615
+ /** Who the assistant is talking to; `{identity}` + `{instructions}`. */
616
+ readonly identity?: {
617
+ readonly enabled?: boolean;
618
+ readonly template?: string;
619
+ };
620
+ /** Source-provenance rules; `{reportTool}` names the subagent report tool. */
621
+ readonly sources?: {
622
+ readonly enabled?: boolean;
623
+ readonly template?: string;
624
+ /** The sentence appended when the report-tool fallback is on. */
625
+ readonly fallbackTemplate?: string;
626
+ };
627
+ /** How to label background delegations; no placeholders. */
628
+ readonly delegation?: {
629
+ readonly enabled?: boolean;
630
+ readonly template?: string;
631
+ };
632
+ /** Which reader an attached office document belongs to; no placeholders. */
633
+ readonly documents?: {
634
+ readonly enabled?: boolean;
635
+ readonly template?: string;
636
+ };
637
+ /** Where an answer should come from; no placeholders. */
638
+ readonly sourcePriority?: {
639
+ readonly enabled?: boolean;
640
+ readonly template?: string;
641
+ };
642
+ }
507
643
  export interface QaSurfaceConfig {
508
644
  readonly enabled?: boolean;
509
645
  readonly route?: {
@@ -684,6 +820,43 @@ export interface QaSurfaceConfig {
684
820
  };
685
821
  readonly sources?: QaSourcesConfig;
686
822
  readonly attachments?: QaAttachmentsConfig;
823
+ readonly notes?: QaNotesConfig;
824
+ readonly integration?: QaIntegrationConfig;
825
+ }
826
+ /**
827
+ * The HTTP API an external application (the ticket bridge) uses to ask
828
+ * questions and read its own conversations back: `POST {basePath}/ask`,
829
+ * `GET {basePath}/session` and `GET {basePath}/health`, authenticated with an
830
+ * account's integration token. Off unless a deployment asks for it.
831
+ */
832
+ export interface QaIntegrationConfig {
833
+ /** Serve the API at all. Requires accounts; off by default. */
834
+ readonly enabled?: boolean;
835
+ /** Route namespace; the endpoints all hang off it. */
836
+ readonly basePath?: string;
837
+ /** Default lifetime of a minted integration token, in days. */
838
+ readonly tokenTtlDays?: number;
839
+ /**
840
+ * Wall-clock budget for one question. The endpoint answers within it — with
841
+ * an escalation when the turn is still running — because the caller's own
842
+ * timeout is a fixed part of the contract.
843
+ */
844
+ readonly requestTimeoutMs?: number;
845
+ /** Questions answered at the same time, deployment wide. */
846
+ readonly maxConcurrent?: number;
847
+ /** Requests one token may make per rolling minute. */
848
+ readonly requestsPerMinute?: number;
849
+ /** Ceiling on one request body, in bytes. */
850
+ readonly maxRequestBytes?: number;
851
+ /** Ceiling on one inline image attachment, in bytes. */
852
+ readonly maxAttachmentBytes?: number;
853
+ /**
854
+ * Ceiling on the published answer, in characters. The caller posts it into a
855
+ * ticket comment, whose own budget is smaller than a model's answer, and a
856
+ * cut made here at a paragraph boundary is readable where the caller's own
857
+ * silent truncation is not.
858
+ */
859
+ readonly maxAnswerCharacters?: number;
687
860
  }
688
861
  /** What a QA visitor may attach to one message. */
689
862
  export interface QaAttachmentsConfig {
@@ -854,6 +1027,7 @@ export interface ResolvedQaSurfaceConfig {
854
1027
  readonly allowRawToggle: boolean;
855
1028
  readonly maxBytes: number;
856
1029
  readonly maxMarkdownRenderBytes: number;
1030
+ readonly maxListingEntries: number;
857
1031
  };
858
1032
  readonly subagents: {
859
1033
  readonly inheritSources: boolean;
@@ -872,6 +1046,40 @@ export interface ResolvedQaSurfaceConfig {
872
1046
  readonly maxPending: number;
873
1047
  readonly extensions: readonly string[];
874
1048
  };
1049
+ readonly notes: {
1050
+ readonly identity: {
1051
+ readonly enabled: boolean;
1052
+ readonly template: string;
1053
+ };
1054
+ readonly sources: {
1055
+ readonly enabled: boolean;
1056
+ readonly template: string;
1057
+ readonly fallbackTemplate: string;
1058
+ };
1059
+ readonly delegation: {
1060
+ readonly enabled: boolean;
1061
+ readonly template: string;
1062
+ };
1063
+ readonly documents: {
1064
+ readonly enabled: boolean;
1065
+ readonly template: string;
1066
+ };
1067
+ readonly sourcePriority: {
1068
+ readonly enabled: boolean;
1069
+ readonly template: string;
1070
+ };
1071
+ };
1072
+ readonly integration: {
1073
+ readonly enabled: boolean;
1074
+ readonly basePath: string;
1075
+ readonly tokenTtlDays: number;
1076
+ readonly requestTimeoutMs: number;
1077
+ readonly maxConcurrent: number;
1078
+ readonly requestsPerMinute: number;
1079
+ readonly maxRequestBytes: number;
1080
+ readonly maxAttachmentBytes: number;
1081
+ readonly maxAnswerCharacters: number;
1082
+ };
875
1083
  }
876
1084
  /** Which native registry one unified entry came from. */
877
1085
  export type QaSlashEntryKind = "skill" | "command";
@@ -1038,6 +1246,51 @@ export interface QaSourceFilePreview {
1038
1246
  readonly markdown: boolean;
1039
1247
  readonly renderableMarkdown: boolean;
1040
1248
  }
1249
+ /**
1250
+ * A file the panel renders by conversion rather than by bytes: the document
1251
+ * pipeline turned a Word file into PDF, and the browser shows that PDF.
1252
+ */
1253
+ export interface QaDocumentPreview {
1254
+ readonly kind: "pdf";
1255
+ readonly base64: string;
1256
+ readonly mime: "application/pdf";
1257
+ readonly name: string;
1258
+ readonly bytes: number;
1259
+ }
1260
+ /** One directory entry of a chat's own workspace, as the files panel browses it. */
1261
+ export interface QaWorkspaceEntry {
1262
+ readonly name: string;
1263
+ readonly type: "file" | "directory";
1264
+ readonly size: number | null;
1265
+ }
1266
+ /**
1267
+ * One directory of the chat's workspace. `path` is the canonical form of the
1268
+ * directory as requested — the chat root itself is the empty string — so the
1269
+ * panel can build a breadcrumb without another round trip.
1270
+ */
1271
+ export interface QaWorkspaceListing {
1272
+ readonly path: string;
1273
+ readonly entries: readonly QaWorkspaceEntry[];
1274
+ /** More children existed than one listing carries. */
1275
+ readonly truncated: boolean;
1276
+ }
1277
+ /**
1278
+ * One file of the chat's workspace: decoded text when it reads as UTF-8, base64
1279
+ * bytes when it does not. The panel needs both — documents the agent produced
1280
+ * are binary, while notes and transcripts preview as text.
1281
+ */
1282
+ export interface QaWorkspaceFile {
1283
+ readonly path: string;
1284
+ readonly size: number;
1285
+ readonly truncated: boolean;
1286
+ readonly markdown: boolean;
1287
+ readonly renderableMarkdown: boolean;
1288
+ readonly mime: string;
1289
+ /** Present when the file decoded as text; absent for binary content. */
1290
+ readonly text?: string;
1291
+ /** Present when the file is not text; base64 of at most the byte cap. */
1292
+ readonly base64?: string;
1293
+ }
1041
1294
  /** Host-attested facts required before the QA composer may become writable. */
1042
1295
  export interface QaLockdownProof {
1043
1296
  readonly sessionId: string;
@@ -1357,7 +1610,9 @@ export interface QaReviewQueueItem {
1357
1610
  readonly feedbackId?: string;
1358
1611
  }
1359
1612
  /** Administrative actions recorded in the audit trail. */
1360
- export type QaAdminAuditAction = "user.created" | "user.updated" | "user.enabled" | "user.disabled" | "authorization.changed" | "subrole.assignment.changed" | "subrole.created" | "subrole.updated" | "subrole.deleted" | "common_capabilities.updated" | "conversation.reviewed" | "conversation.deleted" | "review.updated" | "review.queued" | "admin.settings.updated";
1613
+ export type QaAdminAuditAction = "user.created" | "user.updated" | "user.enabled" | "user.disabled"
1614
+ /** An operator set a new password for an account that had requested one. */
1615
+ | "user.password-reset" | "authorization.changed" | "subrole.assignment.changed" | "subrole.created" | "subrole.updated" | "subrole.deleted" | "common_capabilities.updated" | "conversation.reviewed" | "conversation.deleted" | "review.updated" | "review.queued" | "admin.settings.updated" | "skill.created" | "skill.updated" | "skill.deleted";
1361
1616
  export interface QaAdminAuditEvent {
1362
1617
  readonly id: string;
1363
1618
  readonly timestamp: string;
@@ -1614,7 +1869,12 @@ export interface QaAdminUserDetail {
1614
1869
  }[];
1615
1870
  readonly activity: {
1616
1871
  readonly conversations: number;
1617
- readonly messages: number;
1872
+ /**
1873
+ * Unknown until the conversations page is opened: the count needs every
1874
+ * conversation's log read, so the detail card reports null instead of
1875
+ * blocking its payload on the scan.
1876
+ */
1877
+ readonly messages: number | null;
1618
1878
  readonly positiveRatings: number;
1619
1879
  readonly negativeRatings: number;
1620
1880
  };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The deployment UI mode, as the host half of the plugin sees it.
3
+ *
4
+ * `DSH_UI_MODE=qa` (the kiosk) moves the frontend URL-space ownership from
5
+ * this plugin to the harness: the harness route policy serves `/qa` directly,
6
+ * redirects `/` into it, and answers every other frontend path with 404. The
7
+ * plugin's own navigation redirect route must then stay unregistered — it
8
+ * exists for the overlay composition, where the index is served at `/` and a
9
+ * browser navigation to `/qa` has to bounce through the marker hand-off —
10
+ * because a registered route shadows the harness fallback seat and would
11
+ * loop every `/qa` navigation back onto itself.
12
+ */
13
+ /**
14
+ * Whether this harness process runs the QA kiosk UI mode.
15
+ * @param env - the process environment; overridable for tests.
16
+ */
17
+ export declare function qaKioskDeployment(env?: Readonly<Record<string, string | undefined>>): boolean;
18
+ //# sourceMappingURL=ui-mode.d.ts.map
package/lib/ui-mode.js ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The deployment UI mode, as the host half of the plugin sees it.
3
+ *
4
+ * `DSH_UI_MODE=qa` (the kiosk) moves the frontend URL-space ownership from
5
+ * this plugin to the harness: the harness route policy serves `/qa` directly,
6
+ * redirects `/` into it, and answers every other frontend path with 404. The
7
+ * plugin's own navigation redirect route must then stay unregistered — it
8
+ * exists for the overlay composition, where the index is served at `/` and a
9
+ * browser navigation to `/qa` has to bounce through the marker hand-off —
10
+ * because a registered route shadows the harness fallback seat and would
11
+ * loop every `/qa` navigation back onto itself.
12
+ */
13
+ /** Environment variable selecting the deployment UI mode (`qa` = kiosk). */
14
+ const UI_MODE_ENV = "DSH_UI_MODE";
15
+ /**
16
+ * Whether this harness process runs the QA kiosk UI mode.
17
+ * @param env - the process environment; overridable for tests.
18
+ */
19
+ export function qaKioskDeployment(env = process.env) {
20
+ return (env[UI_MODE_ENV] ?? "").trim() === "qa";
21
+ }
22
+ //# sourceMappingURL=ui-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-mode.js","sourceRoot":"","sources":["../src/ui-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,4EAA4E;AAC5E,MAAM,WAAW,GAAG,aAAa,CAAC;AAElC;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAG,GAAiD,OAAO,CAAC,GAAG;IAE/D,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC;AAClD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yadsh/dsh-qa-surface",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "A focused end-user QA surface backed by native DeepSeek Harness sessions",
5
5
  "repository": {
6
6
  "type": "git",
@@ -102,15 +102,14 @@
102
102
  },
103
103
  "peerDependencies": {
104
104
  "@deepseek-ai/cordis": "^4.0.2",
105
- "@deepseek-ai/schemastery": "^3.18.2",
106
- "@deepseek-ai/dsh-api-gateway": ">=0.1.5-rc.2 <0.2.0",
107
105
  "@deepseek-ai/dsh-agent": ">=0.1.5-rc.2 <0.2.0",
108
106
  "@deepseek-ai/dsh-agent-presets": ">=0.1.5-rc.2 <0.2.0",
107
+ "@deepseek-ai/dsh-api-gateway": ">=0.1.5-rc.2 <0.2.0",
109
108
  "@deepseek-ai/dsh-api-session-controller": ">=0.1.5-rc.2 <0.2.0",
110
109
  "@deepseek-ai/dsh-api-workspace-controller": ">=0.1.5-rc.2 <0.2.0",
111
110
  "@deepseek-ai/dsh-client-connection": ">=0.1.5-rc.2 <0.2.0",
112
- "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.5-rc.2 <0.2.0",
113
111
  "@deepseek-ai/dsh-client-ui-chat": ">=0.1.5-rc.2 <0.2.0",
112
+ "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.5-rc.2 <0.2.0",
114
113
  "@deepseek-ai/dsh-client-ui-layout": ">=0.1.5-rc.2 <0.2.0",
115
114
  "@deepseek-ai/dsh-client-ui-renderer": ">=0.1.5-rc.2 <0.2.0",
116
115
  "@deepseek-ai/dsh-client-ui-settings": ">=0.1.5-rc.2 <0.2.0",
@@ -127,28 +126,29 @@
127
126
  "@deepseek-ai/dsh-tools": ">=0.1.5-rc.2 <0.2.0",
128
127
  "@deepseek-ai/dsh-typert-protocol": ">=0.1.5-rc.2 <0.2.0",
129
128
  "@deepseek-ai/dsh-workspace": ">=0.1.5-rc.2 <0.2.0",
129
+ "@deepseek-ai/schemastery": "^3.18.2",
130
130
  "react": "^18.2.0",
131
131
  "react-dom": "^18.2.0"
132
132
  },
133
133
  "dependencies": {
134
134
  "yaml": "^2.9.0",
135
135
  "zod": "^4.4.3",
136
- "@yadsh/dsh-audit-ui": "^0.1.0",
137
136
  "@yadsh/dsh-audit-core": "^0.1.0",
138
- "@yadsh/dsh-plugin-kit": "^0.3.0",
139
- "@yadsh/dsh-plugin-log": "^0.4.0"
137
+ "@yadsh/dsh-audit-ui": "^0.1.0",
138
+ "@yadsh/dsh-documents": "^0.5.0",
139
+ "@yadsh/dsh-plugin-log": "^0.4.0",
140
+ "@yadsh/dsh-plugin-kit": "^0.3.0"
140
141
  },
141
142
  "devDependencies": {
142
143
  "@deepseek-ai/cordis": "4.0.2",
143
- "@deepseek-ai/schemastery": "3.18.2",
144
- "@deepseek-ai/dsh-api-gateway": "0.1.5-rc.2",
145
144
  "@deepseek-ai/dsh-agent": "0.1.5-rc.2",
146
145
  "@deepseek-ai/dsh-agent-presets": "0.1.5-rc.2",
146
+ "@deepseek-ai/dsh-api-gateway": "0.1.5-rc.2",
147
147
  "@deepseek-ai/dsh-api-session-controller": "0.1.5-rc.2",
148
148
  "@deepseek-ai/dsh-api-workspace-controller": "0.1.5-rc.2",
149
149
  "@deepseek-ai/dsh-client-connection": "0.1.5-rc.2",
150
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.5-rc.2",
151
150
  "@deepseek-ai/dsh-client-ui-chat": "0.1.5-rc.2",
151
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.5-rc.2",
152
152
  "@deepseek-ai/dsh-client-ui-layout": "0.1.5-rc.2",
153
153
  "@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.2",
154
154
  "@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.2",
@@ -167,12 +167,14 @@
167
167
  "@deepseek-ai/dsh-typert-generator": "0.1.5-rc.2",
168
168
  "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2",
169
169
  "@deepseek-ai/dsh-workspace": "0.1.5-rc.2",
170
+ "@deepseek-ai/schemastery": "3.18.2",
170
171
  "@testing-library/react": "^16.3.0",
171
172
  "@types/node": "^26.4.0",
172
173
  "@types/react": "18.3.28",
173
174
  "@types/react-dom": "18.3.7",
174
175
  "eslint": "10.9.1",
175
176
  "jsdom": "^26.1.0",
177
+ "katex": "^0.16.47",
176
178
  "playwright": "1.62.1",
177
179
  "react": "18.3.1",
178
180
  "react-dom": "18.3.1",