@yadsh/dsh-qa-surface 0.3.0 → 0.4.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 (245) hide show
  1. package/README.md +153 -12
  2. package/lib/account-remotes.js +100 -0
  3. package/lib/account-remotes.js.map +1 -0
  4. package/lib/accounts/credentials.js +27 -0
  5. package/lib/accounts/credentials.js.map +1 -0
  6. package/lib/accounts/errors.js +9 -0
  7. package/lib/accounts/errors.js.map +1 -0
  8. package/lib/accounts/file.js +101 -0
  9. package/lib/accounts/file.js.map +1 -0
  10. package/lib/accounts/store.js +144 -161
  11. package/lib/accounts/store.js.map +1 -1
  12. package/lib/accounts/token.js +61 -0
  13. package/lib/accounts/token.js.map +1 -0
  14. package/lib/attachment-rules.js +111 -0
  15. package/lib/attachment-rules.js.map +1 -0
  16. package/lib/cli.js +122 -9
  17. package/lib/cli.js.map +1 -1
  18. package/lib/client/QaAccountsController.js +32 -2
  19. package/lib/client/QaAccountsController.js.map +1 -1
  20. package/lib/client/QaSessionController.js +47 -65
  21. package/lib/client/QaSessionController.js.map +1 -1
  22. package/lib/client/QaSurface.js +121 -107
  23. package/lib/client/QaSurface.js.map +1 -1
  24. package/lib/client/QaTranscriptAdapter.js +71 -6
  25. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  26. package/lib/client/attachments.js +150 -0
  27. package/lib/client/attachments.js.map +1 -0
  28. package/lib/client/attestation.js +1 -1
  29. package/lib/client/attestation.js.map +1 -1
  30. package/lib/client/base64.js +16 -0
  31. package/lib/client/base64.js.map +1 -0
  32. package/lib/client/chat-files.js +48 -0
  33. package/lib/client/chat-files.js.map +1 -0
  34. package/lib/client/components/Markdown.js +1 -1
  35. package/lib/client/components/Markdown.js.map +1 -1
  36. package/lib/client/components/QaChangelog.js +38 -19
  37. package/lib/client/components/QaChangelog.js.map +1 -1
  38. package/lib/client/components/QaComposer.js +56 -74
  39. package/lib/client/components/QaComposer.js.map +1 -1
  40. package/lib/client/components/QaFileAttachment.js +19 -0
  41. package/lib/client/components/QaFileAttachment.js.map +1 -0
  42. package/lib/client/components/QaFilesPanel.js +45 -0
  43. package/lib/client/components/QaFilesPanel.js.map +1 -0
  44. package/lib/client/components/QaHeader.js +34 -0
  45. package/lib/client/components/QaHeader.js.map +1 -0
  46. package/lib/client/components/QaMessage.js +17 -4
  47. package/lib/client/components/QaMessage.js.map +1 -1
  48. package/lib/client/components/QaModal.js +31 -0
  49. package/lib/client/components/QaModal.js.map +1 -0
  50. package/lib/client/components/QaProfile.js +64 -0
  51. package/lib/client/components/QaProfile.js.map +1 -0
  52. package/lib/client/components/QaRightRail.js +15 -0
  53. package/lib/client/components/QaRightRail.js.map +1 -0
  54. package/lib/client/components/QaSidebar.js +6 -1
  55. package/lib/client/components/QaSidebar.js.map +1 -1
  56. package/lib/client/components/{QaSourcesDrawer.js → QaSourcesPanel.js} +3 -3
  57. package/lib/client/components/QaSourcesPanel.js.map +1 -0
  58. package/lib/client/components/QaTurnRail.js +15 -0
  59. package/lib/client/components/QaTurnRail.js.map +1 -1
  60. package/lib/client/components/QaWidthHandle.js +25 -20
  61. package/lib/client/components/QaWidthHandle.js.map +1 -1
  62. package/lib/client/components/QaWorkGroup.js +19 -20
  63. package/lib/client/components/QaWorkGroup.js.map +1 -1
  64. package/lib/client/components/surface-utils.js +28 -0
  65. package/lib/client/components/surface-utils.js.map +1 -0
  66. package/lib/client/components/thinking-phrases.js +24 -0
  67. package/lib/client/components/thinking-phrases.js.map +1 -0
  68. package/lib/client/create-session.js +7 -32
  69. package/lib/client/create-session.js.map +1 -1
  70. package/lib/client/failure-copy.js +63 -0
  71. package/lib/client/failure-copy.js.map +1 -0
  72. package/lib/client/index.js +38 -7
  73. package/lib/client/index.js.map +1 -1
  74. package/lib/client/prompt-content.js +54 -0
  75. package/lib/client/prompt-content.js.map +1 -0
  76. package/lib/client/settings/card.js +143 -0
  77. package/lib/client/settings/card.js.map +1 -0
  78. package/lib/client/settings/fields.js +145 -0
  79. package/lib/client/settings/fields.js.map +1 -0
  80. package/lib/client/settings/format.js +255 -0
  81. package/lib/client/settings/format.js.map +1 -0
  82. package/lib/client/settings/sections/access.js +25 -0
  83. package/lib/client/settings/sections/access.js.map +1 -0
  84. package/lib/client/settings/sections/accounts.js +47 -0
  85. package/lib/client/settings/sections/accounts.js.map +1 -0
  86. package/lib/client/settings/sections/attachments.js +46 -0
  87. package/lib/client/settings/sections/attachments.js.map +1 -0
  88. package/lib/client/settings/sections/branding.js +28 -0
  89. package/lib/client/settings/sections/branding.js.map +1 -0
  90. package/lib/client/settings/sections/common.js +20 -0
  91. package/lib/client/settings/sections/common.js.map +1 -0
  92. package/lib/client/settings/sections/embedding.js +19 -0
  93. package/lib/client/settings/sections/embedding.js.map +1 -0
  94. package/lib/client/settings/sections/interface.js +60 -0
  95. package/lib/client/settings/sections/interface.js.map +1 -0
  96. package/lib/client/settings/sections/lockdown.js +82 -0
  97. package/lib/client/settings/sections/lockdown.js.map +1 -0
  98. package/lib/client/settings/sections/session.js +53 -0
  99. package/lib/client/settings/sections/session.js.map +1 -0
  100. package/lib/client/settings/sections/sources.js +72 -0
  101. package/lib/client/settings/sections/sources.js.map +1 -0
  102. package/lib/client/settings/sections/status.js +37 -0
  103. package/lib/client/settings/sections/status.js.map +1 -0
  104. package/lib/client/settings/sections.js +23 -0
  105. package/lib/client/settings/sections.js.map +1 -0
  106. package/lib/client/settings/styles.js +57 -0
  107. package/lib/client/settings/styles.js.map +1 -0
  108. package/lib/client/stream-publisher.js +47 -0
  109. package/lib/client/stream-publisher.js.map +1 -0
  110. package/lib/client/styles.js +85 -19
  111. package/lib/client/styles.js.map +1 -1
  112. package/lib/client/types.js.map +1 -1
  113. package/lib/client/use-right-rail.js +96 -0
  114. package/lib/client/use-right-rail.js.map +1 -0
  115. package/lib/client/use-session-ui-state.js +26 -19
  116. package/lib/client/use-session-ui-state.js.map +1 -1
  117. package/lib/client.js +4788 -869
  118. package/lib/client.js.map +1 -1
  119. package/lib/config-resolvers/accounts.js +60 -0
  120. package/lib/config-resolvers/accounts.js.map +1 -0
  121. package/lib/config-resolvers/attachments.js +28 -0
  122. package/lib/config-resolvers/attachments.js.map +1 -0
  123. package/lib/config-resolvers/basics.js +59 -0
  124. package/lib/config-resolvers/basics.js.map +1 -0
  125. package/lib/config-resolvers/defaults.js +132 -0
  126. package/lib/config-resolvers/defaults.js.map +1 -0
  127. package/lib/config-resolvers/lockdown.js +79 -0
  128. package/lib/config-resolvers/lockdown.js.map +1 -0
  129. package/lib/config-resolvers/session.js +42 -0
  130. package/lib/config-resolvers/session.js.map +1 -0
  131. package/lib/config-resolvers/shared.js +42 -0
  132. package/lib/config-resolvers/shared.js.map +1 -0
  133. package/lib/config-resolvers/sources.js +81 -0
  134. package/lib/config-resolvers/sources.js.map +1 -0
  135. package/lib/config-resolvers/ui.js +20 -0
  136. package/lib/config-resolvers/ui.js.map +1 -0
  137. package/lib/config.js +65 -4
  138. package/lib/config.js.map +1 -1
  139. package/lib/entry-redirect.js +2 -1
  140. package/lib/entry-redirect.js.map +1 -1
  141. package/lib/index.js +123 -74
  142. package/lib/index.js.map +1 -1
  143. package/lib/profile.js +214 -0
  144. package/lib/profile.js.map +1 -0
  145. package/lib/prompt-notes.js +231 -0
  146. package/lib/prompt-notes.js.map +1 -0
  147. package/lib/resolve-config.js +35 -410
  148. package/lib/resolve-config.js.map +1 -1
  149. package/lib/secure-session.js +82 -16
  150. package/lib/secure-session.js.map +1 -1
  151. package/lib/shared/session-key.js +18 -0
  152. package/lib/shared/session-key.js.map +1 -0
  153. package/lib/shared/settings.js +10 -0
  154. package/lib/shared/settings.js.map +1 -0
  155. package/lib/thinking-phrases.js +68 -0
  156. package/lib/thinking-phrases.js.map +1 -0
  157. package/lib/typert.host.js +162 -17
  158. package/lib/typert.remote-client.d.ts +5 -1
  159. package/lib/typert.remote-client.js +132 -13
  160. package/lib/types/account-remotes.d.ts +42 -0
  161. package/lib/types/accounts/credentials.d.ts +14 -0
  162. package/lib/types/accounts/errors.d.ts +11 -0
  163. package/lib/types/accounts/file.d.ts +82 -0
  164. package/lib/types/accounts/store.d.ts +66 -43
  165. package/lib/types/accounts/token.d.ts +31 -0
  166. package/lib/types/attachment-rules.d.ts +44 -0
  167. package/lib/types/cli.d.ts +2 -2
  168. package/lib/types/client/QaAccountsController.d.ts +8 -1
  169. package/lib/types/client/QaSessionController.d.ts +16 -16
  170. package/lib/types/client/QaSurface.d.ts +7 -1
  171. package/lib/types/client/attachments.d.ts +54 -0
  172. package/lib/types/client/base64.d.ts +10 -0
  173. package/lib/types/client/chat-files.d.ts +30 -0
  174. package/lib/types/client/components/QaChangelog.d.ts +1 -1
  175. package/lib/types/client/components/QaComposer.d.ts +8 -4
  176. package/lib/types/client/components/QaFileAttachment.d.ts +14 -0
  177. package/lib/types/client/components/QaFilesPanel.d.ts +15 -0
  178. package/lib/types/client/components/QaHeader.d.ts +41 -0
  179. package/lib/types/client/components/QaMessage.d.ts +3 -1
  180. package/lib/types/client/components/QaModal.d.ts +26 -0
  181. package/lib/types/client/components/QaProfile.d.ts +25 -0
  182. package/lib/types/client/components/QaRightRail.d.ts +23 -0
  183. package/lib/types/client/components/QaSidebar.d.ts +14 -0
  184. package/lib/types/client/components/{QaSourcesDrawer.d.ts → QaSourcesPanel.d.ts} +7 -4
  185. package/lib/types/client/components/QaTurnRail.d.ts +6 -0
  186. package/lib/types/client/components/QaWidthHandle.d.ts +14 -7
  187. package/lib/types/client/components/QaWorkGroup.d.ts +5 -3
  188. package/lib/types/client/components/surface-utils.d.ts +11 -0
  189. package/lib/types/client/components/thinking-phrases.d.ts +9 -0
  190. package/lib/types/client/create-session.d.ts +6 -9
  191. package/lib/types/client/failure-copy.d.ts +19 -0
  192. package/lib/types/client/prompt-content.d.ts +30 -0
  193. package/lib/types/client/settings/card.d.ts +23 -0
  194. package/lib/types/client/settings/fields.d.ts +139 -0
  195. package/lib/types/client/settings/format.d.ts +108 -0
  196. package/lib/types/client/settings/sections/access.d.ts +9 -0
  197. package/lib/types/client/settings/sections/accounts.d.ts +9 -0
  198. package/lib/types/client/settings/sections/attachments.d.ts +15 -0
  199. package/lib/types/client/settings/sections/branding.d.ts +8 -0
  200. package/lib/types/client/settings/sections/common.d.ts +28 -0
  201. package/lib/types/client/settings/sections/embedding.d.ts +8 -0
  202. package/lib/types/client/settings/sections/interface.d.ts +9 -0
  203. package/lib/types/client/settings/sections/lockdown.d.ts +9 -0
  204. package/lib/types/client/settings/sections/session.d.ts +9 -0
  205. package/lib/types/client/settings/sections/sources.d.ts +9 -0
  206. package/lib/types/client/settings/sections/status.d.ts +22 -0
  207. package/lib/types/client/settings/sections.d.ts +25 -0
  208. package/lib/types/client/settings/styles.d.ts +8 -0
  209. package/lib/types/client/stream-publisher.d.ts +28 -0
  210. package/lib/types/client/types.d.ts +29 -1
  211. package/lib/types/client/use-right-rail.d.ts +56 -0
  212. package/lib/types/client/use-session-ui-state.d.ts +13 -7
  213. package/lib/types/config-resolvers/accounts.d.ts +15 -0
  214. package/lib/types/config-resolvers/attachments.d.ts +6 -0
  215. package/lib/types/config-resolvers/basics.d.ts +8 -0
  216. package/lib/types/config-resolvers/defaults.d.ts +4 -0
  217. package/lib/types/config-resolvers/lockdown.d.ts +10 -0
  218. package/lib/types/config-resolvers/session.d.ts +6 -0
  219. package/lib/types/config-resolvers/shared.d.ts +16 -0
  220. package/lib/types/config-resolvers/sources.d.ts +6 -0
  221. package/lib/types/config-resolvers/ui.d.ts +6 -0
  222. package/lib/types/index.d.ts +20 -13
  223. package/lib/types/profile.d.ts +76 -0
  224. package/lib/types/prompt-notes.d.ts +110 -0
  225. package/lib/types/resolve-config.d.ts +8 -3
  226. package/lib/types/secure-session.d.ts +26 -1
  227. package/lib/types/shared/session-key.d.ts +23 -0
  228. package/lib/types/shared/settings.d.ts +10 -0
  229. package/lib/types/thinking-phrases.d.ts +17 -0
  230. package/lib/types/types.d.ts +123 -5
  231. package/lib/types/user-workspace.d.ts +38 -0
  232. package/lib/user-workspace.js +231 -0
  233. package/lib/user-workspace.js.map +1 -0
  234. package/package.json +14 -7
  235. package/CHANGELOG.md +0 -176
  236. package/SPEC-dsh-qa-surface.md +0 -2425
  237. package/docs/ARCHITECTURE.md +0 -66
  238. package/docs/COMPATIBILITY.md +0 -14
  239. package/docs/CONFIGURATION.md +0 -199
  240. package/docs/EMBEDDING.md +0 -13
  241. package/docs/SOURCES-MIGRATION.md +0 -28
  242. package/docs/SOURCES-PROVENANCE-AUDIT.md +0 -88
  243. package/docs/SPEC-dsh-qa-surface-accounts.md +0 -219
  244. package/docs/SPEC-dsh-qa-surface-sources-provenance.md +0 -1692
  245. package/lib/client/components/QaSourcesDrawer.js.map +0 -1
@@ -1,10 +1,12 @@
1
1
  import { type Dispatch, type SetStateAction } from "react";
2
- import type { QaImageDraft, QaSource, QaTurnSources } from "../types.js";
2
+ import type { QaAttachmentDraft, QaSource, QaTurnSources } from "../types.js";
3
3
  /** Snapshot completeness captured when a drawer was opened from a message. */
4
4
  export interface QaDrawerCompleteness {
5
5
  readonly complete: boolean;
6
6
  readonly incompleteOrigins?: QaTurnSources["incompleteOrigins"];
7
7
  }
8
+ /** The rail tab ids; the agents drawer has not become a tab yet. */
9
+ export type QaRailTab = "sources" | "files";
8
10
  export interface QaSessionUiState {
9
11
  /** Per group: how many answers back from the newest is shown (0 = newest). */
10
12
  readonly variantOffsets: Record<string, number>;
@@ -14,22 +16,26 @@ export interface QaSessionUiState {
14
16
  readonly setActiveTurn: Dispatch<SetStateAction<number | null>>;
15
17
  readonly agentsOpen: boolean;
16
18
  readonly setAgentsOpen: Dispatch<SetStateAction<boolean>>;
17
- readonly sourcesOpen: boolean;
18
- readonly setSourcesOpen: Dispatch<SetStateAction<boolean>>;
19
+ /** Whether the right rail column is shown. */
20
+ readonly railOpen: boolean;
21
+ readonly setRailOpen: Dispatch<SetStateAction<boolean>>;
22
+ /** Which rail tab is active; meaningful only while the rail is open. */
23
+ readonly railTab: QaRailTab;
24
+ readonly setRailTab: Dispatch<SetStateAction<QaRailTab>>;
19
25
  readonly drawerSources: readonly QaSource[] | null;
20
26
  readonly setDrawerSources: Dispatch<SetStateAction<readonly QaSource[] | null>>;
21
27
  readonly drawerCompleteness: QaDrawerCompleteness | null;
22
28
  readonly setDrawerCompleteness: Dispatch<SetStateAction<QaDrawerCompleteness | null>>;
23
29
  readonly drawerDetail: QaSource | null;
24
30
  readonly setDrawerDetail: Dispatch<SetStateAction<QaSource | null>>;
25
- readonly pendingImages: readonly QaImageDraft[];
26
- readonly setPendingImages: (next: readonly QaImageDraft[]) => void;
31
+ readonly pendingAttachments: readonly QaAttachmentDraft[];
32
+ readonly setPendingAttachments: (next: readonly QaAttachmentDraft[]) => void;
27
33
  }
28
34
  /**
29
35
  * Per-chat UI state: composer attachments, variant offsets, the rail mark and
30
36
  * the drawers. Everything here describes the chat it was made in, so a
31
- * session change clears it instead of leaking a draft, an image or a drawer
32
- * from one conversation into the next.
37
+ * session change clears it instead of leaking a draft, an attachment or a
38
+ * drawer from one conversation into the next.
33
39
  */
34
40
  export declare function useSessionUiState(sessionId: string | null): QaSessionUiState;
35
41
  //# sourceMappingURL=use-session-ui-state.d.ts.map
@@ -0,0 +1,15 @@
1
+ import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "../types.js";
2
+ type AccountsSlice = ResolvedQaSurfaceConfig["accounts"];
3
+ /** Resolved neighbors the per-user workspace boundary is checked against. */
4
+ export interface AccountsDependencies {
5
+ readonly session: ResolvedQaSurfaceConfig["session"];
6
+ readonly lockdown: ResolvedQaSurfaceConfig["lockdown"];
7
+ }
8
+ /**
9
+ * Resolve the accounts domain. The per-user workspace boundary spans session
10
+ * and lockdown, so their resolved slices arrive as dependencies and the
11
+ * boundary checks run here, next to the flag they guard.
12
+ */
13
+ export declare function resolveAccounts(input: QaSurfaceConfig, dependencies: AccountsDependencies): AccountsSlice;
14
+ export {};
15
+ //# sourceMappingURL=accounts.d.ts.map
@@ -0,0 +1,6 @@
1
+ import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "../types.js";
2
+ type AttachmentsSlice = ResolvedQaSurfaceConfig["attachments"];
3
+ /** Resolve the attachments domain: intake toggles and byte/line bounds. */
4
+ export declare function resolveAttachments(input: QaSurfaceConfig): AttachmentsSlice;
5
+ export {};
6
+ //# sourceMappingURL=attachments.d.ts.map
@@ -0,0 +1,8 @@
1
+ import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "../types.js";
2
+ export declare function normalizeRoutePath(value: string): string;
3
+ /** The scalar domains that carry no table-shaped or cross-domain rules. */
4
+ type BasicsSlice = Pick<ResolvedQaSurfaceConfig, "enabled" | "route" | "branding" | "embedding" | "entry" | "interaction">;
5
+ /** Resolve the master switch, route, branding, embedding, and entry domains. */
6
+ export declare function resolveBasics(input: QaSurfaceConfig): BasicsSlice;
7
+ export {};
8
+ //# sourceMappingURL=basics.d.ts.map
@@ -0,0 +1,4 @@
1
+ import type { ResolvedQaSurfaceConfig } from "../types.js";
2
+ /** The canonical resolved config; every domain resolver defaults from it. */
3
+ export declare const DEFAULT_QA_SURFACE_CONFIG: ResolvedQaSurfaceConfig;
4
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1,10 @@
1
+ import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "../types.js";
2
+ type LockdownSlice = ResolvedQaSurfaceConfig["lockdown"];
3
+ /**
4
+ * Resolve the lockdown domain. The capability flags are clamped shut, and
5
+ * showing the reset control needs an explicit authorization here, so the
6
+ * resolved UI slice arrives as a neighbor.
7
+ */
8
+ export declare function resolveLockdown(input: QaSurfaceConfig, ui: ResolvedQaSurfaceConfig["ui"]): LockdownSlice;
9
+ export {};
10
+ //# sourceMappingURL=lockdown.d.ts.map
@@ -0,0 +1,6 @@
1
+ import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "../types.js";
2
+ type SessionSlice = ResolvedQaSurfaceConfig["session"];
3
+ /** Resolve the session domain: policy, pinning, and model selection. */
4
+ export declare function resolveSession(input: QaSurfaceConfig): SessionSlice;
5
+ export {};
6
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1,16 @@
1
+ /** Trim an optional string; a blank value collapses to null. */
2
+ export declare function optionalText(value: string | null | undefined): string | null;
3
+ /**
4
+ * Shared numeric guard for operator-tuned limits: the value has to be a safe
5
+ * integer inside [min, max], and every rejection carries the same message.
6
+ */
7
+ export declare function assertIntInRange(name: string, value: number, min: number, max: number): void;
8
+ /** Deduplicate and trim the operator's quick questions. */
9
+ export declare function uniqueQuestions(values: readonly string[]): readonly string[];
10
+ /**
11
+ * Normalize the operator's phrase list. Unlike quick questions, an empty list
12
+ * cannot mean "hide the control": the running indicator has to say something,
13
+ * so emptiness restores the built-in phrases.
14
+ */
15
+ export declare function uniquePhrases(values: readonly string[]): readonly string[];
16
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1,6 @@
1
+ import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "../types.js";
2
+ type SourcesSlice = ResolvedQaSurfaceConfig["sources"];
3
+ /** Resolve the sources domain: collection, display, and preview bounds. */
4
+ export declare function resolveSources(input: QaSurfaceConfig): SourcesSlice;
5
+ export {};
6
+ //# sourceMappingURL=sources.d.ts.map
@@ -0,0 +1,6 @@
1
+ import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "../types.js";
2
+ type UiSlice = ResolvedQaSurfaceConfig["ui"];
3
+ /** Resolve the UI domain: widget visibility and the content width floor. */
4
+ export declare function resolveUi(input: QaSurfaceConfig): UiSlice;
5
+ export {};
6
+ //# sourceMappingURL=ui.d.ts.map
@@ -1,10 +1,11 @@
1
1
  import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
2
2
  import type { Context } from "@deepseek-ai/cordis";
3
3
  import type { QaTurnSources } from "./provenance/types.js";
4
- import type { QaAccountSession, QaClaimResult, QaLockdownProof, QaOwnershipEntry, QaSurfaceConfig, ResolvedQaSurfaceConfig, QaSourceFilePreview, QaWhoamiResult } from "./types.js";
4
+ import type { QaAccountProfileInput, QaAccountSession, QaAccountUserPublic, QaClaimResult, QaLockdownProof, QaOwnershipEntry, QaSurfaceConfig, ResolvedQaSurfaceConfig, QaSourceFilePreview, QaWhoamiResult } from "./types.js";
5
5
  export declare const name = "qa-surface";
6
6
  export declare const inject: string[];
7
- export declare const QA_SURFACE_SETTINGS_NAMESPACE = "qa-surface";
7
+ import { QA_SURFACE_SETTINGS_NAMESPACE } from "./shared/settings.js";
8
+ export { QA_SURFACE_SETTINGS_NAMESPACE };
8
9
  export declare const Config: import("@deepseek-ai/schemastery").default<QaSurfaceConfig>;
9
10
  declare module "@deepseek-ai/cordis" {
10
11
  interface Context {
@@ -19,23 +20,15 @@ export declare class QaSurface extends TypertRemoteService {
19
20
  private readonly logger;
20
21
  private readonly admission;
21
22
  private readonly provenance;
22
- private accounts;
23
- private accountsOptions;
23
+ private readonly notes;
24
+ /** Account-remote bodies; the wire signatures stay on this class. */
25
+ private readonly accountRemotes;
24
26
  private readonly launchToken;
25
27
  private webServer;
26
28
  private disposeRoute;
27
29
  private routeKey;
28
30
  constructor(ctx: Context, entry?: QaSurfaceConfig);
29
31
  getConfig(): ResolvedQaSurfaceConfig;
30
- /**
31
- * The accounts store behind the runtime toggle. Rebuilt only when the
32
- * account-affecting options change; the file is shared across rebuilds.
33
- */
34
- private accountsFor;
35
- /** The accounts store, or the disabled refusal the browser maps to copy. */
36
- private requireAccounts;
37
- /** Account failures ride the shared `(reason: <code>)` wire marker. */
38
- private accountsRemote;
39
32
  /**
40
33
  * Self-service signup; the first account ever created becomes admin. The
41
34
  * display name derives from the email: the generated client enforces exact
@@ -59,6 +52,13 @@ export declare class QaSurface extends TypertRemoteService {
59
52
  accountsListOwnership(token: string): {
60
53
  readonly entries: readonly QaOwnershipEntry[];
61
54
  };
55
+ /**
56
+ * Replace the caller's own self-declared profile. The token is the only
57
+ * identity the wire carries: a browser can never name a profile but its own,
58
+ * and the deployment's declared fields and length limits are enforced in the
59
+ * store before anything is written.
60
+ */
61
+ accountsUpdateProfile(token: string, input: QaAccountProfileInput): QaAccountUserPublic;
62
62
  /**
63
63
  * Serve the effective QA configuration to the browser. The DSH gateway pins
64
64
  * settings RPCs to loopback, so a browser served over the LAN always sees
@@ -67,6 +67,12 @@ export declare class QaSurface extends TypertRemoteService {
67
67
  * boundary stays in {@link secureSession}.
68
68
  */
69
69
  describe(): ResolvedQaSurfaceConfig;
70
+ /**
71
+ * Create a QA session from Host-owned inputs. With account workspaces on,
72
+ * cwd is `<configured workspace>/.qa-users/<account UUID>` and the child is
73
+ * intentionally not registered or attached as another DSH workspace.
74
+ */
75
+ createSession(token: string): Promise<string>;
70
76
  /** Pin and attest the effective policy. The browser supplies identity only. */
71
77
  secureSession(token: string, sessionId: string): QaLockdownProof;
72
78
  /** Return canonical Host snapshots; replay is rebuilt from qa/sources events. */
@@ -83,6 +89,7 @@ export { entryRedirectRow, entryRedirectScript } from "./entry-redirect.js";
83
89
  export { registerQaNavigationRoute } from "./host-route.js";
84
90
  export { qaToolDenial, qaToolPolicyPlan } from "./lockdown-policy.js";
85
91
  export { QaPolicyAdmission } from "./secure-session.js";
92
+ export { QaPromptNotes, renderUserIdentity, QA_IDENTITY_NOTE, QA_SOURCES_NOTE, } from "./prompt-notes.js";
86
93
  export * from "./provenance/index.js";
87
94
  export type * from "./types.js";
88
95
  export default QaSurface;
@@ -0,0 +1,76 @@
1
+ import type { QaAccountIdentityField, QaAccountProfile } from "./types.js";
2
+ /**
3
+ * Profile shape, limits, and the normalization both halves of the plugin
4
+ * agree on. Deliberately free of Node built-ins: the configuration resolver
5
+ * and the browser-side form import these same limits, and a Host-only import
6
+ * here would drag the accounts store into the client bundle.
7
+ */
8
+ /** Longest accepted full name. */
9
+ export declare const QA_PROFILE_MAX_FULL_NAME = 200;
10
+ /** Longest accepted value of one external-system handle. */
11
+ export declare const QA_PROFILE_MAX_IDENTITY_VALUE = 200;
12
+ /** Most handles one profile may carry. */
13
+ export declare const QA_PROFILE_MAX_IDENTITIES = 16;
14
+ /** Handle keys are lowercase labels; the deployment declares which ones exist. */
15
+ export declare const QA_PROFILE_IDENTITY_KEY: RegExp;
16
+ /** Longest accepted display label of one declared handle field. */
17
+ export declare const QA_PROFILE_MAX_IDENTITY_LABEL = 40;
18
+ /** Most handle fields one deployment may declare. */
19
+ export declare const QA_PROFILE_MAX_IDENTITY_FIELDS = 8;
20
+ /** Default cap on the user's free-form agent guidance. */
21
+ export declare const QA_PROFILE_DEFAULT_INSTRUCTIONS_MAX = 2000;
22
+ /** Bounds within which a deployment may set that cap. */
23
+ export declare const QA_PROFILE_INSTRUCTIONS_MAX_MIN = 200;
24
+ export declare const QA_PROFILE_INSTRUCTIONS_MAX_MAX = 20000;
25
+ /** The profile of an account that never filled one in. */
26
+ export declare function emptyProfile(): QaAccountProfile;
27
+ /**
28
+ * Read one stored (or wire-delivered) profile into its public shape. Unknown
29
+ * or hand-edited input degrades to the readable subset instead of throwing:
30
+ * a malformed profile must never cost the account its session. Overlong text
31
+ * is truncated here — the write path rejects it with a message instead.
32
+ */
33
+ export declare function normalizeProfile(value: unknown): QaAccountProfile;
34
+ /** Validated profile values, before the store stamps `updatedAt`. */
35
+ export interface QaProfileWrite {
36
+ readonly fullName: string;
37
+ readonly identities: Readonly<Record<string, string>>;
38
+ readonly instructions: string;
39
+ }
40
+ export type QaProfileWriteResult = {
41
+ readonly ok: true;
42
+ readonly value: QaProfileWrite;
43
+ } | {
44
+ readonly ok: false;
45
+ readonly message: string;
46
+ };
47
+ export interface QaProfileWriteOptions {
48
+ readonly instructionsMaxLength: number;
49
+ /**
50
+ * Fields the deployment declares; a write may name only these keys. Omit to
51
+ * check the key shape alone — the operator CLI path, where the writer is the
52
+ * same person who owns the configuration.
53
+ */
54
+ readonly identities?: readonly QaAccountIdentityField[];
55
+ }
56
+ /**
57
+ * Validate one full-replace profile write. Values are cleaned the same way
58
+ * the read path cleans them, so what a caller sends is what the prompt will
59
+ * later render; limits are refused with a message instead of truncated, so a
60
+ * user pasting an essay learns why it was not stored.
61
+ */
62
+ export declare function validateProfileWrite(input: unknown, options: QaProfileWriteOptions): QaProfileWriteResult;
63
+ export type QaIdentityFieldsResult = {
64
+ readonly ok: true;
65
+ readonly value: readonly QaAccountIdentityField[];
66
+ } | {
67
+ readonly ok: false;
68
+ readonly message: string;
69
+ };
70
+ /**
71
+ * Validate the deployment's declared handle fields: the profile form renders
72
+ * one input per entry and the prompt names exactly these, so a typo in a key
73
+ * becomes a refusal at configuration time rather than a silent no-op.
74
+ */
75
+ export declare function validateIdentityFields(value: unknown): QaIdentityFieldsResult;
76
+ //# sourceMappingURL=profile.d.ts.map
@@ -0,0 +1,110 @@
1
+ import type { Context } from "@deepseek-ai/cordis";
2
+ import type { PluginLogger } from "@yadsh/dsh-plugin-log";
3
+ import type { QaAccounts } from "./accounts/store.js";
4
+ import type { QaAccountIdentityField, QaAccountProfile, ResolvedQaSurfaceConfig } from "./types.js";
5
+ /**
6
+ * Plugin marker on every injected message. The chat projection turns a
7
+ * plugin-sourced user message into injected context rather than a chat
8
+ * bubble, and the QA transcript keeps exactly those hidden.
9
+ */
10
+ export declare const QA_NOTES_PLUGIN = "qa-surface";
11
+ /** Note name carrying who the assistant is talking to. */
12
+ export declare const QA_IDENTITY_NOTE = "dsh-qa-surface:user-identity";
13
+ /** Note name carrying the deployment's rule about source provenance. */
14
+ export declare const QA_SOURCES_NOTE = "dsh-qa-surface:structured-sources";
15
+ export interface QaIdentityRenderInput {
16
+ /** The owner's account address; the one fact accounts always provide. */
17
+ readonly email: string;
18
+ readonly profile: QaAccountProfile;
19
+ /** Handle fields the deployment declares, in its configured order. */
20
+ readonly identities: readonly QaAccountIdentityField[];
21
+ }
22
+ /** The two identity parts one user resolves to; either may be empty. */
23
+ export interface QaRenderedIdentity {
24
+ readonly identity: string;
25
+ readonly instructions: string;
26
+ }
27
+ /**
28
+ * Render the identity text for one attested user.
29
+ *
30
+ * The wording is deliberately explicit about provenance: these are the user's
31
+ * own claims, so the model is told to name the identifier it searched by and
32
+ * to ask when the results contradict the request. A wrong handle that the
33
+ * model trusts silently is the failure mode this text exists to prevent.
34
+ */
35
+ export declare function renderUserIdentity(input: QaIdentityRenderInput): QaRenderedIdentity;
36
+ /** One named block the injector can add to a step. */
37
+ export interface QaPromptNote {
38
+ /** Source-section name, and the marker that finds the note again. */
39
+ readonly name: string;
40
+ readonly text: string;
41
+ }
42
+ export interface QaPromptNotesOptions {
43
+ readonly config: () => ResolvedQaSurfaceConfig;
44
+ /** The live accounts store, or undefined while accounts are disabled. */
45
+ readonly accounts: () => QaAccounts | undefined;
46
+ /**
47
+ * Whether one session belongs to the QA surface. The admission answers it:
48
+ * only an attested session reaches the QA audience the notes are written
49
+ * for, and delegated children resolve through their root session.
50
+ */
51
+ readonly isQaSession: (sessionId: string) => boolean;
52
+ readonly logger: PluginLogger;
53
+ }
54
+ /**
55
+ * Delivers the QA surface's ambient notes to the agent: who the assistant is
56
+ * talking to, and what the deployment expects around source provenance.
57
+ *
58
+ * A system-prompt section would be the natural home for both, and this plugin
59
+ * used one for each. Neither survives the QA deployment's own preset: the
60
+ * `qa-research` persona registers with `complete: true` (the persona IS the
61
+ * whole system prompt, so every other section is discarded) and
62
+ * `includeRuntimeContext: false` (which drops every context contribution as
63
+ * well). The preset says so outright — no plugin adds prompt text.
64
+ *
65
+ * What stays open is the conversation: a plugin-sourced user message is
66
+ * admitted to the request as injected context, survives both switches, and
67
+ * the transcript projection already hides every non-`subagent` context note
68
+ * from the QA audience. Each note is written once per text rather than once
69
+ * per step — the session's own surface is the state, so a resume or a plugin
70
+ * reload never duplicates a note — and written again only when its text
71
+ * actually changes.
72
+ *
73
+ * The notes are advisory text, never authority: nothing here is enforced by
74
+ * the model's compliance. The lockdown (allow-list, guards, permission
75
+ * preset) is host-side and holds whatever the conversation says.
76
+ */
77
+ export declare class QaPromptNotes {
78
+ private readonly ctx;
79
+ private readonly options;
80
+ /** `${agentId}:${noteName}` → the text the note already carries. */
81
+ private readonly carried;
82
+ private readonly disposePreStep;
83
+ private disposed;
84
+ constructor(ctx: Context, options: QaPromptNotesOptions);
85
+ dispose(): void;
86
+ /** Append every note whose text this step does not already carry. */
87
+ private inject;
88
+ /** Who is asking: the owner's name, handles and their own instructions. */
89
+ private identityNotes;
90
+ /** What the deployment expects around the sources the surface collects. */
91
+ private sourcesNotes;
92
+ private carriedKey;
93
+ /**
94
+ * The text one note already carries in this agent's conversation. Process
95
+ * memory answers it after the first step; a cold read walks the durable
96
+ * surface so a resumed session or a reloaded plugin does not write twice.
97
+ */
98
+ private carriedText;
99
+ /**
100
+ * The session a chat started from. Delegated children are joined to their
101
+ * preset's standing scope rather than to their parent agent, so the chain
102
+ * has to be walked through the durable session headers; an unresolvable link
103
+ * (a resumed session whose parent is no longer loaded) degrades to the
104
+ * farthest ancestor known at that moment.
105
+ */
106
+ private rootSessionId;
107
+ /** The owner's email and profile, or nothing while the chat is anonymous. */
108
+ private identityOf;
109
+ }
110
+ //# sourceMappingURL=prompt-notes.d.ts.map
@@ -1,6 +1,11 @@
1
+ import { normalizeRoutePath } from "./config-resolvers/basics.js";
2
+ import { DEFAULT_QA_SURFACE_CONFIG } from "./config-resolvers/defaults.js";
1
3
  import type { QaSurfaceConfig, ResolvedQaSurfaceConfig } from "./types.js";
2
- export declare const DEFAULT_QA_SURFACE_CONFIG: ResolvedQaSurfaceConfig;
3
- export declare function normalizeRoutePath(value: string): string;
4
- /** Materialize defaults and enforce route/session/model safety constraints. */
4
+ export { DEFAULT_QA_SURFACE_CONFIG, normalizeRoutePath };
5
+ /**
6
+ * Materialize defaults and enforce route/session/model safety constraints by
7
+ * running one resolver per config domain — in the order the checks have
8
+ * always fired — and assembling the frozen result.
9
+ */
5
10
  export declare function resolveConfig(input?: QaSurfaceConfig): ResolvedQaSurfaceConfig;
6
11
  //# sourceMappingURL=resolve-config.d.ts.map
@@ -7,7 +7,10 @@ import type { QaLockdownProof, ResolvedQaSurfaceConfig } from "./types.js";
7
7
  * pair or throw the coarse `QaAttestationError`; see {@link QaAccounts}.
8
8
  */
9
9
  export interface QaAccountsGate {
10
- enforceSessionAccess(token: string, sessionId: string): void;
10
+ enforceSessionAccess(token: string, sessionId: string): {
11
+ readonly id: string;
12
+ } | undefined;
13
+ userWorkspace(userId: string, registeredWorkspacePath: string): string;
11
14
  }
12
15
  /**
13
16
  * Host-side QA policy admission boundary — the only browser-callable operation
@@ -23,8 +26,30 @@ export declare class QaPolicyAdmission {
23
26
  private readonly logger;
24
27
  private readonly accounts?;
25
28
  private readonly appliedPolicies;
29
+ /**
30
+ * Sessions the QA surface has attested. The provenance note is written for
31
+ * exactly these, and a delegated child resolves through its root session, so
32
+ * one set answers for the whole chat.
33
+ */
34
+ private readonly attested;
35
+ private readonly workspaceRoots;
36
+ private readonly disposeWorkspaceGuard;
26
37
  constructor(ctx: Context, config: () => ResolvedQaSurfaceConfig, logger: PluginLogger, accounts?: QaAccountsGate | undefined);
38
+ /**
39
+ * The mounted attachment store's verbatim root, when the backend exposes
40
+ * one. It sits outside every workspace, so the per-user fence would
41
+ * otherwise deny the model the exact file an upload produced and the prompt
42
+ * points it at. A backend without a resolvable root simply keeps the fence
43
+ * closed — attachments then only work where reads are not fenced per user.
44
+ */
45
+ private attachmentRoot;
27
46
  secureSession(token: string, sessionId: string): QaLockdownProof;
47
+ /**
48
+ * Whether one session went through this boundary. The provenance note is
49
+ * written only for attested sessions, which is what keeps a deployment's
50
+ * source rules out of unrelated chats served by the same process.
51
+ */
52
+ knowsSession(sessionId: string): boolean;
28
53
  /** Detach every pinned tool policy; wired as a disposal effect by the entry. */
29
54
  dispose(): void;
30
55
  }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The browser-local key namespace every QA-side index derives from: the
3
+ * configured storage key pinned to the served route, versioned once so the
4
+ * Host's head-script injection and the client bundle cannot drift apart.
5
+ *
6
+ * Dependency-free like every `src/shared` module: both bundles inline it.
7
+ */
8
+ /**
9
+ * The versioned key prefix for browser-local QA state of one deployment.
10
+ * Callers append their own scope suffix (`:account-token`, `:welcome-notice`,
11
+ * `:chat:<id>`, …).
12
+ * @param config - configuration holding the storage key and the route path.
13
+ * @returns the versioned prefix, e.g. `dsh-qa-surface.session:v1:/qa`.
14
+ */
15
+ export declare function qaStorageNamespace(config: Readonly<{
16
+ session: {
17
+ storageKey: string;
18
+ };
19
+ route: {
20
+ path: string;
21
+ };
22
+ }>): string;
23
+ //# sourceMappingURL=session-key.d.ts.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Identity shared by the Host plugin and its browser settings card.
3
+ *
4
+ * This module must stay dependency-free: the card bundle inlines it, and a
5
+ * browser build must not pull the Host config surface (schemastery) into the
6
+ * page just to learn the namespace name.
7
+ */
8
+ /** Settings namespace the QA surface owns and its card binds to. */
9
+ export declare const QA_SURFACE_SETTINGS_NAMESPACE = "qa-surface";
10
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Phrases the running indicator cycles through. The list deliberately mixes
3
+ * Russian idiom with workshop imagery: a turn that keeps reshuffling the same
4
+ * thought in new words reads as alive, while a frozen one reads as stuck.
5
+ *
6
+ * Operators replace the list through `thinkingPhrases`; this module holds the
7
+ * canonical default so the config schema, the resolver and the browser all
8
+ * read one list.
9
+ */
10
+ export declare const DEFAULT_THINKING_PHRASES: readonly string[];
11
+ /**
12
+ * Phrase shown `elapsedMs` into a running turn. The list is operator supplied,
13
+ * so an empty one falls back to the default: the indicator always needs a
14
+ * label.
15
+ */
16
+ export declare function thinkingPhrase(elapsedMs: number, phrases?: readonly string[]): string;
17
+ //# sourceMappingURL=thinking-phrases.d.ts.map