@yadsh/dsh-qa-surface 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/README.md +269 -2
  2. package/lib/access/service.js +49 -10
  3. package/lib/access/service.js.map +1 -1
  4. package/lib/account-remotes.js +41 -0
  5. package/lib/account-remotes.js.map +1 -1
  6. package/lib/accounts/database.js +140 -0
  7. package/lib/accounts/database.js.map +1 -1
  8. package/lib/accounts/errors.js.map +1 -1
  9. package/lib/accounts/service-token.js +103 -0
  10. package/lib/accounts/service-token.js.map +1 -0
  11. package/lib/accounts/store.js +291 -5
  12. package/lib/accounts/store.js.map +1 -1
  13. package/lib/admin/conversation-log.js +14 -8
  14. package/lib/admin/conversation-log.js.map +1 -1
  15. package/lib/admin/permissions.js +5 -0
  16. package/lib/admin/permissions.js.map +1 -1
  17. package/lib/admin/quality-store.js +4 -0
  18. package/lib/admin/quality-store.js.map +1 -1
  19. package/lib/admin/service.js +180 -7
  20. package/lib/admin/service.js.map +1 -1
  21. package/lib/admin/session-log.js +39 -8
  22. package/lib/admin/session-log.js.map +1 -1
  23. package/lib/attachment-rules.js +39 -6
  24. package/lib/attachment-rules.js.map +1 -1
  25. package/lib/cli.js +83 -1
  26. package/lib/cli.js.map +1 -1
  27. package/lib/client/QaAccountsController.js +213 -4
  28. package/lib/client/QaAccountsController.js.map +1 -1
  29. package/lib/client/QaSessionController.js +49 -21
  30. package/lib/client/QaSessionController.js.map +1 -1
  31. package/lib/client/QaSurface.js +51 -9
  32. package/lib/client/QaSurface.js.map +1 -1
  33. package/lib/client/QaSurfaceGuard.js +12 -5
  34. package/lib/client/QaSurfaceGuard.js.map +1 -1
  35. package/lib/client/admin/QaAdmin.js +14 -2
  36. package/lib/client/admin/QaAdmin.js.map +1 -1
  37. package/lib/client/admin/pages/SkillFiles.js +78 -0
  38. package/lib/client/admin/pages/SkillFiles.js.map +1 -0
  39. package/lib/client/admin/pages/Users.js +74 -3
  40. package/lib/client/admin/pages/Users.js.map +1 -1
  41. package/lib/client/admin/routes.js +8 -1
  42. package/lib/client/admin/routes.js.map +1 -1
  43. package/lib/client/admin/shared.js +5 -1
  44. package/lib/client/admin/shared.js.map +1 -1
  45. package/lib/client/admin/styles.js +2 -0
  46. package/lib/client/admin/styles.js.map +1 -1
  47. package/lib/client/attachments.js +41 -11
  48. package/lib/client/attachments.js.map +1 -1
  49. package/lib/client/base64.js +22 -1
  50. package/lib/client/base64.js.map +1 -1
  51. package/lib/client/components/QaAgentsDrawer.js +9 -6
  52. package/lib/client/components/QaAgentsDrawer.js.map +1 -1
  53. package/lib/client/components/QaApproval.js +1 -1
  54. package/lib/client/components/QaApproval.js.map +1 -1
  55. package/lib/client/components/QaAuthGate.js +19 -10
  56. package/lib/client/components/QaAuthGate.js.map +1 -1
  57. package/lib/client/components/QaChangelog.js +56 -0
  58. package/lib/client/components/QaChangelog.js.map +1 -1
  59. package/lib/client/components/QaFilesPanel.js +17 -11
  60. package/lib/client/components/QaFilesPanel.js.map +1 -1
  61. package/lib/client/components/QaHeader.js +3 -11
  62. package/lib/client/components/QaHeader.js.map +1 -1
  63. package/lib/client/components/QaModal.js.map +1 -1
  64. package/lib/client/components/QaQuestions.js +4 -4
  65. package/lib/client/components/QaQuestions.js.map +1 -1
  66. package/lib/client/components/QaSidebar.js +10 -2
  67. package/lib/client/components/QaSidebar.js.map +1 -1
  68. package/lib/client/components/QaWidthHandle.js +111 -5
  69. package/lib/client/components/QaWidthHandle.js.map +1 -1
  70. package/lib/client/components/QaWorkspaceBrowser.js +231 -0
  71. package/lib/client/components/QaWorkspaceBrowser.js.map +1 -0
  72. package/lib/client/index.js +122 -53
  73. package/lib/client/index.js.map +1 -1
  74. package/lib/client/kiosk.js +51 -0
  75. package/lib/client/kiosk.js.map +1 -0
  76. package/lib/client/lineage.js +64 -0
  77. package/lib/client/lineage.js.map +1 -1
  78. package/lib/client/markdown/blocks.js +122 -7
  79. package/lib/client/markdown/blocks.js.map +1 -1
  80. package/lib/client/markdown/inline.js +108 -12
  81. package/lib/client/markdown/inline.js.map +1 -1
  82. package/lib/client/markdown/katex-css.js +12 -0
  83. package/lib/client/markdown/katex-css.js.map +1 -0
  84. package/lib/client/markdown/math.js +84 -0
  85. package/lib/client/markdown/math.js.map +1 -0
  86. package/lib/client/markdown/render.js +74 -5
  87. package/lib/client/markdown/render.js.map +1 -1
  88. package/lib/client/settings/card.js +2 -2
  89. package/lib/client/settings/card.js.map +1 -1
  90. package/lib/client/settings/sections/attachments.js +6 -5
  91. package/lib/client/settings/sections/attachments.js.map +1 -1
  92. package/lib/client/settings/sections/notes.js +64 -0
  93. package/lib/client/settings/sections/notes.js.map +1 -0
  94. package/lib/client/settings/sections/sources.js +4 -1
  95. package/lib/client/settings/sections/sources.js.map +1 -1
  96. package/lib/client/settings/sections.js +1 -0
  97. package/lib/client/settings/sections.js.map +1 -1
  98. package/lib/client/settlement.js +1 -1
  99. package/lib/client/settlement.js.map +1 -1
  100. package/lib/client/source-preview.js +3 -0
  101. package/lib/client/source-preview.js.map +1 -1
  102. package/lib/client/styles.js +106 -18
  103. package/lib/client/styles.js.map +1 -1
  104. package/lib/client/types.js.map +1 -1
  105. package/lib/client/user-settings/IntegrationTokensPage.js +150 -0
  106. package/lib/client/user-settings/IntegrationTokensPage.js.map +1 -0
  107. package/lib/client/user-settings/PasswordSettingsPage.js +48 -0
  108. package/lib/client/user-settings/PasswordSettingsPage.js.map +1 -0
  109. package/lib/client/user-settings/SkillCatalog.js +2 -2
  110. package/lib/client/user-settings/SkillCatalog.js.map +1 -1
  111. package/lib/client/user-settings/UserSettingsDialog.js +17 -2
  112. package/lib/client/user-settings/UserSettingsDialog.js.map +1 -1
  113. package/lib/client/user-settings/copy.js +20 -0
  114. package/lib/client/user-settings/copy.js.map +1 -1
  115. package/lib/client.js +31007 -686
  116. package/lib/client.js.map +1 -1
  117. package/lib/config-resolvers/attachments.js +6 -5
  118. package/lib/config-resolvers/attachments.js.map +1 -1
  119. package/lib/config-resolvers/defaults.js +33 -2
  120. package/lib/config-resolvers/defaults.js.map +1 -1
  121. package/lib/config-resolvers/integration.js +94 -0
  122. package/lib/config-resolvers/integration.js.map +1 -0
  123. package/lib/config-resolvers/notes.js +26 -0
  124. package/lib/config-resolvers/notes.js.map +1 -0
  125. package/lib/config-resolvers/sources.js +4 -0
  126. package/lib/config-resolvers/sources.js.map +1 -1
  127. package/lib/config.js +107 -0
  128. package/lib/config.js.map +1 -1
  129. package/lib/index.js +348 -12
  130. package/lib/index.js.map +1 -1
  131. package/lib/integration/answer.js +100 -0
  132. package/lib/integration/answer.js.map +1 -0
  133. package/lib/integration/attachments.js +231 -0
  134. package/lib/integration/attachments.js.map +1 -0
  135. package/lib/integration/contract.js +53 -0
  136. package/lib/integration/contract.js.map +1 -0
  137. package/lib/integration/host-runner.js +243 -0
  138. package/lib/integration/host-runner.js.map +1 -0
  139. package/lib/integration/http.js +538 -0
  140. package/lib/integration/http.js.map +1 -0
  141. package/lib/integration/service.js +331 -0
  142. package/lib/integration/service.js.map +1 -0
  143. package/lib/integration/transcript-reader.js +202 -0
  144. package/lib/integration/transcript-reader.js.map +1 -0
  145. package/lib/integration/transcript.js +148 -0
  146. package/lib/integration/transcript.js.map +1 -0
  147. package/lib/personal-skills/index.js +2 -2
  148. package/lib/personal-skills/index.js.map +1 -1
  149. package/lib/personal-skills/paths.js +14 -8
  150. package/lib/personal-skills/paths.js.map +1 -1
  151. package/lib/personal-skills/provider.js +16 -4
  152. package/lib/personal-skills/provider.js.map +1 -1
  153. package/lib/personal-skills/service.js +240 -30
  154. package/lib/personal-skills/service.js.map +1 -1
  155. package/lib/prompt-notes.js +103 -6
  156. package/lib/prompt-notes.js.map +1 -1
  157. package/lib/provenance/document-preview.js +60 -0
  158. package/lib/provenance/document-preview.js.map +1 -0
  159. package/lib/provenance/file-preview.js +191 -19
  160. package/lib/provenance/file-preview.js.map +1 -1
  161. package/lib/qa-tools/catalog.js +18 -1
  162. package/lib/qa-tools/catalog.js.map +1 -1
  163. package/lib/qa-tools/docs-tools.js +563 -0
  164. package/lib/qa-tools/docs-tools.js.map +1 -0
  165. package/lib/qa-tools/file-delete-gate.js +60 -0
  166. package/lib/qa-tools/file-delete-gate.js.map +1 -0
  167. package/lib/qa-tools/file-delete.js +156 -0
  168. package/lib/qa-tools/file-delete.js.map +1 -0
  169. package/lib/resolve-config.js +6 -0
  170. package/lib/resolve-config.js.map +1 -1
  171. package/lib/secure-session.js +83 -3
  172. package/lib/secure-session.js.map +1 -1
  173. package/lib/shared/documents.js +22 -0
  174. package/lib/shared/documents.js.map +1 -0
  175. package/lib/shared/integration-tokens.js +23 -0
  176. package/lib/shared/integration-tokens.js.map +1 -0
  177. package/lib/typert.host.js +1320 -134
  178. package/lib/typert.remote-client.d.ts +33 -1
  179. package/lib/typert.remote-client.js +1102 -74
  180. package/lib/types/access/service.d.ts +33 -2
  181. package/lib/types/account-remotes.d.ts +30 -1
  182. package/lib/types/accounts/database.d.ts +53 -0
  183. package/lib/types/accounts/errors.d.ts +5 -1
  184. package/lib/types/accounts/service-token.d.ts +70 -0
  185. package/lib/types/accounts/store.d.ts +131 -1
  186. package/lib/types/admin/conversation-log.d.ts +12 -0
  187. package/lib/types/admin/service.d.ts +56 -1
  188. package/lib/types/admin/session-log.d.ts +21 -0
  189. package/lib/types/attachment-rules.d.ts +26 -3
  190. package/lib/types/client/QaAccountsController.d.ts +64 -5
  191. package/lib/types/client/QaSessionController.d.ts +24 -2
  192. package/lib/types/client/admin/pages/SkillFiles.d.ts +17 -0
  193. package/lib/types/client/admin/routes.d.ts +2 -0
  194. package/lib/types/client/admin/shared.d.ts +2 -0
  195. package/lib/types/client/attachments.d.ts +21 -4
  196. package/lib/types/client/base64.d.ts +13 -1
  197. package/lib/types/client/components/QaAgentsDrawer.d.ts +2 -1
  198. package/lib/types/client/components/QaFilesPanel.d.ts +16 -4
  199. package/lib/types/client/components/QaHeader.d.ts +9 -3
  200. package/lib/types/client/components/QaModal.d.ts +4 -3
  201. package/lib/types/client/components/QaWidthHandle.d.ts +48 -2
  202. package/lib/types/client/components/QaWorkspaceBrowser.d.ts +15 -0
  203. package/lib/types/client/index.d.ts +1 -1
  204. package/lib/types/client/kiosk.d.ts +34 -0
  205. package/lib/types/client/lineage.d.ts +42 -0
  206. package/lib/types/client/markdown/blocks.d.ts +14 -1
  207. package/lib/types/client/markdown/inline.d.ts +23 -7
  208. package/lib/types/client/markdown/katex-css.d.ts +11 -0
  209. package/lib/types/client/markdown/math.d.ts +23 -0
  210. package/lib/types/client/markdown/render.d.ts +2 -1
  211. package/lib/types/client/settings/sections/notes.d.ts +12 -0
  212. package/lib/types/client/settings/sections.d.ts +1 -0
  213. package/lib/types/client/settlement.d.ts +4 -1
  214. package/lib/types/client/styles.d.ts +15 -2
  215. package/lib/types/client/types.d.ts +120 -1
  216. package/lib/types/client/user-settings/IntegrationTokensPage.d.ts +21 -0
  217. package/lib/types/client/user-settings/PasswordSettingsPage.d.ts +19 -0
  218. package/lib/types/client/user-settings/UserSettingsDialog.d.ts +11 -2
  219. package/lib/types/client/user-settings/copy.d.ts +10 -1
  220. package/lib/types/config-resolvers/integration.d.ts +47 -0
  221. package/lib/types/config-resolvers/notes.d.ts +10 -0
  222. package/lib/types/config.d.ts +10 -0
  223. package/lib/types/index.d.ts +111 -1
  224. package/lib/types/integration/answer.d.ts +65 -0
  225. package/lib/types/integration/attachments.d.ts +85 -0
  226. package/lib/types/integration/contract.d.ts +196 -0
  227. package/lib/types/integration/host-runner.d.ts +44 -0
  228. package/lib/types/integration/http.d.ts +79 -0
  229. package/lib/types/integration/service.d.ts +120 -0
  230. package/lib/types/integration/transcript-reader.d.ts +100 -0
  231. package/lib/types/integration/transcript.d.ts +59 -0
  232. package/lib/types/personal-skills/index.d.ts +2 -2
  233. package/lib/types/personal-skills/paths.d.ts +15 -3
  234. package/lib/types/personal-skills/provider.d.ts +14 -2
  235. package/lib/types/personal-skills/service.d.ts +89 -14
  236. package/lib/types/prompt-notes.d.ts +37 -0
  237. package/lib/types/provenance/document-preview.d.ts +28 -0
  238. package/lib/types/provenance/file-preview.d.ts +69 -2
  239. package/lib/types/qa-tools/catalog.d.ts +1 -1
  240. package/lib/types/qa-tools/docs-tools.d.ts +160 -0
  241. package/lib/types/qa-tools/file-delete-gate.d.ts +42 -0
  242. package/lib/types/qa-tools/file-delete.d.ts +32 -0
  243. package/lib/types/secure-session.d.ts +52 -1
  244. package/lib/types/shared/documents.d.ts +20 -0
  245. package/lib/types/shared/integration-tokens.d.ts +24 -0
  246. package/lib/types/types.d.ts +263 -3
  247. package/lib/types/ui-mode.d.ts +18 -0
  248. package/lib/ui-mode.js +22 -0
  249. package/lib/ui-mode.js.map +1 -0
  250. package/package.json +12 -10
@@ -0,0 +1,538 @@
1
+ import { isIntegrationDocumentMediaType, isIntegrationTextMediaType, } from "./attachments.js";
2
+ import { QA_INTEGRATION_MAX_TRANSCRIPT_MESSAGES } from "./transcript.js";
3
+ import { QaIntegrationError, } from "./contract.js";
4
+ /**
5
+ * The integration API's HTTP transport.
6
+ *
7
+ * Three exact routes under one configurable base path — the required
8
+ * `POST {base}/ask`, `GET {base}/session` and the optional `GET {base}/health`
9
+ * of the ticket bridge contract — speaking `application/json` and
10
+ * `multipart/form-data`, which is what the bridge sends. Everything below the
11
+ * transport (credentials, scopes, budgets, turns) lives in
12
+ * {@link QaIntegrationService}; this file owns bytes, encodings and status
13
+ * codes and nothing else.
14
+ *
15
+ * Method checking happens inside each handler rather than by registering one
16
+ * route per verb: a `GET /qa/api/ask` must answer 405 with an `Allow` header,
17
+ * and a route that only matched POST would instead fall through to the SPA
18
+ * fallback and answer 200 with an HTML page.
19
+ */
20
+ /** Raster formats the prompt content can carry inline; the rest need uploads. */
21
+ const INLINE_IMAGE_MEDIA_TYPES = Object.freeze([
22
+ "image/png",
23
+ "image/jpeg",
24
+ "image/webp",
25
+ "image/gif",
26
+ ]);
27
+ /** The bridge's own ceiling: five attachments per question. */
28
+ export const QA_INTEGRATION_MAX_FILES = 5;
29
+ /**
30
+ * Register the integration routes on the host web server.
31
+ * @param webServer - the route table owner.
32
+ * @param options - resolved config, the service and the plugin logger.
33
+ * @returns the disposer removing every route this call registered.
34
+ */
35
+ export function registerQaIntegrationRoutes(webServer, options) {
36
+ const base = options.config.integration.basePath;
37
+ const disposers = [
38
+ webServer.register({
39
+ kind: "exact",
40
+ path: `${base}/ask`,
41
+ handler: (request, response) => handleAsk(request, response, options).catch(() => sendRefusal(response, new QaIntegrationError("unavailable", "the request could not be answered"))),
42
+ }),
43
+ webServer.register({
44
+ kind: "exact",
45
+ path: `${base}/session`,
46
+ handler: (request, response) => handleSession(request, response, options).catch(() => sendRefusal(response, new QaIntegrationError("unavailable", "the conversation could not be read"))),
47
+ }),
48
+ webServer.register({
49
+ kind: "exact",
50
+ path: `${base}/health`,
51
+ handler: (request, response) => handleHealth(request, response, options).catch(() => sendRefusal(response, new QaIntegrationError("unavailable", "health could not be answered"))),
52
+ }),
53
+ ];
54
+ return () => {
55
+ for (const dispose of disposers)
56
+ dispose();
57
+ };
58
+ }
59
+ async function handleAsk(request, response, options) {
60
+ if (request.method !== "POST") {
61
+ sendMethodNotAllowed(response, "POST");
62
+ return;
63
+ }
64
+ try {
65
+ const body = await readBody(request, options.config.integration.maxRequestBytes);
66
+ const parsed = parseAskBody(body, contentTypeOf(request), options.config);
67
+ const answer = await options.service.ask(headerOf(request, "authorization"), parsed, clientSignal(response));
68
+ sendJson(response, 200, answerPayload(answer));
69
+ }
70
+ catch (error) {
71
+ sendRefusal(response, error);
72
+ }
73
+ }
74
+ /** The page size a caller gets when it does not ask for one. */
75
+ export const QA_INTEGRATION_DEFAULT_TRANSCRIPT_LIMIT = 50;
76
+ /**
77
+ * Read one conversation back, for the application that owns it.
78
+ *
79
+ * `GET {base}/session?chat_id=…&after=…&limit=…`: the chat id is the required
80
+ * part, `after` is the caller's own cursor (the `last_seq` of its previous
81
+ * read) and `limit` bounds the page. Path parameters were avoided on purpose —
82
+ * one exact route per endpoint is what this table is good at, and a chat id in
83
+ * a query string never has to be unescaped out of a path.
84
+ */
85
+ async function handleSession(request, response, options) {
86
+ if (request.method !== "GET" && request.method !== "HEAD") {
87
+ sendMethodNotAllowed(response, "GET, HEAD");
88
+ return;
89
+ }
90
+ try {
91
+ const query = queryOf(request);
92
+ const chatId = (query.get("chat_id") ?? "").trim();
93
+ if (chatId === "") {
94
+ throw new QaIntegrationError("invalid-request", "chat_id is required");
95
+ }
96
+ const after = integerParameter(query, "after", 0);
97
+ if (after < 0) {
98
+ throw new QaIntegrationError("invalid-request", "after must not be negative");
99
+ }
100
+ // A page size is a preference, not a contract: a caller that asks for more
101
+ // than the ceiling gets the ceiling rather than a refusal, because the
102
+ // window it needs is still in the answer, just shorter.
103
+ const requested = integerParameter(query, "limit", QA_INTEGRATION_DEFAULT_TRANSCRIPT_LIMIT);
104
+ if (requested <= 0) {
105
+ throw new QaIntegrationError("invalid-request", "limit must be positive");
106
+ }
107
+ const transcript = await options.service.session(headerOf(request, "authorization"), {
108
+ chatId,
109
+ after,
110
+ limit: Math.min(requested, QA_INTEGRATION_MAX_TRANSCRIPT_MESSAGES),
111
+ });
112
+ sendJson(response, 200, {
113
+ chat_id: transcript.chatId,
114
+ messages: transcript.messages.map((message) => ({
115
+ seq: message.seq,
116
+ role: message.role,
117
+ text: message.text,
118
+ at: message.at ?? null,
119
+ })),
120
+ last_seq: transcript.lastSeq,
121
+ truncated: transcript.truncated,
122
+ });
123
+ }
124
+ catch (error) {
125
+ sendRefusal(response, error);
126
+ }
127
+ }
128
+ /** The query string of a request, decoded once into a lookup. */
129
+ function queryOf(request) {
130
+ const raw = request.url?.split("?")[1] ?? "";
131
+ const query = new Map();
132
+ for (const pair of raw.split("&")) {
133
+ if (pair === "")
134
+ continue;
135
+ const separator = pair.indexOf("=");
136
+ const key = decodeURIComponent(separator === -1 ? pair : pair.slice(0, separator));
137
+ const value = decodeURIComponent(separator === -1 ? "" : pair.slice(separator + 1));
138
+ if (!query.has(key))
139
+ query.set(key, value);
140
+ }
141
+ return query;
142
+ }
143
+ /**
144
+ * One numeric query parameter, refused rather than coerced when it is not a
145
+ * number: a cursor the caller did not mean is worse than a clear refusal.
146
+ */
147
+ function integerParameter(query, name, fallback) {
148
+ const raw = query.get(name)?.trim() ?? "";
149
+ if (raw === "")
150
+ return fallback;
151
+ if (!/^\d+$/u.test(raw)) {
152
+ throw new QaIntegrationError("invalid-request", `${name} must be a whole number`);
153
+ }
154
+ return Number(raw);
155
+ }
156
+ async function handleHealth(request, response, options) {
157
+ if (request.method !== "GET" && request.method !== "HEAD") {
158
+ sendMethodNotAllowed(response, "GET, HEAD");
159
+ return;
160
+ }
161
+ try {
162
+ const health = await options.service.health(headerOf(request, "authorization"));
163
+ // The bridge reads snake_case here (its own field names), unlike the ask
164
+ // response, which it also defines — the contract is reproduced exactly.
165
+ sendJson(response, 200, {
166
+ ok: health.ok,
167
+ version: health.version,
168
+ models: health.models,
169
+ uptime_s: health.uptimeS,
170
+ });
171
+ }
172
+ catch (error) {
173
+ sendRefusal(response, error);
174
+ }
175
+ }
176
+ /** The `{chat_id, answer, …}` body the bridge publishes from. */
177
+ function answerPayload(answer) {
178
+ return {
179
+ chat_id: answer.chatId,
180
+ answer: answer.answer,
181
+ sources: answer.sources,
182
+ confidence: answer.confidence,
183
+ escalate: answer.escalate,
184
+ reason: answer.reason,
185
+ };
186
+ }
187
+ /**
188
+ * Parse one `POST /ask` body out of whichever encoding carried it.
189
+ *
190
+ * JSON is the primary form. Multipart exists because the bridge sends the
191
+ * ticket's attachments through it, and images ride a prompt inline in this
192
+ * harness — so an image-only multipart request is answered like a JSON one. A
193
+ * non-image attachment has nowhere to go: files reach a prompt as a receipt
194
+ * minted by the browser upload path, which an external caller has no session
195
+ * to mint. That request is refused with 415, which is exactly the signal the
196
+ * bridge's own fallback waits for: it repeats the question without
197
+ * attachments rather than failing.
198
+ *
199
+ * @param body - the raw request body.
200
+ * @param contentType - the request's content type, parameters included.
201
+ * @param config - resolved config, for the attachment ceilings.
202
+ * @returns the normalized request.
203
+ */
204
+ export function parseAskBody(body, contentType, config) {
205
+ const media = (contentType ?? "").split(";")[0]?.trim().toLowerCase() ?? "";
206
+ if (media === "application/json" || media === "") {
207
+ return parseJsonAsk(body);
208
+ }
209
+ if (media === "multipart/form-data") {
210
+ const boundary = boundaryOf(contentType);
211
+ if (boundary === null) {
212
+ throw new QaIntegrationError("invalid-request", "multipart/form-data without a boundary parameter");
213
+ }
214
+ return parseMultipartAsk(parseMultipart(body, boundary), config);
215
+ }
216
+ throw new QaIntegrationError("unsupported-media", `unsupported content type ${media}`);
217
+ }
218
+ function parseJsonAsk(body) {
219
+ let parsed;
220
+ try {
221
+ parsed = JSON.parse(body.toString("utf8"));
222
+ }
223
+ catch {
224
+ throw new QaIntegrationError("invalid-request", "the body is not valid JSON");
225
+ }
226
+ return fromFields(record(parsed), null);
227
+ }
228
+ const MAX_MESSAGE_CHARS = 200_000;
229
+ const MAX_CONTEXT_CHARS = 4_000;
230
+ function parseMultipartAsk(multipart, config) {
231
+ const attachments = [];
232
+ for (const file of multipart.files) {
233
+ const media = file.mediaType.split(";")[0]?.trim().toLowerCase() ?? "";
234
+ if (file.bytes.length > config.integration.maxAttachmentBytes) {
235
+ throw new QaIntegrationError("payload-too-large", `attachment ${file.filename} exceeds the configured limit`);
236
+ }
237
+ if (INLINE_IMAGE_MEDIA_TYPES.includes(media)) {
238
+ // An image is the one attachment the prompt carries as bytes.
239
+ attachments.push(Object.freeze({
240
+ kind: "image",
241
+ mediaType: media,
242
+ data: file.bytes.toString("base64"),
243
+ ...(file.filename === "" ? {} : { name: file.filename }),
244
+ }));
245
+ continue;
246
+ }
247
+ if (!isIntegrationTextMediaType(media) &&
248
+ !isIntegrationDocumentMediaType(media)) {
249
+ // Deliberate 415: it makes the bridge send the question again without
250
+ // attachments, publishing an answer instead of failing the ticket. The
251
+ // accepted families are the caller's own filter (text, PDF, OOXML);
252
+ // archives, executables and media never get here from the bridge, and a
253
+ // caller that sends them gets the fallback rather than a prompt full of
254
+ // bytes the model cannot read.
255
+ throw new QaIntegrationError("unsupported-media", `unsupported attachment type ${media}; repeat the request without attachments`);
256
+ }
257
+ // A document is read on the Host — decoded when its bytes are the content,
258
+ // extracted through the document pipeline otherwise — and joins the prompt
259
+ // as text. Nothing is stored, so the bytes are all this layer keeps.
260
+ attachments.push(Object.freeze({
261
+ kind: "file",
262
+ mediaType: media,
263
+ // A file name has to survive being a file name: a media type carries a
264
+ // slash, which a temporary file on Windows cannot.
265
+ name: file.filename === ""
266
+ ? `attachment.${media.replace("/", ".")}`
267
+ : file.filename,
268
+ bytes: file.bytes,
269
+ }));
270
+ }
271
+ const context = parseContextField(multipart.fields.get("context"));
272
+ return fromFields({
273
+ message: multipart.fields.get("message"),
274
+ version: emptyToNull(multipart.fields.get("version")),
275
+ session_id: emptyToNull(multipart.fields.get("session_id")),
276
+ context: {
277
+ ticket_key: context.ticketKey,
278
+ reporter: context.reporter,
279
+ reporter_name: context.reporterName,
280
+ },
281
+ }, attachments);
282
+ }
283
+ /**
284
+ * Normalize the fields both encodings share into one request, refusing what a
285
+ * turn cannot be opened with.
286
+ * @param fields - the request as an object, however it arrived.
287
+ * @param attachments - inline images, or null for the JSON encoding.
288
+ * @returns the validated request.
289
+ */
290
+ function fromFields(fields, attachments) {
291
+ const message = typeof fields?.message === "string" ? fields.message : "";
292
+ if (message.trim() === "") {
293
+ throw new QaIntegrationError("invalid-request", "message is required");
294
+ }
295
+ if (message.length > MAX_MESSAGE_CHARS) {
296
+ throw new QaIntegrationError("payload-too-large", "message is longer than the accepted maximum");
297
+ }
298
+ const context = fields === undefined ? undefined : record(fields.context);
299
+ return Object.freeze({
300
+ message,
301
+ version: stringOrNull(fields?.version),
302
+ sessionId: stringOrNull(fields?.session_id ?? fields?.sessionId),
303
+ context: context === undefined
304
+ ? EMPTY_CONTEXT
305
+ : Object.freeze({
306
+ ticketKey: stringOrNull(context.ticket_key ?? context.ticketKey),
307
+ reporter: stringOrNull(context.reporter),
308
+ reporterName: stringOrNull(context.reporter_name ?? context.reporterName),
309
+ }),
310
+ attachments: Object.freeze([...(attachments ?? [])]),
311
+ });
312
+ }
313
+ const EMPTY_CONTEXT = Object.freeze({
314
+ ticketKey: null,
315
+ reporter: null,
316
+ reporterName: null,
317
+ });
318
+ /** The `context` field of a multipart form: a JSON string, not an object. */
319
+ function parseContextField(raw) {
320
+ const value = raw === undefined ? "" : raw.trim();
321
+ if (value === "")
322
+ return EMPTY_CONTEXT;
323
+ if (value.length > MAX_CONTEXT_CHARS) {
324
+ throw new QaIntegrationError("invalid-request", "the context field is too long");
325
+ }
326
+ let parsed;
327
+ try {
328
+ parsed = JSON.parse(value);
329
+ }
330
+ catch {
331
+ throw new QaIntegrationError("invalid-request", "the context field is not valid JSON");
332
+ }
333
+ const entry = record(parsed) ?? {};
334
+ return Object.freeze({
335
+ ticketKey: stringOrNull(entry.ticket_key ?? entry.ticketKey),
336
+ reporter: stringOrNull(entry.reporter),
337
+ reporterName: stringOrNull(entry.reporter_name ?? entry.reporterName),
338
+ });
339
+ }
340
+ /**
341
+ * Split a multipart body into its text fields and files.
342
+ *
343
+ * Hand-written and deliberately minimal: one request shape (a flat form of
344
+ * scalar fields and `files` parts), one boundary, no nested multiparts. The
345
+ * body is already bounded by the caller, so no part can grow without limit.
346
+ *
347
+ * @param body - the raw request body.
348
+ * @param boundary - the boundary parameter of the content type.
349
+ * @returns text fields and file parts, in the order they appeared.
350
+ */
351
+ export function parseMultipart(body, boundary) {
352
+ const delimiter = Buffer.from(`--${boundary}`);
353
+ const fields = new Map();
354
+ const files = [];
355
+ let cursor = body.indexOf(delimiter);
356
+ if (cursor === -1) {
357
+ throw new QaIntegrationError("invalid-request", "the multipart body does not contain its boundary");
358
+ }
359
+ while (cursor !== -1) {
360
+ const start = cursor + delimiter.length;
361
+ // A closing delimiter is "--" right after the boundary.
362
+ if (body.subarray(start, start + 2).toString("latin1") === "--")
363
+ break;
364
+ const next = body.indexOf(delimiter, start);
365
+ if (next === -1) {
366
+ throw new QaIntegrationError("invalid-request", "the multipart body is truncated");
367
+ }
368
+ // Each part is "\r\n" headers "\r\n\r\n" content "\r\n".
369
+ const raw = body.subarray(start, next);
370
+ const split = raw.indexOf("\r\n\r\n");
371
+ if (split !== -1) {
372
+ const headers = raw.subarray(0, split).toString("utf8");
373
+ const content = raw.subarray(split + 4);
374
+ const trimmed = content.subarray(0, content.length >= 2 &&
375
+ content[content.length - 2] === 0x0d &&
376
+ content[content.length - 1] === 0x0a
377
+ ? content.length - 2
378
+ : content.length);
379
+ const part = parsePartHeaders(headers);
380
+ if (part !== null) {
381
+ if (part.filename === null) {
382
+ fields.set(part.name, trimmed.toString("utf8"));
383
+ }
384
+ else {
385
+ files.push(Object.freeze({
386
+ filename: part.filename,
387
+ mediaType: part.contentType ?? "application/octet-stream",
388
+ bytes: Buffer.from(trimmed),
389
+ }));
390
+ }
391
+ }
392
+ }
393
+ cursor = next;
394
+ }
395
+ if (files.length > QA_INTEGRATION_MAX_FILES) {
396
+ throw new QaIntegrationError("invalid-request", `at most ${String(QA_INTEGRATION_MAX_FILES)} attachments are accepted`);
397
+ }
398
+ return Object.freeze({ fields, files: Object.freeze(files) });
399
+ }
400
+ function parsePartHeaders(headers) {
401
+ let name = null;
402
+ let filename = null;
403
+ let contentType;
404
+ for (const line of headers.split("\r\n")) {
405
+ const colon = line.indexOf(":");
406
+ if (colon === -1)
407
+ continue;
408
+ const key = line.slice(0, colon).trim().toLowerCase();
409
+ const value = line.slice(colon + 1).trim();
410
+ if (key === "content-disposition") {
411
+ name = parameterOf(value, "name");
412
+ filename = parameterOf(value, "filename");
413
+ }
414
+ else if (key === "content-type") {
415
+ contentType = value;
416
+ }
417
+ }
418
+ if (name === null)
419
+ return null;
420
+ return { name, filename, contentType };
421
+ }
422
+ /** One quoted parameter of a header value, or null when it is absent. */
423
+ function parameterOf(value, key) {
424
+ const match = new RegExp(`${key}="([^"]*)"`, "iu").exec(value);
425
+ return match?.[1] ?? null;
426
+ }
427
+ function boundaryOf(contentType) {
428
+ if (typeof contentType !== "string")
429
+ return null;
430
+ const match = /boundary=(?:"([^"]+)"|([^;\s]+))/iu.exec(contentType);
431
+ const boundary = match?.[1] ?? match?.[2];
432
+ return boundary === undefined || boundary === "" ? null : boundary;
433
+ }
434
+ /**
435
+ * Read the whole request body under a byte ceiling.
436
+ * @param request - the incoming request.
437
+ * @param limit - accepted body size in bytes.
438
+ * @returns the body.
439
+ */
440
+ export async function readBody(request, limit) {
441
+ const declared = Number(headerOf(request, "content-length"));
442
+ if (Number.isFinite(declared) && declared > limit) {
443
+ throw new QaIntegrationError("payload-too-large", "the request body is larger than the configured limit");
444
+ }
445
+ const chunks = [];
446
+ let total = 0;
447
+ for await (const chunk of request) {
448
+ const buffer = Buffer.isBuffer(chunk)
449
+ ? chunk
450
+ : Buffer.from(chunk);
451
+ total += buffer.length;
452
+ if (total > limit) {
453
+ throw new QaIntegrationError("payload-too-large", "the request body is larger than the configured limit");
454
+ }
455
+ chunks.push(buffer);
456
+ }
457
+ return Buffer.concat(chunks);
458
+ }
459
+ function contentTypeOf(request) {
460
+ return headerOf(request, "content-type");
461
+ }
462
+ function headerOf(request, name) {
463
+ const value = request.headers?.[name];
464
+ if (typeof value === "string")
465
+ return value;
466
+ return Array.isArray(value) ? value[0] : undefined;
467
+ }
468
+ /**
469
+ * The caller's own lifetime: a dropped connection stops the turn's wait.
470
+ *
471
+ * Watched on the *response*, not the request. A request's `close` fires as
472
+ * soon as its body has been consumed — which is before the turn even starts —
473
+ * so watching it would abort every request that was read successfully. The
474
+ * response's `close` fires when the exchange is over, and
475
+ * `writableFinished` says which way it ended: a finished response was
476
+ * delivered, an unfinished one was abandoned by the client.
477
+ * @param response - the response being written.
478
+ * @returns a signal aborted only when the client goes away.
479
+ */
480
+ function clientSignal(response) {
481
+ const controller = new AbortController();
482
+ response.once("close", () => {
483
+ if (!response.writableFinished) {
484
+ controller.abort(new Error("the client disconnected"));
485
+ }
486
+ });
487
+ return controller.signal;
488
+ }
489
+ function sendJson(response, status, payload) {
490
+ const body = Buffer.from(JSON.stringify(payload), "utf8");
491
+ response.writeHead(status, {
492
+ "content-type": "application/json; charset=utf-8",
493
+ "content-length": String(body.length),
494
+ "cache-control": "no-store",
495
+ });
496
+ response.end(body);
497
+ }
498
+ /**
499
+ * One refusal, mapped onto its status.
500
+ *
501
+ * An unexpected error is answered as `unavailable` rather than leaking a stack
502
+ * trace: the bridge retries a 5xx, and the deployment's own log holds the
503
+ * detail.
504
+ */
505
+ export function sendRefusal(response, error) {
506
+ const refusal = error instanceof QaIntegrationError
507
+ ? error
508
+ : new QaIntegrationError("unavailable", "the request could not be answered");
509
+ sendJson(response, refusal.status, {
510
+ error: refusal.message,
511
+ code: refusal.reason,
512
+ });
513
+ }
514
+ function sendMethodNotAllowed(response, allow) {
515
+ const body = Buffer.from(JSON.stringify({ error: "method not allowed", code: "invalid-request" }), "utf8");
516
+ response.writeHead(405, {
517
+ "content-type": "application/json; charset=utf-8",
518
+ "content-length": String(body.length),
519
+ allow,
520
+ "cache-control": "no-store",
521
+ });
522
+ response.end(body);
523
+ }
524
+ function record(value) {
525
+ return typeof value === "object" && value !== null && !Array.isArray(value)
526
+ ? value
527
+ : undefined;
528
+ }
529
+ function stringOrNull(value) {
530
+ if (typeof value !== "string")
531
+ return null;
532
+ const trimmed = value.trim();
533
+ return trimmed === "" ? null : trimmed;
534
+ }
535
+ function emptyToNull(value) {
536
+ return value === undefined || value.trim() === "" ? null : value.trim();
537
+ }
538
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/integration/http.ts"],"names":[],"mappings":"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"}