@yadsh/dsh-qa-surface 0.1.1 → 0.3.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 (192) hide show
  1. package/CHANGELOG.md +151 -0
  2. package/README.md +239 -16
  3. package/SPEC-dsh-qa-surface.md +600 -96
  4. package/capability-policy.json +5 -0
  5. package/compatibility.json +18 -4
  6. package/cordis.patch.yml +11 -0
  7. package/docs/ARCHITECTURE.md +50 -8
  8. package/docs/COMPATIBILITY.md +5 -4
  9. package/docs/CONFIGURATION.md +184 -3
  10. package/docs/SOURCES-MIGRATION.md +28 -0
  11. package/docs/SOURCES-PROVENANCE-AUDIT.md +88 -0
  12. package/docs/SPEC-dsh-qa-surface-accounts.md +219 -0
  13. package/docs/SPEC-dsh-qa-surface-sources-provenance.md +1692 -0
  14. package/lib/accounts/index.js +2 -0
  15. package/lib/accounts/index.js.map +1 -0
  16. package/lib/accounts/store.js +478 -0
  17. package/lib/accounts/store.js.map +1 -0
  18. package/lib/attestation.js +10 -0
  19. package/lib/attestation.js.map +1 -0
  20. package/lib/cli.js +143 -0
  21. package/lib/cli.js.map +1 -0
  22. package/lib/client/QaAccountsController.js +329 -0
  23. package/lib/client/QaAccountsController.js.map +1 -0
  24. package/lib/client/QaConfigController.js +111 -4
  25. package/lib/client/QaConfigController.js.map +1 -1
  26. package/lib/client/QaSessionController.js +621 -163
  27. package/lib/client/QaSessionController.js.map +1 -1
  28. package/lib/client/QaSurface.js +303 -24
  29. package/lib/client/QaSurface.js.map +1 -1
  30. package/lib/client/QaTranscriptAdapter.js +324 -49
  31. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  32. package/lib/client/attestation.js +66 -0
  33. package/lib/client/attestation.js.map +1 -0
  34. package/lib/client/chat-index.js +86 -0
  35. package/lib/client/chat-index.js.map +1 -0
  36. package/lib/client/components/Markdown.js +124 -13
  37. package/lib/client/components/Markdown.js.map +1 -1
  38. package/lib/client/components/QaAgentsDrawer.js +40 -0
  39. package/lib/client/components/QaAgentsDrawer.js.map +1 -0
  40. package/lib/client/components/QaAuthGate.js +40 -0
  41. package/lib/client/components/QaAuthGate.js.map +1 -0
  42. package/lib/client/components/QaChangelog.js +112 -0
  43. package/lib/client/components/QaChangelog.js.map +1 -0
  44. package/lib/client/components/QaComposer.js +132 -15
  45. package/lib/client/components/QaComposer.js.map +1 -1
  46. package/lib/client/components/QaMessage.js +214 -10
  47. package/lib/client/components/QaMessage.js.map +1 -1
  48. package/lib/client/components/QaSidebar.js +167 -0
  49. package/lib/client/components/QaSidebar.js.map +1 -0
  50. package/lib/client/components/QaSourcesDrawer.js +127 -0
  51. package/lib/client/components/QaSourcesDrawer.js.map +1 -0
  52. package/lib/client/components/QaTurnRail.js +281 -0
  53. package/lib/client/components/QaTurnRail.js.map +1 -0
  54. package/lib/client/components/QaWelcomeNotice.js +125 -0
  55. package/lib/client/components/QaWelcomeNotice.js.map +1 -0
  56. package/lib/client/components/QaWidthHandle.js +142 -0
  57. package/lib/client/components/QaWidthHandle.js.map +1 -0
  58. package/lib/client/components/QaWorkGroup.js +135 -0
  59. package/lib/client/components/QaWorkGroup.js.map +1 -0
  60. package/lib/client/components/VariantSwitcher.js +29 -0
  61. package/lib/client/components/VariantSwitcher.js.map +1 -0
  62. package/lib/client/components/format.js +48 -0
  63. package/lib/client/components/format.js.map +1 -0
  64. package/lib/client/components/source-refs.js +78 -0
  65. package/lib/client/components/source-refs.js.map +1 -0
  66. package/lib/client/create-session.js +51 -0
  67. package/lib/client/create-session.js.map +1 -0
  68. package/lib/client/index.js +166 -35
  69. package/lib/client/index.js.map +1 -1
  70. package/lib/client/project-session-state.js +78 -0
  71. package/lib/client/project-session-state.js.map +1 -0
  72. package/lib/client/session-admission.js +38 -0
  73. package/lib/client/session-admission.js.map +1 -0
  74. package/lib/client/session-assets.js +52 -0
  75. package/lib/client/session-assets.js.map +1 -0
  76. package/lib/client/session-sources.js +61 -0
  77. package/lib/client/session-sources.js.map +1 -0
  78. package/lib/client/settlement.js +24 -0
  79. package/lib/client/settlement.js.map +1 -0
  80. package/lib/client/styles.js +450 -43
  81. package/lib/client/styles.js.map +1 -1
  82. package/lib/client/tool-presentation.js +102 -0
  83. package/lib/client/tool-presentation.js.map +1 -0
  84. package/lib/client/turn-sources.js +98 -0
  85. package/lib/client/turn-sources.js.map +1 -0
  86. package/lib/client/types.js +15 -0
  87. package/lib/client/types.js.map +1 -0
  88. package/lib/client/use-session-ui-state.js +68 -0
  89. package/lib/client/use-session-ui-state.js.map +1 -0
  90. package/lib/client/use-transcript-view.js +44 -0
  91. package/lib/client/use-transcript-view.js.map +1 -0
  92. package/lib/client/wait-for.js +49 -0
  93. package/lib/client/wait-for.js.map +1 -0
  94. package/lib/client.js +12551 -918
  95. package/lib/client.js.map +1 -1
  96. package/lib/config.js +226 -58
  97. package/lib/config.js.map +1 -1
  98. package/lib/entry-redirect.js +44 -0
  99. package/lib/entry-redirect.js.map +1 -0
  100. package/lib/host-route.js +25 -1
  101. package/lib/host-route.js.map +1 -1
  102. package/lib/index.js +354 -72
  103. package/lib/index.js.map +1 -1
  104. package/lib/launch-token.js +42 -0
  105. package/lib/launch-token.js.map +1 -0
  106. package/lib/lockdown-policy.js +20 -0
  107. package/lib/lockdown-policy.js.map +1 -0
  108. package/lib/provenance/collector.js +40 -0
  109. package/lib/provenance/collector.js.map +1 -0
  110. package/lib/provenance/connectors.js +147 -0
  111. package/lib/provenance/connectors.js.map +1 -0
  112. package/lib/provenance/dedupe.js +89 -0
  113. package/lib/provenance/dedupe.js.map +1 -0
  114. package/lib/provenance/extractors.js +340 -0
  115. package/lib/provenance/extractors.js.map +1 -0
  116. package/lib/provenance/file-preview.js +39 -0
  117. package/lib/provenance/file-preview.js.map +1 -0
  118. package/lib/provenance/host-store.js +387 -0
  119. package/lib/provenance/host-store.js.map +1 -0
  120. package/lib/provenance/index.js +9 -0
  121. package/lib/provenance/index.js.map +1 -0
  122. package/lib/provenance/normalize.js +128 -0
  123. package/lib/provenance/normalize.js.map +1 -0
  124. package/lib/provenance/reported.js +53 -0
  125. package/lib/provenance/reported.js.map +1 -0
  126. package/lib/provenance/types.js +2 -0
  127. package/lib/provenance/types.js.map +1 -0
  128. package/lib/resolve-config.js +283 -10
  129. package/lib/resolve-config.js.map +1 -1
  130. package/lib/secure-session.js +212 -0
  131. package/lib/secure-session.js.map +1 -0
  132. package/lib/typert.host.d.ts +3 -0
  133. package/lib/typert.host.js +784 -0
  134. package/lib/typert.remote-client.d.ts +40 -0
  135. package/lib/typert.remote-client.js +597 -0
  136. package/lib/types/accounts/index.d.ts +2 -0
  137. package/lib/types/accounts/store.d.ts +121 -0
  138. package/lib/types/attestation.d.ts +17 -0
  139. package/lib/types/cli.d.ts +9 -0
  140. package/lib/types/client/QaAccountsController.d.ts +95 -0
  141. package/lib/types/client/QaConfigController.d.ts +35 -3
  142. package/lib/types/client/QaSessionController.d.ts +146 -20
  143. package/lib/types/client/QaSurface.d.ts +11 -5
  144. package/lib/types/client/QaTranscriptAdapter.d.ts +13 -3
  145. package/lib/types/client/attestation.d.ts +25 -0
  146. package/lib/types/client/chat-index.d.ts +28 -0
  147. package/lib/types/client/components/Markdown.d.ts +17 -3
  148. package/lib/types/client/components/QaAgentsDrawer.d.ts +25 -0
  149. package/lib/types/client/components/QaAuthGate.d.ts +15 -0
  150. package/lib/types/client/components/QaChangelog.d.ts +21 -0
  151. package/lib/types/client/components/QaComposer.d.ts +12 -2
  152. package/lib/types/client/components/QaMessage.d.ts +22 -2
  153. package/lib/types/client/components/QaSidebar.d.ts +69 -0
  154. package/lib/types/client/components/QaSourcesDrawer.d.ts +20 -0
  155. package/lib/types/client/components/QaTurnRail.d.ts +59 -0
  156. package/lib/types/client/components/QaWelcomeNotice.d.ts +27 -0
  157. package/lib/types/client/components/QaWidthHandle.d.ts +36 -0
  158. package/lib/types/client/components/QaWorkGroup.d.ts +19 -0
  159. package/lib/types/client/components/VariantSwitcher.d.ts +19 -0
  160. package/lib/types/client/components/format.d.ts +9 -0
  161. package/lib/types/client/components/source-refs.d.ts +16 -0
  162. package/lib/types/client/create-session.d.ts +16 -0
  163. package/lib/types/client/index.d.ts +2 -5
  164. package/lib/types/client/project-session-state.d.ts +30 -0
  165. package/lib/types/client/session-admission.d.ts +23 -0
  166. package/lib/types/client/session-assets.d.ts +20 -0
  167. package/lib/types/client/session-sources.d.ts +28 -0
  168. package/lib/types/client/settlement.d.ts +6 -0
  169. package/lib/types/client/tool-presentation.d.ts +6 -0
  170. package/lib/types/client/turn-sources.d.ts +14 -0
  171. package/lib/types/client/types.d.ts +93 -0
  172. package/lib/types/client/use-session-ui-state.d.ts +35 -0
  173. package/lib/types/client/use-transcript-view.d.ts +20 -0
  174. package/lib/types/client/wait-for.d.ts +11 -0
  175. package/lib/types/entry-redirect.d.ts +20 -0
  176. package/lib/types/host-route.d.ts +14 -1
  177. package/lib/types/index.d.ts +67 -7
  178. package/lib/types/launch-token.d.ts +21 -0
  179. package/lib/types/lockdown-policy.d.ts +18 -0
  180. package/lib/types/provenance/collector.d.ts +26 -0
  181. package/lib/types/provenance/connectors.d.ts +11 -0
  182. package/lib/types/provenance/dedupe.d.ts +6 -0
  183. package/lib/types/provenance/extractors.d.ts +14 -0
  184. package/lib/types/provenance/file-preview.d.ts +10 -0
  185. package/lib/types/provenance/host-store.d.ts +54 -0
  186. package/lib/types/provenance/index.d.ts +10 -0
  187. package/lib/types/provenance/normalize.d.ts +13 -0
  188. package/lib/types/provenance/reported.d.ts +5 -0
  189. package/lib/types/provenance/types.d.ts +78 -0
  190. package/lib/types/secure-session.d.ts +31 -0
  191. package/lib/types/types.d.ts +304 -1
  192. package/package.json +70 -27
@@ -1,3 +1,40 @@
1
+ import { chatLegacyOf } from "./turn-sources.js";
2
+ import { parseSettlement } from "./settlement.js";
3
+ import { flattenToolOutput, toolStatus, workTool, } from "./tool-presentation.js";
4
+ /**
5
+ * The hidden regeneration prompt. Regenerate sends this as an ordinary
6
+ * prompt — the session has no truncation seam, so a "variant" is a real
7
+ * follow-up turn — and the projection drops it from the visible transcript,
8
+ * leaving the consecutive answer turns to read as variants of one question.
9
+ */
10
+ export const QA_REGENERATE_MARKER = "Перегенерируй свой предыдущий ответ — дай новый вариант, не повторяя предыдущий.";
11
+ /**
12
+ * Durable image references carried by user content. The core ContentBlock
13
+ * vocabulary is not installed client-side, so the shape is matched
14
+ * structurally against the host contract ({type:"image", attachment:{...}}).
15
+ */
16
+ function visibleContentImages(content) {
17
+ const images = [];
18
+ for (const block of content) {
19
+ if (typeof block !== "object" || block === null)
20
+ continue;
21
+ const record = block;
22
+ if (record.type !== "image")
23
+ continue;
24
+ const attachment = record.attachment;
25
+ const attachmentId = attachment?.attachmentId;
26
+ const mediaType = attachment?.mediaType;
27
+ if (typeof attachmentId !== "string" || attachmentId === "")
28
+ continue;
29
+ images.push({
30
+ attachmentId,
31
+ mediaType: (typeof mediaType === "string"
32
+ ? mediaType
33
+ : "image/png"),
34
+ });
35
+ }
36
+ return images;
37
+ }
1
38
  function visibleContentText(content) {
2
39
  return content
3
40
  .flatMap((block) => {
@@ -16,77 +53,315 @@ function visibleAssistantText(blocks) {
16
53
  .map((block) => block.text)
17
54
  .join("");
18
55
  }
19
- /** Project only end-user-safe text from the public DSH conversation snapshot. */
56
+ /**
57
+ * Response timing for the message row, straight from the host-recorded step
58
+ * boundaries. Tokens per second is an estimate — the client never sees a
59
+ * token-count contract, so visible text is measured at the usual ≈4
60
+ * characters per token over the generation window (first token → completed).
61
+ */
62
+ function messageStats(text, timing) {
63
+ if (timing === undefined)
64
+ return undefined;
65
+ const start = timing.stepStartTime;
66
+ const first = timing.firstTokenTime;
67
+ const end = timing.completedTime;
68
+ if (start === null && first === null)
69
+ return undefined;
70
+ const durationMs = start === null
71
+ ? Math.max(0, end - (first ?? end))
72
+ : Math.max(0, end - start);
73
+ const ttftMs = start === null || first === null ? null : Math.max(0, first - start);
74
+ let tokensPerSecond = null;
75
+ if (first !== null && end > first && text.length > 0) {
76
+ tokensPerSecond = Math.round(text.length / 4 / ((end - first) / 1_000));
77
+ }
78
+ return { durationMs, ttftMs, tokensPerSecond };
79
+ }
80
+ function getTurn(turns, turn) {
81
+ let buffer = turns.get(turn);
82
+ if (buffer === undefined) {
83
+ buffer = { turn, text: [], work: [] };
84
+ turns.set(turn, buffer);
85
+ }
86
+ return buffer;
87
+ }
88
+ function collectAssistant(node, turns, toolHeads, showReasoning) {
89
+ const turn = getTurn(turns, node.turn);
90
+ const text = visibleAssistantText(node.blocks);
91
+ if (text !== "") {
92
+ turn.text.push({
93
+ id: `assistant:${node.messageId ?? node.seq}`,
94
+ order: node.seq,
95
+ text,
96
+ status: "committed",
97
+ timestamp: node.time,
98
+ turn: node.turn,
99
+ stats: messageStats(text, node.timing),
100
+ });
101
+ }
102
+ node.blocks.forEach((block, index) => {
103
+ const order = node.seq + index / 1_000;
104
+ if (block.kind === "reasoning" && showReasoning && block.text.trim()) {
105
+ turn.work.push({
106
+ order,
107
+ item: {
108
+ id: `reasoning:${node.messageId ?? node.seq}:${index}`,
109
+ kind: "reasoning",
110
+ text: block.text,
111
+ status: "complete",
112
+ },
113
+ });
114
+ }
115
+ else if (block.kind === "tool-call" && block.callId !== "") {
116
+ toolHeads.set(block.callId, {
117
+ turn: node.turn,
118
+ order,
119
+ name: block.name,
120
+ argsRaw: block.argsRaw,
121
+ time: node.time,
122
+ });
123
+ }
124
+ });
125
+ }
126
+ function collectSettledTools(nodes, turns, toolHeads) {
127
+ const settled = new Set();
128
+ let nearestTurn;
129
+ for (const node of nodes) {
130
+ if (node.kind === "assistant")
131
+ nearestTurn = node.turn;
132
+ // Errored results render as failed rows (toolStatus maps them) so the
133
+ // work view does not silently drop activity; source collection keeps
134
+ // skipping them — a failed tool produced no evidence.
135
+ if (node.kind !== "tool-result")
136
+ continue;
137
+ const head = toolHeads.get(node.callId);
138
+ const turnNumber = head?.turn ?? nearestTurn;
139
+ if (turnNumber === undefined)
140
+ continue;
141
+ const name = head?.name ?? node.call?.name ?? node.callId;
142
+ const argsRaw = head?.argsRaw ?? node.call?.argsRaw ?? "";
143
+ getTurn(turns, turnNumber).work.push({
144
+ order: head?.order ?? node.seq,
145
+ item: workTool(node.callId, name, argsRaw, toolStatus(node), node.callTime ?? head?.time, node.time, flattenToolOutput(node)),
146
+ });
147
+ settled.add(node.callId);
148
+ }
149
+ return settled;
150
+ }
151
+ function collectRunningTool(call, turns, toolHeads) {
152
+ const head = toolHeads.get(call.callId);
153
+ getTurn(turns, call.turn).work.push({
154
+ order: head?.order ?? Number.MAX_SAFE_INTEGER - call.time,
155
+ item: workTool(call.callId, call.name, call.argsRaw, "running", call.time, undefined, null),
156
+ });
157
+ }
158
+ function emitTurn(legacy, running, turn, output) {
159
+ const timing = legacy.turnTimings.get(turn.turn);
160
+ const completed = timing?.endTime !== undefined || legacy.turnEnds.has(turn.turn);
161
+ const sortedText = [...turn.text].sort((left, right) => left.order - right.order);
162
+ const partial = sortedText.find((message) => message.status === "streaming");
163
+ const committed = sortedText.filter((message) => message.status === "committed");
164
+ const hasVisibleActiveWork = running &&
165
+ !completed &&
166
+ turn.work.some(({ item }) => item.status === "running");
167
+ const finalText = partial ?? (hasVisibleActiveWork ? undefined : committed.at(-1));
168
+ const progress = finalText === undefined
169
+ ? committed
170
+ : committed.filter((message) => message !== finalText);
171
+ for (const message of progress) {
172
+ turn.work.push({
173
+ order: message.order,
174
+ item: {
175
+ id: `progress:${message.id}`,
176
+ kind: "progress",
177
+ text: message.text,
178
+ status: "complete",
179
+ },
180
+ });
181
+ }
182
+ if (turn.work.length > 0) {
183
+ const items = [...turn.work]
184
+ .sort((left, right) => left.order - right.order)
185
+ .map(({ item }) => item);
186
+ const workOrder = Math.min(...turn.work.map(({ order }) => order), (finalText?.order ?? Number.MAX_SAFE_INTEGER) - 0.001);
187
+ output.push({
188
+ order: workOrder,
189
+ message: {
190
+ id: `work:${turn.turn}`,
191
+ role: "work",
192
+ turn: turn.turn,
193
+ status: completed || !running ? "complete" : "running",
194
+ ...(timing?.startTime === undefined
195
+ ? {}
196
+ : { startedAt: timing.startTime }),
197
+ ...(timing?.endTime === undefined ? {} : { endedAt: timing.endTime }),
198
+ items,
199
+ },
200
+ });
201
+ }
202
+ else {
203
+ for (const message of progress) {
204
+ output.push({
205
+ order: message.order,
206
+ message: {
207
+ id: message.id,
208
+ role: "assistant",
209
+ text: message.text,
210
+ status: message.status,
211
+ turn: turn.turn,
212
+ ...(message.timestamp === undefined
213
+ ? {}
214
+ : { timestamp: message.timestamp }),
215
+ ...(message.stats === undefined ? {} : { stats: message.stats }),
216
+ },
217
+ });
218
+ }
219
+ }
220
+ if (finalText !== undefined) {
221
+ output.push({
222
+ order: finalText.order,
223
+ message: {
224
+ id: finalText.id,
225
+ role: "assistant",
226
+ text: finalText.text,
227
+ status: finalText.status,
228
+ turn: turn.turn,
229
+ ...(finalText.timestamp === undefined
230
+ ? {}
231
+ : { timestamp: finalText.timestamp }),
232
+ ...(finalText.stats === undefined ? {} : { stats: finalText.stats }),
233
+ },
234
+ });
235
+ }
236
+ }
237
+ /** Project end-user messages plus optional operator-approved work detail. */
20
238
  export function projectTranscript(snapshot, options = {}) {
21
- const messages = [];
22
- for (const node of snapshot.nodes) {
239
+ const legacy = chatLegacyOf(snapshot);
240
+ const running = options.running === true;
241
+ const output = [];
242
+ const turns = new Map();
243
+ const toolHeads = new Map();
244
+ for (const node of legacy.nodes) {
23
245
  if (node.kind === "user" || node.kind === "steering") {
24
246
  const text = visibleContentText(node.content);
25
- if (text !== "") {
26
- messages.push({
247
+ const images = visibleContentImages(node.content);
248
+ if (text === QA_REGENERATE_MARKER)
249
+ continue;
250
+ if (text === "" && images.length === 0)
251
+ continue;
252
+ output.push({
253
+ order: node.seq,
254
+ message: {
27
255
  id: `${node.kind}:${node.seq}`,
28
256
  role: "user",
29
257
  text,
30
258
  status: "committed",
31
259
  timestamp: node.time,
32
- });
33
- }
34
- continue;
260
+ ...(images.length === 0 ? {} : { images }),
261
+ },
262
+ });
35
263
  }
36
- if (node.kind === "assistant") {
37
- const text = visibleAssistantText(node.blocks);
38
- if (text !== "") {
39
- messages.push({
40
- id: `assistant:${node.messageId ?? node.seq}`,
41
- role: "assistant",
42
- text,
43
- status: "committed",
264
+ else if (node.kind === "assistant") {
265
+ collectAssistant(node, turns, toolHeads, options.showReasoning === true);
266
+ }
267
+ else if (node.kind === "context") {
268
+ // Subagent settlement notices (the host injects them when a background
269
+ // child finishes) read as status rows; other context injections stay
270
+ // hidden — they are operator plumbing, not QA-facing content.
271
+ const label = node.provenance.label ?? "";
272
+ if (!label.toLowerCase().startsWith("subagent"))
273
+ continue;
274
+ const text = visibleContentText(node.content);
275
+ if (text.trim() === "")
276
+ continue;
277
+ const notice = parseSettlement(text);
278
+ output.push({
279
+ order: node.seq,
280
+ message: {
281
+ id: `context:${node.seq}`,
282
+ role: "system",
283
+ text: notice === undefined
284
+ ? text.replace(/\s+/gu, " ").trim().slice(0, 280)
285
+ : notice.title,
286
+ status: "info",
44
287
  timestamp: node.time,
45
- });
46
- }
47
- continue;
288
+ ...(notice === undefined ? {} : { notice }),
289
+ },
290
+ });
48
291
  }
49
- if (node.kind === "turn-error") {
50
- messages.push({
51
- id: `turn-error:${node.seq}`,
52
- role: "system",
53
- text: "The assistant could not complete this response.",
54
- status: "error",
55
- timestamp: node.time,
292
+ else if (node.kind === "turn-error") {
293
+ output.push({
294
+ order: node.seq,
295
+ message: {
296
+ id: `turn-error:${node.seq}`,
297
+ role: "system",
298
+ text: "Помощнику не удалось завершить ответ.",
299
+ status: "error",
300
+ timestamp: node.time,
301
+ },
56
302
  });
57
- continue;
58
303
  }
59
- if (node.kind === "turn-max-tokens") {
60
- messages.push({
61
- id: `turn-max-tokens:${node.seq}`,
62
- role: "system",
63
- text: "The response reached its length limit.",
64
- status: "info",
65
- timestamp: node.time,
304
+ else if (node.kind === "turn-max-tokens") {
305
+ output.push({
306
+ order: node.seq,
307
+ message: {
308
+ id: `turn-max-tokens:${node.seq}`,
309
+ role: "system",
310
+ text: "Ответ достиг предельной длины.",
311
+ status: "info",
312
+ timestamp: node.time,
313
+ },
66
314
  });
67
315
  }
68
316
  }
69
- if (snapshot.partial !== null) {
70
- const text = visibleAssistantText(snapshot.partial.blocks);
317
+ if (options.showToolActivity === true) {
318
+ const settled = collectSettledTools(legacy.nodes, turns, toolHeads);
319
+ for (const call of legacy.runningCalls) {
320
+ if (!settled.has(call.callId)) {
321
+ collectRunningTool(call, turns, toolHeads);
322
+ }
323
+ }
324
+ }
325
+ if (legacy.partial !== null) {
326
+ const partialTurn = getTurn(turns, legacy.partial.turn);
327
+ const text = visibleAssistantText(legacy.partial.blocks);
71
328
  if (text !== "") {
72
- messages.push({
73
- id: `assistant:partial:${snapshot.partial.turn}:${snapshot.partial.step}`,
74
- role: "assistant",
329
+ partialTurn.text.push({
330
+ id: `assistant:partial:${legacy.partial.turn}:${legacy.partial.step}`,
331
+ order: Number.MAX_SAFE_INTEGER - 1,
75
332
  text,
76
333
  status: "streaming",
77
334
  });
78
335
  }
79
- }
80
- if (options.showToolActivity === true &&
81
- snapshot.runningCalls.length > 0 &&
82
- snapshot.partial === null) {
83
- messages.push({
84
- id: "tool-activity",
85
- role: "system",
86
- text: "Working…",
87
- status: "info",
336
+ legacy.partial.blocks.forEach((block, index) => {
337
+ if (block.kind === "reasoning" &&
338
+ options.showReasoning === true &&
339
+ block.text.trim()) {
340
+ partialTurn.work.push({
341
+ order: Number.MAX_SAFE_INTEGER - 10 + index / 1_000,
342
+ item: {
343
+ id: `reasoning:partial:${legacy.partial?.turn}:${legacy.partial?.step}:${index}`,
344
+ kind: "reasoning",
345
+ text: block.text,
346
+ status: "running",
347
+ },
348
+ });
349
+ }
350
+ else if (block.kind === "tool-call" &&
351
+ options.showToolActivity === true &&
352
+ block.callId !== "" &&
353
+ !legacy.runningCalls.some((call) => call.callId === block.callId)) {
354
+ partialTurn.work.push({
355
+ order: Number.MAX_SAFE_INTEGER - 9 + index / 1_000,
356
+ item: workTool(block.callId, block.name, block.argsRaw, "running", undefined, undefined, null),
357
+ });
358
+ }
88
359
  });
89
360
  }
90
- return messages;
361
+ for (const turn of turns.values())
362
+ emitTurn(legacy, running, turn, output);
363
+ return output
364
+ .sort((left, right) => left.order - right.order)
365
+ .map(({ message }) => message);
91
366
  }
92
367
  //# sourceMappingURL=QaTranscriptAdapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"QaTranscriptAdapter.js","sourceRoot":"","sources":["../../src/client/QaTranscriptAdapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"QaTranscriptAdapter.js","sourceRoot":"","sources":["../../src/client/QaTranscriptAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /** The `(reason: <code>)` marker the Host folds into attestation wire failures. */
2
+ const ATTESTATION_REASON_MARKER = /\(reason: ([a-z-]+)\)/u;
3
+ /**
4
+ * Browser-side reading of Host policy attestation: one error type the session
5
+ * lifecycle branches on, plus pure diagnostics for the console. The specific
6
+ * mismatch facts stay in the Host logs; a refusal only reveals the coarse
7
+ * reason class and an operator hint.
8
+ */
9
+ export class QaPolicyAttestationError extends Error {
10
+ constructor() {
11
+ super("QA session policy could not be attested.");
12
+ this.name = "QaPolicyAttestationError";
13
+ }
14
+ }
15
+ /**
16
+ * Extract the coarse attestation reason code from a Host wire failure, if the
17
+ * failure carries the marker.
18
+ */
19
+ export function attestationReasonOf(failure) {
20
+ const match = ATTESTATION_REASON_MARKER.exec(failure?.message ?? "");
21
+ const reason = match?.[1];
22
+ return reason === undefined ? null : reason;
23
+ }
24
+ export function attestationHint(reason) {
25
+ if (reason === "unknown-tools") {
26
+ return "A lockdown.toolPolicy name is not mounted in this session's tool catalog — check the deployment agent preset and the tool's server availability.";
27
+ }
28
+ if (reason === "workspace-unavailable") {
29
+ return "The configured session.workspaceId does not match a registered workspace - create the workspace or fix the id (session.cwd is the no-registry alternative).";
30
+ }
31
+ if (reason === "composition-mismatch") {
32
+ return "The session's agent preset, workspace or model no longer matches the deployment QA config.";
33
+ }
34
+ if (reason === "permission-preset") {
35
+ return "The configured permission preset did not resolve to the pinned sandbox/approval policy.";
36
+ }
37
+ if (reason === "adoption-refused") {
38
+ return "This browser tried to adopt a session created outside the current QA policy.";
39
+ }
40
+ if (reason === "session-owned-elsewhere") {
41
+ return "The session belongs to another QA account; the deployment's ownership map refused this browser.";
42
+ }
43
+ if (reason === "auth-required") {
44
+ return "The account token is absent, expired or rotated - sign in again through the QA gate.";
45
+ }
46
+ return "The specific mismatch facts are written to the Host logs.";
47
+ }
48
+ /**
49
+ * Whether a Host proof answers the deployment lockdown config this browser
50
+ * holds. Every field must match; the allow-list is compared as exact JSON so
51
+ * order differences refuse too, mirroring the Host's pinned list.
52
+ */
53
+ export function proofMatchesConfig(proof, lockdown, sessionId) {
54
+ return (proof.sessionId === sessionId &&
55
+ proof.enabled &&
56
+ proof.agentPresetMatches &&
57
+ proof.workspaceMatches &&
58
+ proof.modelMatches &&
59
+ proof.sandboxIsReadOnly &&
60
+ proof.approvalIsNever &&
61
+ proof.permissionPreset === lockdown.permissionPreset &&
62
+ proof.toolPolicyLoaded &&
63
+ JSON.stringify(proof.toolAllowList) ===
64
+ JSON.stringify(lockdown.toolPolicy.allow));
65
+ }
66
+ //# sourceMappingURL=attestation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation.js","sourceRoot":"","sources":["../../src/client/attestation.ts"],"names":[],"mappings":"AAEA,mFAAmF;AACnF,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACjD;QACE,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAKQ;IAER,MAAM,KAAK,GAAG,yBAAyB,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;IACrE,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1B,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAqB;IACnD,IAAI,MAAM,KAAK,eAAe,EAAE,CAAC;QAC/B,OAAO,kJAAkJ,CAAC;IAC5J,CAAC;IACD,IAAI,MAAM,KAAK,uBAAuB,EAAE,CAAC;QACvC,OAAO,6JAA6J,CAAC;IACvK,CAAC;IACD,IAAI,MAAM,KAAK,sBAAsB,EAAE,CAAC;QACtC,OAAO,4FAA4F,CAAC;IACtG,CAAC;IACD,IAAI,MAAM,KAAK,mBAAmB,EAAE,CAAC;QACnC,OAAO,yFAAyF,CAAC;IACnG,CAAC;IACD,IAAI,MAAM,KAAK,kBAAkB,EAAE,CAAC;QAClC,OAAO,8EAA8E,CAAC;IACxF,CAAC;IACD,IAAI,MAAM,KAAK,yBAAyB,EAAE,CAAC;QACzC,OAAO,iGAAiG,CAAC;IAC3G,CAAC;IACD,IAAI,MAAM,KAAK,eAAe,EAAE,CAAC;QAC/B,OAAO,sFAAsF,CAAC;IAChG,CAAC;IACD,OAAO,2DAA2D,CAAC;AACrE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAsB,EACtB,QAA6C,EAC7C,SAAiB;IAEjB,OAAO,CACL,KAAK,CAAC,SAAS,KAAK,SAAS;QAC7B,KAAK,CAAC,OAAO;QACb,KAAK,CAAC,kBAAkB;QACxB,KAAK,CAAC,gBAAgB;QACtB,KAAK,CAAC,YAAY;QAClB,KAAK,CAAC,iBAAiB;QACvB,KAAK,CAAC,eAAe;QACrB,KAAK,CAAC,gBAAgB,KAAK,QAAQ,CAAC,gBAAgB;QACpD,KAAK,CAAC,gBAAgB;QACtB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC;YACjC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAC5C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,86 @@
1
+ /** Cap on the per-browser chat index so localStorage cannot grow unbounded. */
2
+ const MAX_INDEXED_CHATS = 50;
3
+ /**
4
+ * Browser-local chat bookkeeping: a most-recently-used index of chat ids for
5
+ * the sidebar plus the id of the chat this browser reopens on load. Both live
6
+ * under the deployment's storage key and route path, and every access
7
+ * tolerates a denied or broken store — persistence must never prevent a real
8
+ * DSH session.
9
+ */
10
+ export class QaChatIndex {
11
+ storage;
12
+ sessionKey;
13
+ chatKey;
14
+ constructor(storage, prefix) {
15
+ this.storage = storage;
16
+ this.sessionKey = `${prefix}:session`;
17
+ this.chatKey = `${prefix}:chats`;
18
+ }
19
+ /** This browser's indexed chat ids, most recently used first. */
20
+ chatIds() {
21
+ try {
22
+ const raw = this.storage?.getItem(this.chatKey) ?? "[]";
23
+ const parsed = JSON.parse(raw);
24
+ if (!Array.isArray(parsed))
25
+ return [];
26
+ return [
27
+ ...new Set(parsed.filter((id) => typeof id === "string")),
28
+ ].slice(0, MAX_INDEXED_CHATS);
29
+ }
30
+ catch {
31
+ return [];
32
+ }
33
+ }
34
+ /**
35
+ * Add one chat to the index without reordering anything. Display order is
36
+ * the host's `updatedAt`, so merely opening a chat must not move it — the
37
+ * index is membership only.
38
+ */
39
+ addChat(sessionId) {
40
+ try {
41
+ if (this.chatIds().includes(sessionId))
42
+ return;
43
+ const next = [sessionId, ...this.chatIds()].slice(0, MAX_INDEXED_CHATS);
44
+ this.storage?.setItem(this.chatKey, JSON.stringify(next));
45
+ }
46
+ catch {
47
+ // A denied localStorage write must not prevent the bound chat.
48
+ }
49
+ }
50
+ forgetChat(sessionId) {
51
+ try {
52
+ const next = this.chatIds().filter((id) => id !== sessionId);
53
+ this.storage?.setItem(this.chatKey, JSON.stringify(next));
54
+ }
55
+ catch {
56
+ // A denied localStorage removal is harmless; the id is revalidated later.
57
+ }
58
+ }
59
+ /** The persisted chat id this browser reopens on load, or null. */
60
+ activeId() {
61
+ try {
62
+ const value = this.storage?.getItem(this.sessionKey)?.trim() ?? "";
63
+ return value === "" ? null : value;
64
+ }
65
+ catch {
66
+ return null;
67
+ }
68
+ }
69
+ saveActive(sessionId) {
70
+ try {
71
+ this.storage?.setItem(this.sessionKey, sessionId);
72
+ }
73
+ catch {
74
+ // A denied localStorage write must not prevent a real DSH session.
75
+ }
76
+ }
77
+ clearActive() {
78
+ try {
79
+ this.storage?.removeItem(this.sessionKey);
80
+ }
81
+ catch {
82
+ // A denied localStorage removal is harmless; the id is revalidated later.
83
+ }
84
+ }
85
+ }
86
+ //# sourceMappingURL=chat-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-index.js","sourceRoot":"","sources":["../../src/client/chat-index.ts"],"names":[],"mappings":"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"}