@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
@@ -0,0 +1,102 @@
1
+ function firstLine(value) {
2
+ return value.split(/\r?\n/u, 1)[0]?.trim() ?? "";
3
+ }
4
+ function truncate(value, length = 140) {
5
+ return value.length <= length ? value : `${value.slice(0, length - 3)}...`;
6
+ }
7
+ export function flattenToolOutput(node) {
8
+ const parts = node.content.map((block) => block.type === "text" ? block.text : JSON.stringify(block, null, 2));
9
+ if (parts.length === 0 && node.error !== undefined) {
10
+ parts.push(`${node.error.name}: ${node.error.code}`);
11
+ }
12
+ return parts.join("\n") || null;
13
+ }
14
+ function formatToolInput(argsRaw) {
15
+ if (argsRaw === "")
16
+ return null;
17
+ try {
18
+ return JSON.stringify(JSON.parse(argsRaw), null, 2);
19
+ }
20
+ catch {
21
+ return argsRaw;
22
+ }
23
+ }
24
+ function toolSummary(name, argsRaw) {
25
+ try {
26
+ const parsed = JSON.parse(argsRaw);
27
+ if (typeof parsed === "object" && parsed !== null) {
28
+ const values = parsed;
29
+ for (const key of [
30
+ "description",
31
+ "path",
32
+ "file_path",
33
+ "query",
34
+ "pattern",
35
+ "url",
36
+ "command",
37
+ ]) {
38
+ const value = values[key];
39
+ if (typeof value === "string" && value.trim() !== "") {
40
+ return truncate(firstLine(value));
41
+ }
42
+ }
43
+ const fallback = Object.values(values).find((value) => typeof value === "string" && value.trim() !== "");
44
+ if (fallback !== undefined)
45
+ return truncate(firstLine(fallback));
46
+ }
47
+ }
48
+ catch {
49
+ const raw = firstLine(argsRaw);
50
+ if (raw !== "")
51
+ return truncate(raw);
52
+ }
53
+ return name;
54
+ }
55
+ const TOOL_LABELS = Object.freeze({
56
+ bash: "Bash",
57
+ pwsh: "PowerShell",
58
+ read: "Чтение",
59
+ web_fetch: "Загрузка",
60
+ web_search: "Поиск",
61
+ grep: "Поиск",
62
+ glob: "Поиск",
63
+ write: "Запись",
64
+ edit: "Правка",
65
+ str_replace_editor: "Правка",
66
+ run_code: "Код",
67
+ subagent: "Субагент",
68
+ subagent_fork: "Субагент (форк)",
69
+ send_message: "Сообщение агенту",
70
+ list_agents: "Список агентов",
71
+ interrupt_agent: "Остановка агента",
72
+ });
73
+ /** The durable id a continuable launch reports back ("started subagent <id>"). */
74
+ const SUBAGENT_STARTED = /started subagent ([0-9a-f][0-9a-f-]*)/iu;
75
+ function toolLabel(name) {
76
+ return (TOOL_LABELS[name] ?? name.replaceAll("_", " ")) || "Инструмент";
77
+ }
78
+ export function toolStatus(node) {
79
+ if (node.error?.code === "interrupted")
80
+ return "stopped";
81
+ return node.isError ? "error" : "ok";
82
+ }
83
+ export function workTool(callId, name, argsRaw, status, startedAt, endedAt, output) {
84
+ const launched = name === "subagent" || name === "subagent_fork"
85
+ ? (SUBAGENT_STARTED.exec(output ?? "")?.[1] ??
86
+ SUBAGENT_STARTED.exec(argsRaw)?.[1])
87
+ : undefined;
88
+ return {
89
+ id: `tool:${callId}`,
90
+ kind: "tool",
91
+ name,
92
+ label: toolLabel(name),
93
+ summary: toolSummary(name, argsRaw),
94
+ input: formatToolInput(argsRaw),
95
+ output,
96
+ status,
97
+ ...(launched === undefined ? {} : { subagentId: launched }),
98
+ ...(startedAt === undefined ? {} : { startedAt }),
99
+ ...(endedAt === undefined ? {} : { endedAt }),
100
+ };
101
+ }
102
+ //# sourceMappingURL=tool-presentation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-presentation.js","sourceRoot":"","sources":["../../src/client/tool-presentation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ import { QaSourceCollector } from "../provenance/collector.js";
2
+ import { createDefaultSourceExtractorRegistry } from "../provenance/extractors.js";
3
+ /** Empty Chat slice matching the host's EMPTY_CHAT_SNAPSHOT, without a value import. */
4
+ const EMPTY_LEGACY = Object.freeze({
5
+ nodes: Object.freeze([]),
6
+ turnTimings: new Map(),
7
+ turnEnds: new Map(),
8
+ partial: null,
9
+ runningCalls: Object.freeze([]),
10
+ });
11
+ /** The transcript-bearing Chat slice of one Conversation snapshot (absent before the view activates). */
12
+ export function chatLegacyOf(snapshot) {
13
+ return snapshot?.views.get("chat")?.legacy ?? EMPTY_LEGACY;
14
+ }
15
+ const DEFAULT_SOURCE_EXTRACTORS = createDefaultSourceExtractorRegistry();
16
+ /**
17
+ * Rebuild canonical turn bundles from durable tool-result metadata. Since the
18
+ * metadata is persisted by DSH, this projection is identical on live updates
19
+ * and replay and requires no assistant-authored bibliography.
20
+ */
21
+ export function projectTurnSources(snapshot, sessionId = "unknown", workspaceRoot) {
22
+ const legacy = chatLegacyOf(snapshot);
23
+ const heads = new Map();
24
+ for (const node of legacy.nodes) {
25
+ if (node.kind !== "assistant")
26
+ continue;
27
+ for (const block of node.blocks) {
28
+ if (block.kind !== "tool-call" || block.callId === "")
29
+ continue;
30
+ heads.set(block.callId, {
31
+ turn: node.turn,
32
+ step: node.step,
33
+ name: block.name,
34
+ argsRaw: block.argsRaw,
35
+ });
36
+ }
37
+ }
38
+ const collectors = new Map();
39
+ const collectorFor = (turn) => {
40
+ let collector = collectors.get(turn);
41
+ if (collector === undefined) {
42
+ collector = new QaSourceCollector({
43
+ sessionId,
44
+ turn,
45
+ registry: DEFAULT_SOURCE_EXTRACTORS,
46
+ });
47
+ collectors.set(turn, collector);
48
+ }
49
+ return collector;
50
+ };
51
+ for (const node of legacy.nodes) {
52
+ if (node.kind === "assistant")
53
+ collectorFor(node.turn);
54
+ }
55
+ let nearestTurn;
56
+ let nearestStep;
57
+ for (const node of legacy.nodes) {
58
+ if (node.kind === "assistant") {
59
+ nearestTurn = node.turn;
60
+ nearestStep = node.step;
61
+ continue;
62
+ }
63
+ if (node.kind !== "tool-result" || node.isError)
64
+ continue;
65
+ const head = heads.get(node.callId);
66
+ // A truncated event window can retain a result after its assistant call
67
+ // head. Keep it addressable in the synthetic turn 0 instead of dropping
68
+ // durable evidence altogether.
69
+ const turn = head?.turn ?? nearestTurn ?? 0;
70
+ const name = head?.name ?? node.call?.name ?? node.callId;
71
+ const argsRaw = head?.argsRaw ?? node.call?.argsRaw ?? "";
72
+ collectorFor(turn).observe({
73
+ toolName: name,
74
+ args: argsRaw,
75
+ result: node.content,
76
+ presentation: node.meta,
77
+ origin: {
78
+ sessionId,
79
+ turn,
80
+ ...((head?.step ?? nearestStep) === undefined
81
+ ? {}
82
+ : { step: head?.step ?? nearestStep }),
83
+ toolCallId: node.callId,
84
+ toolName: name,
85
+ role: "parent",
86
+ },
87
+ ...(workspaceRoot === undefined ? {} : { workspaceRoot }),
88
+ });
89
+ }
90
+ return [...collectors.entries()]
91
+ .sort(([left], [right]) => left - right)
92
+ .map(([, collector]) => collector.snapshot());
93
+ }
94
+ /** Visible evidence sources for the latest turn, shared by the drawer/footer. */
95
+ export function projectSources(snapshot, sessionId = "unknown", workspaceRoot) {
96
+ return (projectTurnSources(snapshot, sessionId, workspaceRoot).at(-1)?.sources ?? []);
97
+ }
98
+ //# sourceMappingURL=turn-sources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turn-sources.js","sourceRoot":"","sources":["../../src/client/turn-sources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /** The state projected while no QA chat is bound (route inactive or booting). */
2
+ export const QA_SESSION_IDLE_STATE = Object.freeze({
3
+ phase: "idle",
4
+ sessionId: null,
5
+ messages: Object.freeze([]),
6
+ error: null,
7
+ canSend: false,
8
+ canStop: false,
9
+ chatsRevision: 0,
10
+ sources: Object.freeze([]),
11
+ sourcesComplete: true,
12
+ incompleteSourceOrigins: undefined,
13
+ viewingSubagent: null,
14
+ });
15
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"AAuHA,iFAAiF;AACjF,MAAM,CAAC,MAAM,qBAAqB,GAAmB,MAAM,CAAC,MAAM,CAAC;IACjE,KAAK,EAAE,MAAM;IACb,SAAS,EAAE,IAAI;IACf,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAC3B,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,KAAK;IACd,aAAa,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B,eAAe,EAAE,IAAI;IACrB,uBAAuB,EAAE,SAAS;IAClC,eAAe,EAAE,IAAI;CACtB,CAAC,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { useCallback, useEffect, useRef, useState, } from "react";
2
+ import { revokeObjectUrlIfBlob } from "./session-assets.js";
3
+ /**
4
+ * Per-chat UI state: composer attachments, variant offsets, the rail mark and
5
+ * the drawers. Everything here describes the chat it was made in, so a
6
+ * session change clears it instead of leaking a draft, an image or a drawer
7
+ * from one conversation into the next.
8
+ */
9
+ export function useSessionUiState(sessionId) {
10
+ /** Per group: how many answers back from the newest is shown (0 = newest). */
11
+ const [variantOffsets, setVariantOffsets] = useState({});
12
+ const [activeTurn, setActiveTurn] = useState(null);
13
+ const [agentsOpen, setAgentsOpen] = useState(false);
14
+ const [sourcesOpen, setSourcesOpen] = useState(false);
15
+ const [drawerSources, setDrawerSources] = useState(null);
16
+ const [drawerCompleteness, setDrawerCompleteness] = useState(null);
17
+ const [drawerDetail, setDrawerDetail] = useState(null);
18
+ const [pendingImages, setPendingImagesState] = useState([]);
19
+ /** Mirror of the live drafts: blob URLs to revoke when they leave state. */
20
+ const pendingImagesRef = useRef([]);
21
+ /**
22
+ * The single entry point that changes the draft set: every image that
23
+ * leaves state has its preview blob URL revoked here, whether it was
24
+ * removed by the composer, cleared by a send or dropped on a chat switch.
25
+ */
26
+ const setPendingImages = useCallback((next) => {
27
+ for (const draft of pendingImagesRef.current) {
28
+ if (!next.includes(draft))
29
+ revokeObjectUrlIfBlob(draft.previewUrl);
30
+ }
31
+ pendingImagesRef.current = next;
32
+ setPendingImagesState(next);
33
+ }, []);
34
+ useEffect(() => {
35
+ setVariantOffsets({});
36
+ setActiveTurn(null);
37
+ setAgentsOpen(false);
38
+ setSourcesOpen(false);
39
+ setDrawerSources(null);
40
+ setDrawerCompleteness(null);
41
+ setDrawerDetail(null);
42
+ setPendingImages([]);
43
+ }, [sessionId, setPendingImages]);
44
+ // Whatever is still attached dies with the surface, and its URLs with it.
45
+ useEffect(() => () => {
46
+ for (const draft of pendingImagesRef.current)
47
+ revokeObjectUrlIfBlob(draft.previewUrl);
48
+ }, []);
49
+ return {
50
+ variantOffsets,
51
+ setVariantOffsets,
52
+ activeTurn,
53
+ setActiveTurn,
54
+ agentsOpen,
55
+ setAgentsOpen,
56
+ sourcesOpen,
57
+ setSourcesOpen,
58
+ drawerSources,
59
+ setDrawerSources,
60
+ drawerCompleteness,
61
+ setDrawerCompleteness,
62
+ drawerDetail,
63
+ setDrawerDetail,
64
+ pendingImages,
65
+ setPendingImages,
66
+ };
67
+ }
68
+ //# sourceMappingURL=use-session-ui-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-session-ui-state.js","sourceRoot":"","sources":["../../src/client/use-session-ui-state.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,SAAS,EACT,MAAM,EACN,QAAQ,GAGT,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAiC5D;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAwB;IACxD,8EAA8E;IAC9E,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAClD,EAAE,CACH,CAAC;IACF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAClE,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAEhD,IAAI,CAAC,CAAC;IACR,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAC/C,QAAQ,CAA8B,IAAI,CAAC,CAAC;IAC9C,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAkB,IAAI,CAAC,CAAC;IACxE,MAAM,CAAC,aAAa,EAAE,qBAAqB,CAAC,GAAG,QAAQ,CAErD,EAAE,CAAC,CAAC;IACN,4EAA4E;IAC5E,MAAM,gBAAgB,GAAG,MAAM,CAA0B,EAAE,CAAC,CAAC;IAE7D;;;;OAIG;IACH,MAAM,gBAAgB,GAAG,WAAW,CAAC,CAAC,IAA6B,EAAE,EAAE;QACrE,KAAK,MAAM,KAAK,IAAI,gBAAgB,CAAC,OAAO,EAAE,CAAC;YAC7C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,qBAAqB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACrE,CAAC;QACD,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAC;QAChC,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,SAAS,CAAC,GAAG,EAAE;QACb,iBAAiB,CAAC,EAAE,CAAC,CAAC;QACtB,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,cAAc,CAAC,KAAK,CAAC,CAAC;QACtB,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACvB,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC5B,eAAe,CAAC,IAAI,CAAC,CAAC;QACtB,gBAAgB,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC,EAAE,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAElC,0EAA0E;IAC1E,SAAS,CACP,GAAG,EAAE,CAAC,GAAG,EAAE;QACT,KAAK,MAAM,KAAK,IAAI,gBAAgB,CAAC,OAAO;YAC1C,qBAAqB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5C,CAAC,EACD,EAAE,CACH,CAAC;IAEF,OAAO;QACL,cAAc;QACd,iBAAiB;QACjB,UAAU;QACV,aAAa;QACb,UAAU;QACV,aAAa;QACb,WAAW;QACX,cAAc;QACd,aAAa;QACb,gBAAgB;QAChB,kBAAkB;QAClB,qBAAqB;QACrB,YAAY;QACZ,eAAe;QACf,aAAa;QACb,gBAAgB;KACjB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { useMemo } from "react";
2
+ import { buildTurnRailItems, } from "./components/QaTurnRail.js";
3
+ import { collectVariantGroups, } from "./components/VariantSwitcher.js";
4
+ /**
5
+ * Memoized transcript view model. The controller republishes state with a
6
+ * fresh messages array on every stream frame, but re-renders that keep the
7
+ * transcript unchanged (drawers, the active turn mark, variant offsets) must
8
+ * not re-run the projections — and per-row group lookups go through a map
9
+ * instead of a linear find inside the render loop.
10
+ */
11
+ export function useTranscriptView(messages, variantOffsets) {
12
+ return useMemo(() => {
13
+ const groups = collectVariantGroups(messages);
14
+ const groupByPromptId = new Map();
15
+ const turnToGroup = new Map();
16
+ const selectedTurn = new Map();
17
+ for (const group of groups) {
18
+ groupByPromptId.set(group.groupId, group);
19
+ const offset = variantOffsets[group.groupId] ?? 0;
20
+ const turn = group.turns[Math.max(0, group.turns.length - 1 - offset)] ??
21
+ group.turns.at(-1);
22
+ if (turn !== undefined) {
23
+ selectedTurn.set(group.groupId, turn);
24
+ for (const groupTurn of group.turns)
25
+ turnToGroup.set(groupTurn, group.groupId);
26
+ }
27
+ }
28
+ const visibleMessages = messages.filter((message) => {
29
+ if ((message.role === "assistant" || message.role === "work") &&
30
+ message.turn !== undefined) {
31
+ const groupId = turnToGroup.get(message.turn);
32
+ return (groupId === undefined || selectedTurn.get(groupId) === message.turn);
33
+ }
34
+ return true;
35
+ });
36
+ return {
37
+ visibleMessages,
38
+ groupByPromptId,
39
+ selectedTurn,
40
+ railItems: buildTurnRailItems(visibleMessages),
41
+ };
42
+ }, [messages, variantOffsets]);
43
+ }
44
+ //# sourceMappingURL=use-transcript-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-transcript-view.js","sourceRoot":"","sources":["../../src/client/use-transcript-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,EACL,kBAAkB,GAEnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,oBAAoB,GAErB,MAAM,iCAAiC,CAAC;AAWzC;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAA8B,EAC9B,cAAsC;IAEtC,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,MAAM,MAAM,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAC;QAC1D,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC9C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC/C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC1C,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAClD,MAAM,IAAI,GACR,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;gBACzD,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBACtC,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,KAAK;oBACjC,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QACD,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;YAClD,IACE,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC;gBACzD,OAAO,CAAC,IAAI,KAAK,SAAS,EAC1B,CAAC;gBACD,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC9C,OAAO,CACL,OAAO,KAAK,SAAS,IAAI,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CACpE,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;QACH,OAAO;YACL,eAAe;YACf,eAAe;YACf,YAAY;YACZ,SAAS,EAAE,kBAAkB,CAAC,eAAe,CAAC;SAC/C,CAAC;IACJ,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Resolve with the first snapshot of an observable source that satisfies
3
+ * `predicate`, or reject after `timeoutMs`. This is the DSH-runtime glue the
4
+ * QA surface needs instead of ad-hoc sleeps; the source only has to expose
5
+ * the getSnapshot/subscribe store pair used across the client bundle.
6
+ */
7
+ export function waitFor(source, predicate, timeoutMs) {
8
+ const current = source.getSnapshot();
9
+ if (predicate(current))
10
+ return Promise.resolve(current);
11
+ return new Promise((resolve, reject) => {
12
+ let settled = false;
13
+ const timeout = {};
14
+ let unsubscribe = () => undefined;
15
+ const finish = (value) => {
16
+ if (settled)
17
+ return;
18
+ settled = true;
19
+ if (timeout.id !== undefined)
20
+ clearTimeout(timeout.id);
21
+ unsubscribe();
22
+ resolve(value);
23
+ };
24
+ unsubscribe = source.subscribe(() => {
25
+ const next = source.getSnapshot();
26
+ if (predicate(next))
27
+ finish(next);
28
+ });
29
+ // Tolerate observable implementations that notify synchronously while a
30
+ // subscriber is being installed, and close that subscription afterward.
31
+ if (settled) {
32
+ unsubscribe();
33
+ return;
34
+ }
35
+ const afterSubscribe = source.getSnapshot();
36
+ if (predicate(afterSubscribe)) {
37
+ finish(afterSubscribe);
38
+ return;
39
+ }
40
+ timeout.id = setTimeout(() => {
41
+ if (settled)
42
+ return;
43
+ settled = true;
44
+ unsubscribe();
45
+ reject(new Error("Timed out waiting for the DSH runtime."));
46
+ }, timeoutMs);
47
+ });
48
+ }
49
+ //# sourceMappingURL=wait-for.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait-for.js","sourceRoot":"","sources":["../../src/client/wait-for.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CACrB,MAGC,EACD,SAAgC,EAChC,SAAiB;IAEjB,MAAM,OAAO,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,SAAS,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACxC,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,OAAO,GAA2C,EAAE,CAAC;QAC3D,IAAI,WAAW,GAAe,GAAG,EAAE,CAAC,SAAS,CAAC;QAC9C,MAAM,MAAM,GAAG,CAAC,KAAQ,EAAE,EAAE;YAC1B,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS;gBAAE,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACvD,WAAW,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC,CAAC;QACF,WAAW,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE;YAClC,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;YAClC,IAAI,SAAS,CAAC,IAAI,CAAC;gBAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QACH,wEAAwE;QACxE,wEAAwE;QACxE,IAAI,OAAO,EAAE,CAAC;YACZ,WAAW,EAAE,CAAC;YACd,OAAO;QACT,CAAC;QACD,MAAM,cAAc,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;YAC9B,MAAM,CAAC,cAAc,CAAC,CAAC;YACvB,OAAO;QACT,CAAC;QACD,OAAO,CAAC,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE;YAC3B,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,WAAW,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC,CAAC;QAC9D,CAAC,EAAE,SAAS,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC"}