@yadsh/dsh-qa-surface 0.18.0 → 0.20.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 +201 -22
  2. package/lib/access/model-choices.js +103 -0
  3. package/lib/access/model-choices.js.map +1 -0
  4. package/lib/access/model-policy.js +79 -7
  5. package/lib/access/model-policy.js.map +1 -1
  6. package/lib/access/model.js +29 -1
  7. package/lib/access/model.js.map +1 -1
  8. package/lib/access/queue-policy.js +36 -0
  9. package/lib/access/queue-policy.js.map +1 -0
  10. package/lib/access/service.js +124 -7
  11. package/lib/access/service.js.map +1 -1
  12. package/lib/account-remotes.js +10 -1
  13. package/lib/account-remotes.js.map +1 -1
  14. package/lib/accounts/database.js +44 -3
  15. package/lib/accounts/database.js.map +1 -1
  16. package/lib/accounts/store.js +28 -0
  17. package/lib/accounts/store.js.map +1 -1
  18. package/lib/admin/service.js +6 -1
  19. package/lib/admin/service.js.map +1 -1
  20. package/lib/attachment-access.js +147 -0
  21. package/lib/attachment-access.js.map +1 -0
  22. package/lib/chat-sharing/search.js +89 -0
  23. package/lib/chat-sharing/search.js.map +1 -0
  24. package/lib/chat-sharing/transport.js +8 -9
  25. package/lib/chat-sharing/transport.js.map +1 -1
  26. package/lib/client/QaAccountsController.js +43 -8
  27. package/lib/client/QaAccountsController.js.map +1 -1
  28. package/lib/client/QaSessionController.js +106 -32
  29. package/lib/client/QaSessionController.js.map +1 -1
  30. package/lib/client/QaSurface.js +64 -5
  31. package/lib/client/QaSurface.js.map +1 -1
  32. package/lib/client/admin/ModelPolicyEditor.js +28 -2
  33. package/lib/client/admin/ModelPolicyEditor.js.map +1 -1
  34. package/lib/client/admin/RoleEditor.js +18 -1
  35. package/lib/client/admin/RoleEditor.js.map +1 -1
  36. package/lib/client/admin/pages/SkillFiles.js +1 -1
  37. package/lib/client/admin/pages/SkillFiles.js.map +1 -1
  38. package/lib/client/admin/pages/Users.js +36 -16
  39. package/lib/client/admin/pages/Users.js.map +1 -1
  40. package/lib/client/admin/styles.js +3 -0
  41. package/lib/client/admin/styles.js.map +1 -1
  42. package/lib/client/code-source-styles.js +12 -0
  43. package/lib/client/code-source-styles.js.map +1 -0
  44. package/lib/client/components/QaChangelog.js +96 -0
  45. package/lib/client/components/QaChangelog.js.map +1 -1
  46. package/lib/client/components/QaChatActions.js +36 -14
  47. package/lib/client/components/QaChatActions.js.map +1 -1
  48. package/lib/client/components/QaCodeSourcePicker.js +18 -0
  49. package/lib/client/components/QaCodeSourcePicker.js.map +1 -0
  50. package/lib/client/components/QaComposer.js +11 -12
  51. package/lib/client/components/QaComposer.js.map +1 -1
  52. package/lib/client/components/QaComposerSettings.js +202 -0
  53. package/lib/client/components/QaComposerSettings.js.map +1 -0
  54. package/lib/client/components/QaFormItem.js +74 -38
  55. package/lib/client/components/QaFormItem.js.map +1 -1
  56. package/lib/client/components/QaHistoryCatalog.js +261 -0
  57. package/lib/client/components/QaHistoryCatalog.js.map +1 -0
  58. package/lib/client/components/QaInputForm.js +115 -32
  59. package/lib/client/components/QaInputForm.js.map +1 -1
  60. package/lib/client/components/QaModelSelector.js +21 -0
  61. package/lib/client/components/QaModelSelector.js.map +1 -0
  62. package/lib/client/components/QaRequestWait.js +15 -0
  63. package/lib/client/components/QaRequestWait.js.map +1 -0
  64. package/lib/client/components/QaSidebar.js +25 -24
  65. package/lib/client/components/QaSidebar.js.map +1 -1
  66. package/lib/client/composer-settings-styles.js +21 -0
  67. package/lib/client/composer-settings-styles.js.map +1 -0
  68. package/lib/client/forms-styles.js +35 -11
  69. package/lib/client/forms-styles.js.map +1 -1
  70. package/lib/client/history-organization-styles.js +31 -0
  71. package/lib/client/history-organization-styles.js.map +1 -0
  72. package/lib/client/history-organization.js +155 -0
  73. package/lib/client/history-organization.js.map +1 -0
  74. package/lib/client/index.js +13 -2
  75. package/lib/client/index.js.map +1 -1
  76. package/lib/client/project-session-state.js.map +1 -1
  77. package/lib/client/request-wait-styles.js +7 -0
  78. package/lib/client/request-wait-styles.js.map +1 -0
  79. package/lib/client/settings/sections/attachments.js +7 -1
  80. package/lib/client/settings/sections/attachments.js.map +1 -1
  81. package/lib/client/settings/sections/session.js +1 -1
  82. package/lib/client/settings/sections/session.js.map +1 -1
  83. package/lib/client/styles.js +20 -1
  84. package/lib/client/styles.js.map +1 -1
  85. package/lib/client/types.js.map +1 -1
  86. package/lib/client/use-chat-code-source.js +156 -0
  87. package/lib/client/use-chat-code-source.js.map +1 -0
  88. package/lib/client/use-history-organization.js +48 -0
  89. package/lib/client/use-history-organization.js.map +1 -0
  90. package/lib/client/use-model-selection.js +96 -0
  91. package/lib/client/use-model-selection.js.map +1 -0
  92. package/lib/client/use-qa-file-drop.js +81 -0
  93. package/lib/client/use-qa-file-drop.js.map +1 -0
  94. package/lib/client/user-settings/IntegrationTokensPage.js +42 -6
  95. package/lib/client/user-settings/IntegrationTokensPage.js.map +1 -1
  96. package/lib/client/user-settings/UserSettingsDialog.js +1 -1
  97. package/lib/client/user-settings/UserSettingsDialog.js.map +1 -1
  98. package/lib/client.js +131 -27
  99. package/lib/client.js.map +1 -1
  100. package/lib/code-source-selection.js +102 -0
  101. package/lib/code-source-selection.js.map +1 -0
  102. package/lib/config-resolvers/accounts.js +26 -1
  103. package/lib/config-resolvers/accounts.js.map +1 -1
  104. package/lib/config-resolvers/defaults.js +5 -0
  105. package/lib/config-resolvers/defaults.js.map +1 -1
  106. package/lib/config-resolvers/integration.js +8 -1
  107. package/lib/config-resolvers/integration.js.map +1 -1
  108. package/lib/config-resolvers/session.js +2 -0
  109. package/lib/config-resolvers/session.js.map +1 -1
  110. package/lib/config.js +51 -3
  111. package/lib/config.js.map +1 -1
  112. package/lib/enforcement/skill-policy.js +37 -2
  113. package/lib/enforcement/skill-policy.js.map +1 -1
  114. package/lib/filesystem-intent.js +39 -0
  115. package/lib/filesystem-intent.js.map +1 -0
  116. package/lib/forms/attachments.js +18 -2
  117. package/lib/forms/attachments.js.map +1 -1
  118. package/lib/forms/errors.js +6 -1
  119. package/lib/forms/errors.js.map +1 -1
  120. package/lib/forms/gate.js +28 -2
  121. package/lib/forms/gate.js.map +1 -1
  122. package/lib/forms/schema-errors.js +47 -0
  123. package/lib/forms/schema-errors.js.map +1 -0
  124. package/lib/forms/schema.js +29 -20
  125. package/lib/forms/schema.js.map +1 -1
  126. package/lib/index.js +189 -84
  127. package/lib/index.js.map +1 -1
  128. package/lib/integration/http.js +9 -10
  129. package/lib/integration/http.js.map +1 -1
  130. package/lib/integration/service.js +9 -0
  131. package/lib/integration/service.js.map +1 -1
  132. package/lib/personal-skills/provider.js +9 -1
  133. package/lib/personal-skills/provider.js.map +1 -1
  134. package/lib/personal-skills/service.js +4 -0
  135. package/lib/personal-skills/service.js.map +1 -1
  136. package/lib/personal-skills/shared-seed.js +65 -0
  137. package/lib/personal-skills/shared-seed.js.map +1 -0
  138. package/lib/prompt-notes.js +19 -1
  139. package/lib/prompt-notes.js.map +1 -1
  140. package/lib/provenance/collector.js +1 -0
  141. package/lib/provenance/collector.js.map +1 -1
  142. package/lib/provenance/extractors.js +6 -1
  143. package/lib/provenance/extractors.js.map +1 -1
  144. package/lib/qa-tools/catalog.js +18 -1
  145. package/lib/qa-tools/catalog.js.map +1 -1
  146. package/lib/qa-tools/code-files.js +207 -0
  147. package/lib/qa-tools/code-files.js.map +1 -0
  148. package/lib/qa-tools/code-tools.js +158 -0
  149. package/lib/qa-tools/code-tools.js.map +1 -0
  150. package/lib/qa-tools/docs-tools.js +49 -12
  151. package/lib/qa-tools/docs-tools.js.map +1 -1
  152. package/lib/qa-tools/index.js +4 -0
  153. package/lib/qa-tools/index.js.map +1 -1
  154. package/lib/qa-tools/request-user-form.js +27 -7
  155. package/lib/qa-tools/request-user-form.js.map +1 -1
  156. package/lib/request-scheduler.js +262 -0
  157. package/lib/request-scheduler.js.map +1 -0
  158. package/lib/resolve-config.js +9 -1
  159. package/lib/resolve-config.js.map +1 -1
  160. package/lib/secure-session.js +62 -56
  161. package/lib/secure-session.js.map +1 -1
  162. package/lib/session-create.js +125 -0
  163. package/lib/session-create.js.map +1 -0
  164. package/lib/session-model.js +43 -1
  165. package/lib/session-model.js.map +1 -1
  166. package/lib/shared/history-folder.js +18 -0
  167. package/lib/shared/history-folder.js.map +1 -0
  168. package/lib/typert.host.js +793 -159
  169. package/lib/typert.remote-client.d.ts +19 -7
  170. package/lib/typert.remote-client.js +726 -148
  171. package/lib/types/access/model-choices.d.ts +16 -0
  172. package/lib/types/access/model-policy.d.ts +13 -7
  173. package/lib/types/access/model.d.ts +9 -0
  174. package/lib/types/access/queue-policy.d.ts +30 -0
  175. package/lib/types/access/service.d.ts +27 -0
  176. package/lib/types/account-remotes.d.ts +5 -4
  177. package/lib/types/accounts/database.d.ts +5 -0
  178. package/lib/types/accounts/store.d.ts +6 -0
  179. package/lib/types/attachment-access.d.ts +29 -0
  180. package/lib/types/chat-sharing/search.d.ts +5 -0
  181. package/lib/types/chat-sharing/transport.d.ts +1 -1
  182. package/lib/types/client/QaAccountsController.d.ts +3 -1
  183. package/lib/types/client/QaSessionController.d.ts +31 -14
  184. package/lib/types/client/QaSurface.d.ts +2 -0
  185. package/lib/types/client/admin/ModelPolicyEditor.d.ts +2 -0
  186. package/lib/types/client/code-source-styles.d.ts +2 -0
  187. package/lib/types/client/components/QaChatActions.d.ts +3 -1
  188. package/lib/types/client/components/QaCodeSourcePicker.d.ts +9 -0
  189. package/lib/types/client/components/QaComposer.d.ts +2 -0
  190. package/lib/types/client/components/QaComposerSettings.d.ts +16 -0
  191. package/lib/types/client/components/QaFormItem.d.ts +4 -2
  192. package/lib/types/client/components/QaHistoryCatalog.d.ts +19 -0
  193. package/lib/types/client/components/QaInputForm.d.ts +3 -2
  194. package/lib/types/client/components/QaModelSelector.d.ts +4 -0
  195. package/lib/types/client/components/QaRequestWait.d.ts +6 -0
  196. package/lib/types/client/components/QaSidebar.d.ts +3 -0
  197. package/lib/types/client/composer-settings-styles.d.ts +2 -0
  198. package/lib/types/client/forms-styles.d.ts +1 -1
  199. package/lib/types/client/history-organization-styles.d.ts +3 -0
  200. package/lib/types/client/history-organization.d.ts +38 -0
  201. package/lib/types/client/project-session-state.d.ts +2 -4
  202. package/lib/types/client/request-wait-styles.d.ts +2 -0
  203. package/lib/types/client/types.d.ts +15 -7
  204. package/lib/types/client/use-chat-code-source.d.ts +20 -0
  205. package/lib/types/client/use-history-organization.d.ts +8 -0
  206. package/lib/types/client/use-model-selection.d.ts +24 -0
  207. package/lib/types/client/use-qa-file-drop.d.ts +12 -0
  208. package/lib/types/code-source-selection.d.ts +28 -0
  209. package/lib/types/code-sources.js +2 -0
  210. package/lib/types/code-sources.js.map +1 -0
  211. package/lib/types/config-resolvers/integration.d.ts +7 -1
  212. package/lib/types/filesystem-intent.d.ts +12 -0
  213. package/lib/types/forms/attachments.d.ts +5 -2
  214. package/lib/types/forms/errors.d.ts +3 -2
  215. package/lib/types/forms/gate.d.ts +4 -2
  216. package/lib/types/forms/schema-errors.d.ts +7 -0
  217. package/lib/types/forms/types.d.ts +14 -0
  218. package/lib/types/index.d.ts +41 -15
  219. package/lib/types/integration/http.d.ts +1 -3
  220. package/lib/types/integration/service.d.ts +2 -0
  221. package/lib/types/personal-skills/shared-seed.d.ts +12 -0
  222. package/lib/types/prompt-notes.d.ts +5 -1
  223. package/lib/types/qa-tools/catalog.d.ts +4 -3
  224. package/lib/types/qa-tools/code-files.d.ts +59 -0
  225. package/lib/types/qa-tools/code-tools.d.ts +7 -0
  226. package/lib/types/qa-tools/docs-tools.d.ts +4 -0
  227. package/lib/types/qa-tools/index.d.ts +3 -1
  228. package/lib/types/qa-tools/request-user-form.d.ts +1 -1
  229. package/lib/types/request-scheduler.d.ts +47 -0
  230. package/lib/types/secure-session.d.ts +12 -26
  231. package/lib/types/session-create.d.ts +29 -0
  232. package/lib/types/session-model.d.ts +11 -2
  233. package/lib/types/shared/history-folder.d.ts +4 -0
  234. package/lib/types/types/accounts.d.ts +11 -0
  235. package/lib/types/types/capability.d.ts +31 -4
  236. package/lib/types/types/code-sources.d.ts +12 -0
  237. package/lib/types/types/config.d.ts +20 -0
  238. package/lib/types/types/session.d.ts +8 -0
  239. package/lib/types/types.d.ts +1 -0
  240. package/lib/types/user-workspace.d.ts +4 -6
  241. package/lib/user-workspace.js +20 -71
  242. package/lib/user-workspace.js.map +1 -1
  243. package/package.json +13 -10
package/lib/index.js CHANGED
@@ -32,9 +32,10 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
32
32
  if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
33
  done = true;
34
34
  };
35
- import { randomUUID } from "node:crypto";
36
35
  import { readSourceImage as readSourceImagePreview } from "./provenance/source-image.js";
37
36
  import path from "node:path";
37
+ import { QaCodeSourceSelection } from "./code-source-selection.js";
38
+ import { qaDelegatedHeader } from "./shared/session-lineage.js";
38
39
  import { defaultAccountsFilePath } from "./accounts/store.js";
39
40
  import { QaChatSharingStore } from "./chat-sharing/store.js";
40
41
  import { QaChatTransport } from "./chat-sharing/transport.js";
@@ -44,9 +45,9 @@ import { QaIntegrationQuestionPolicy } from "./integration/question-policy.js";
44
45
  import { qaChatPublishedFile, qaChatAttachmentPath, } from "./chat-sharing/resources.js";
45
46
  import { installQaChatUploads } from "./chat-sharing/uploads.js";
46
47
  import { forkQaSession } from "./session-fork-host.js";
48
+ import { createQaSession } from "./session-create.js";
47
49
  import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
48
50
  import { SessionId } from "@deepseek-ai/dsh-session/types";
49
- import { WorkspaceId } from "@deepseek-ai/dsh-workspace";
50
51
  import { createHostLoggerSink, getPluginLogger, } from "@yadsh/dsh-plugin-log";
51
52
  import { ConfigSchema, qaSurfaceVersion, readConfigRefs, resolveConfig, } from "./config.js";
52
53
  import { createQaAccountRemotes } from "./account-remotes.js";
@@ -55,7 +56,7 @@ import { QaQualityStore } from "./admin/quality-store.js";
55
56
  import { createSessionEraser, createSessionLogReader, } from "./admin/session-log.js";
56
57
  import { createQaPersonalSkillRemotes, QaPersonalSkillsHost, } from "./personal-skills/index.js";
57
58
  import { QaApprovalGate } from "./approvals.js";
58
- import { QaAttestationError, qaAttestationFailureMessage, } from "./attestation.js";
59
+ import { QaAttestationError } from "./attestation.js";
59
60
  import { QaFileDeleteGate } from "./qa-tools/file-delete-gate.js";
60
61
  import { QaQuestionGate } from "./questions.js";
61
62
  import { QaFormStore } from "./forms/store.js";
@@ -78,11 +79,11 @@ import { createQaIntegrationRunner } from "./integration/host-runner.js";
78
79
  import { QaIntegrationService } from "./integration/service.js";
79
80
  import { QaPolicyAdmission } from "./secure-session.js";
80
81
  import { QaAccessService } from "./access/service.js";
81
- import { applySessionModelPolicy } from "./session-model.js";
82
+ import { userModelOptions, selectUserModel } from "./access/model-choices.js";
82
83
  import { userInvocableSkillNames } from "./access/model.js";
83
84
  import { createQaSlashRemotes } from "./slash/remotes.js";
84
85
  import { QaPromptNotes } from "./prompt-notes.js";
85
- import { qaActiveRequests, qaQueueStatus } from "./request-queue.js";
86
+ import { QaRequestScheduler, qaRequestFamilyBusy, qaRequestRoots, } from "./request-scheduler.js";
86
87
  import { QaTools } from "./qa-tools/index.js";
87
88
  import { docsDefaultVersionOf } from "./config-resolvers/tools.js";
88
89
  import { QaProvenanceHost } from "./provenance/host-store.js";
@@ -90,7 +91,7 @@ import { defaultLegacyProvenanceFilePath, defaultQaProvenanceDirectoryPath, File
90
91
  import { previewConvertibleDocument, previewSourceDocument, } from "./provenance/document-preview.js";
91
92
  import { readWorkspaceFileChunk } from "./provenance/file-download.js";
92
93
  import { listWorkspaceDirectory, readSourceFilePreview, readWorkspaceFile, QaSourcePreviewError, } from "./provenance/file-preview.js";
93
- import { existingQaUserWorkspace, prepareQaUserWorkspace, } from "./user-workspace.js";
94
+ import { existingQaUserWorkspace } from "./user-workspace.js";
94
95
  export const name = "qa-surface";
95
96
  export const inject = [
96
97
  "agents",
@@ -101,6 +102,7 @@ export const inject = [
101
102
  "systemPrompt",
102
103
  "workspaceRegistry",
103
104
  "sessionController",
105
+ "llm",
104
106
  ];
105
107
  // One home for the namespace: the browser card binds to the same constant
106
108
  // through `src/shared/settings.ts`, which avoids importing this module (and
@@ -144,6 +146,8 @@ function releaseScopeLease(lease) {
144
146
  let QaSurface = (() => {
145
147
  let _classSuper = TypertRemoteService;
146
148
  let _instanceExtraInitializers = [];
149
+ let _chatCodeSources_decorators;
150
+ let _chatSelectCodeSource_decorators;
147
151
  let _accountsRegister_decorators;
148
152
  let _accountsLogin_decorators;
149
153
  let _accountsOidcStart_decorators;
@@ -162,6 +166,7 @@ let QaSurface = (() => {
162
166
  let _accountsCreateServiceToken_decorators;
163
167
  let _accountsRevokeServiceToken_decorators;
164
168
  let _accountsSetServiceTokenClarifications_decorators;
169
+ let _accountsSetServiceTokenHistoryFolder_decorators;
165
170
  let _describe_decorators;
166
171
  let _queueStatus_decorators;
167
172
  let _createSession_decorators;
@@ -172,6 +177,7 @@ let QaSurface = (() => {
172
177
  let _accessCreateSubrole_decorators;
173
178
  let _accessUpdateSubrole_decorators;
174
179
  let _accessModelCatalog_decorators;
180
+ let _accessUserModels_decorators;
175
181
  let _accessDeleteSubrole_decorators;
176
182
  let _accessUpdateCommon_decorators;
177
183
  let _accessUpdateAssignment_decorators;
@@ -257,6 +263,8 @@ let QaSurface = (() => {
257
263
  return class QaSurface extends _classSuper {
258
264
  static {
259
265
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
266
+ _chatCodeSources_decorators = [Remote("chatCodeSources")];
267
+ _chatSelectCodeSource_decorators = [Remote("chatSelectCodeSource")];
260
268
  _accountsRegister_decorators = [Remote("accountsRegister")];
261
269
  _accountsLogin_decorators = [Remote("accountsLogin")];
262
270
  _accountsOidcStart_decorators = [Remote("accountsOidcStart")];
@@ -275,6 +283,7 @@ let QaSurface = (() => {
275
283
  _accountsCreateServiceToken_decorators = [Remote("accountsCreateServiceToken")];
276
284
  _accountsRevokeServiceToken_decorators = [Remote("accountsRevokeServiceToken")];
277
285
  _accountsSetServiceTokenClarifications_decorators = [Remote("accountsSetServiceTokenClarifications")];
286
+ _accountsSetServiceTokenHistoryFolder_decorators = [Remote("accountsSetServiceTokenHistoryFolder")];
278
287
  _describe_decorators = [Remote("describe")];
279
288
  _queueStatus_decorators = [Remote("queueStatus")];
280
289
  _createSession_decorators = [Remote("createSession")];
@@ -285,6 +294,7 @@ let QaSurface = (() => {
285
294
  _accessCreateSubrole_decorators = [Remote("accessCreateSubrole")];
286
295
  _accessUpdateSubrole_decorators = [Remote("accessUpdateSubrole")];
287
296
  _accessModelCatalog_decorators = [Remote("accessModelCatalog")];
297
+ _accessUserModels_decorators = [Remote("accessUserModels")];
288
298
  _accessDeleteSubrole_decorators = [Remote("accessDeleteSubrole")];
289
299
  _accessUpdateCommon_decorators = [Remote("accessUpdateCommon")];
290
300
  _accessUpdateAssignment_decorators = [Remote("accessUpdateAssignment")];
@@ -367,6 +377,8 @@ let QaSurface = (() => {
367
377
  _skillsTools_decorators = [Remote("skillsTools")];
368
378
  _slashCatalog_decorators = [Remote("slashCatalog")];
369
379
  _slashExecute_decorators = [Remote("slashExecute")];
380
+ __esDecorate(this, null, _chatCodeSources_decorators, { kind: "method", name: "chatCodeSources", static: false, private: false, access: { has: obj => "chatCodeSources" in obj, get: obj => obj.chatCodeSources }, metadata: _metadata }, null, _instanceExtraInitializers);
381
+ __esDecorate(this, null, _chatSelectCodeSource_decorators, { kind: "method", name: "chatSelectCodeSource", static: false, private: false, access: { has: obj => "chatSelectCodeSource" in obj, get: obj => obj.chatSelectCodeSource }, metadata: _metadata }, null, _instanceExtraInitializers);
370
382
  __esDecorate(this, null, _accountsRegister_decorators, { kind: "method", name: "accountsRegister", static: false, private: false, access: { has: obj => "accountsRegister" in obj, get: obj => obj.accountsRegister }, metadata: _metadata }, null, _instanceExtraInitializers);
371
383
  __esDecorate(this, null, _accountsLogin_decorators, { kind: "method", name: "accountsLogin", static: false, private: false, access: { has: obj => "accountsLogin" in obj, get: obj => obj.accountsLogin }, metadata: _metadata }, null, _instanceExtraInitializers);
372
384
  __esDecorate(this, null, _accountsOidcStart_decorators, { kind: "method", name: "accountsOidcStart", static: false, private: false, access: { has: obj => "accountsOidcStart" in obj, get: obj => obj.accountsOidcStart }, metadata: _metadata }, null, _instanceExtraInitializers);
@@ -385,6 +397,7 @@ let QaSurface = (() => {
385
397
  __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);
386
398
  __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);
387
399
  __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);
400
+ __esDecorate(this, null, _accountsSetServiceTokenHistoryFolder_decorators, { kind: "method", name: "accountsSetServiceTokenHistoryFolder", static: false, private: false, access: { has: obj => "accountsSetServiceTokenHistoryFolder" in obj, get: obj => obj.accountsSetServiceTokenHistoryFolder }, metadata: _metadata }, null, _instanceExtraInitializers);
388
401
  __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);
389
402
  __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);
390
403
  __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);
@@ -395,6 +408,7 @@ let QaSurface = (() => {
395
408
  __esDecorate(this, null, _accessCreateSubrole_decorators, { kind: "method", name: "accessCreateSubrole", static: false, private: false, access: { has: obj => "accessCreateSubrole" in obj, get: obj => obj.accessCreateSubrole }, metadata: _metadata }, null, _instanceExtraInitializers);
396
409
  __esDecorate(this, null, _accessUpdateSubrole_decorators, { kind: "method", name: "accessUpdateSubrole", static: false, private: false, access: { has: obj => "accessUpdateSubrole" in obj, get: obj => obj.accessUpdateSubrole }, metadata: _metadata }, null, _instanceExtraInitializers);
397
410
  __esDecorate(this, null, _accessModelCatalog_decorators, { kind: "method", name: "accessModelCatalog", static: false, private: false, access: { has: obj => "accessModelCatalog" in obj, get: obj => obj.accessModelCatalog }, metadata: _metadata }, null, _instanceExtraInitializers);
411
+ __esDecorate(this, null, _accessUserModels_decorators, { kind: "method", name: "accessUserModels", static: false, private: false, access: { has: obj => "accessUserModels" in obj, get: obj => obj.accessUserModels }, metadata: _metadata }, null, _instanceExtraInitializers);
398
412
  __esDecorate(this, null, _accessDeleteSubrole_decorators, { kind: "method", name: "accessDeleteSubrole", static: false, private: false, access: { has: obj => "accessDeleteSubrole" in obj, get: obj => obj.accessDeleteSubrole }, metadata: _metadata }, null, _instanceExtraInitializers);
399
413
  __esDecorate(this, null, _accessUpdateCommon_decorators, { kind: "method", name: "accessUpdateCommon", static: false, private: false, access: { has: obj => "accessUpdateCommon" in obj, get: obj => obj.accessUpdateCommon }, metadata: _metadata }, null, _instanceExtraInitializers);
400
414
  __esDecorate(this, null, _accessUpdateAssignment_decorators, { kind: "method", name: "accessUpdateAssignment", static: false, private: false, access: { has: obj => "accessUpdateAssignment" in obj, get: obj => obj.accessUpdateAssignment }, metadata: _metadata }, null, _instanceExtraInitializers);
@@ -479,9 +493,20 @@ let QaSurface = (() => {
479
493
  __esDecorate(this, null, _slashExecute_decorators, { kind: "method", name: "slashExecute", static: false, private: false, access: { has: obj => "slashExecute" in obj, get: obj => obj.slashExecute }, metadata: _metadata }, null, _instanceExtraInitializers);
480
494
  if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
481
495
  }
496
+ sourceSelections = __runInitializers(this, _instanceExtraInitializers);
497
+ codeSourceStore() {
498
+ return (this.sourceSelections ??= new QaCodeSourceSelection(path.join(path.dirname(defaultAccountsFilePath()), "qa-code-sources.db"), () => this.getConfig().codeSources, (id) => this.ctx.sessions.get(SessionId(id)), (id) => {
499
+ const agent = this.ctx.agents.get(SessionId(id));
500
+ return (agent !== undefined &&
501
+ (agent.status === "running" ||
502
+ agent.inbox.nextStep.length > 0 ||
503
+ qaRequestFamilyBusy(this.ctx, agent) ||
504
+ this.requestScheduler.status(id).waiting === true));
505
+ }));
506
+ }
482
507
  static inject = inject;
483
508
  static Config = ConfigSchema;
484
- source = __runInitializers(this, _instanceExtraInitializers);
509
+ source;
485
510
  logger;
486
511
  admission;
487
512
  approvals;
@@ -545,6 +570,7 @@ let QaSurface = (() => {
545
570
  chatSharingStore;
546
571
  chatTransport;
547
572
  chatTurnGuard;
573
+ requestScheduler;
548
574
  sharing() {
549
575
  const accounts = () => {
550
576
  const store = this.accountRemotes.resolve(this.getConfig());
@@ -561,11 +587,26 @@ let QaSurface = (() => {
561
587
  // the one live source: each read folds its current snapshots, and a settings
562
588
  // write is visible on the next read without reloading the plugin.
563
589
  this.source = () => readConfigRefs(entry);
590
+ ctx.effect(() => ctx.on("agent/created", ({ agent }) => {
591
+ const { parentSession } = agent.session.header;
592
+ if (parentSession !== undefined &&
593
+ (qaDelegatedHeader(agent.session.header) ||
594
+ agent.session.header.isSeeded === true)) {
595
+ this.codeSourceStore().inherit(String(agent.session.id), String(parentSession), this.admission.knowsSession(String(parentSession)));
596
+ }
597
+ }, { global: true }), "dsh-qa-surface.code-source-inheritance");
598
+ ctx.effect(() => () => this.sourceSelections?.close(), "dsh-qa-surface.code-source-store");
599
+ this.requestScheduler = new QaRequestScheduler(() => this.getConfig().session.maxActiveRequests, () => qaRequestRoots(ctx, this.getConfig().session.maxActiveRequests > 0), Date.now, (agent) => qaRequestFamilyBusy(ctx, agent),
600
+ // The ceiling one turn fills against, resolved per admission: a role or
601
+ // an account that overrides the deployment's number is read here, where
602
+ // the scheduler decides, not once at boot.
603
+ (agent) => this.queueSlotsOverride(agent));
604
+ ctx.effect(() => this.requestScheduler.install(ctx), "dsh-qa-surface.request-queue");
564
605
  this.logger = getPluginLogger({
565
606
  pluginId: "dsh-qa-surface",
566
607
  consoleSink: createHostLoggerSink(ctx.logger),
567
608
  });
568
- this.formAttachments = new QaFormAttachmentAdapter(() => this.forms(), () => ctx.get("attachments"));
609
+ this.formAttachments = new QaFormAttachmentAdapter(() => this.forms(), () => ctx.get("attachments"), (sessionId, file) => this.admission.grantAttachmentFile(sessionId, file));
569
610
  this.accountRemotes = createQaAccountRemotes({
570
611
  getConfig: () => this.getConfig(),
571
612
  logger: this.logger,
@@ -665,7 +706,16 @@ let QaSurface = (() => {
665
706
  // that is where the caller's account has just been matched against the
666
707
  // ownership record. The browser's `secureSession` remote keeps its own
667
708
  // write: there the compared identity is the token's.
668
- this.integrationPrincipals);
709
+ this.integrationPrincipals, {
710
+ readEvents: async (sessionId) => {
711
+ const result = await sessionLog.read(sessionId);
712
+ return result.ok ? result.events : [];
713
+ },
714
+ restoreFiles: async (sessionId) => {
715
+ if (this.getConfig().forms.enabled)
716
+ await this.formAttachments.restore(sessionId);
717
+ },
718
+ });
669
719
  this.provenance = new QaProvenanceHost(ctx, () => this.getConfig(),
670
720
  // Sharded per chat and bounded by the resolved retention policy: the
671
721
  // turn path must never rewrite history it did not touch.
@@ -756,6 +806,7 @@ let QaSurface = (() => {
756
806
  // complete persona closes the system prompt to plugins, the conversation
757
807
  // stays open.
758
808
  this.notes = new QaPromptNotes(ctx, {
809
+ codeSources: (sessionId) => this.getCodeSources(sessionId),
759
810
  config: () => this.getConfig(),
760
811
  accounts: () => this.accountRemotes.resolve(this.getConfig()),
761
812
  isQaSession: (sessionId) => this.admission.knowsSession(sessionId),
@@ -783,9 +834,13 @@ let QaSurface = (() => {
783
834
  // The QA tool catalog is attached per agent, never at boot: nothing here
784
835
  // reaches the model until a managed agent loads the activation skill.
785
836
  this.tools = new QaTools(ctx, {
837
+ codeSources: (exec) => this.getCodeSources(exec?.agent?.session?.id === undefined
838
+ ? undefined
839
+ : String(exec.agent.session.id)),
840
+ codeReadRoots: () => this.getConfig().lockdown.sharedReadOnlyRoots,
786
841
  forms: this.formGate,
787
842
  formsEnabled: () => this.getConfig().forms.enabled,
788
- formProjection: (submission) => this.formAttachments.readable(submission),
843
+ formProjection: (submission, sessionId) => this.formAttachments.readable(submission, sessionId),
789
844
  logger: this.logger,
790
845
  dynamicActivation: this.getConfig().tools.dynamicActivation,
791
846
  activationSkill: this.getConfig().tools.activationSkill,
@@ -962,6 +1017,33 @@ let QaSurface = (() => {
962
1017
  modelPolicyForSession(sessionId) {
963
1018
  return this.access.modelPolicyFor(sessionId).pair;
964
1019
  }
1020
+ /** Shared source catalogue consumed by preset-mounted Git tools at call time. */
1021
+ getCodeSources(sessionId) {
1022
+ return sessionId === undefined
1023
+ ? this.getConfig().codeSources
1024
+ : this.codeSourceStore().catalog(sessionId);
1025
+ }
1026
+ getSelectedCodeSource(sessionId) {
1027
+ return this.codeSourceStore().selected(sessionId);
1028
+ }
1029
+ async chatCodeSources(token, sessionId) {
1030
+ const finish = await this.admitChatRead(token, sessionId);
1031
+ let owner = true;
1032
+ try {
1033
+ this.requireChatOwner(token, sessionId);
1034
+ }
1035
+ catch {
1036
+ owner = false;
1037
+ }
1038
+ finish();
1039
+ return this.codeSourceStore().view(sessionId, owner);
1040
+ }
1041
+ async chatSelectCodeSource(token, sessionId, source) {
1042
+ const finish = await this.admitChatRead(token, sessionId);
1043
+ this.requireChatOwner(token, sessionId);
1044
+ finish();
1045
+ return this.codeSourceStore().select(sessionId, source);
1046
+ }
965
1047
  getConfig() {
966
1048
  return resolveConfig(this.source());
967
1049
  }
@@ -1108,6 +1190,9 @@ let QaSurface = (() => {
1108
1190
  accountsSetServiceTokenClarifications(token, tokenId, allowed) {
1109
1191
  return this.accountRemotes.setServiceTokenClarifications(token, tokenId, allowed);
1110
1192
  }
1193
+ accountsSetServiceTokenHistoryFolder(token, tokenId, folder) {
1194
+ return this.accountRemotes.setServiceTokenHistoryFolder(token, tokenId, folder);
1195
+ }
1111
1196
  /**
1112
1197
  * Serve the effective QA configuration to the browser. The DSH gateway pins
1113
1198
  * settings RPCs to loopback, so a browser served over the LAN always sees
@@ -1119,20 +1204,71 @@ let QaSurface = (() => {
1119
1204
  return this.getConfig();
1120
1205
  }
1121
1206
  /**
1122
- * Report how much of the deployment's request ceiling the stand is using, so
1123
- * a browser holds its question back instead of opening another turn on a
1124
- * model that is busy answering the ones it allows.
1207
+ * Report server admission. Global reads expose counts only; a chat's FIFO
1208
+ * position requires that account's current read access to the chat. The
1209
+ * scheduler gates every root turn, including native and integration sends.
1125
1210
  *
1126
- * The count is the Host's, not the browser's: a visitor cannot see another
1127
- * account's chats, and the HTTP API's questions are invisible to every chat
1128
- * view. Read-only, and a ceiling rather than a lock — a prompt rides the
1129
- * native session RPC this plugin does not own, so the boundary is the
1130
- * browser's own courtesy, and two questions sent in the same instant can
1131
- * still overshoot by one. What the ceiling buys is that steady state, not a
1132
- * strict bound.
1211
+ * Both arguments are part of the wire contract: the gateway client counts
1212
+ * declared parameters rather than TypeScript optionals, so a call that omits
1213
+ * them is refused on the browser before the Host ever sees it. An empty
1214
+ * session id is the global read — the shape every initial send asks for,
1215
+ * while its draft chat has no session to name yet.
1133
1216
  */
1134
- queueStatus() {
1135
- return qaQueueStatus(this.getConfig().session.maxActiveRequests, qaActiveRequests(this.ctx.agents.roots()));
1217
+ queueStatus(token, sessionId) {
1218
+ const requested = sessionId === "" ? undefined : sessionId;
1219
+ if (requested !== undefined && this.getConfig().accounts.enabled) {
1220
+ this.sharing().access(token, requested);
1221
+ }
1222
+ return this.requestScheduler.status(requested, this.queueCeiling(token, requested));
1223
+ }
1224
+ /**
1225
+ * The ceiling this read answers against: the chat's own account chain when
1226
+ * the read names a chat, the caller's account chain when it does not (the
1227
+ * pre-send check carries a token but no chat yet), and the deployment's
1228
+ * number whenever accounts are off or nobody matches. `undefined` is the
1229
+ * scheduler's signal to fall back to that number, so the branch is a value
1230
+ * rather than a flag.
1231
+ */
1232
+ queueCeiling(token, sessionId) {
1233
+ const config = this.getConfig();
1234
+ if (!config.accounts.enabled)
1235
+ return undefined;
1236
+ const accounts = this.accountRemotes.resolve(config);
1237
+ if (accounts === undefined)
1238
+ return undefined;
1239
+ if (sessionId !== undefined) {
1240
+ return accounts.ownerIdOf(sessionId) === undefined
1241
+ ? undefined
1242
+ : this.access.queueSlotsFor(sessionId);
1243
+ }
1244
+ try {
1245
+ return this.access.queueSlotsForUser(accounts.currentUser(token).id);
1246
+ }
1247
+ catch {
1248
+ // An anonymous or stale browser still deserves the deployment's numbers:
1249
+ // the read is advisory, and the browser holds its question back on its
1250
+ // own only for a ceiling it can actually name.
1251
+ return undefined;
1252
+ }
1253
+ }
1254
+ /**
1255
+ * The ceiling override one arriving turn fills against, or `undefined` when
1256
+ * the deployment default governs it: without accounts every turn shares the
1257
+ * one number, and an unowned session (an integration or an admin preview)
1258
+ * stays in that shared pool whatever its role might say.
1259
+ */
1260
+ queueSlotsOverride(agent) {
1261
+ const config = this.getConfig();
1262
+ if (!config.accounts.enabled)
1263
+ return undefined;
1264
+ const sessionId = String(agent.session.id);
1265
+ if (sessionId === "")
1266
+ return undefined;
1267
+ const accounts = this.accountRemotes.resolve(config);
1268
+ if (accounts === undefined || accounts.ownerIdOf(sessionId) === undefined) {
1269
+ return undefined;
1270
+ }
1271
+ return this.access.queueSlotsFor(sessionId);
1136
1272
  }
1137
1273
  /**
1138
1274
  * Create a QA session from Host-owned inputs. With account workspaces on,
@@ -1141,65 +1277,26 @@ let QaSurface = (() => {
1141
1277
  */
1142
1278
  async createSession(token, subroleId, adminPreview) {
1143
1279
  const config = this.getConfig();
1144
- if (config.session.policy === "fixed") {
1145
- throw new Error("Fixed QA sessions cannot be created.");
1146
- }
1147
- const id = SessionId(`session-${randomUUID()}`);
1148
1280
  const accounts = this.accountRemotes.resolve(config);
1149
- const owner = accounts === undefined
1150
- ? undefined
1151
- : this.accountRemotes.run(() => this.access.reserveSession(token, String(id), subroleId, adminPreview));
1152
- try {
1153
- // Check deployment-only pins before creating a durable Host session.
1154
- // Full admission below still verifies the composed agent and tool view.
1155
- this.admission.preflightDeployment();
1156
- let userCwd;
1157
- if (config.accounts.perUserWorkspace) {
1158
- const workspaceId = config.session.workspaceId;
1159
- if (owner === undefined || workspaceId === null) {
1160
- throw new Error("Per-user QA workspace configuration is unavailable.");
1161
- }
1162
- const workspace = this.ctx.workspaceRegistry.get(WorkspaceId(workspaceId));
1163
- if (workspace === undefined) {
1164
- throw new Error(`Configured QA workspace ${workspaceId} is unavailable.`);
1165
- }
1166
- userCwd = prepareQaUserWorkspace(workspace.path, owner.id);
1167
- }
1168
- const created = await this.ctx.sessionController.create({
1169
- sessionId: id,
1170
- ...(userCwd !== undefined
1171
- ? { cwd: userCwd }
1172
- : config.session.workspaceId !== null
1173
- ? { workspaceId: WorkspaceId(config.session.workspaceId) }
1174
- : config.session.cwd !== null
1175
- ? { cwd: config.session.cwd }
1176
- : {}),
1177
- ...(config.session.agentPreset === null
1178
- ? {}
1179
- : { agentPreset: config.session.agentPreset }),
1180
- });
1181
- await applySessionModelPolicy(this.ctx, created.sessionId, this.access.modelPolicyFor(String(created.sessionId)), this.logger);
1182
- const sessionId = String(created.sessionId);
1183
- await this.admission.secureSession(token, sessionId);
1184
- this.integrationPrincipals.attest(sessionId, owner?.id, accounts?.ownerIdOf(sessionId));
1185
- return sessionId;
1186
- }
1187
- catch (error) {
1188
- // This call is the only way the browser could have learned the id, so a
1189
- // failure at any stage — the Host creating the session, selecting the
1190
- // model, the admission refusing the composition — leaves no chat behind
1191
- // and the reservation goes with it. A kept record would put an empty
1192
- // chat in the account's list, and nothing else would ever remove it.
1193
- if (owner !== undefined) {
1194
- accounts?.releaseSessionReservation(owner.id, String(id));
1195
- }
1196
- this.logger.error("session.create-rejected", {
1197
- sessionId: String(id),
1198
- reason: error instanceof QaAttestationError ? error.reason : undefined,
1199
- error: error instanceof Error ? error.message : String(error),
1200
- });
1201
- throw new Error(qaAttestationFailureMessage("Unable to create a QA session.", error), { cause: error });
1202
- }
1281
+ return createQaSession({
1282
+ ctx: this.ctx,
1283
+ config,
1284
+ logger: this.logger,
1285
+ sessionFiles: createSessionEraser(),
1286
+ reserve: (id) => accounts === undefined
1287
+ ? undefined
1288
+ : this.accountRemotes.run(() => this.access.reserveSession(token, id, subroleId, adminPreview)),
1289
+ release: (owner, id) => accounts?.releaseSessionReservation(owner, id),
1290
+ modelPolicy: (id) => this.access.modelPolicyFor(id),
1291
+ preflight: () => this.admission.preflightDeployment(),
1292
+ admit: (id) => this.admission.secureSession(token, id),
1293
+ attest: (id, owner) => this.integrationPrincipals.attest(id, owner, accounts?.ownerIdOf(id)),
1294
+ reject: (id) => {
1295
+ this.integrationPrincipals.attest(id, undefined, undefined);
1296
+ this.admission.rejectSession(id);
1297
+ },
1298
+ forget: (id) => this.admission.forgetRejectedSession(id),
1299
+ });
1203
1300
  }
1204
1301
  /** Create an independently admitted ordinary branch of the caller's own chat. */
1205
1302
  async forkSession(token, sourceId, answerSeq) {
@@ -1244,6 +1341,11 @@ let QaSurface = (() => {
1244
1341
  async accessModelCatalog(token) {
1245
1342
  return await this.accountRemotes.runAsync(() => this.access.modelCatalog(token));
1246
1343
  }
1344
+ async accessUserModels(token, sessionId, subroleId, adminPreview) {
1345
+ if (sessionId !== null)
1346
+ this.requireChatOwner(token, sessionId);
1347
+ return this.accountRemotes.runAsync(() => userModelOptions(this.ctx, this.access, token, sessionId, subroleId, adminPreview));
1348
+ }
1247
1349
  accessDeleteSubrole(token, id, replacementId) {
1248
1350
  return this.accountRemotes.run(() => {
1249
1351
  this.access.deleteSubrole(token, id, replacementId);
@@ -1524,9 +1626,12 @@ let QaSurface = (() => {
1524
1626
  }
1525
1627
  chatSelectModel(token, request) {
1526
1628
  this.requireChatOwner(token, String(request.sessionId));
1527
- if (this.getConfig().lockdown.enforceFixedModel)
1528
- throw new Error("The chat model is fixed by its policy.");
1529
- return this.chatTransport.selectModel(token, request);
1629
+ return this.chatTransport.selectModel(token, request, async () => {
1630
+ const id = String(request.sessionId);
1631
+ if (this.requestScheduler.status(id).waiting === true)
1632
+ throw new Error("Wait for the queued request before changing the model.");
1633
+ return selectUserModel(this.ctx, this.access, token, request);
1634
+ });
1530
1635
  }
1531
1636
  async chatPage(token, request, signal) {
1532
1637
  return (await this.chatTransport.page(token, request, signal));
@@ -2077,7 +2182,7 @@ let QaSurface = (() => {
2077
2182
  refreshIntegrationRoutes() {
2078
2183
  const config = this.getConfig();
2079
2184
  const key = config.integration.enabled && config.accounts.enabled
2080
- ? `${config.integration.basePath}:${String(config.integration.maxRequestBytes)}:${String(config.integration.maxAttachmentBytes)}`
2185
+ ? `${config.integration.basePath}:${String(config.integration.maxRequestBytes)}:${String(config.integration.maxAttachmentBytes)}:${String(config.integration.maxAttachments)}`
2081
2186
  : undefined;
2082
2187
  if (key === this.integrationRouteKey)
2083
2188
  return;