@yadsh/dsh-qa-surface 0.15.7 → 0.16.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 (243) hide show
  1. package/README.md +8 -0
  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/accounts/store.js +2 -2
  7. package/lib/accounts/store.js.map +1 -1
  8. package/lib/admin/service.js +4 -2
  9. package/lib/admin/service.js.map +1 -1
  10. package/lib/admin/session-log.js +3 -0
  11. package/lib/admin/session-log.js.map +1 -1
  12. package/lib/agent-scope.js +9 -0
  13. package/lib/agent-scope.js.map +1 -0
  14. package/lib/chat-sharing/native-fence.js +111 -0
  15. package/lib/chat-sharing/native-fence.js.map +1 -0
  16. package/lib/chat-sharing/resources.js +57 -0
  17. package/lib/chat-sharing/resources.js.map +1 -0
  18. package/lib/chat-sharing/store.js +193 -0
  19. package/lib/chat-sharing/store.js.map +1 -0
  20. package/lib/chat-sharing/transport.js +274 -0
  21. package/lib/chat-sharing/transport.js.map +1 -0
  22. package/lib/chat-sharing/turn-guard.js +154 -0
  23. package/lib/chat-sharing/turn-guard.js.map +1 -0
  24. package/lib/chat-sharing/types.js +2 -0
  25. package/lib/chat-sharing/types.js.map +1 -0
  26. package/lib/chat-sharing/uploads.js +55 -0
  27. package/lib/chat-sharing/uploads.js.map +1 -0
  28. package/lib/client/QaAccountsController.js +29 -2
  29. package/lib/client/QaAccountsController.js.map +1 -1
  30. package/lib/client/QaConfigController.js +7 -12
  31. package/lib/client/QaConfigController.js.map +1 -1
  32. package/lib/client/QaSessionController.js +186 -19
  33. package/lib/client/QaSessionController.js.map +1 -1
  34. package/lib/client/QaSurface.js +110 -9
  35. package/lib/client/QaSurface.js.map +1 -1
  36. package/lib/client/QaSurfaceGuard.js +6 -1
  37. package/lib/client/QaSurfaceGuard.js.map +1 -1
  38. package/lib/client/QaTranscriptAdapter.js +13 -3
  39. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  40. package/lib/client/account-conversation.js +33 -0
  41. package/lib/client/account-conversation.js.map +1 -0
  42. package/lib/client/account-sessions.js +106 -0
  43. package/lib/client/account-sessions.js.map +1 -0
  44. package/lib/client/account-upload.js +30 -0
  45. package/lib/client/account-upload.js.map +1 -0
  46. package/lib/client/chat-artifacts.js +17 -3
  47. package/lib/client/chat-artifacts.js.map +1 -1
  48. package/lib/client/chat-sharing-api.js +2 -0
  49. package/lib/client/chat-sharing-api.js.map +1 -0
  50. package/lib/client/components/QaChangelog.js +57 -3
  51. package/lib/client/components/QaChangelog.js.map +1 -1
  52. package/lib/client/components/QaChatSharing.js +92 -0
  53. package/lib/client/components/QaChatSharing.js.map +1 -0
  54. package/lib/client/components/QaComposer.js +8 -4
  55. package/lib/client/components/QaComposer.js.map +1 -1
  56. package/lib/client/components/QaFileAttachment.js +12 -3
  57. package/lib/client/components/QaFileAttachment.js.map +1 -1
  58. package/lib/client/components/QaFilesPanel.js +11 -4
  59. package/lib/client/components/QaFilesPanel.js.map +1 -1
  60. package/lib/client/components/QaHeader.js +3 -3
  61. package/lib/client/components/QaHeader.js.map +1 -1
  62. package/lib/client/components/QaMessage.js +34 -9
  63. package/lib/client/components/QaMessage.js.map +1 -1
  64. package/lib/client/components/QaSidebar.js +1 -1
  65. package/lib/client/components/QaSidebar.js.map +1 -1
  66. package/lib/client/components/QaSourcesPanel.js +12 -4
  67. package/lib/client/components/QaSourcesPanel.js.map +1 -1
  68. package/lib/client/components/QaWorkspaceBrowser.js +28 -7
  69. package/lib/client/components/QaWorkspaceBrowser.js.map +1 -1
  70. package/lib/client/components/source-refs.js +42 -23
  71. package/lib/client/components/source-refs.js.map +1 -1
  72. package/lib/client/index.js +60 -6
  73. package/lib/client/index.js.map +1 -1
  74. package/lib/client/lineage.js +4 -3
  75. package/lib/client/lineage.js.map +1 -1
  76. package/lib/client/markdown/katex-css.js +1 -1
  77. package/lib/client/markdown/render.js +3 -4
  78. package/lib/client/markdown/render.js.map +1 -1
  79. package/lib/client/markdown/source-chip.js +4 -1
  80. package/lib/client/markdown/source-chip.js.map +1 -1
  81. package/lib/client/notifications/notification-dispatcher.js +50 -11
  82. package/lib/client/notifications/notification-dispatcher.js.map +1 -1
  83. package/lib/client/notifications/use-turn-notifications.js +107 -18
  84. package/lib/client/notifications/use-turn-notifications.js.map +1 -1
  85. package/lib/client/project-session-state.js +28 -13
  86. package/lib/client/project-session-state.js.map +1 -1
  87. package/lib/client/session-admission.js +9 -1
  88. package/lib/client/session-admission.js.map +1 -1
  89. package/lib/client/session-sources.js +44 -3
  90. package/lib/client/session-sources.js.map +1 -1
  91. package/lib/client/slash/useSlashNavigation.js +8 -5
  92. package/lib/client/slash/useSlashNavigation.js.map +1 -1
  93. package/lib/client/source-preview.js +1 -1
  94. package/lib/client/source-preview.js.map +1 -1
  95. package/lib/client/styles.js +9 -2
  96. package/lib/client/styles.js.map +1 -1
  97. package/lib/client/turn-sources.js +2 -1
  98. package/lib/client/turn-sources.js.map +1 -1
  99. package/lib/client/types.js.map +1 -1
  100. package/lib/client/workspace-download.js +42 -2
  101. package/lib/client/workspace-download.js.map +1 -1
  102. package/lib/client.js +3329 -947
  103. package/lib/client.js.map +1 -1
  104. package/lib/enforcement/skill-policy.js +29 -4
  105. package/lib/enforcement/skill-policy.js.map +1 -1
  106. package/lib/enforcement/skill-resource-paths.js +32 -0
  107. package/lib/enforcement/skill-resource-paths.js.map +1 -0
  108. package/lib/enforcement/structured-result.js +38 -0
  109. package/lib/enforcement/structured-result.js.map +1 -0
  110. package/lib/enforcement/tool-grants.js +3 -1
  111. package/lib/enforcement/tool-grants.js.map +1 -1
  112. package/lib/index.js +397 -14
  113. package/lib/index.js.map +1 -1
  114. package/lib/prompt-notes.js +18 -1
  115. package/lib/prompt-notes.js.map +1 -1
  116. package/lib/provenance/collector.js +13 -1
  117. package/lib/provenance/collector.js.map +1 -1
  118. package/lib/provenance/connectors.js +32 -8
  119. package/lib/provenance/connectors.js.map +1 -1
  120. package/lib/provenance/dedupe.js +8 -1
  121. package/lib/provenance/dedupe.js.map +1 -1
  122. package/lib/provenance/document-preview.js +19 -1
  123. package/lib/provenance/document-preview.js.map +1 -1
  124. package/lib/provenance/extractors.js +67 -1
  125. package/lib/provenance/extractors.js.map +1 -1
  126. package/lib/provenance/file-download.js +56 -0
  127. package/lib/provenance/file-download.js.map +1 -0
  128. package/lib/provenance/file-preview.js +12 -1
  129. package/lib/provenance/file-preview.js.map +1 -1
  130. package/lib/provenance/host-store.js +59 -10
  131. package/lib/provenance/host-store.js.map +1 -1
  132. package/lib/provenance/integration-extractor.js +63 -0
  133. package/lib/provenance/integration-extractor.js.map +1 -0
  134. package/lib/qa-tools/docs-tools.js +14 -0
  135. package/lib/qa-tools/docs-tools.js.map +1 -1
  136. package/lib/secure-session.js +9 -3
  137. package/lib/secure-session.js.map +1 -1
  138. package/lib/session-fork-host.js +157 -0
  139. package/lib/session-fork-host.js.map +1 -0
  140. package/lib/session-fork.js +34 -0
  141. package/lib/session-fork.js.map +1 -0
  142. package/lib/session-ownership.js +5 -1
  143. package/lib/session-ownership.js.map +1 -1
  144. package/lib/shared/session-lineage.js +6 -0
  145. package/lib/shared/session-lineage.js.map +1 -0
  146. package/lib/slash/draft-target.js +21 -0
  147. package/lib/slash/draft-target.js.map +1 -0
  148. package/lib/slash/remotes.js +39 -4
  149. package/lib/slash/remotes.js.map +1 -1
  150. package/lib/typert.host.js +1633 -236
  151. package/lib/typert.remote-client.d.ts +48 -1
  152. package/lib/typert.remote-client.js +1477 -234
  153. package/lib/types/access/capability-catalog.d.ts +1 -1
  154. package/lib/types/access/service.d.ts +7 -0
  155. package/lib/types/access.js +2 -0
  156. package/lib/types/access.js.map +1 -0
  157. package/lib/types/accounts/store.d.ts +1 -1
  158. package/lib/types/accounts.js +2 -0
  159. package/lib/types/accounts.js.map +1 -0
  160. package/lib/types/admin/session-log.d.ts +2 -0
  161. package/lib/types/admin.js +2 -0
  162. package/lib/types/admin.js.map +1 -0
  163. package/lib/types/agent-scope.d.ts +4 -0
  164. package/lib/types/capability.js +2 -0
  165. package/lib/types/capability.js.map +1 -0
  166. package/lib/types/chat-sharing/native-fence.d.ts +11 -0
  167. package/lib/types/chat-sharing/resources.d.ts +5 -0
  168. package/lib/types/chat-sharing/store.d.ts +28 -0
  169. package/lib/types/chat-sharing/transport.d.ts +31 -0
  170. package/lib/types/chat-sharing/turn-guard.d.ts +21 -0
  171. package/lib/types/chat-sharing/types.d.ts +25 -0
  172. package/lib/types/chat-sharing/uploads.d.ts +5 -0
  173. package/lib/types/client/QaAccountsController.d.ts +3 -0
  174. package/lib/types/client/QaConfigController.d.ts +3 -2
  175. package/lib/types/client/QaSessionController.d.ts +17 -3
  176. package/lib/types/client/QaSurface.d.ts +6 -1
  177. package/lib/types/client/account-conversation.d.ts +6 -0
  178. package/lib/types/client/account-sessions.d.ts +7 -0
  179. package/lib/types/client/account-upload.d.ts +15 -0
  180. package/lib/types/client/chat-sharing-api.d.ts +35 -0
  181. package/lib/types/client/components/QaChatSharing.d.ts +10 -0
  182. package/lib/types/client/components/QaComposer.d.ts +2 -0
  183. package/lib/types/client/components/QaFileAttachment.d.ts +3 -2
  184. package/lib/types/client/components/QaFilesPanel.d.ts +4 -1
  185. package/lib/types/client/components/QaMessage.d.ts +5 -2
  186. package/lib/types/client/components/QaWorkspaceBrowser.d.ts +8 -1
  187. package/lib/types/client/components/source-refs.d.ts +1 -0
  188. package/lib/types/client/lineage.d.ts +2 -2
  189. package/lib/types/client/notifications/notification-dispatcher.d.ts +10 -6
  190. package/lib/types/client/notifications/use-turn-notifications.d.ts +4 -0
  191. package/lib/types/client/project-session-state.d.ts +1 -0
  192. package/lib/types/client/session-admission.d.ts +2 -0
  193. package/lib/types/client/session-sources.d.ts +1 -0
  194. package/lib/types/client/turn-sources.d.ts +1 -1
  195. package/lib/types/client/types.d.ts +8 -1
  196. package/lib/types/client/workspace-download.d.ts +9 -1
  197. package/lib/types/config.js +2 -0
  198. package/lib/types/config.js.map +1 -0
  199. package/lib/types/documents.js +2 -0
  200. package/lib/types/documents.js.map +1 -0
  201. package/lib/types/enforcement/skill-resource-paths.d.ts +5 -0
  202. package/lib/types/enforcement/structured-result.d.ts +11 -0
  203. package/lib/types/expert-memory.js +2 -0
  204. package/lib/types/expert-memory.js.map +1 -0
  205. package/lib/types/index.d.ts +35 -1
  206. package/lib/types/policy.js +2 -0
  207. package/lib/types/policy.js.map +1 -0
  208. package/lib/types/prompt-notes.d.ts +2 -0
  209. package/lib/types/provenance/connectors.d.ts +4 -1
  210. package/lib/types/provenance/document-preview.d.ts +2 -0
  211. package/lib/types/provenance/extractors.d.ts +2 -0
  212. package/lib/types/provenance/file-download.d.ts +10 -0
  213. package/lib/types/provenance/host-store.d.ts +2 -0
  214. package/lib/types/provenance/integration-extractor.d.ts +5 -0
  215. package/lib/types/provenance/types.d.ts +2 -0
  216. package/lib/types/qa-tools/docs-tools.d.ts +2 -0
  217. package/lib/types/quality.js +7 -0
  218. package/lib/types/quality.js.map +1 -0
  219. package/lib/types/session-fork-host.d.ts +27 -0
  220. package/lib/types/session-fork.d.ts +7 -0
  221. package/lib/types/session.js +2 -0
  222. package/lib/types/session.js.map +1 -0
  223. package/lib/types/shared/session-lineage.d.ts +7 -0
  224. package/lib/types/skills.js +2 -0
  225. package/lib/types/skills.js.map +1 -0
  226. package/lib/types/slash/draft-target.d.ts +7 -0
  227. package/lib/types/slash/remotes.d.ts +7 -0
  228. package/lib/types/slash.js +2 -0
  229. package/lib/types/slash.js.map +1 -0
  230. package/lib/types/types/access.d.ts +43 -0
  231. package/lib/types/types/accounts.d.ts +173 -0
  232. package/lib/types/types/admin.d.ts +286 -0
  233. package/lib/types/types/capability.d.ts +230 -0
  234. package/lib/types/types/config.d.ts +594 -0
  235. package/lib/types/types/documents.d.ts +34 -0
  236. package/lib/types/types/expert-memory.d.ts +35 -0
  237. package/lib/types/types/policy.d.ts +54 -0
  238. package/lib/types/types/quality.d.ts +100 -0
  239. package/lib/types/types/session.d.ts +382 -0
  240. package/lib/types/types/skills.d.ts +143 -0
  241. package/lib/types/types/slash.d.ts +159 -0
  242. package/lib/types/types.d.ts +13 -2180
  243. package/package.json +8 -7
package/lib/index.js CHANGED
@@ -33,6 +33,15 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
33
33
  done = true;
34
34
  };
35
35
  import { randomUUID } from "node:crypto";
36
+ import path from "node:path";
37
+ import { defaultAccountsFilePath } from "./accounts/store.js";
38
+ import { QaChatSharingStore } from "./chat-sharing/store.js";
39
+ import { QaChatTransport } from "./chat-sharing/transport.js";
40
+ import { QaChatTurnGuard } from "./chat-sharing/turn-guard.js";
41
+ import { installQaNativeFence } from "./chat-sharing/native-fence.js";
42
+ import { qaChatPublishedFile, qaChatAttachmentPath, } from "./chat-sharing/resources.js";
43
+ import { installQaChatUploads } from "./chat-sharing/uploads.js";
44
+ import { forkQaSession } from "./session-fork-host.js";
36
45
  import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
37
46
  import { SessionId } from "@deepseek-ai/dsh-session/types";
38
47
  import { WorkspaceId } from "@deepseek-ai/dsh-workspace";
@@ -68,7 +77,8 @@ import { QaTools } from "./qa-tools/index.js";
68
77
  import { docsDefaultVersionOf } from "./config-resolvers/tools.js";
69
78
  import { QaProvenanceHost } from "./provenance/host-store.js";
70
79
  import { defaultLegacyProvenanceFilePath, defaultQaProvenanceDirectoryPath, FileQaProvenanceSnapshotStore, } from "./provenance/snapshot-store.js";
71
- import { previewConvertibleDocument } from "./provenance/document-preview.js";
80
+ import { previewConvertibleDocument, previewSourceDocument, } from "./provenance/document-preview.js";
81
+ import { readWorkspaceFileChunk } from "./provenance/file-download.js";
72
82
  import { listWorkspaceDirectory, readSourceFilePreview, readWorkspaceFile, QaSourcePreviewError, } from "./provenance/file-preview.js";
73
83
  import { existingQaUserWorkspace, prepareQaUserWorkspace, } from "./user-workspace.js";
74
84
  export const name = "qa-surface";
@@ -141,6 +151,7 @@ let QaSurface = (() => {
141
151
  let _describe_decorators;
142
152
  let _queueStatus_decorators;
143
153
  let _createSession_decorators;
154
+ let _forkSession_decorators;
144
155
  let _accessCurrent_decorators;
145
156
  let _accessSession_decorators;
146
157
  let _accessAdminSnapshot_decorators;
@@ -181,6 +192,25 @@ let QaSurface = (() => {
181
192
  let _adminMetrics_decorators;
182
193
  let _adminAudit_decorators;
183
194
  let _secureSession_decorators;
195
+ let _chatVisible_decorators;
196
+ let _chatAccess_decorators;
197
+ let _chatGrants_decorators;
198
+ let _chatSetGrant_decorators;
199
+ let _chatAuthors_decorators;
200
+ let _chatAudit_decorators;
201
+ let _chatAttachmentPath_decorators;
202
+ let _chatList_decorators;
203
+ let _chatSearch_decorators;
204
+ let _chatSelectModel_decorators;
205
+ let _chatPage_decorators;
206
+ let _chatFollow_decorators;
207
+ let _chatControl_decorators;
208
+ let _chatProjections_decorators;
209
+ let _chatPrompt_decorators;
210
+ let _chatAttachment_decorators;
211
+ let _chatRename_decorators;
212
+ let _chatCancel_decorators;
213
+ let _chatUpdateQueue_decorators;
184
214
  let _sources_decorators;
185
215
  let _pendingApprovals_decorators;
186
216
  let _answerApproval_decorators;
@@ -190,6 +220,9 @@ let QaSurface = (() => {
190
220
  let _readSourceFile_decorators;
191
221
  let _listWorkspaceFiles_decorators;
192
222
  let _readWorkspaceFile_decorators;
223
+ let _readWorkspaceFileChunk_decorators;
224
+ let _documentWorkflowStatus_decorators;
225
+ let _approveDocumentWorkflow_decorators;
193
226
  let _previewWorkspaceDocument_decorators;
194
227
  let _skillsList_decorators;
195
228
  let _skillsGet_decorators;
@@ -220,6 +253,7 @@ let QaSurface = (() => {
220
253
  _describe_decorators = [Remote("describe")];
221
254
  _queueStatus_decorators = [Remote("queueStatus")];
222
255
  _createSession_decorators = [Remote("createSession")];
256
+ _forkSession_decorators = [Remote("forkSession")];
223
257
  _accessCurrent_decorators = [Remote("accessCurrent")];
224
258
  _accessSession_decorators = [Remote("accessSession")];
225
259
  _accessAdminSnapshot_decorators = [Remote("accessAdminSnapshot")];
@@ -260,6 +294,25 @@ let QaSurface = (() => {
260
294
  _adminMetrics_decorators = [Remote("adminMetrics")];
261
295
  _adminAudit_decorators = [Remote("adminAudit")];
262
296
  _secureSession_decorators = [Remote("secureSession")];
297
+ _chatVisible_decorators = [Remote("chatVisible")];
298
+ _chatAccess_decorators = [Remote("chatAccess")];
299
+ _chatGrants_decorators = [Remote("chatGrants")];
300
+ _chatSetGrant_decorators = [Remote("chatSetGrant")];
301
+ _chatAuthors_decorators = [Remote("chatAuthors")];
302
+ _chatAudit_decorators = [Remote("chatAudit")];
303
+ _chatAttachmentPath_decorators = [Remote("chatAttachmentPath")];
304
+ _chatList_decorators = [Remote("chatList")];
305
+ _chatSearch_decorators = [Remote("chatSearch")];
306
+ _chatSelectModel_decorators = [Remote("chatSelectModel")];
307
+ _chatPage_decorators = [Remote("chatPage")];
308
+ _chatFollow_decorators = [Remote({ mode: "stream" })];
309
+ _chatControl_decorators = [Remote({ mode: "stream" })];
310
+ _chatProjections_decorators = [Remote("chatProjections")];
311
+ _chatPrompt_decorators = [Remote("chatPrompt")];
312
+ _chatAttachment_decorators = [Remote("chatAttachment")];
313
+ _chatRename_decorators = [Remote("chatRename")];
314
+ _chatCancel_decorators = [Remote("chatCancel")];
315
+ _chatUpdateQueue_decorators = [Remote("chatUpdateQueue")];
263
316
  _sources_decorators = [Remote("sources")];
264
317
  _pendingApprovals_decorators = [Remote("pendingApprovals")];
265
318
  _answerApproval_decorators = [Remote("answerApproval")];
@@ -269,6 +322,9 @@ let QaSurface = (() => {
269
322
  _readSourceFile_decorators = [Remote("readSourceFile")];
270
323
  _listWorkspaceFiles_decorators = [Remote("listWorkspaceFiles")];
271
324
  _readWorkspaceFile_decorators = [Remote("readWorkspaceFile")];
325
+ _readWorkspaceFileChunk_decorators = [Remote("readWorkspaceFileChunk")];
326
+ _documentWorkflowStatus_decorators = [Remote("documentWorkflowStatus")];
327
+ _approveDocumentWorkflow_decorators = [Remote("approveDocumentWorkflow")];
272
328
  _previewWorkspaceDocument_decorators = [Remote("previewWorkspaceDocument")];
273
329
  _skillsList_decorators = [Remote("skillsList")];
274
330
  _skillsGet_decorators = [Remote("skillsGet")];
@@ -296,6 +352,7 @@ let QaSurface = (() => {
296
352
  __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
353
  __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
354
  __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);
355
+ __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
356
  __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
357
  __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
358
  __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 +393,25 @@ let QaSurface = (() => {
336
393
  __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
394
  __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
395
  __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);
396
+ __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);
397
+ __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);
398
+ __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);
399
+ __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);
400
+ __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);
401
+ __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);
402
+ __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);
403
+ __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);
404
+ __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);
405
+ __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);
406
+ __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);
407
+ __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);
408
+ __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);
409
+ __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);
410
+ __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);
411
+ __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);
412
+ __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);
413
+ __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);
414
+ __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
415
  __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
416
  __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
417
  __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);
@@ -345,6 +421,9 @@ let QaSurface = (() => {
345
421
  __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);
346
422
  __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
423
  __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);
424
+ __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);
425
+ __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);
426
+ __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
427
  __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
428
  __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
429
  __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 +486,19 @@ let QaSurface = (() => {
407
486
  * opens the admin console never grows one.
408
487
  */
409
488
  qualityStore;
489
+ chatSharingStore;
490
+ chatTransport;
491
+ chatTurnGuard;
492
+ sharing() {
493
+ const accounts = () => {
494
+ const store = this.accountRemotes.resolve(this.getConfig());
495
+ if (store === undefined)
496
+ throw new Error("QA accounts are required for chat sharing.");
497
+ return store;
498
+ };
499
+ accounts();
500
+ return (this.chatSharingStore ??= new QaChatSharingStore(path.join(path.dirname(defaultAccountsFilePath()), "qa-chat-sharing.db"), accounts));
501
+ }
410
502
  constructor(ctx, entry = {}) {
411
503
  super(ctx, "qaSurface", { namespace: "qaSurface" });
412
504
  // Every Config field is volatile, so the reference the Host hands here is
@@ -453,6 +545,7 @@ let QaSurface = (() => {
453
545
  // Deletion is the console's alone: the sidebar's delete stays a
454
546
  // per-browser row, and only an administrator removes the chat itself.
455
547
  sessionFiles: createSessionEraser(),
548
+ ...(this.getConfig().accounts.enabled ? { sharing: this.sharing() } : {}),
456
549
  dropSources: (sessionId) => this.provenance.dropSession(sessionId),
457
550
  // The console writes skills through the same service the owner's editor
458
551
  // uses, so an administrator's save is path-checked, validated and
@@ -472,6 +565,23 @@ let QaSurface = (() => {
472
565
  });
473
566
  this.slashRemotes = createQaSlashRemotes({
474
567
  ctx,
568
+ draftSkills: async (token, target) => {
569
+ this.accountRemotes.resolve(this.getConfig());
570
+ const preview = await this.access.slashDraftSkills(token, target.subroleId, target.adminPreview);
571
+ return {
572
+ skills: preview.skills.map((skill) => ({
573
+ name: skill.name,
574
+ description: skill.description,
575
+ modelInvocable: skill.invocation.modelInvocable,
576
+ ...(skill.whenToUse === undefined
577
+ ? {}
578
+ : { whenToUse: skill.whenToUse }),
579
+ })),
580
+ grantedSkills: preview.policy === undefined
581
+ ? undefined
582
+ : userInvocableSkillNames(preview.policy),
583
+ };
584
+ },
475
585
  getConfig: () => this.getConfig(),
476
586
  logger: this.logger,
477
587
  sessionGrant: (token, sessionId, agent) => this.slashSessionGrant(token, sessionId, agent),
@@ -505,6 +615,20 @@ let QaSurface = (() => {
505
615
  new FileQaProvenanceSnapshotStore(defaultQaProvenanceDirectoryPath(), () => this.getConfig().sources.retention, defaultLegacyProvenanceFilePath()), (error) => this.logger.error("sources.persistence-failed", {
506
616
  message: error instanceof Error ? error.message : String(error),
507
617
  }));
618
+ this.chatTransport = new QaChatTransport(ctx, () => this.sharing(), (token, id) => this.secureSession(token, id), (userId, id) => this.access.participantPolicy(userId, id));
619
+ this.chatTurnGuard = new QaChatTurnGuard(ctx, () => this.sharing(), (userId, id) => this.access.participantPolicy(userId, id), () => this.getConfig().accounts.enabled);
620
+ ctx.effect(() => () => {
621
+ this.chatTurnGuard.dispose();
622
+ this.chatSharingStore?.storage.close();
623
+ }, "dsh-qa-surface.chat-sharing");
624
+ ctx.inject(["typertGateway", "connection"], () => {
625
+ const dispose = installQaNativeFence(ctx, () => this.getConfig().accounts.enabled);
626
+ const disposeUploads = installQaChatUploads(ctx, () => this.sharing(), (token, id) => this.secureSession(token, id));
627
+ return async () => {
628
+ dispose();
629
+ await disposeUploads();
630
+ };
631
+ });
508
632
  this.integration = new QaIntegrationService({
509
633
  getConfig: () => this.getConfig(),
510
634
  accounts: () => this.accountRemotes.resolve(this.getConfig()),
@@ -711,6 +835,8 @@ let QaSurface = (() => {
711
835
  }
712
836
  /** Resolve only a directly QA-owned root session; delegated children fail closed. */
713
837
  principalForSession(sessionId) {
838
+ if (this.chatTurnGuard.collaborative(sessionId))
839
+ return undefined;
714
840
  const accounts = this.accountRemotes.resolve(this.getConfig());
715
841
  if (accounts === undefined)
716
842
  return undefined;
@@ -965,6 +1091,20 @@ let QaSurface = (() => {
965
1091
  throw new Error(qaAttestationFailureMessage("Unable to create a QA session.", error), { cause: error });
966
1092
  }
967
1093
  }
1094
+ /** Create an independently admitted ordinary branch of the caller's own chat. */
1095
+ async forkSession(token, sourceId, answerSeq) {
1096
+ return this.accountRemotes.runAsync(() => forkQaSession({
1097
+ ctx: this.ctx,
1098
+ config: this.getConfig(),
1099
+ accounts: this.accountRemotes.resolve(this.getConfig()),
1100
+ access: this.access,
1101
+ admission: this.admission,
1102
+ principals: this.integrationPrincipals,
1103
+ provenance: this.provenance,
1104
+ sessionFiles: createSessionEraser(),
1105
+ logger: this.logger,
1106
+ }, token, sourceId, answerSeq), sourceId);
1107
+ }
968
1108
  /** The selector model for the signed-in user; admin grants are irrelevant. */
969
1109
  accessCurrent(token) {
970
1110
  return this.accountRemotes.run(() => this.access.current(token));
@@ -1125,7 +1265,13 @@ let QaSurface = (() => {
1125
1265
  * stays what it always was, a per-browser row.
1126
1266
  */
1127
1267
  adminDeleteConversation(token, conversationId) {
1128
- return this.accountRemotes.runAsync(() => this.admin.deleteConversation(token, conversationId));
1268
+ return this.accountRemotes.runAsync(async () => {
1269
+ const result = await this.admin.deleteConversation(token, conversationId);
1270
+ if (this.getConfig().accounts.enabled)
1271
+ for (const id of result.sessions)
1272
+ this.sharing().dropSession(id);
1273
+ return result;
1274
+ });
1129
1275
  }
1130
1276
  adminFeedback(token, query, cursor, limit) {
1131
1277
  return this.accountRemotes.runAsync(() => this.admin.feedback(token, query, cursor ?? undefined, limit ?? undefined));
@@ -1163,16 +1309,46 @@ let QaSurface = (() => {
1163
1309
  /** Pin and attest the effective policy. The browser supplies identity only. */
1164
1310
  async secureSession(token, sessionId) {
1165
1311
  try {
1312
+ const accountsForSharing = this.accountRemotes.resolve(this.getConfig());
1313
+ const actor = accountsForSharing?.currentUser(token);
1314
+ const actualOwnerId = accountsForSharing?.ownerIdOf(sessionId);
1315
+ if (actualOwnerId !== undefined && actor?.id !== actualOwnerId) {
1316
+ let shared;
1317
+ try {
1318
+ shared = this.sharing().access(token, sessionId);
1319
+ }
1320
+ catch (error) {
1321
+ if (actor?.role !== "admin" ||
1322
+ !this.getConfig().accounts.showOtherUsersChats)
1323
+ throw error;
1324
+ }
1325
+ if (shared !== undefined) {
1326
+ const proof = await this.admission.secureSessionForUser(shared.ownerId, sessionId);
1327
+ this.sharing().revalidate(token, shared);
1328
+ return { ...proof, chatAccess: shared };
1329
+ }
1330
+ }
1166
1331
  const principal = this.principalForToken(token);
1167
1332
  const proof = await this.admission.secureSession(token, sessionId);
1168
1333
  const accounts = this.accountRemotes.resolve(this.getConfig());
1169
1334
  const ownerId = accounts?.ownerIdOf(sessionId);
1170
1335
  // Admin cross-user viewing is intentionally not credential delegation.
1171
- this.integrationPrincipals.attest(sessionId, principal?.userId, ownerId);
1172
- return proof;
1336
+ if (principal?.userId === ownerId)
1337
+ this.integrationPrincipals.attest(sessionId, principal?.userId, ownerId);
1338
+ const session = this.ctx.sessions.get(SessionId(sessionId));
1339
+ const chatAccess = actualOwnerId === actor?.id && actor !== undefined
1340
+ ? this.sharing().access(token, sessionId)
1341
+ : undefined;
1342
+ return {
1343
+ ...proof,
1344
+ ...(chatAccess === undefined ? {} : { chatAccess }),
1345
+ ...(session?.header.isSeeded === true &&
1346
+ session.header.origin !== "subagent"
1347
+ ? { inheritedThroughSeq: Number(session.inheritedEventCount) - 1 }
1348
+ : {}),
1349
+ };
1173
1350
  }
1174
1351
  catch (error) {
1175
- this.integrationPrincipals.attest(sessionId, undefined, undefined);
1176
1352
  // The carrier empties error.details, so the coarse reason rides the
1177
1353
  // wire message for the browser console; the specific mismatch facts
1178
1354
  // stay in this log only.
@@ -1189,9 +1365,110 @@ let QaSurface = (() => {
1189
1365
  });
1190
1366
  }
1191
1367
  }
1368
+ chatVisible(token) {
1369
+ return this.sharing().visible(token);
1370
+ }
1371
+ chatAccess(token, sessionId) {
1372
+ return this.sharing().access(token, sessionId);
1373
+ }
1374
+ chatGrants(token, sessionId) {
1375
+ return this.sharing().grants(token, sessionId);
1376
+ }
1377
+ chatSetGrant(token, sessionId, email, mode) {
1378
+ if (this.access.isDelegatedChild(sessionId) ||
1379
+ this.getConfig().session.policy === "fixed")
1380
+ throw new Error("Only an ordinary account-owned chat may be shared.");
1381
+ const value = this.sharing().set(token, sessionId, email, mode);
1382
+ this.chatTurnGuard.revoke(sessionId);
1383
+ return value;
1384
+ }
1385
+ chatAuthors(token, sessionId) {
1386
+ return this.sharing().authors(token, sessionId);
1387
+ }
1388
+ async chatAudit(token, sessionId, full) {
1389
+ this.requireChatOwner(token, sessionId);
1390
+ await this.secureSession(token, sessionId);
1391
+ this.requireChatOwner(token, sessionId);
1392
+ const audit = this.ctx.get("sessionAudit");
1393
+ if (audit === undefined)
1394
+ throw new Error("Session audit is unavailable.");
1395
+ const value = full
1396
+ ? await audit.audit(sessionId)
1397
+ : audit.summary(sessionId);
1398
+ this.requireChatOwner(token, sessionId);
1399
+ return value;
1400
+ }
1401
+ async chatAttachmentPath(token, sessionId, attachmentId) {
1402
+ const finish = await this.admitChatRead(token, sessionId);
1403
+ const value = qaChatAttachmentPath(this.ctx, sessionId, attachmentId);
1404
+ finish();
1405
+ return value;
1406
+ }
1407
+ async chatList(token, signal) {
1408
+ return (await this.chatTransport.list(token, signal));
1409
+ }
1410
+ async chatSearch(token, request, signal) {
1411
+ return (await this.chatTransport.search(token, request, signal));
1412
+ }
1413
+ chatSelectModel(token, request) {
1414
+ this.requireChatOwner(token, String(request.sessionId));
1415
+ if (this.getConfig().lockdown.enforceFixedModel)
1416
+ throw new Error("The chat model is fixed by its policy.");
1417
+ return this.chatTransport.selectModel(token, request);
1418
+ }
1419
+ async chatPage(token, request, signal) {
1420
+ return (await this.chatTransport.page(token, request, signal));
1421
+ }
1422
+ async *chatFollow(token, request, signal) {
1423
+ for await (const frame of this.chatTransport.follow(token, request, signal))
1424
+ yield frame;
1425
+ }
1426
+ async *chatControl(token, signal) {
1427
+ for await (const frame of this.chatTransport.control(token, signal))
1428
+ yield frame;
1429
+ }
1430
+ async chatProjections(token, sessionId, signal) {
1431
+ return (await this.chatTransport.projections(token, sessionId, signal));
1432
+ }
1433
+ chatPrompt(token, request, signal) {
1434
+ return this.chatTransport.prompt(token, request, signal);
1435
+ }
1436
+ chatAttachment(token, request) {
1437
+ return this.chatTransport.attachment(token, request);
1438
+ }
1439
+ chatRename(token, request) {
1440
+ return this.chatTransport.rename(token, request);
1441
+ }
1442
+ chatCancel(token, sessionId) {
1443
+ return this.chatTransport.cancel(token, sessionId);
1444
+ }
1445
+ chatUpdateQueue(token, request) {
1446
+ return this.chatTransport.updateQueue(token, request);
1447
+ }
1448
+ async admitChatRead(token, sessionId, filePath) {
1449
+ if (!this.getConfig().accounts.enabled) {
1450
+ await this.admission.secureSession(token, sessionId);
1451
+ return () => undefined;
1452
+ }
1453
+ const access = this.sharing().access(token, sessionId);
1454
+ await this.secureSession(token, sessionId);
1455
+ this.sharing().revalidate(token, access);
1456
+ if (filePath !== undefined &&
1457
+ access.mode !== "owner" &&
1458
+ !qaChatPublishedFile(this.ctx, sessionId, filePath, (id, path) => this.provenance.sourceAllowed(id, path)))
1459
+ throw new Error("This file has not been shared in the chat.");
1460
+ return () => {
1461
+ this.sharing().revalidate(token, access);
1462
+ };
1463
+ }
1464
+ requireChatOwner(token, sessionId) {
1465
+ if (this.getConfig().accounts.enabled)
1466
+ this.sharing().owner(token, sessionId);
1467
+ }
1192
1468
  /** Return canonical Host snapshots from plugin-owned durable provenance. */
1193
1469
  async sources(token, sessionId) {
1194
- await this.admission.secureSession(token, sessionId);
1470
+ const finish = await this.admitChatRead(token, sessionId);
1471
+ finish();
1195
1472
  return this.provenance.bundles(sessionId);
1196
1473
  }
1197
1474
  /**
@@ -1199,7 +1476,10 @@ let QaSurface = (() => {
1199
1476
  * deployment with blocked approvals answers with an empty list.
1200
1477
  */
1201
1478
  async pendingApprovals(token, sessionId) {
1202
- await this.admission.secureSession(token, sessionId);
1479
+ await this.secureSession(token, sessionId);
1480
+ if (this.getConfig().accounts.enabled &&
1481
+ this.sharing().access(token, sessionId).mode !== "owner")
1482
+ return [];
1203
1483
  return this.approvals.list(sessionId);
1204
1484
  }
1205
1485
  /**
@@ -1208,7 +1488,9 @@ let QaSurface = (() => {
1208
1488
  * the agent went away) is refused with `false`.
1209
1489
  */
1210
1490
  async answerApproval(token, sessionId, requestId, decision) {
1491
+ this.requireChatOwner(token, sessionId);
1211
1492
  await this.admission.secureSession(token, sessionId);
1493
+ this.requireChatOwner(token, sessionId);
1212
1494
  return this.approvals.answer(sessionId, requestId, decision);
1213
1495
  }
1214
1496
  /**
@@ -1216,7 +1498,10 @@ let QaSurface = (() => {
1216
1498
  * deployment with unsupported questions answers with an empty list.
1217
1499
  */
1218
1500
  async pendingQuestions(token, sessionId) {
1219
- await this.admission.secureSession(token, sessionId);
1501
+ await this.secureSession(token, sessionId);
1502
+ if (this.getConfig().accounts.enabled &&
1503
+ this.sharing().access(token, sessionId).mode !== "owner")
1504
+ return [];
1220
1505
  return this.userQuestions.list(sessionId);
1221
1506
  }
1222
1507
  /**
@@ -1225,12 +1510,16 @@ let QaSurface = (() => {
1225
1510
  * a skip.
1226
1511
  */
1227
1512
  async answerQuestion(token, sessionId, requestId, answers) {
1513
+ this.requireChatOwner(token, sessionId);
1228
1514
  await this.admission.secureSession(token, sessionId);
1515
+ this.requireChatOwner(token, sessionId);
1229
1516
  return this.userQuestions.answer(sessionId, requestId, answers);
1230
1517
  }
1231
1518
  /** Close a parked question request without answering it. */
1232
1519
  async cancelQuestion(token, sessionId, requestId) {
1520
+ this.requireChatOwner(token, sessionId);
1233
1521
  await this.admission.secureSession(token, sessionId);
1522
+ this.requireChatOwner(token, sessionId);
1234
1523
  return this.userQuestions.cancel(sessionId, requestId);
1235
1524
  }
1236
1525
  /**
@@ -1243,7 +1532,7 @@ let QaSurface = (() => {
1243
1532
  * the per-account scratch directory — could never be opened in the panel.
1244
1533
  */
1245
1534
  async readSourceFile(token, sessionId, sourcePath) {
1246
- await this.admission.secureSession(token, sessionId);
1535
+ const finish = await this.admitChatRead(token, sessionId, sourcePath);
1247
1536
  const config = this.getConfig();
1248
1537
  if (!config.sources.filePreview.enabled) {
1249
1538
  throw sourcePreviewRefusal("unavailable");
@@ -1254,7 +1543,7 @@ let QaSurface = (() => {
1254
1543
  throw sourcePreviewRefusal("unavailable");
1255
1544
  const attachmentRoot = this.admission.attachmentRoot();
1256
1545
  try {
1257
- return await readSourceFilePreview({
1546
+ const value = await readSourceFilePreview({
1258
1547
  sourcePath,
1259
1548
  cwd,
1260
1549
  isEvidence: (canonicalPath) => this.provenance.sourceAllowed(sessionId, canonicalPath),
@@ -1262,7 +1551,32 @@ let QaSurface = (() => {
1262
1551
  ...(attachmentRoot === undefined ? {} : { attachmentRoot }),
1263
1552
  maxBytes: config.sources.filePreview.maxBytes,
1264
1553
  maxMarkdownRenderBytes: config.sources.filePreview.maxMarkdownRenderBytes,
1554
+ }).catch(async (error) => {
1555
+ // Only a format refusal follows successful evidence and root checks.
1556
+ if (!(error instanceof QaSourcePreviewError) ||
1557
+ error.reason !== "unsupported")
1558
+ throw error;
1559
+ const document = await previewSourceDocument({
1560
+ filePath: sourcePath,
1561
+ cwd,
1562
+ sessionId,
1563
+ sharedReadOnlyRoots: config.lockdown.sharedReadOnlyRoots,
1564
+ ...(attachmentRoot === undefined ? {} : { attachmentRoot }),
1565
+ documents: () => this.ctx.get("documents"),
1566
+ maxBytes: config.sources.filePreview.maxBytes,
1567
+ });
1568
+ return {
1569
+ path: sourcePath,
1570
+ content: "",
1571
+ size: document.bytes,
1572
+ truncated: false,
1573
+ markdown: false,
1574
+ renderableMarkdown: false,
1575
+ document,
1576
+ };
1265
1577
  });
1578
+ finish();
1579
+ return value;
1266
1580
  }
1267
1581
  catch (error) {
1268
1582
  this.logger.debug("source.preview-refused", {
@@ -1281,6 +1595,7 @@ let QaSurface = (() => {
1281
1595
  * `readWorkspaceFile` opens one entry of such a listing.
1282
1596
  */
1283
1597
  async listWorkspaceFiles(token, sessionId, path) {
1598
+ this.requireChatOwner(token, sessionId);
1284
1599
  await this.admission.secureSession(token, sessionId);
1285
1600
  const { config, cwd } = await this.browseContext(sessionId);
1286
1601
  try {
@@ -1303,11 +1618,11 @@ let QaSurface = (() => {
1303
1618
  * reopening a cited source.
1304
1619
  */
1305
1620
  async readWorkspaceFile(token, sessionId, path) {
1306
- await this.admission.secureSession(token, sessionId);
1621
+ const finish = await this.admitChatRead(token, sessionId, path);
1307
1622
  const { config, cwd } = await this.browseContext(sessionId);
1308
1623
  const attachmentRoot = this.admission.attachmentRoot();
1309
1624
  try {
1310
- return await readWorkspaceFile({
1625
+ const value = await readWorkspaceFile({
1311
1626
  filePath: path ?? "",
1312
1627
  cwd,
1313
1628
  sharedReadOnlyRoots: config.lockdown.sharedReadOnlyRoots,
@@ -1315,11 +1630,77 @@ let QaSurface = (() => {
1315
1630
  maxBytes: config.sources.filePreview.maxBytes,
1316
1631
  maxMarkdownRenderBytes: config.sources.filePreview.maxMarkdownRenderBytes,
1317
1632
  });
1633
+ finish();
1634
+ return value;
1318
1635
  }
1319
1636
  catch (error) {
1320
1637
  throw this.browseRefusal("workspace.read-refused", sessionId, error);
1321
1638
  }
1322
1639
  }
1640
+ /** Download one bounded chunk after revalidating this chat's ownership. */
1641
+ async readWorkspaceFileChunk(token, sessionId, path, offset, version) {
1642
+ const finish = await this.admitChatRead(token, sessionId, path);
1643
+ const { config, cwd } = await this.browseContext(sessionId);
1644
+ const attachmentRoot = this.admission.attachmentRoot();
1645
+ try {
1646
+ const value = await readWorkspaceFileChunk({
1647
+ filePath: path ?? "",
1648
+ cwd,
1649
+ sharedReadOnlyRoots: config.lockdown.sharedReadOnlyRoots,
1650
+ ...(attachmentRoot === undefined ? {} : { attachmentRoot }),
1651
+ offset,
1652
+ version,
1653
+ });
1654
+ finish();
1655
+ return value;
1656
+ }
1657
+ catch (error) {
1658
+ throw this.browseRefusal("workspace.download-refused", sessionId, error);
1659
+ }
1660
+ }
1661
+ async documentWorkflowStatus(token, sessionId, workflowId) {
1662
+ const finish = await this.admitChatRead(token, sessionId);
1663
+ const { cwd } = await this.browseContext(sessionId);
1664
+ const workflow = this.ctx.get("documents")
1665
+ ?.workflow;
1666
+ if (workflow === undefined)
1667
+ throw new Error("Document workflow is unavailable.");
1668
+ const view = await workflow.read({ workspaceRoot: cwd, sessionId }, workflowId);
1669
+ finish();
1670
+ return {
1671
+ id: view.id,
1672
+ revision: view.revision,
1673
+ status: view.status,
1674
+ sha256: view.draft?.sha256 ?? null,
1675
+ blockers: view.blockers,
1676
+ };
1677
+ }
1678
+ /** Browser-authenticated human consent; intentionally absent from the agent's tool registry. */
1679
+ async approveDocumentWorkflow(token, sessionId, workflowId, revision, sha256) {
1680
+ this.requireChatOwner(token, sessionId);
1681
+ await this.admission.secureSession(token, sessionId);
1682
+ this.requireChatOwner(token, sessionId);
1683
+ const caller = this.principalForToken(token);
1684
+ const ownerId = this.accountRemotes.resolve(this.getConfig())?.ownerIdOf(sessionId) ??
1685
+ (this.getConfig().accounts.enabled
1686
+ ? undefined
1687
+ : this.principalForSession(sessionId)?.userId);
1688
+ if (caller === undefined || ownerId !== caller.userId)
1689
+ throw new Error("Document approval requires the chat owner's account.");
1690
+ const { cwd } = await this.browseContext(sessionId);
1691
+ const workflow = this.ctx.get("documents")
1692
+ ?.workflow;
1693
+ if (workflow === undefined)
1694
+ throw new Error("Document workflow is unavailable.");
1695
+ const view = await workflow.approve({ workspaceRoot: cwd, sessionId }, workflowId, revision, sha256, caller.userId);
1696
+ return {
1697
+ id: view.id,
1698
+ revision: view.revision,
1699
+ status: view.status,
1700
+ sha256: view.draft?.sha256 ?? null,
1701
+ blockers: view.blockers,
1702
+ };
1703
+ }
1323
1704
  /**
1324
1705
  * Render one Word document of the chat's workspace as a PDF for the panel.
1325
1706
  *
@@ -1331,11 +1712,11 @@ let QaSurface = (() => {
1331
1712
  * reaches an unfenced byte route.
1332
1713
  */
1333
1714
  async previewWorkspaceDocument(token, sessionId, path) {
1334
- await this.admission.secureSession(token, sessionId);
1715
+ const finish = await this.admitChatRead(token, sessionId, path);
1335
1716
  const { config, cwd } = await this.browseContext(sessionId);
1336
1717
  const attachmentRoot = this.admission.attachmentRoot();
1337
1718
  try {
1338
- return await previewConvertibleDocument({
1719
+ const value = await previewConvertibleDocument({
1339
1720
  filePath: path ?? "",
1340
1721
  cwd,
1341
1722
  sharedReadOnlyRoots: config.lockdown.sharedReadOnlyRoots,
@@ -1344,6 +1725,8 @@ let QaSurface = (() => {
1344
1725
  sessionId,
1345
1726
  maxBytes: config.sources.filePreview.maxBytes,
1346
1727
  });
1728
+ finish();
1729
+ return value;
1347
1730
  }
1348
1731
  catch (error) {
1349
1732
  throw this.browseRefusal("workspace.preview-refused", sessionId, error);