@yadsh/dsh-qa-surface 0.15.7 → 0.17.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 (348) hide show
  1. package/README.md +27 -2
  2. package/lib/access/capability-catalog.js +11 -4
  3. package/lib/access/capability-catalog.js.map +1 -1
  4. package/lib/access/service.js +46 -5
  5. package/lib/access/service.js.map +1 -1
  6. package/lib/account-remotes.js +9 -0
  7. package/lib/account-remotes.js.map +1 -1
  8. package/lib/accounts/database.js +34 -3
  9. package/lib/accounts/database.js.map +1 -1
  10. package/lib/accounts/store.js +22 -2
  11. package/lib/accounts/store.js.map +1 -1
  12. package/lib/admin/service.js +4 -2
  13. package/lib/admin/service.js.map +1 -1
  14. package/lib/admin/session-log.js +3 -0
  15. package/lib/admin/session-log.js.map +1 -1
  16. package/lib/agent-scope.js +9 -0
  17. package/lib/agent-scope.js.map +1 -0
  18. package/lib/chat-sharing/native-fence.js +120 -0
  19. package/lib/chat-sharing/native-fence.js.map +1 -0
  20. package/lib/chat-sharing/resources.js +57 -0
  21. package/lib/chat-sharing/resources.js.map +1 -0
  22. package/lib/chat-sharing/store.js +199 -0
  23. package/lib/chat-sharing/store.js.map +1 -0
  24. package/lib/chat-sharing/transport.js +329 -0
  25. package/lib/chat-sharing/transport.js.map +1 -0
  26. package/lib/chat-sharing/turn-guard.js +154 -0
  27. package/lib/chat-sharing/turn-guard.js.map +1 -0
  28. package/lib/chat-sharing/types.js +2 -0
  29. package/lib/chat-sharing/types.js.map +1 -0
  30. package/lib/chat-sharing/uploads.js +55 -0
  31. package/lib/chat-sharing/uploads.js.map +1 -0
  32. package/lib/client/QaAccountsController.js +47 -2
  33. package/lib/client/QaAccountsController.js.map +1 -1
  34. package/lib/client/QaConfigController.js +7 -12
  35. package/lib/client/QaConfigController.js.map +1 -1
  36. package/lib/client/QaSessionController.js +195 -19
  37. package/lib/client/QaSessionController.js.map +1 -1
  38. package/lib/client/QaSurface.js +156 -14
  39. package/lib/client/QaSurface.js.map +1 -1
  40. package/lib/client/QaSurfaceGuard.js +6 -1
  41. package/lib/client/QaSurfaceGuard.js.map +1 -1
  42. package/lib/client/QaTranscriptAdapter.js +28 -5
  43. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  44. package/lib/client/account-conversation.js +33 -0
  45. package/lib/client/account-conversation.js.map +1 -0
  46. package/lib/client/account-sessions.js +106 -0
  47. package/lib/client/account-sessions.js.map +1 -0
  48. package/lib/client/account-upload.js +30 -0
  49. package/lib/client/account-upload.js.map +1 -0
  50. package/lib/client/answer-review.js +89 -0
  51. package/lib/client/answer-review.js.map +1 -0
  52. package/lib/client/chat-artifacts.js +18 -3
  53. package/lib/client/chat-artifacts.js.map +1 -1
  54. package/lib/client/chat-sharing-api.js +2 -0
  55. package/lib/client/chat-sharing-api.js.map +1 -0
  56. package/lib/client/components/QaAnswerReviewStatus.js +45 -0
  57. package/lib/client/components/QaAnswerReviewStatus.js.map +1 -0
  58. package/lib/client/components/QaChangelog.js +92 -3
  59. package/lib/client/components/QaChangelog.js.map +1 -1
  60. package/lib/client/components/QaChatActions.js +52 -0
  61. package/lib/client/components/QaChatActions.js.map +1 -0
  62. package/lib/client/components/QaChatSharing.js +95 -0
  63. package/lib/client/components/QaChatSharing.js.map +1 -0
  64. package/lib/client/components/QaComposer.js +8 -4
  65. package/lib/client/components/QaComposer.js.map +1 -1
  66. package/lib/client/components/QaFileAttachment.js +12 -3
  67. package/lib/client/components/QaFileAttachment.js.map +1 -1
  68. package/lib/client/components/QaFilesPanel.js +11 -4
  69. package/lib/client/components/QaFilesPanel.js.map +1 -1
  70. package/lib/client/components/QaHeader.js +3 -3
  71. package/lib/client/components/QaHeader.js.map +1 -1
  72. package/lib/client/components/QaMarkdownPreview.js +86 -0
  73. package/lib/client/components/QaMarkdownPreview.js.map +1 -0
  74. package/lib/client/components/QaMessage.js +41 -10
  75. package/lib/client/components/QaMessage.js.map +1 -1
  76. package/lib/client/components/QaModal.js +17 -0
  77. package/lib/client/components/QaModal.js.map +1 -1
  78. package/lib/client/components/QaRightRail.js +6 -4
  79. package/lib/client/components/QaRightRail.js.map +1 -1
  80. package/lib/client/components/QaRightRailResize.js +129 -0
  81. package/lib/client/components/QaRightRailResize.js.map +1 -0
  82. package/lib/client/components/QaSidebar.js +11 -2
  83. package/lib/client/components/QaSidebar.js.map +1 -1
  84. package/lib/client/components/QaSourceFilters.js +22 -0
  85. package/lib/client/components/QaSourceFilters.js.map +1 -0
  86. package/lib/client/components/QaSourcesPanel.js +66 -14
  87. package/lib/client/components/QaSourcesPanel.js.map +1 -1
  88. package/lib/client/components/QaSpreadsheetPreview.js +56 -0
  89. package/lib/client/components/QaSpreadsheetPreview.js.map +1 -0
  90. package/lib/client/components/QaWelcomeNotice.js +2 -2
  91. package/lib/client/components/QaWelcomeNotice.js.map +1 -1
  92. package/lib/client/components/QaWorkspaceBrowser.js +46 -12
  93. package/lib/client/components/QaWorkspaceBrowser.js.map +1 -1
  94. package/lib/client/components/QaZoomImage.js +56 -0
  95. package/lib/client/components/QaZoomImage.js.map +1 -0
  96. package/lib/client/components/source-refs.js +57 -24
  97. package/lib/client/components/source-refs.js.map +1 -1
  98. package/lib/client/index.js +76 -8
  99. package/lib/client/index.js.map +1 -1
  100. package/lib/client/lineage.js +4 -3
  101. package/lib/client/lineage.js.map +1 -1
  102. package/lib/client/markdown/SourceImage.js +52 -0
  103. package/lib/client/markdown/SourceImage.js.map +1 -0
  104. package/lib/client/markdown/blocks.js +150 -115
  105. package/lib/client/markdown/blocks.js.map +1 -1
  106. package/lib/client/markdown/katex-css.js +1 -1
  107. package/lib/client/markdown/render.js +26 -9
  108. package/lib/client/markdown/render.js.map +1 -1
  109. package/lib/client/markdown/source-chip.js +6 -2
  110. package/lib/client/markdown/source-chip.js.map +1 -1
  111. package/lib/client/notifications/notification-dispatcher.js +50 -11
  112. package/lib/client/notifications/notification-dispatcher.js.map +1 -1
  113. package/lib/client/notifications/use-turn-notifications.js +107 -18
  114. package/lib/client/notifications/use-turn-notifications.js.map +1 -1
  115. package/lib/client/project-session-state.js +28 -13
  116. package/lib/client/project-session-state.js.map +1 -1
  117. package/lib/client/session-admission.js +9 -1
  118. package/lib/client/session-admission.js.map +1 -1
  119. package/lib/client/session-sources.js +44 -3
  120. package/lib/client/session-sources.js.map +1 -1
  121. package/lib/client/settings/sections/sources.js +1 -1
  122. package/lib/client/settings/sections/sources.js.map +1 -1
  123. package/lib/client/settings/styles.js +18 -28
  124. package/lib/client/settings/styles.js.map +1 -1
  125. package/lib/client/slash/useSlashNavigation.js +8 -5
  126. package/lib/client/slash/useSlashNavigation.js.map +1 -1
  127. package/lib/client/source-filters-styles.js +11 -0
  128. package/lib/client/source-filters-styles.js.map +1 -0
  129. package/lib/client/source-preview.js +1 -1
  130. package/lib/client/source-preview.js.map +1 -1
  131. package/lib/client/styles.js +62 -4
  132. package/lib/client/styles.js.map +1 -1
  133. package/lib/client/turn-sources.js +2 -1
  134. package/lib/client/turn-sources.js.map +1 -1
  135. package/lib/client/types.js.map +1 -1
  136. package/lib/client/use-right-rail.js +1 -1
  137. package/lib/client/use-right-rail.js.map +1 -1
  138. package/lib/client/user-settings/IntegrationTokensPage.js +30 -6
  139. package/lib/client/user-settings/IntegrationTokensPage.js.map +1 -1
  140. package/lib/client/workspace-download.js +42 -2
  141. package/lib/client/workspace-download.js.map +1 -1
  142. package/lib/client.js +6481 -2234
  143. package/lib/client.js.map +1 -1
  144. package/lib/config-resolvers/defaults.js +4 -3
  145. package/lib/config-resolvers/defaults.js.map +1 -1
  146. package/lib/config-resolvers/sources.js +2 -0
  147. package/lib/config-resolvers/sources.js.map +1 -1
  148. package/lib/config.js +3 -0
  149. package/lib/config.js.map +1 -1
  150. package/lib/enforcement/skill-policy.js +29 -4
  151. package/lib/enforcement/skill-policy.js.map +1 -1
  152. package/lib/enforcement/skill-resource-paths.js +32 -0
  153. package/lib/enforcement/skill-resource-paths.js.map +1 -0
  154. package/lib/enforcement/structured-result.js +38 -0
  155. package/lib/enforcement/structured-result.js.map +1 -0
  156. package/lib/enforcement/tool-grants.js +3 -1
  157. package/lib/enforcement/tool-grants.js.map +1 -1
  158. package/lib/index.js +447 -17
  159. package/lib/index.js.map +1 -1
  160. package/lib/integration/host-runner.js +1 -0
  161. package/lib/integration/host-runner.js.map +1 -1
  162. package/lib/integration/question-policy.js +126 -0
  163. package/lib/integration/question-policy.js.map +1 -0
  164. package/lib/integration/service.js +2 -0
  165. package/lib/integration/service.js.map +1 -1
  166. package/lib/llm-identity.js +27 -0
  167. package/lib/llm-identity.js.map +1 -0
  168. package/lib/markdown-frontmatter.js +47 -0
  169. package/lib/markdown-frontmatter.js.map +1 -0
  170. package/lib/markdown-images.js +33 -0
  171. package/lib/markdown-images.js.map +1 -0
  172. package/lib/prompt-notes.js +19 -2
  173. package/lib/prompt-notes.js.map +1 -1
  174. package/lib/provenance/collector.js +15 -1
  175. package/lib/provenance/collector.js.map +1 -1
  176. package/lib/provenance/connectors.js +57 -27
  177. package/lib/provenance/connectors.js.map +1 -1
  178. package/lib/provenance/dedupe.js +25 -1
  179. package/lib/provenance/dedupe.js.map +1 -1
  180. package/lib/provenance/document-preview.js +31 -3
  181. package/lib/provenance/document-preview.js.map +1 -1
  182. package/lib/provenance/extractors.js +88 -4
  183. package/lib/provenance/extractors.js.map +1 -1
  184. package/lib/provenance/file-download.js +56 -0
  185. package/lib/provenance/file-download.js.map +1 -0
  186. package/lib/provenance/file-preview.js +20 -2
  187. package/lib/provenance/file-preview.js.map +1 -1
  188. package/lib/provenance/host-store.js +59 -10
  189. package/lib/provenance/host-store.js.map +1 -1
  190. package/lib/provenance/integration-extractor.js +62 -0
  191. package/lib/provenance/integration-extractor.js.map +1 -0
  192. package/lib/provenance/snapshot-store.js +2 -0
  193. package/lib/provenance/snapshot-store.js.map +1 -1
  194. package/lib/provenance/source-content.js +103 -0
  195. package/lib/provenance/source-content.js.map +1 -0
  196. package/lib/provenance/source-image.js +57 -0
  197. package/lib/provenance/source-image.js.map +1 -0
  198. package/lib/provenance/spreadsheet-preview.js +52 -0
  199. package/lib/provenance/spreadsheet-preview.js.map +1 -0
  200. package/lib/qa-tools/docs-tools.js +14 -0
  201. package/lib/qa-tools/docs-tools.js.map +1 -1
  202. package/lib/questions.js +6 -1
  203. package/lib/questions.js.map +1 -1
  204. package/lib/secure-session.js +9 -3
  205. package/lib/secure-session.js.map +1 -1
  206. package/lib/session-fork-host.js +157 -0
  207. package/lib/session-fork-host.js.map +1 -0
  208. package/lib/session-fork.js +34 -0
  209. package/lib/session-fork.js.map +1 -0
  210. package/lib/session-ownership.js +5 -1
  211. package/lib/session-ownership.js.map +1 -1
  212. package/lib/shared/documents.js +12 -0
  213. package/lib/shared/documents.js.map +1 -1
  214. package/lib/shared/session-lineage.js +6 -0
  215. package/lib/shared/session-lineage.js.map +1 -0
  216. package/lib/slash/draft-target.js +21 -0
  217. package/lib/slash/draft-target.js.map +1 -0
  218. package/lib/slash/remotes.js +39 -4
  219. package/lib/slash/remotes.js.map +1 -1
  220. package/lib/typert.host.js +1869 -163
  221. package/lib/typert.remote-client.d.ts +56 -5
  222. package/lib/typert.remote-client.js +1678 -154
  223. package/lib/types/access/capability-catalog.d.ts +1 -1
  224. package/lib/types/access/service.d.ts +7 -0
  225. package/lib/types/access.js +2 -0
  226. package/lib/types/access.js.map +1 -0
  227. package/lib/types/account-remotes.d.ts +3 -0
  228. package/lib/types/accounts/database.d.ts +5 -0
  229. package/lib/types/accounts/store.d.ts +7 -2
  230. package/lib/types/accounts.js +2 -0
  231. package/lib/types/accounts.js.map +1 -0
  232. package/lib/types/admin/session-log.d.ts +2 -0
  233. package/lib/types/admin.js +2 -0
  234. package/lib/types/admin.js.map +1 -0
  235. package/lib/types/agent-scope.d.ts +4 -0
  236. package/lib/types/answer-review.js +2 -0
  237. package/lib/types/answer-review.js.map +1 -0
  238. package/lib/types/capability.js +2 -0
  239. package/lib/types/capability.js.map +1 -0
  240. package/lib/types/chat-sharing/native-fence.d.ts +11 -0
  241. package/lib/types/chat-sharing/resources.d.ts +5 -0
  242. package/lib/types/chat-sharing/store.d.ts +29 -0
  243. package/lib/types/chat-sharing/transport.d.ts +32 -0
  244. package/lib/types/chat-sharing/turn-guard.d.ts +21 -0
  245. package/lib/types/chat-sharing/types.d.ts +25 -0
  246. package/lib/types/chat-sharing/uploads.d.ts +5 -0
  247. package/lib/types/client/QaAccountsController.d.ts +4 -0
  248. package/lib/types/client/QaConfigController.d.ts +3 -2
  249. package/lib/types/client/QaSessionController.d.ts +17 -3
  250. package/lib/types/client/QaSurface.d.ts +6 -1
  251. package/lib/types/client/account-conversation.d.ts +6 -0
  252. package/lib/types/client/account-sessions.d.ts +7 -0
  253. package/lib/types/client/account-upload.d.ts +15 -0
  254. package/lib/types/client/answer-review.d.ts +16 -0
  255. package/lib/types/client/chat-sharing-api.d.ts +35 -0
  256. package/lib/types/client/components/QaAnswerReviewStatus.d.ts +8 -0
  257. package/lib/types/client/components/QaChatActions.d.ts +7 -0
  258. package/lib/types/client/components/QaChatSharing.d.ts +12 -0
  259. package/lib/types/client/components/QaComposer.d.ts +2 -0
  260. package/lib/types/client/components/QaFileAttachment.d.ts +3 -2
  261. package/lib/types/client/components/QaFilesPanel.d.ts +4 -1
  262. package/lib/types/client/components/QaMarkdownPreview.d.ts +13 -0
  263. package/lib/types/client/components/QaMessage.d.ts +5 -2
  264. package/lib/types/client/components/QaModal.d.ts +9 -0
  265. package/lib/types/client/components/QaRightRail.d.ts +3 -2
  266. package/lib/types/client/components/QaRightRailResize.d.ts +9 -0
  267. package/lib/types/client/components/QaSidebar.d.ts +2 -0
  268. package/lib/types/client/components/QaSourceFilters.d.ts +12 -0
  269. package/lib/types/client/components/QaSpreadsheetPreview.d.ts +8 -0
  270. package/lib/types/client/components/QaWelcomeNotice.d.ts +1 -1
  271. package/lib/types/client/components/QaWorkspaceBrowser.d.ts +8 -1
  272. package/lib/types/client/components/QaZoomImage.d.ts +38 -0
  273. package/lib/types/client/components/source-refs.d.ts +1 -0
  274. package/lib/types/client/lineage.d.ts +2 -2
  275. package/lib/types/client/markdown/SourceImage.d.ts +7 -0
  276. package/lib/types/client/markdown/blocks.d.ts +8 -1
  277. package/lib/types/client/markdown/render.d.ts +5 -1
  278. package/lib/types/client/markdown/source-chip.d.ts +1 -0
  279. package/lib/types/client/notifications/notification-dispatcher.d.ts +10 -6
  280. package/lib/types/client/notifications/use-turn-notifications.d.ts +4 -0
  281. package/lib/types/client/project-session-state.d.ts +1 -0
  282. package/lib/types/client/session-admission.d.ts +2 -0
  283. package/lib/types/client/session-sources.d.ts +1 -0
  284. package/lib/types/client/settings/styles.d.ts +2 -5
  285. package/lib/types/client/source-filters-styles.d.ts +2 -0
  286. package/lib/types/client/turn-sources.d.ts +1 -1
  287. package/lib/types/client/types.d.ts +18 -5
  288. package/lib/types/client/workspace-download.d.ts +9 -1
  289. package/lib/types/config.js +2 -0
  290. package/lib/types/config.js.map +1 -0
  291. package/lib/types/documents.js +2 -0
  292. package/lib/types/documents.js.map +1 -0
  293. package/lib/types/enforcement/skill-resource-paths.d.ts +5 -0
  294. package/lib/types/enforcement/structured-result.d.ts +11 -0
  295. package/lib/types/expert-memory.js +2 -0
  296. package/lib/types/expert-memory.js.map +1 -0
  297. package/lib/types/index.d.ts +42 -3
  298. package/lib/types/integration/contract.d.ts +1 -0
  299. package/lib/types/integration/question-policy.d.ts +20 -0
  300. package/lib/types/integration/service.d.ts +1 -0
  301. package/lib/types/llm-identity.d.ts +20 -0
  302. package/lib/types/markdown-frontmatter.d.ts +10 -0
  303. package/lib/types/markdown-images.d.ts +3 -0
  304. package/lib/types/policy.js +2 -0
  305. package/lib/types/policy.js.map +1 -0
  306. package/lib/types/prompt-notes.d.ts +3 -1
  307. package/lib/types/provenance/connectors.d.ts +4 -1
  308. package/lib/types/provenance/document-preview.d.ts +5 -2
  309. package/lib/types/provenance/extractors.d.ts +2 -0
  310. package/lib/types/provenance/file-download.d.ts +10 -0
  311. package/lib/types/provenance/file-preview.d.ts +2 -1
  312. package/lib/types/provenance/host-store.d.ts +2 -0
  313. package/lib/types/provenance/integration-extractor.d.ts +5 -0
  314. package/lib/types/provenance/source-content.d.ts +19 -0
  315. package/lib/types/provenance/source-image.d.ts +4 -0
  316. package/lib/types/provenance/spreadsheet-preview.d.ts +5 -0
  317. package/lib/types/provenance/types.d.ts +5 -0
  318. package/lib/types/qa-tools/docs-tools.d.ts +2 -0
  319. package/lib/types/quality.js +7 -0
  320. package/lib/types/quality.js.map +1 -0
  321. package/lib/types/questions.d.ts +2 -1
  322. package/lib/types/session-fork-host.d.ts +27 -0
  323. package/lib/types/session-fork.d.ts +7 -0
  324. package/lib/types/session.js +2 -0
  325. package/lib/types/session.js.map +1 -0
  326. package/lib/types/shared/documents.d.ts +2 -0
  327. package/lib/types/shared/session-lineage.d.ts +7 -0
  328. package/lib/types/skills.js +2 -0
  329. package/lib/types/skills.js.map +1 -0
  330. package/lib/types/slash/draft-target.d.ts +7 -0
  331. package/lib/types/slash/remotes.d.ts +7 -0
  332. package/lib/types/slash.js +2 -0
  333. package/lib/types/slash.js.map +1 -0
  334. package/lib/types/types/access.d.ts +43 -0
  335. package/lib/types/types/accounts.d.ts +177 -0
  336. package/lib/types/types/admin.d.ts +286 -0
  337. package/lib/types/types/answer-review.d.ts +11 -0
  338. package/lib/types/types/capability.d.ts +230 -0
  339. package/lib/types/types/config.d.ts +597 -0
  340. package/lib/types/types/documents.d.ts +34 -0
  341. package/lib/types/types/expert-memory.d.ts +35 -0
  342. package/lib/types/types/policy.d.ts +54 -0
  343. package/lib/types/types/quality.d.ts +100 -0
  344. package/lib/types/types/session.d.ts +397 -0
  345. package/lib/types/types/skills.d.ts +143 -0
  346. package/lib/types/types/slash.d.ts +159 -0
  347. package/lib/types/types.d.ts +14 -2180
  348. package/package.json +8 -7
package/lib/index.js CHANGED
@@ -33,6 +33,17 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
33
33
  done = true;
34
34
  };
35
35
  import { randomUUID } from "node:crypto";
36
+ import { readSourceImage as readSourceImagePreview } from "./provenance/source-image.js";
37
+ import path from "node:path";
38
+ import { defaultAccountsFilePath } from "./accounts/store.js";
39
+ import { QaChatSharingStore } from "./chat-sharing/store.js";
40
+ import { QaChatTransport } from "./chat-sharing/transport.js";
41
+ import { QaChatTurnGuard } from "./chat-sharing/turn-guard.js";
42
+ import { installQaNativeFence } from "./chat-sharing/native-fence.js";
43
+ import { QaIntegrationQuestionPolicy } from "./integration/question-policy.js";
44
+ import { qaChatPublishedFile, qaChatAttachmentPath, } from "./chat-sharing/resources.js";
45
+ import { installQaChatUploads } from "./chat-sharing/uploads.js";
46
+ import { forkQaSession } from "./session-fork-host.js";
36
47
  import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
37
48
  import { SessionId } from "@deepseek-ai/dsh-session/types";
38
49
  import { WorkspaceId } from "@deepseek-ai/dsh-workspace";
@@ -48,6 +59,7 @@ import { QaAttestationError, qaAttestationFailureMessage, } from "./attestation.
48
59
  import { QaFileDeleteGate } from "./qa-tools/file-delete-gate.js";
49
60
  import { QaQuestionGate } from "./questions.js";
50
61
  import { QaSessionOwnership } from "./session-ownership.js";
62
+ import { QaLlmIdentity } from "./llm-identity.js";
51
63
  import { registerTurnFailureLog } from "./turn-failure-log.js";
52
64
  import { entryRedirectRow } from "./entry-redirect.js";
53
65
  import { qaKioskDeployment } from "./ui-mode.js";
@@ -68,7 +80,8 @@ import { QaTools } from "./qa-tools/index.js";
68
80
  import { docsDefaultVersionOf } from "./config-resolvers/tools.js";
69
81
  import { QaProvenanceHost } from "./provenance/host-store.js";
70
82
  import { defaultLegacyProvenanceFilePath, defaultQaProvenanceDirectoryPath, FileQaProvenanceSnapshotStore, } from "./provenance/snapshot-store.js";
71
- import { previewConvertibleDocument } from "./provenance/document-preview.js";
83
+ import { previewConvertibleDocument, previewSourceDocument, } from "./provenance/document-preview.js";
84
+ import { readWorkspaceFileChunk } from "./provenance/file-download.js";
72
85
  import { listWorkspaceDirectory, readSourceFilePreview, readWorkspaceFile, QaSourcePreviewError, } from "./provenance/file-preview.js";
73
86
  import { existingQaUserWorkspace, prepareQaUserWorkspace, } from "./user-workspace.js";
74
87
  export const name = "qa-surface";
@@ -138,9 +151,11 @@ let QaSurface = (() => {
138
151
  let _accountsListServiceTokens_decorators;
139
152
  let _accountsCreateServiceToken_decorators;
140
153
  let _accountsRevokeServiceToken_decorators;
154
+ let _accountsSetServiceTokenClarifications_decorators;
141
155
  let _describe_decorators;
142
156
  let _queueStatus_decorators;
143
157
  let _createSession_decorators;
158
+ let _forkSession_decorators;
144
159
  let _accessCurrent_decorators;
145
160
  let _accessSession_decorators;
146
161
  let _accessAdminSnapshot_decorators;
@@ -181,6 +196,25 @@ let QaSurface = (() => {
181
196
  let _adminMetrics_decorators;
182
197
  let _adminAudit_decorators;
183
198
  let _secureSession_decorators;
199
+ let _chatVisible_decorators;
200
+ let _chatAccess_decorators;
201
+ let _chatGrants_decorators;
202
+ let _chatSetGrant_decorators;
203
+ let _chatAuthors_decorators;
204
+ let _chatAudit_decorators;
205
+ let _chatAttachmentPath_decorators;
206
+ let _chatList_decorators;
207
+ let _chatSearch_decorators;
208
+ let _chatSelectModel_decorators;
209
+ let _chatPage_decorators;
210
+ let _chatFollow_decorators;
211
+ let _chatControl_decorators;
212
+ let _chatProjections_decorators;
213
+ let _chatPrompt_decorators;
214
+ let _chatAttachment_decorators;
215
+ let _chatRename_decorators;
216
+ let _chatCancel_decorators;
217
+ let _chatUpdateQueue_decorators;
184
218
  let _sources_decorators;
185
219
  let _pendingApprovals_decorators;
186
220
  let _answerApproval_decorators;
@@ -188,8 +222,12 @@ let QaSurface = (() => {
188
222
  let _answerQuestion_decorators;
189
223
  let _cancelQuestion_decorators;
190
224
  let _readSourceFile_decorators;
225
+ let _readSourceImage_decorators;
191
226
  let _listWorkspaceFiles_decorators;
192
227
  let _readWorkspaceFile_decorators;
228
+ let _readWorkspaceFileChunk_decorators;
229
+ let _documentWorkflowStatus_decorators;
230
+ let _approveDocumentWorkflow_decorators;
193
231
  let _previewWorkspaceDocument_decorators;
194
232
  let _skillsList_decorators;
195
233
  let _skillsGet_decorators;
@@ -217,9 +255,11 @@ let QaSurface = (() => {
217
255
  _accountsListServiceTokens_decorators = [Remote("accountsListServiceTokens")];
218
256
  _accountsCreateServiceToken_decorators = [Remote("accountsCreateServiceToken")];
219
257
  _accountsRevokeServiceToken_decorators = [Remote("accountsRevokeServiceToken")];
258
+ _accountsSetServiceTokenClarifications_decorators = [Remote("accountsSetServiceTokenClarifications")];
220
259
  _describe_decorators = [Remote("describe")];
221
260
  _queueStatus_decorators = [Remote("queueStatus")];
222
261
  _createSession_decorators = [Remote("createSession")];
262
+ _forkSession_decorators = [Remote("forkSession")];
223
263
  _accessCurrent_decorators = [Remote("accessCurrent")];
224
264
  _accessSession_decorators = [Remote("accessSession")];
225
265
  _accessAdminSnapshot_decorators = [Remote("accessAdminSnapshot")];
@@ -260,6 +300,25 @@ let QaSurface = (() => {
260
300
  _adminMetrics_decorators = [Remote("adminMetrics")];
261
301
  _adminAudit_decorators = [Remote("adminAudit")];
262
302
  _secureSession_decorators = [Remote("secureSession")];
303
+ _chatVisible_decorators = [Remote("chatVisible")];
304
+ _chatAccess_decorators = [Remote("chatAccess")];
305
+ _chatGrants_decorators = [Remote("chatGrants")];
306
+ _chatSetGrant_decorators = [Remote("chatSetGrant")];
307
+ _chatAuthors_decorators = [Remote("chatAuthors")];
308
+ _chatAudit_decorators = [Remote("chatAudit")];
309
+ _chatAttachmentPath_decorators = [Remote("chatAttachmentPath")];
310
+ _chatList_decorators = [Remote("chatList")];
311
+ _chatSearch_decorators = [Remote("chatSearch")];
312
+ _chatSelectModel_decorators = [Remote("chatSelectModel")];
313
+ _chatPage_decorators = [Remote("chatPage")];
314
+ _chatFollow_decorators = [Remote({ mode: "stream" })];
315
+ _chatControl_decorators = [Remote({ mode: "stream" })];
316
+ _chatProjections_decorators = [Remote("chatProjections")];
317
+ _chatPrompt_decorators = [Remote("chatPrompt")];
318
+ _chatAttachment_decorators = [Remote("chatAttachment")];
319
+ _chatRename_decorators = [Remote("chatRename")];
320
+ _chatCancel_decorators = [Remote("chatCancel")];
321
+ _chatUpdateQueue_decorators = [Remote("chatUpdateQueue")];
263
322
  _sources_decorators = [Remote("sources")];
264
323
  _pendingApprovals_decorators = [Remote("pendingApprovals")];
265
324
  _answerApproval_decorators = [Remote("answerApproval")];
@@ -267,8 +326,12 @@ let QaSurface = (() => {
267
326
  _answerQuestion_decorators = [Remote("answerQuestion")];
268
327
  _cancelQuestion_decorators = [Remote("cancelQuestion")];
269
328
  _readSourceFile_decorators = [Remote("readSourceFile")];
329
+ _readSourceImage_decorators = [Remote("readSourceImage")];
270
330
  _listWorkspaceFiles_decorators = [Remote("listWorkspaceFiles")];
271
331
  _readWorkspaceFile_decorators = [Remote("readWorkspaceFile")];
332
+ _readWorkspaceFileChunk_decorators = [Remote("readWorkspaceFileChunk")];
333
+ _documentWorkflowStatus_decorators = [Remote("documentWorkflowStatus")];
334
+ _approveDocumentWorkflow_decorators = [Remote("approveDocumentWorkflow")];
272
335
  _previewWorkspaceDocument_decorators = [Remote("previewWorkspaceDocument")];
273
336
  _skillsList_decorators = [Remote("skillsList")];
274
337
  _skillsGet_decorators = [Remote("skillsGet")];
@@ -293,9 +356,11 @@ let QaSurface = (() => {
293
356
  __esDecorate(this, null, _accountsListServiceTokens_decorators, { kind: "method", name: "accountsListServiceTokens", static: false, private: false, access: { has: obj => "accountsListServiceTokens" in obj, get: obj => obj.accountsListServiceTokens }, metadata: _metadata }, null, _instanceExtraInitializers);
294
357
  __esDecorate(this, null, _accountsCreateServiceToken_decorators, { kind: "method", name: "accountsCreateServiceToken", static: false, private: false, access: { has: obj => "accountsCreateServiceToken" in obj, get: obj => obj.accountsCreateServiceToken }, metadata: _metadata }, null, _instanceExtraInitializers);
295
358
  __esDecorate(this, null, _accountsRevokeServiceToken_decorators, { kind: "method", name: "accountsRevokeServiceToken", static: false, private: false, access: { has: obj => "accountsRevokeServiceToken" in obj, get: obj => obj.accountsRevokeServiceToken }, metadata: _metadata }, null, _instanceExtraInitializers);
359
+ __esDecorate(this, null, _accountsSetServiceTokenClarifications_decorators, { kind: "method", name: "accountsSetServiceTokenClarifications", static: false, private: false, access: { has: obj => "accountsSetServiceTokenClarifications" in obj, get: obj => obj.accountsSetServiceTokenClarifications }, metadata: _metadata }, null, _instanceExtraInitializers);
296
360
  __esDecorate(this, null, _describe_decorators, { kind: "method", name: "describe", static: false, private: false, access: { has: obj => "describe" in obj, get: obj => obj.describe }, metadata: _metadata }, null, _instanceExtraInitializers);
297
361
  __esDecorate(this, null, _queueStatus_decorators, { kind: "method", name: "queueStatus", static: false, private: false, access: { has: obj => "queueStatus" in obj, get: obj => obj.queueStatus }, metadata: _metadata }, null, _instanceExtraInitializers);
298
362
  __esDecorate(this, null, _createSession_decorators, { kind: "method", name: "createSession", static: false, private: false, access: { has: obj => "createSession" in obj, get: obj => obj.createSession }, metadata: _metadata }, null, _instanceExtraInitializers);
363
+ __esDecorate(this, null, _forkSession_decorators, { kind: "method", name: "forkSession", static: false, private: false, access: { has: obj => "forkSession" in obj, get: obj => obj.forkSession }, metadata: _metadata }, null, _instanceExtraInitializers);
299
364
  __esDecorate(this, null, _accessCurrent_decorators, { kind: "method", name: "accessCurrent", static: false, private: false, access: { has: obj => "accessCurrent" in obj, get: obj => obj.accessCurrent }, metadata: _metadata }, null, _instanceExtraInitializers);
300
365
  __esDecorate(this, null, _accessSession_decorators, { kind: "method", name: "accessSession", static: false, private: false, access: { has: obj => "accessSession" in obj, get: obj => obj.accessSession }, metadata: _metadata }, null, _instanceExtraInitializers);
301
366
  __esDecorate(this, null, _accessAdminSnapshot_decorators, { kind: "method", name: "accessAdminSnapshot", static: false, private: false, access: { has: obj => "accessAdminSnapshot" in obj, get: obj => obj.accessAdminSnapshot }, metadata: _metadata }, null, _instanceExtraInitializers);
@@ -336,6 +401,25 @@ let QaSurface = (() => {
336
401
  __esDecorate(this, null, _adminMetrics_decorators, { kind: "method", name: "adminMetrics", static: false, private: false, access: { has: obj => "adminMetrics" in obj, get: obj => obj.adminMetrics }, metadata: _metadata }, null, _instanceExtraInitializers);
337
402
  __esDecorate(this, null, _adminAudit_decorators, { kind: "method", name: "adminAudit", static: false, private: false, access: { has: obj => "adminAudit" in obj, get: obj => obj.adminAudit }, metadata: _metadata }, null, _instanceExtraInitializers);
338
403
  __esDecorate(this, null, _secureSession_decorators, { kind: "method", name: "secureSession", static: false, private: false, access: { has: obj => "secureSession" in obj, get: obj => obj.secureSession }, metadata: _metadata }, null, _instanceExtraInitializers);
404
+ __esDecorate(this, null, _chatVisible_decorators, { kind: "method", name: "chatVisible", static: false, private: false, access: { has: obj => "chatVisible" in obj, get: obj => obj.chatVisible }, metadata: _metadata }, null, _instanceExtraInitializers);
405
+ __esDecorate(this, null, _chatAccess_decorators, { kind: "method", name: "chatAccess", static: false, private: false, access: { has: obj => "chatAccess" in obj, get: obj => obj.chatAccess }, metadata: _metadata }, null, _instanceExtraInitializers);
406
+ __esDecorate(this, null, _chatGrants_decorators, { kind: "method", name: "chatGrants", static: false, private: false, access: { has: obj => "chatGrants" in obj, get: obj => obj.chatGrants }, metadata: _metadata }, null, _instanceExtraInitializers);
407
+ __esDecorate(this, null, _chatSetGrant_decorators, { kind: "method", name: "chatSetGrant", static: false, private: false, access: { has: obj => "chatSetGrant" in obj, get: obj => obj.chatSetGrant }, metadata: _metadata }, null, _instanceExtraInitializers);
408
+ __esDecorate(this, null, _chatAuthors_decorators, { kind: "method", name: "chatAuthors", static: false, private: false, access: { has: obj => "chatAuthors" in obj, get: obj => obj.chatAuthors }, metadata: _metadata }, null, _instanceExtraInitializers);
409
+ __esDecorate(this, null, _chatAudit_decorators, { kind: "method", name: "chatAudit", static: false, private: false, access: { has: obj => "chatAudit" in obj, get: obj => obj.chatAudit }, metadata: _metadata }, null, _instanceExtraInitializers);
410
+ __esDecorate(this, null, _chatAttachmentPath_decorators, { kind: "method", name: "chatAttachmentPath", static: false, private: false, access: { has: obj => "chatAttachmentPath" in obj, get: obj => obj.chatAttachmentPath }, metadata: _metadata }, null, _instanceExtraInitializers);
411
+ __esDecorate(this, null, _chatList_decorators, { kind: "method", name: "chatList", static: false, private: false, access: { has: obj => "chatList" in obj, get: obj => obj.chatList }, metadata: _metadata }, null, _instanceExtraInitializers);
412
+ __esDecorate(this, null, _chatSearch_decorators, { kind: "method", name: "chatSearch", static: false, private: false, access: { has: obj => "chatSearch" in obj, get: obj => obj.chatSearch }, metadata: _metadata }, null, _instanceExtraInitializers);
413
+ __esDecorate(this, null, _chatSelectModel_decorators, { kind: "method", name: "chatSelectModel", static: false, private: false, access: { has: obj => "chatSelectModel" in obj, get: obj => obj.chatSelectModel }, metadata: _metadata }, null, _instanceExtraInitializers);
414
+ __esDecorate(this, null, _chatPage_decorators, { kind: "method", name: "chatPage", static: false, private: false, access: { has: obj => "chatPage" in obj, get: obj => obj.chatPage }, metadata: _metadata }, null, _instanceExtraInitializers);
415
+ __esDecorate(this, null, _chatFollow_decorators, { kind: "method", name: "chatFollow", static: false, private: false, access: { has: obj => "chatFollow" in obj, get: obj => obj.chatFollow }, metadata: _metadata }, null, _instanceExtraInitializers);
416
+ __esDecorate(this, null, _chatControl_decorators, { kind: "method", name: "chatControl", static: false, private: false, access: { has: obj => "chatControl" in obj, get: obj => obj.chatControl }, metadata: _metadata }, null, _instanceExtraInitializers);
417
+ __esDecorate(this, null, _chatProjections_decorators, { kind: "method", name: "chatProjections", static: false, private: false, access: { has: obj => "chatProjections" in obj, get: obj => obj.chatProjections }, metadata: _metadata }, null, _instanceExtraInitializers);
418
+ __esDecorate(this, null, _chatPrompt_decorators, { kind: "method", name: "chatPrompt", static: false, private: false, access: { has: obj => "chatPrompt" in obj, get: obj => obj.chatPrompt }, metadata: _metadata }, null, _instanceExtraInitializers);
419
+ __esDecorate(this, null, _chatAttachment_decorators, { kind: "method", name: "chatAttachment", static: false, private: false, access: { has: obj => "chatAttachment" in obj, get: obj => obj.chatAttachment }, metadata: _metadata }, null, _instanceExtraInitializers);
420
+ __esDecorate(this, null, _chatRename_decorators, { kind: "method", name: "chatRename", static: false, private: false, access: { has: obj => "chatRename" in obj, get: obj => obj.chatRename }, metadata: _metadata }, null, _instanceExtraInitializers);
421
+ __esDecorate(this, null, _chatCancel_decorators, { kind: "method", name: "chatCancel", static: false, private: false, access: { has: obj => "chatCancel" in obj, get: obj => obj.chatCancel }, metadata: _metadata }, null, _instanceExtraInitializers);
422
+ __esDecorate(this, null, _chatUpdateQueue_decorators, { kind: "method", name: "chatUpdateQueue", static: false, private: false, access: { has: obj => "chatUpdateQueue" in obj, get: obj => obj.chatUpdateQueue }, metadata: _metadata }, null, _instanceExtraInitializers);
339
423
  __esDecorate(this, null, _sources_decorators, { kind: "method", name: "sources", static: false, private: false, access: { has: obj => "sources" in obj, get: obj => obj.sources }, metadata: _metadata }, null, _instanceExtraInitializers);
340
424
  __esDecorate(this, null, _pendingApprovals_decorators, { kind: "method", name: "pendingApprovals", static: false, private: false, access: { has: obj => "pendingApprovals" in obj, get: obj => obj.pendingApprovals }, metadata: _metadata }, null, _instanceExtraInitializers);
341
425
  __esDecorate(this, null, _answerApproval_decorators, { kind: "method", name: "answerApproval", static: false, private: false, access: { has: obj => "answerApproval" in obj, get: obj => obj.answerApproval }, metadata: _metadata }, null, _instanceExtraInitializers);
@@ -343,8 +427,12 @@ let QaSurface = (() => {
343
427
  __esDecorate(this, null, _answerQuestion_decorators, { kind: "method", name: "answerQuestion", static: false, private: false, access: { has: obj => "answerQuestion" in obj, get: obj => obj.answerQuestion }, metadata: _metadata }, null, _instanceExtraInitializers);
344
428
  __esDecorate(this, null, _cancelQuestion_decorators, { kind: "method", name: "cancelQuestion", static: false, private: false, access: { has: obj => "cancelQuestion" in obj, get: obj => obj.cancelQuestion }, metadata: _metadata }, null, _instanceExtraInitializers);
345
429
  __esDecorate(this, null, _readSourceFile_decorators, { kind: "method", name: "readSourceFile", static: false, private: false, access: { has: obj => "readSourceFile" in obj, get: obj => obj.readSourceFile }, metadata: _metadata }, null, _instanceExtraInitializers);
430
+ __esDecorate(this, null, _readSourceImage_decorators, { kind: "method", name: "readSourceImage", static: false, private: false, access: { has: obj => "readSourceImage" in obj, get: obj => obj.readSourceImage }, metadata: _metadata }, null, _instanceExtraInitializers);
346
431
  __esDecorate(this, null, _listWorkspaceFiles_decorators, { kind: "method", name: "listWorkspaceFiles", static: false, private: false, access: { has: obj => "listWorkspaceFiles" in obj, get: obj => obj.listWorkspaceFiles }, metadata: _metadata }, null, _instanceExtraInitializers);
347
432
  __esDecorate(this, null, _readWorkspaceFile_decorators, { kind: "method", name: "readWorkspaceFile", static: false, private: false, access: { has: obj => "readWorkspaceFile" in obj, get: obj => obj.readWorkspaceFile }, metadata: _metadata }, null, _instanceExtraInitializers);
433
+ __esDecorate(this, null, _readWorkspaceFileChunk_decorators, { kind: "method", name: "readWorkspaceFileChunk", static: false, private: false, access: { has: obj => "readWorkspaceFileChunk" in obj, get: obj => obj.readWorkspaceFileChunk }, metadata: _metadata }, null, _instanceExtraInitializers);
434
+ __esDecorate(this, null, _documentWorkflowStatus_decorators, { kind: "method", name: "documentWorkflowStatus", static: false, private: false, access: { has: obj => "documentWorkflowStatus" in obj, get: obj => obj.documentWorkflowStatus }, metadata: _metadata }, null, _instanceExtraInitializers);
435
+ __esDecorate(this, null, _approveDocumentWorkflow_decorators, { kind: "method", name: "approveDocumentWorkflow", static: false, private: false, access: { has: obj => "approveDocumentWorkflow" in obj, get: obj => obj.approveDocumentWorkflow }, metadata: _metadata }, null, _instanceExtraInitializers);
348
436
  __esDecorate(this, null, _previewWorkspaceDocument_decorators, { kind: "method", name: "previewWorkspaceDocument", static: false, private: false, access: { has: obj => "previewWorkspaceDocument" in obj, get: obj => obj.previewWorkspaceDocument }, metadata: _metadata }, null, _instanceExtraInitializers);
349
437
  __esDecorate(this, null, _skillsList_decorators, { kind: "method", name: "skillsList", static: false, private: false, access: { has: obj => "skillsList" in obj, get: obj => obj.skillsList }, metadata: _metadata }, null, _instanceExtraInitializers);
350
438
  __esDecorate(this, null, _skillsGet_decorators, { kind: "method", name: "skillsGet", static: false, private: false, access: { has: obj => "skillsGet" in obj, get: obj => obj.skillsGet }, metadata: _metadata }, null, _instanceExtraInitializers);
@@ -407,6 +495,19 @@ let QaSurface = (() => {
407
495
  * opens the admin console never grows one.
408
496
  */
409
497
  qualityStore;
498
+ chatSharingStore;
499
+ chatTransport;
500
+ chatTurnGuard;
501
+ sharing() {
502
+ const accounts = () => {
503
+ const store = this.accountRemotes.resolve(this.getConfig());
504
+ if (store === undefined)
505
+ throw new Error("QA accounts are required for chat sharing.");
506
+ return store;
507
+ };
508
+ accounts();
509
+ return (this.chatSharingStore ??= new QaChatSharingStore(path.join(path.dirname(defaultAccountsFilePath()), "qa-chat-sharing.db"), accounts));
510
+ }
410
511
  constructor(ctx, entry = {}) {
411
512
  super(ctx, "qaSurface", { namespace: "qaSurface" });
412
513
  // Every Config field is volatile, so the reference the Host hands here is
@@ -453,6 +554,7 @@ let QaSurface = (() => {
453
554
  // Deletion is the console's alone: the sidebar's delete stays a
454
555
  // per-browser row, and only an administrator removes the chat itself.
455
556
  sessionFiles: createSessionEraser(),
557
+ ...(this.getConfig().accounts.enabled ? { sharing: this.sharing() } : {}),
456
558
  dropSources: (sessionId) => this.provenance.dropSession(sessionId),
457
559
  // The console writes skills through the same service the owner's editor
458
560
  // uses, so an administrator's save is path-checked, validated and
@@ -472,6 +574,23 @@ let QaSurface = (() => {
472
574
  });
473
575
  this.slashRemotes = createQaSlashRemotes({
474
576
  ctx,
577
+ draftSkills: async (token, target) => {
578
+ this.accountRemotes.resolve(this.getConfig());
579
+ const preview = await this.access.slashDraftSkills(token, target.subroleId, target.adminPreview);
580
+ return {
581
+ skills: preview.skills.map((skill) => ({
582
+ name: skill.name,
583
+ description: skill.description,
584
+ modelInvocable: skill.invocation.modelInvocable,
585
+ ...(skill.whenToUse === undefined
586
+ ? {}
587
+ : { whenToUse: skill.whenToUse }),
588
+ })),
589
+ grantedSkills: preview.policy === undefined
590
+ ? undefined
591
+ : userInvocableSkillNames(preview.policy),
592
+ };
593
+ },
475
594
  getConfig: () => this.getConfig(),
476
595
  logger: this.logger,
477
596
  sessionGrant: (token, sessionId, agent) => this.slashSessionGrant(token, sessionId, agent),
@@ -505,6 +624,20 @@ let QaSurface = (() => {
505
624
  new FileQaProvenanceSnapshotStore(defaultQaProvenanceDirectoryPath(), () => this.getConfig().sources.retention, defaultLegacyProvenanceFilePath()), (error) => this.logger.error("sources.persistence-failed", {
506
625
  message: error instanceof Error ? error.message : String(error),
507
626
  }));
627
+ this.chatTransport = new QaChatTransport(ctx, () => this.sharing(), (token, id) => this.secureSession(token, id), (userId, id) => this.access.participantPolicy(userId, id));
628
+ this.chatTurnGuard = new QaChatTurnGuard(ctx, () => this.sharing(), (userId, id) => this.access.participantPolicy(userId, id), () => this.getConfig().accounts.enabled);
629
+ ctx.effect(() => () => {
630
+ this.chatTurnGuard.dispose();
631
+ this.chatSharingStore?.storage.close();
632
+ }, "dsh-qa-surface.chat-sharing");
633
+ ctx.inject(["typertGateway", "connection"], () => {
634
+ const dispose = installQaNativeFence(ctx, () => this.getConfig().accounts.enabled);
635
+ const disposeUploads = installQaChatUploads(ctx, () => this.sharing(), (token, id) => this.secureSession(token, id));
636
+ return async () => {
637
+ dispose();
638
+ await disposeUploads();
639
+ };
640
+ });
508
641
  this.integration = new QaIntegrationService({
509
642
  getConfig: () => this.getConfig(),
510
643
  accounts: () => this.accountRemotes.resolve(this.getConfig()),
@@ -530,8 +663,15 @@ let QaSurface = (() => {
530
663
  // operator's answer while they are interactive. The question seam shares
531
664
  // the ownership map: one chat, one surface answering it.
532
665
  const ownership = new QaSessionOwnership((sessionId) => this.admission.knowsSession(sessionId));
666
+ ownership.install(ctx);
667
+ new QaLlmIdentity(ctx, {
668
+ rootOf: (sessionId) => ownership.rootOf(sessionId),
669
+ accounts: () => this.accountRemotes.resolve(this.getConfig()),
670
+ });
533
671
  this.approvals = new QaApprovalGate(ctx, () => this.getConfig().interaction.approvals === "interactive", ownership, this.logger);
534
- this.userQuestions = new QaQuestionGate(ctx, () => this.getConfig().interaction.questions === "interactive", ownership, this.logger);
672
+ const integrationQuestionPolicy = new QaIntegrationQuestionPolicy(ctx, () => this.accountRemotes.resolve(this.getConfig()), (id) => ownership.rootOf(id));
673
+ ctx.effect(() => () => integrationQuestionPolicy.dispose(), "qa-surface: integration question policy");
674
+ this.userQuestions = new QaQuestionGate(ctx, () => this.getConfig().interaction.questions === "interactive", ownership, this.logger, (agent) => integrationQuestionPolicy.allowed(agent));
535
675
  // The destructive tool of the QA catalog composes the same approval flow
536
676
  // around itself: registered without `prepend`, it sits inside the approval
537
677
  // gate and answers `ask` for every file_delete call of an attested chat,
@@ -711,6 +851,8 @@ let QaSurface = (() => {
711
851
  }
712
852
  /** Resolve only a directly QA-owned root session; delegated children fail closed. */
713
853
  principalForSession(sessionId) {
854
+ if (this.chatTurnGuard.collaborative(sessionId))
855
+ return undefined;
714
856
  const accounts = this.accountRemotes.resolve(this.getConfig());
715
857
  if (accounts === undefined)
716
858
  return undefined;
@@ -872,6 +1014,9 @@ let QaSurface = (() => {
872
1014
  accountsRevokeServiceToken(token, tokenId) {
873
1015
  return this.accountRemotes.revokeServiceToken(token, tokenId);
874
1016
  }
1017
+ accountsSetServiceTokenClarifications(token, tokenId, allowed) {
1018
+ return this.accountRemotes.setServiceTokenClarifications(token, tokenId, allowed);
1019
+ }
875
1020
  /**
876
1021
  * Serve the effective QA configuration to the browser. The DSH gateway pins
877
1022
  * settings RPCs to loopback, so a browser served over the LAN always sees
@@ -965,6 +1110,20 @@ let QaSurface = (() => {
965
1110
  throw new Error(qaAttestationFailureMessage("Unable to create a QA session.", error), { cause: error });
966
1111
  }
967
1112
  }
1113
+ /** Create an independently admitted ordinary branch of the caller's own chat. */
1114
+ async forkSession(token, sourceId, answerSeq) {
1115
+ return this.accountRemotes.runAsync(() => forkQaSession({
1116
+ ctx: this.ctx,
1117
+ config: this.getConfig(),
1118
+ accounts: this.accountRemotes.resolve(this.getConfig()),
1119
+ access: this.access,
1120
+ admission: this.admission,
1121
+ principals: this.integrationPrincipals,
1122
+ provenance: this.provenance,
1123
+ sessionFiles: createSessionEraser(),
1124
+ logger: this.logger,
1125
+ }, token, sourceId, answerSeq), sourceId);
1126
+ }
968
1127
  /** The selector model for the signed-in user; admin grants are irrelevant. */
969
1128
  accessCurrent(token) {
970
1129
  return this.accountRemotes.run(() => this.access.current(token));
@@ -1125,7 +1284,13 @@ let QaSurface = (() => {
1125
1284
  * stays what it always was, a per-browser row.
1126
1285
  */
1127
1286
  adminDeleteConversation(token, conversationId) {
1128
- return this.accountRemotes.runAsync(() => this.admin.deleteConversation(token, conversationId));
1287
+ return this.accountRemotes.runAsync(async () => {
1288
+ const result = await this.admin.deleteConversation(token, conversationId);
1289
+ if (this.getConfig().accounts.enabled)
1290
+ for (const id of result.sessions)
1291
+ this.sharing().dropSession(id);
1292
+ return result;
1293
+ });
1129
1294
  }
1130
1295
  adminFeedback(token, query, cursor, limit) {
1131
1296
  return this.accountRemotes.runAsync(() => this.admin.feedback(token, query, cursor ?? undefined, limit ?? undefined));
@@ -1163,16 +1328,46 @@ let QaSurface = (() => {
1163
1328
  /** Pin and attest the effective policy. The browser supplies identity only. */
1164
1329
  async secureSession(token, sessionId) {
1165
1330
  try {
1331
+ const accountsForSharing = this.accountRemotes.resolve(this.getConfig());
1332
+ const actor = accountsForSharing?.currentUser(token);
1333
+ const actualOwnerId = accountsForSharing?.ownerIdOf(sessionId);
1334
+ if (actualOwnerId !== undefined && actor?.id !== actualOwnerId) {
1335
+ let shared;
1336
+ try {
1337
+ shared = this.sharing().access(token, sessionId);
1338
+ }
1339
+ catch (error) {
1340
+ if (actor?.role !== "admin" ||
1341
+ !this.getConfig().accounts.showOtherUsersChats)
1342
+ throw error;
1343
+ }
1344
+ if (shared !== undefined) {
1345
+ const proof = await this.admission.secureSessionForUser(shared.ownerId, sessionId);
1346
+ this.sharing().revalidate(token, shared);
1347
+ return { ...proof, chatAccess: shared };
1348
+ }
1349
+ }
1166
1350
  const principal = this.principalForToken(token);
1167
1351
  const proof = await this.admission.secureSession(token, sessionId);
1168
1352
  const accounts = this.accountRemotes.resolve(this.getConfig());
1169
1353
  const ownerId = accounts?.ownerIdOf(sessionId);
1170
1354
  // Admin cross-user viewing is intentionally not credential delegation.
1171
- this.integrationPrincipals.attest(sessionId, principal?.userId, ownerId);
1172
- return proof;
1355
+ if (principal?.userId === ownerId)
1356
+ this.integrationPrincipals.attest(sessionId, principal?.userId, ownerId);
1357
+ const session = this.ctx.sessions.get(SessionId(sessionId));
1358
+ const chatAccess = actualOwnerId === actor?.id && actor !== undefined
1359
+ ? this.sharing().access(token, sessionId)
1360
+ : undefined;
1361
+ return {
1362
+ ...proof,
1363
+ ...(chatAccess === undefined ? {} : { chatAccess }),
1364
+ ...(session?.header.isSeeded === true &&
1365
+ session.header.origin !== "subagent"
1366
+ ? { inheritedThroughSeq: Number(session.inheritedEventCount) - 1 }
1367
+ : {}),
1368
+ };
1173
1369
  }
1174
1370
  catch (error) {
1175
- this.integrationPrincipals.attest(sessionId, undefined, undefined);
1176
1371
  // The carrier empties error.details, so the coarse reason rides the
1177
1372
  // wire message for the browser console; the specific mismatch facts
1178
1373
  // stay in this log only.
@@ -1189,9 +1384,110 @@ let QaSurface = (() => {
1189
1384
  });
1190
1385
  }
1191
1386
  }
1387
+ chatVisible(token) {
1388
+ return this.sharing().visible(token);
1389
+ }
1390
+ chatAccess(token, sessionId) {
1391
+ return this.sharing().access(token, sessionId);
1392
+ }
1393
+ chatGrants(token, sessionId) {
1394
+ return this.sharing().grants(token, sessionId);
1395
+ }
1396
+ chatSetGrant(token, sessionId, email, mode) {
1397
+ if (this.access.isDelegatedChild(sessionId) ||
1398
+ this.getConfig().session.policy === "fixed")
1399
+ throw new Error("Only an ordinary account-owned chat may be shared.");
1400
+ const value = this.sharing().set(token, sessionId, email, mode);
1401
+ this.chatTurnGuard.revoke(sessionId);
1402
+ return value;
1403
+ }
1404
+ chatAuthors(token, sessionId) {
1405
+ return this.sharing().authors(token, sessionId);
1406
+ }
1407
+ async chatAudit(token, sessionId, full) {
1408
+ this.requireChatOwner(token, sessionId);
1409
+ await this.secureSession(token, sessionId);
1410
+ this.requireChatOwner(token, sessionId);
1411
+ const audit = this.ctx.get("sessionAudit");
1412
+ if (audit === undefined)
1413
+ throw new Error("Session audit is unavailable.");
1414
+ const value = full
1415
+ ? await audit.audit(sessionId)
1416
+ : audit.summary(sessionId);
1417
+ this.requireChatOwner(token, sessionId);
1418
+ return value;
1419
+ }
1420
+ async chatAttachmentPath(token, sessionId, attachmentId) {
1421
+ const finish = await this.admitChatRead(token, sessionId);
1422
+ const value = qaChatAttachmentPath(this.ctx, sessionId, attachmentId);
1423
+ finish();
1424
+ return value;
1425
+ }
1426
+ async chatList(token, signal) {
1427
+ return (await this.chatTransport.list(token, signal));
1428
+ }
1429
+ async chatSearch(token, request, signal) {
1430
+ return (await this.chatTransport.search(token, request, signal));
1431
+ }
1432
+ chatSelectModel(token, request) {
1433
+ this.requireChatOwner(token, String(request.sessionId));
1434
+ if (this.getConfig().lockdown.enforceFixedModel)
1435
+ throw new Error("The chat model is fixed by its policy.");
1436
+ return this.chatTransport.selectModel(token, request);
1437
+ }
1438
+ async chatPage(token, request, signal) {
1439
+ return (await this.chatTransport.page(token, request, signal));
1440
+ }
1441
+ async *chatFollow(token, request, signal) {
1442
+ for await (const frame of this.chatTransport.follow(token, request, signal))
1443
+ yield frame;
1444
+ }
1445
+ async *chatControl(token, signal) {
1446
+ for await (const frame of this.chatTransport.control(token, signal))
1447
+ yield frame;
1448
+ }
1449
+ async chatProjections(token, sessionId, signal) {
1450
+ return (await this.chatTransport.projections(token, sessionId, signal));
1451
+ }
1452
+ chatPrompt(token, request, signal) {
1453
+ return this.chatTransport.prompt(token, request, signal);
1454
+ }
1455
+ chatAttachment(token, request) {
1456
+ return this.chatTransport.attachment(token, request);
1457
+ }
1458
+ chatRename(token, request) {
1459
+ return this.chatTransport.rename(token, request);
1460
+ }
1461
+ chatCancel(token, sessionId) {
1462
+ return this.chatTransport.cancel(token, sessionId);
1463
+ }
1464
+ chatUpdateQueue(token, request) {
1465
+ return this.chatTransport.updateQueue(token, request);
1466
+ }
1467
+ async admitChatRead(token, sessionId, filePath) {
1468
+ if (!this.getConfig().accounts.enabled) {
1469
+ await this.admission.secureSession(token, sessionId);
1470
+ return () => undefined;
1471
+ }
1472
+ const access = this.sharing().access(token, sessionId);
1473
+ await this.secureSession(token, sessionId);
1474
+ this.sharing().revalidate(token, access);
1475
+ if (filePath !== undefined &&
1476
+ access.mode !== "owner" &&
1477
+ !qaChatPublishedFile(this.ctx, sessionId, filePath, (id, path) => this.provenance.sourceAllowed(id, path)))
1478
+ throw new Error("This file has not been shared in the chat.");
1479
+ return () => {
1480
+ this.sharing().revalidate(token, access);
1481
+ };
1482
+ }
1483
+ requireChatOwner(token, sessionId) {
1484
+ if (this.getConfig().accounts.enabled)
1485
+ this.sharing().owner(token, sessionId);
1486
+ }
1192
1487
  /** Return canonical Host snapshots from plugin-owned durable provenance. */
1193
1488
  async sources(token, sessionId) {
1194
- await this.admission.secureSession(token, sessionId);
1489
+ const finish = await this.admitChatRead(token, sessionId);
1490
+ finish();
1195
1491
  return this.provenance.bundles(sessionId);
1196
1492
  }
1197
1493
  /**
@@ -1199,7 +1495,10 @@ let QaSurface = (() => {
1199
1495
  * deployment with blocked approvals answers with an empty list.
1200
1496
  */
1201
1497
  async pendingApprovals(token, sessionId) {
1202
- await this.admission.secureSession(token, sessionId);
1498
+ await this.secureSession(token, sessionId);
1499
+ if (this.getConfig().accounts.enabled &&
1500
+ this.sharing().access(token, sessionId).mode !== "owner")
1501
+ return [];
1203
1502
  return this.approvals.list(sessionId);
1204
1503
  }
1205
1504
  /**
@@ -1208,7 +1507,9 @@ let QaSurface = (() => {
1208
1507
  * the agent went away) is refused with `false`.
1209
1508
  */
1210
1509
  async answerApproval(token, sessionId, requestId, decision) {
1510
+ this.requireChatOwner(token, sessionId);
1211
1511
  await this.admission.secureSession(token, sessionId);
1512
+ this.requireChatOwner(token, sessionId);
1212
1513
  return this.approvals.answer(sessionId, requestId, decision);
1213
1514
  }
1214
1515
  /**
@@ -1216,7 +1517,10 @@ let QaSurface = (() => {
1216
1517
  * deployment with unsupported questions answers with an empty list.
1217
1518
  */
1218
1519
  async pendingQuestions(token, sessionId) {
1219
- await this.admission.secureSession(token, sessionId);
1520
+ await this.secureSession(token, sessionId);
1521
+ if (this.getConfig().accounts.enabled &&
1522
+ this.sharing().access(token, sessionId).mode !== "owner")
1523
+ return [];
1220
1524
  return this.userQuestions.list(sessionId);
1221
1525
  }
1222
1526
  /**
@@ -1225,12 +1529,16 @@ let QaSurface = (() => {
1225
1529
  * a skip.
1226
1530
  */
1227
1531
  async answerQuestion(token, sessionId, requestId, answers) {
1532
+ this.requireChatOwner(token, sessionId);
1228
1533
  await this.admission.secureSession(token, sessionId);
1534
+ this.requireChatOwner(token, sessionId);
1229
1535
  return this.userQuestions.answer(sessionId, requestId, answers);
1230
1536
  }
1231
1537
  /** Close a parked question request without answering it. */
1232
1538
  async cancelQuestion(token, sessionId, requestId) {
1539
+ this.requireChatOwner(token, sessionId);
1233
1540
  await this.admission.secureSession(token, sessionId);
1541
+ this.requireChatOwner(token, sessionId);
1234
1542
  return this.userQuestions.cancel(sessionId, requestId);
1235
1543
  }
1236
1544
  /**
@@ -1242,8 +1550,8 @@ let QaSurface = (() => {
1242
1550
  * read — the normal case for a deployment whose docs and code live beside
1243
1551
  * the per-account scratch directory — could never be opened in the panel.
1244
1552
  */
1245
- async readSourceFile(token, sessionId, sourcePath) {
1246
- await this.admission.secureSession(token, sessionId);
1553
+ async readSourceFile(token, sessionId, sourcePath, selection) {
1554
+ const finish = await this.admitChatRead(token, sessionId, sourcePath);
1247
1555
  const config = this.getConfig();
1248
1556
  if (!config.sources.filePreview.enabled) {
1249
1557
  throw sourcePreviewRefusal("unavailable");
@@ -1254,7 +1562,7 @@ let QaSurface = (() => {
1254
1562
  throw sourcePreviewRefusal("unavailable");
1255
1563
  const attachmentRoot = this.admission.attachmentRoot();
1256
1564
  try {
1257
- return await readSourceFilePreview({
1565
+ const value = await readSourceFilePreview({
1258
1566
  sourcePath,
1259
1567
  cwd,
1260
1568
  isEvidence: (canonicalPath) => this.provenance.sourceAllowed(sessionId, canonicalPath),
@@ -1262,7 +1570,34 @@ let QaSurface = (() => {
1262
1570
  ...(attachmentRoot === undefined ? {} : { attachmentRoot }),
1263
1571
  maxBytes: config.sources.filePreview.maxBytes,
1264
1572
  maxMarkdownRenderBytes: config.sources.filePreview.maxMarkdownRenderBytes,
1573
+ renderFrontmatter: config.sources.filePreview.renderFrontmatter,
1574
+ }).catch(async (error) => {
1575
+ // Only a format refusal follows successful evidence and root checks.
1576
+ if (!(error instanceof QaSourcePreviewError) ||
1577
+ error.reason !== "unsupported")
1578
+ throw error;
1579
+ const document = await previewSourceDocument({
1580
+ filePath: sourcePath,
1581
+ cwd,
1582
+ sessionId,
1583
+ sharedReadOnlyRoots: config.lockdown.sharedReadOnlyRoots,
1584
+ ...(attachmentRoot === undefined ? {} : { attachmentRoot }),
1585
+ documents: () => this.ctx.get("documents"),
1586
+ maxBytes: config.sources.filePreview.maxBytes,
1587
+ ...(selection === undefined ? {} : { selection }),
1588
+ });
1589
+ return {
1590
+ path: sourcePath,
1591
+ content: "",
1592
+ size: document.bytes,
1593
+ truncated: false,
1594
+ markdown: false,
1595
+ renderableMarkdown: false,
1596
+ document,
1597
+ };
1265
1598
  });
1599
+ finish();
1600
+ return value;
1266
1601
  }
1267
1602
  catch (error) {
1268
1603
  this.logger.debug("source.preview-refused", {
@@ -1272,6 +1607,31 @@ let QaSurface = (() => {
1272
1607
  throw sourcePreviewRefusal(error instanceof QaSourcePreviewError ? error.reason : "unavailable");
1273
1608
  }
1274
1609
  }
1610
+ /** Load one relative raster illustration of an attested Markdown source. */
1611
+ async readSourceImage(token, sessionId, sourcePath, imagePath) {
1612
+ const finish = await this.admitChatRead(token, sessionId, sourcePath);
1613
+ const config = this.getConfig();
1614
+ const cwd = this.ctx.agents.get(SessionId(sessionId))?.session.header.cwd;
1615
+ if (!config.sources.filePreview.enabled || cwd === undefined)
1616
+ throw sourcePreviewRefusal("unavailable");
1617
+ const attachmentRoot = this.admission.attachmentRoot();
1618
+ try {
1619
+ const result = await readSourceImagePreview({
1620
+ sourcePath,
1621
+ cwd,
1622
+ isEvidence: (canonicalPath) => this.provenance.sourceAllowed(sessionId, canonicalPath),
1623
+ sharedReadOnlyRoots: config.lockdown.sharedReadOnlyRoots,
1624
+ ...(attachmentRoot === undefined ? {} : { attachmentRoot }),
1625
+ maxBytes: config.sources.filePreview.maxBytes,
1626
+ maxMarkdownRenderBytes: config.sources.filePreview.maxMarkdownRenderBytes,
1627
+ }, imagePath);
1628
+ finish();
1629
+ return result;
1630
+ }
1631
+ catch (error) {
1632
+ throw sourcePreviewRefusal(error instanceof QaSourcePreviewError ? error.reason : "unavailable");
1633
+ }
1634
+ }
1275
1635
  /**
1276
1636
  * List one directory of the chat's own workspace for the files panel.
1277
1637
  *
@@ -1281,6 +1641,7 @@ let QaSurface = (() => {
1281
1641
  * `readWorkspaceFile` opens one entry of such a listing.
1282
1642
  */
1283
1643
  async listWorkspaceFiles(token, sessionId, path) {
1644
+ this.requireChatOwner(token, sessionId);
1284
1645
  await this.admission.secureSession(token, sessionId);
1285
1646
  const { config, cwd } = await this.browseContext(sessionId);
1286
1647
  try {
@@ -1303,11 +1664,11 @@ let QaSurface = (() => {
1303
1664
  * reopening a cited source.
1304
1665
  */
1305
1666
  async readWorkspaceFile(token, sessionId, path) {
1306
- await this.admission.secureSession(token, sessionId);
1667
+ const finish = await this.admitChatRead(token, sessionId, path);
1307
1668
  const { config, cwd } = await this.browseContext(sessionId);
1308
1669
  const attachmentRoot = this.admission.attachmentRoot();
1309
1670
  try {
1310
- return await readWorkspaceFile({
1671
+ const value = await readWorkspaceFile({
1311
1672
  filePath: path ?? "",
1312
1673
  cwd,
1313
1674
  sharedReadOnlyRoots: config.lockdown.sharedReadOnlyRoots,
@@ -1315,11 +1676,77 @@ let QaSurface = (() => {
1315
1676
  maxBytes: config.sources.filePreview.maxBytes,
1316
1677
  maxMarkdownRenderBytes: config.sources.filePreview.maxMarkdownRenderBytes,
1317
1678
  });
1679
+ finish();
1680
+ return value;
1318
1681
  }
1319
1682
  catch (error) {
1320
1683
  throw this.browseRefusal("workspace.read-refused", sessionId, error);
1321
1684
  }
1322
1685
  }
1686
+ /** Download one bounded chunk after revalidating this chat's ownership. */
1687
+ async readWorkspaceFileChunk(token, sessionId, path, offset, version) {
1688
+ const finish = await this.admitChatRead(token, sessionId, path);
1689
+ const { config, cwd } = await this.browseContext(sessionId);
1690
+ const attachmentRoot = this.admission.attachmentRoot();
1691
+ try {
1692
+ const value = await readWorkspaceFileChunk({
1693
+ filePath: path ?? "",
1694
+ cwd,
1695
+ sharedReadOnlyRoots: config.lockdown.sharedReadOnlyRoots,
1696
+ ...(attachmentRoot === undefined ? {} : { attachmentRoot }),
1697
+ offset,
1698
+ version,
1699
+ });
1700
+ finish();
1701
+ return value;
1702
+ }
1703
+ catch (error) {
1704
+ throw this.browseRefusal("workspace.download-refused", sessionId, error);
1705
+ }
1706
+ }
1707
+ async documentWorkflowStatus(token, sessionId, workflowId) {
1708
+ const finish = await this.admitChatRead(token, sessionId);
1709
+ const { cwd } = await this.browseContext(sessionId);
1710
+ const workflow = this.ctx.get("documents")
1711
+ ?.workflow;
1712
+ if (workflow === undefined)
1713
+ throw new Error("Document workflow is unavailable.");
1714
+ const view = await workflow.read({ workspaceRoot: cwd, sessionId }, workflowId);
1715
+ finish();
1716
+ return {
1717
+ id: view.id,
1718
+ revision: view.revision,
1719
+ status: view.status,
1720
+ sha256: view.draft?.sha256 ?? null,
1721
+ blockers: view.blockers,
1722
+ };
1723
+ }
1724
+ /** Browser-authenticated human consent; intentionally absent from the agent's tool registry. */
1725
+ async approveDocumentWorkflow(token, sessionId, workflowId, revision, sha256) {
1726
+ this.requireChatOwner(token, sessionId);
1727
+ await this.admission.secureSession(token, sessionId);
1728
+ this.requireChatOwner(token, sessionId);
1729
+ const caller = this.principalForToken(token);
1730
+ const ownerId = this.accountRemotes.resolve(this.getConfig())?.ownerIdOf(sessionId) ??
1731
+ (this.getConfig().accounts.enabled
1732
+ ? undefined
1733
+ : this.principalForSession(sessionId)?.userId);
1734
+ if (caller === undefined || ownerId !== caller.userId)
1735
+ throw new Error("Document approval requires the chat owner's account.");
1736
+ const { cwd } = await this.browseContext(sessionId);
1737
+ const workflow = this.ctx.get("documents")
1738
+ ?.workflow;
1739
+ if (workflow === undefined)
1740
+ throw new Error("Document workflow is unavailable.");
1741
+ const view = await workflow.approve({ workspaceRoot: cwd, sessionId }, workflowId, revision, sha256, caller.userId);
1742
+ return {
1743
+ id: view.id,
1744
+ revision: view.revision,
1745
+ status: view.status,
1746
+ sha256: view.draft?.sha256 ?? null,
1747
+ blockers: view.blockers,
1748
+ };
1749
+ }
1323
1750
  /**
1324
1751
  * Render one Word document of the chat's workspace as a PDF for the panel.
1325
1752
  *
@@ -1330,12 +1757,12 @@ let QaSurface = (() => {
1330
1757
  * produced PDF is read back here and travels as base64, so the audience never
1331
1758
  * reaches an unfenced byte route.
1332
1759
  */
1333
- async previewWorkspaceDocument(token, sessionId, path) {
1334
- await this.admission.secureSession(token, sessionId);
1760
+ async previewWorkspaceDocument(token, sessionId, path, selection) {
1761
+ const finish = await this.admitChatRead(token, sessionId, path);
1335
1762
  const { config, cwd } = await this.browseContext(sessionId);
1336
1763
  const attachmentRoot = this.admission.attachmentRoot();
1337
1764
  try {
1338
- return await previewConvertibleDocument({
1765
+ const value = await previewConvertibleDocument({
1339
1766
  filePath: path ?? "",
1340
1767
  cwd,
1341
1768
  sharedReadOnlyRoots: config.lockdown.sharedReadOnlyRoots,
@@ -1343,7 +1770,10 @@ let QaSurface = (() => {
1343
1770
  documents: () => this.ctx.get("documents"),
1344
1771
  sessionId,
1345
1772
  maxBytes: config.sources.filePreview.maxBytes,
1773
+ ...(selection === undefined ? {} : { selection }),
1346
1774
  });
1775
+ finish();
1776
+ return value;
1347
1777
  }
1348
1778
  catch (error) {
1349
1779
  throw this.browseRefusal("workspace.preview-refused", sessionId, error);