@beeuni/sdk 0.2.0 → 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 (231) hide show
  1. package/README.md +19 -10
  2. package/dist/beeuni.esm.min.js +37 -35
  3. package/dist/beeuni.global.js +37 -35
  4. package/dist/browser/cache/idb-sync-cache.js +15 -5
  5. package/dist/browser/session-sync/server-transcript-mirror.d.ts +7 -1
  6. package/dist/browser/session-sync/server-transcript-mirror.js +30 -24
  7. package/dist/browser/session-sync/session-sync-registry.d.ts +3 -1
  8. package/dist/browser/session-sync/session-sync-registry.js +48 -3
  9. package/dist/browser/stores/sync-store/keep-unchanged.d.ts +4 -0
  10. package/dist/browser/stores/sync-store/keep-unchanged.js +34 -0
  11. package/dist/browser/stores/sync-store.d.ts +1 -0
  12. package/dist/browser/stores/sync-store.js +72 -16
  13. package/dist/core/attachments/prompt-attachments.d.ts +4 -0
  14. package/dist/core/attachments/prompt-attachments.js +34 -0
  15. package/dist/core/capture/rules.d.ts +17 -0
  16. package/dist/core/capture/rules.js +27 -0
  17. package/dist/core/client/beeuni.d.ts +92 -5
  18. package/dist/core/client/beeuni.js +2 -0
  19. package/dist/core/client/capture.d.ts +105 -0
  20. package/dist/core/client/capture.js +48 -0
  21. package/dist/core/client/facade-identity.d.ts +1 -0
  22. package/dist/core/client/facade-identity.js +1 -0
  23. package/dist/core/client/project-access-resources.d.ts +3 -1
  24. package/dist/core/client/project-access-resources.js +1 -1
  25. package/dist/core/client/project-operations-admin.d.ts +4 -4
  26. package/dist/core/client/project-operations-review.d.ts +2 -3
  27. package/dist/core/client/project-operations-review.js +1 -0
  28. package/dist/core/client/project-operations-workspace.d.ts +4 -4
  29. package/dist/core/client/project-operations-workspace.js +1 -1
  30. package/dist/core/client/project-operations.d.ts +5 -4
  31. package/dist/core/client/session-context.d.ts +2 -0
  32. package/dist/core/client/session-handle.d.ts +13 -0
  33. package/dist/core/client/session-lifecycle-resources.d.ts +11 -0
  34. package/dist/core/client/session-lifecycle-resources.js +4 -0
  35. package/dist/core/client/session-lifecycle-security.d.ts +2 -0
  36. package/dist/core/client/session-lifecycle-security.js +1 -0
  37. package/dist/core/client/session-readiness.d.ts +2 -0
  38. package/dist/core/client/session-readiness.js +20 -1
  39. package/dist/core/http/api-client.d.ts +1 -0
  40. package/dist/core/http/api-client.js +1 -0
  41. package/dist/core/http/config.d.ts +2 -0
  42. package/dist/core/http/response-error.js +26 -11
  43. package/dist/core/http/transport.js +6 -1
  44. package/dist/core/models/composer-model.d.ts +14 -0
  45. package/dist/core/models/composer-model.js +21 -1
  46. package/dist/core/rest/platform-client/capture.d.ts +363 -0
  47. package/dist/core/rest/platform-client/capture.js +116 -0
  48. package/dist/core/rest/platform-client/index.d.ts +1 -0
  49. package/dist/core/rest/platform-client/index.js +1 -0
  50. package/dist/core/rest/platform-client/lifecycle.js +18 -12
  51. package/dist/core/rest/platform-client/shared.d.ts +5 -0
  52. package/dist/core/rest/platform-client/shared.js +18 -0
  53. package/dist/core/rest/projects-client/account-secret-resources.d.ts +2 -1
  54. package/dist/core/rest/projects-client/accounts.d.ts +34 -0
  55. package/dist/core/rest/projects-client/accounts.js +10 -0
  56. package/dist/core/rest/projects-client/admin-providers.d.ts +0 -61
  57. package/dist/core/rest/projects-client/admin-providers.js +0 -6
  58. package/dist/core/rest/projects-client/agent-config.d.ts +3 -0
  59. package/dist/core/rest/projects-client/apps-fleet.d.ts +5 -1
  60. package/dist/core/rest/projects-client/apps-fleet.js +2 -2
  61. package/dist/core/rest/projects-client/apps.d.ts +3 -0
  62. package/dist/core/rest/projects-client/change-requests.d.ts +2 -0
  63. package/dist/core/rest/projects-client/change-requests.js +2 -0
  64. package/dist/core/rest/projects-client/connectors.d.ts +7 -0
  65. package/dist/core/rest/projects-client/connectors.js +3 -0
  66. package/dist/core/rest/projects-client/files.d.ts +3 -0
  67. package/dist/core/rest/projects-client/files.js +4 -0
  68. package/dist/core/rest/projects-client/gateway.d.ts +5 -0
  69. package/dist/core/rest/projects-client/iam-actions.d.ts +76 -0
  70. package/dist/core/rest/projects-client/iam-actions.js +101 -0
  71. package/dist/core/rest/projects-client/iam.d.ts +1 -0
  72. package/dist/core/rest/projects-client/iam.js +1 -0
  73. package/dist/core/rest/projects-client/notifications.d.ts +1 -1
  74. package/dist/core/rest/projects-client/notifications.js +4 -0
  75. package/dist/core/rest/projects-client/projects.d.ts +3 -2
  76. package/dist/core/rest/projects-client/projects.js +2 -3
  77. package/dist/core/rest/projects-client/review-items.d.ts +2 -0
  78. package/dist/core/rest/projects-client/review-items.js +4 -0
  79. package/dist/core/rest/projects-client/review.d.ts +17 -3
  80. package/dist/core/rest/projects-client/review.js +11 -0
  81. package/dist/core/rest/projects-client/secrets.d.ts +3 -0
  82. package/dist/core/rest/projects-client/session-attachments.js +14 -1
  83. package/dist/core/rest/projects-client/sessions.d.ts +29 -2
  84. package/dist/core/rest/projects-client/sessions.js +34 -4
  85. package/dist/core/runtime/runtime-rest-client.js +1 -1
  86. package/dist/core/runtime/runtime-types.d.ts +1 -0
  87. package/dist/core/session/open-bundle.d.ts +4 -4
  88. package/dist/core/session/open-bundle.js +29 -46
  89. package/dist/core/session/turn-end-watch.d.ts +47 -0
  90. package/dist/core/session/turn-end-watch.js +141 -0
  91. package/dist/core/session-log/index.d.ts +4 -0
  92. package/dist/core/session-log/index.js +3 -0
  93. package/dist/core/session-log/tool-call.d.ts +7 -2
  94. package/dist/core/session-log/tool-call.js +25 -6
  95. package/dist/core/session-log/turns/blocks.d.ts +60 -0
  96. package/dist/core/session-log/turns/blocks.js +124 -0
  97. package/dist/core/session-log/turns/history.d.ts +32 -0
  98. package/dist/core/session-log/turns/history.js +99 -0
  99. package/dist/core/session-log/turns/index.d.ts +4 -0
  100. package/dist/core/session-log/turns/index.js +4 -0
  101. package/dist/core/session-log/turns/metrics.d.ts +21 -0
  102. package/dist/core/session-log/turns/metrics.js +29 -0
  103. package/dist/core/session-log/turns/turn.d.ts +55 -0
  104. package/dist/core/session-log/turns/turn.js +279 -0
  105. package/dist/core/session-log/turns/v1-parts.d.ts +8 -0
  106. package/dist/core/session-log/turns/v1-parts.js +43 -0
  107. package/dist/core/session-log/v1-view.d.ts +5 -2
  108. package/dist/core/session-log/v1-view.js +86 -22
  109. package/dist/core/session-log/v1.js +10 -3
  110. package/dist/core/session-sync/saved-transcript.d.ts +15 -1
  111. package/dist/core/session-sync/saved-transcript.js +55 -0
  112. package/dist/core/session-sync/session-sync-controller.js +3 -0
  113. package/dist/core/stream/event-stream.js +3 -3
  114. package/dist/core/turns/classify.js +4 -2
  115. package/dist/core/turns/edit-blocks.d.ts +1 -0
  116. package/dist/core/turns/edit-blocks.js +15 -0
  117. package/dist/core/turns/segments/burst-summary.d.ts +1 -0
  118. package/dist/core/turns/segments/burst-summary.js +24 -0
  119. package/dist/core/turns/segments/group-steps.d.ts +4 -3
  120. package/dist/core/turns/segments/group-steps.js +9 -6
  121. package/dist/core/turns/segments/narration.d.ts +5 -4
  122. package/dist/core/turns/segments/narration.js +12 -3
  123. package/dist/core/turns/segments/session-activity-groups.d.ts +2 -1
  124. package/dist/core/turns/segments/session-activity-groups.js +3 -1
  125. package/dist/core/turns/segments/step-label.d.ts +2 -1
  126. package/dist/core/turns/segments/step-label.js +3 -1
  127. package/dist/core/turns/segments/working-turn.d.ts +4 -2
  128. package/dist/core/turns/segments/working-turn.js +9 -8
  129. package/dist/core/turns/tool-kind.d.ts +1 -1
  130. package/dist/core/turns/tool-kind.js +3 -2
  131. package/dist/core/turns/tool-registry.js +1 -0
  132. package/dist/core/turns/tools/tool-meta.d.ts +1 -1
  133. package/dist/core/turns/tools/tool-meta.js +3 -2
  134. package/dist/core/turns/view-model.js +1 -13
  135. package/dist/genui/catalog.d.ts +28 -0
  136. package/dist/genui/catalog.js +396 -0
  137. package/dist/genui/expansion.d.ts +3 -0
  138. package/dist/genui/expansion.js +295 -0
  139. package/dist/genui/fence-entry.d.ts +2 -0
  140. package/dist/genui/fence-entry.js +1 -0
  141. package/dist/genui/fence.d.ts +21 -0
  142. package/dist/genui/fence.js +138 -0
  143. package/dist/genui/index.d.ts +6 -0
  144. package/dist/genui/index.js +6 -0
  145. package/dist/genui/markdown.d.ts +12 -0
  146. package/dist/genui/markdown.js +104 -0
  147. package/dist/genui/parse.d.ts +6 -0
  148. package/dist/genui/parse.js +75 -0
  149. package/dist/genui/prompt.d.ts +2 -0
  150. package/dist/genui/prompt.js +206 -0
  151. package/dist/genui/react/default-components.d.ts +2 -0
  152. package/dist/genui/react/default-components.js +72 -0
  153. package/dist/genui/react/default-components.test.d.ts +1 -0
  154. package/dist/genui/react/default-components.test.js +94 -0
  155. package/dist/genui/react/genui-block-disabled.test.d.ts +1 -0
  156. package/dist/genui/react/genui-block-disabled.test.js +50 -0
  157. package/dist/genui/react/genui-block.d.ts +28 -0
  158. package/dist/genui/react/genui-block.js +91 -0
  159. package/dist/genui/react/genui-block.test.d.ts +1 -0
  160. package/dist/genui/react/genui-block.test.js +205 -0
  161. package/dist/genui/react/index.d.ts +2 -0
  162. package/dist/genui/react/index.js +2 -0
  163. package/dist/genui/share.d.ts +5 -0
  164. package/dist/genui/share.js +30 -0
  165. package/dist/genui/test-fixtures.d.ts +2 -0
  166. package/dist/genui/test-fixtures.js +16 -0
  167. package/dist/genui/types.d.ts +29 -0
  168. package/dist/genui/types.js +1 -0
  169. package/dist/genui/urls.d.ts +1 -0
  170. package/dist/genui/urls.js +18 -0
  171. package/dist/genui/validate.d.ts +9 -0
  172. package/dist/genui/validate.js +116 -0
  173. package/dist/index.d.ts +2 -2
  174. package/dist/index.js +2 -2
  175. package/dist/internal/connector-catalog.d.ts +1 -0
  176. package/dist/platform/ui.d.ts +8 -2
  177. package/dist/platform/ui.js +19 -4
  178. package/dist/react/chat/use-chat-turns.d.ts +1 -1
  179. package/dist/react/human-presence.d.ts +9 -0
  180. package/dist/react/human-presence.js +12 -0
  181. package/dist/react/index.d.ts +4 -0
  182. package/dist/react/index.js +4 -0
  183. package/dist/react/opencode.d.ts +1 -1
  184. package/dist/react/opencode.js +1 -1
  185. package/dist/react/query-contracts.d.ts +6 -0
  186. package/dist/react/query-contracts.js +6 -0
  187. package/dist/react/query-keys.d.ts +17 -1
  188. package/dist/react/query-keys.js +24 -1
  189. package/dist/react/reset-identity-state.js +2 -0
  190. package/dist/react/session-cache-write.d.ts +1 -0
  191. package/dist/react/session-cache-write.js +20 -0
  192. package/dist/react/session-transcript-subscription.js +1 -1
  193. package/dist/react/sign-in-with-beeuni.d.ts +5 -5
  194. package/dist/react/turn-end-handoff.d.ts +13 -0
  195. package/dist/react/turn-end-handoff.js +101 -0
  196. package/dist/react/use-admin-providers.d.ts +0 -3
  197. package/dist/react/use-admin-providers.js +1 -11
  198. package/dist/react/use-capture.d.ts +47 -0
  199. package/dist/react/use-capture.js +173 -0
  200. package/dist/react/use-feature-flag.js +1 -0
  201. package/dist/react/use-opencode-events/handle-interaction-event.js +8 -3
  202. package/dist/react/use-opencode-events/handle-session-event.js +13 -8
  203. package/dist/react/use-opencode-events/handler-context.d.ts +1 -0
  204. package/dist/react/use-opencode-events/helpers.d.ts +1 -0
  205. package/dist/react/use-opencode-events/helpers.js +11 -1
  206. package/dist/react/use-opencode-local.d.ts +5 -1
  207. package/dist/react/use-opencode-local.js +15 -2
  208. package/dist/react/use-opencode-sessions/commands.d.ts +11 -1
  209. package/dist/react/use-opencode-sessions/commands.js +21 -1
  210. package/dist/react/use-opencode-sessions/permissions.js +28 -1
  211. package/dist/react/use-project-sessions.d.ts +1 -1
  212. package/dist/react/use-project-sessions.js +6 -5
  213. package/dist/react/use-prompt-attachments.js +1 -0
  214. package/dist/react/use-review-summary.d.ts +13 -0
  215. package/dist/react/use-review-summary.js +32 -0
  216. package/dist/react/use-runtime-reconnect.js +2 -2
  217. package/dist/react/use-session-list-state.d.ts +6 -0
  218. package/dist/react/use-session-list-state.js +33 -0
  219. package/dist/react/use-session-log.d.ts +3 -2
  220. package/dist/react/use-session-log.js +26 -17
  221. package/dist/react/use-session-messages.d.ts +2 -1
  222. package/dist/react/use-session-messages.js +15 -14
  223. package/dist/react/use-session-stream.js +12 -1
  224. package/dist/react/use-session-sync.d.ts +2 -2
  225. package/dist/react/use-session-sync.js +10 -8
  226. package/dist/react/use-session-transcript-history.js +2 -12
  227. package/dist/react/use-session-working.d.ts +2 -0
  228. package/dist/react/use-session-working.js +10 -0
  229. package/dist/react/use-session.d.ts +6 -0
  230. package/dist/react/use-session.js +87 -7
  231. package/package.json +49 -3
@@ -0,0 +1,55 @@
1
+ import type { SessionPrompt } from '../../rest/projects-client/sessions.js';
2
+ import { type GatewayErrorDetails } from '../../turns/errors.js';
3
+ import type { ModelPricingLookup, TurnCostInfo } from '../../turns/types.js';
4
+ import { type AttachmentBlock, type CompactionBlock, type SessionLogBlock, type SessionLogMessage, type SessionLogThread, type TextBlock, type ToolCallBlock } from '../types.js';
5
+ export type SessionLogTurnStatus = 'pending' | SessionLogMessage['status'];
6
+ export type SessionLogCallStatus = ToolCallBlock['status'] | 'interrupted';
7
+ export interface SessionLogTurnError {
8
+ code: string;
9
+ message: string;
10
+ details?: GatewayErrorDetails;
11
+ raw?: string;
12
+ }
13
+ export interface SessionLogCompaction {
14
+ block: CompactionBlock | null;
15
+ hasContent: boolean;
16
+ inFlight: boolean;
17
+ }
18
+ export interface SessionLogContinuation {
19
+ marker: string;
20
+ prompt: string | null;
21
+ }
22
+ export interface SessionLogTurn {
23
+ id: string;
24
+ user: SessionLogMessage;
25
+ assistant: SessionLogMessage[];
26
+ partial: boolean;
27
+ continues: SessionLogContinuation | null;
28
+ blocks: SessionLogBlock[];
29
+ status: SessionLogTurnStatus;
30
+ error: SessionLogTurnError | null;
31
+ cost: TurnCostInfo | null;
32
+ compaction: SessionLogCompaction | null;
33
+ threads: string[];
34
+ plan: boolean;
35
+ shell: ToolCallBlock | null;
36
+ response: TextBlock | null;
37
+ attachments: AttachmentBlock[];
38
+ live: boolean;
39
+ queued: boolean;
40
+ retrying: boolean;
41
+ }
42
+ export interface SessionLogTurnsOptions {
43
+ busy?: boolean;
44
+ liveMessageId?: string | null;
45
+ held?: readonly string[];
46
+ threads?: ReadonlyArray<Pick<SessionLogThread, 'thread_id' | 'spawned_by'>>;
47
+ pricing?: ModelPricingLookup;
48
+ hideOutOfContext?: boolean;
49
+ }
50
+ export declare const isClosedByRule: (b: ToolCallBlock) => boolean;
51
+ export declare function sessionLogCallStatus(call: ToolCallBlock, live: boolean): SessionLogCallStatus;
52
+ export declare function sessionLogPromptMessage(prompt: SessionPrompt, threadId: string): SessionLogMessage;
53
+ export declare function usageCostOf(replies: SessionLogMessage[], lookup?: ModelPricingLookup): TurnCostInfo | null;
54
+ export declare function sessionLogRetrying(thread: Pick<SessionLogThread, 'messages'>): boolean;
55
+ export declare function sessionLogTurns(source: SessionLogThread, options?: SessionLogTurnsOptions): SessionLogTurn[];
@@ -0,0 +1,279 @@
1
+ import { extractGatewayErrorDetails, rawErrorText, unwrapError } from '../../turns/errors.js';
2
+ import { hasRetryingAssistantTurn } from '../../turns/open-turn.js';
3
+ import { getChildSessionId, shouldShowToolPart } from '../../turns/parts.js';
4
+ import { resolveWorkingTurn } from '../../turns/segments/working-turn.js';
5
+ import { getTurnTokens } from '../../turns/state.js';
6
+ import { toolKind } from '../../turns/tool-kind.js';
7
+ import { SESSION_LOG_MINOR, SESSION_LOG_SCHEMA, } from '../types.js';
8
+ import { isV1Thread } from '../v1-view.js';
9
+ import { messageOfBlock, v1RowsOf } from './v1-parts.js';
10
+ const V1_IMPORT = 'beeuni-v1-import';
11
+ function getTurnCost(parts, _lookup) {
12
+ const tokens = getTurnTokens(parts);
13
+ return tokens ? { cost: null, tokens } : undefined;
14
+ }
15
+ const V = { schema: SESSION_LOG_SCHEMA, v: SESSION_LOG_MINOR };
16
+ function last(list, test) {
17
+ for (let i = list.length - 1; i >= 0; i--)
18
+ if (test(list[i]))
19
+ return list[i];
20
+ return undefined;
21
+ }
22
+ const isCall = (b) => b.type === 'tool_call';
23
+ const isOpen = (b) => b.status === 'pending' || b.status === 'running';
24
+ export const isClosedByRule = (b) => b.status === 'error' && (b.result?.synthetic === true || b.result?.error?.code === 'interrupted');
25
+ export function sessionLogCallStatus(call, live) {
26
+ const closed = isClosedByRule(call);
27
+ if (!isOpen(call) && !closed)
28
+ return call.status;
29
+ if (!live)
30
+ return 'interrupted';
31
+ return call.status === 'running' || (closed && call.started_at) ? 'running' : 'pending';
32
+ }
33
+ const prompts = new WeakMap();
34
+ export function sessionLogPromptMessage(prompt, threadId) {
35
+ const cached = prompts.get(prompt);
36
+ if (cached)
37
+ return cached;
38
+ const ms = typeof prompt.client_sent_at_ms === 'number' ? prompt.client_sent_at_ms : Date.parse(prompt.created_at);
39
+ const message = {
40
+ ...V, message_id: prompt.message_id || `queued-${prompt.prompt_id}`, thread_id: threadId, seq: Number.MAX_SAFE_INTEGER, role: 'user', kind: 'turn',
41
+ status: 'complete', in_context: true, origin: 'prompt', model: null, usage: null, finish: null, error: null,
42
+ created_at: Number.isFinite(ms) ? new Date(ms).toISOString() : '', completed_at: null,
43
+ producer: { harness: 'beeuni-inbox', harness_version: '', adapter_version: '1' },
44
+ blocks: [{ type: 'text', id: `syn-${prompt.prompt_id}`, text: prompt.full_text ?? prompt.text }],
45
+ };
46
+ prompts.set(prompt, message);
47
+ return message;
48
+ }
49
+ const standIns = new WeakMap();
50
+ function standInFor(reply) {
51
+ let m = standIns.get(reply);
52
+ if (!m) {
53
+ m = {
54
+ ...V, message_id: reply.reply_to, thread_id: reply.thread_id, seq: reply.seq, role: 'user', kind: 'turn', status: 'complete', in_context: true,
55
+ model: null, usage: null, finish: null, error: null, created_at: reply.created_at, completed_at: null, producer: reply.producer, blocks: [],
56
+ };
57
+ standIns.set(reply, m);
58
+ }
59
+ return m;
60
+ }
61
+ const continuations = new WeakMap();
62
+ function continuationOf(marker) {
63
+ let m = continuations.get(marker);
64
+ if (!m) {
65
+ m = {
66
+ ...V, message_id: `${marker.message_id}:continued`, thread_id: marker.thread_id, seq: marker.seq, role: 'user', kind: 'turn', status: 'complete', in_context: true,
67
+ model: null, usage: null, finish: null, error: null, created_at: marker.created_at, completed_at: null, producer: marker.producer, blocks: [],
68
+ };
69
+ continuations.set(marker, m);
70
+ }
71
+ return m;
72
+ }
73
+ const isEmptyShell = (m) => !m.error && m.blocks.length === 0 && !(m.usage && (m.usage.input || m.usage.output || m.usage.reasoning));
74
+ function drafts(messages, held) {
75
+ const turns = [];
76
+ const byId = new Map();
77
+ for (const m of messages) {
78
+ if (m.role !== 'user' || m.kind === 'context' || byId.has(m.message_id))
79
+ continue;
80
+ const d = { user: m, assistant: [], partial: false };
81
+ byId.set(m.message_id, d);
82
+ turns.push(d);
83
+ }
84
+ const partials = [];
85
+ const leading = [];
86
+ const order = new Map();
87
+ const continued = new Map();
88
+ let last = null;
89
+ let compaction = null;
90
+ for (const m of messages) {
91
+ if (m.role === 'user') {
92
+ const d = byId.get(m.message_id);
93
+ if (d && !held.has(m.message_id)) {
94
+ last = d;
95
+ if (!order.has(d))
96
+ order.set(d, order.size);
97
+ if (d.user.kind === 'compaction')
98
+ compaction = d;
99
+ }
100
+ continue;
101
+ }
102
+ if (m.role !== 'assistant' || isEmptyShell(m))
103
+ continue;
104
+ const named = m.reply_to ? byId.get(m.reply_to) : undefined;
105
+ let home = named ?? last;
106
+ if (compaction && home && (home === compaction || (order.get(home) ?? Infinity) < order.get(compaction))) {
107
+ let next = continued.get(compaction);
108
+ if (!next) {
109
+ next = { user: continuationOf(compaction.user), assistant: [], partial: true, continues: { marker: compaction.user.message_id, prompt: home === compaction ? null : home.user.message_id } };
110
+ continued.set(compaction, next);
111
+ }
112
+ home = next;
113
+ }
114
+ if (home) {
115
+ home.assistant.push(m);
116
+ continue;
117
+ }
118
+ if (!m.reply_to) {
119
+ leading.push(m);
120
+ continue;
121
+ }
122
+ const current = partials[partials.length - 1];
123
+ if (current && current.user.message_id === m.reply_to)
124
+ current.assistant.push(m);
125
+ else
126
+ partials.push({ user: standInFor(m), assistant: [m], partial: true });
127
+ }
128
+ if (leading.length) {
129
+ const first = turns[0] ?? partials[0];
130
+ if (first)
131
+ first.assistant.unshift(...leading);
132
+ else
133
+ turns.push({ user: leading[0], assistant: leading.slice(1), partial: false });
134
+ }
135
+ const shown = turns.filter((t) => !held.has(t.user.message_id)).flatMap((t) => {
136
+ const next = continued.get(t);
137
+ return next ? [t, next] : [t];
138
+ });
139
+ return [...partials, ...shown, ...[...held].flatMap((id) => byId.get(id) ?? [])];
140
+ }
141
+ function continuedHint(list, hint) {
142
+ if (!hint)
143
+ return hint;
144
+ let out = hint;
145
+ for (const d of list) {
146
+ const c = d.continues;
147
+ if (c && (out === c.marker || out === c.prompt || hint === c.prompt))
148
+ out = d.user.message_id;
149
+ }
150
+ return out;
151
+ }
152
+ function errorOf(d) {
153
+ const sources = d.user.kind === 'compaction' ? [d.user, ...d.assistant] : d.assistant;
154
+ const m = sources.find((x) => x.error);
155
+ if (!m?.error)
156
+ return null;
157
+ const error = v1RowsOf(m)[0]?.info?.error ?? m.error.message;
158
+ const details = extractGatewayErrorDetails(error);
159
+ const raw = rawErrorText(error);
160
+ return { code: m.error.code, message: details?.message || unwrapError(error), ...(details && { details }), ...(raw !== undefined && { raw }) };
161
+ }
162
+ function costOf(replies, exact, lookup) {
163
+ if (replies.length && replies.every(exact)) {
164
+ return getTurnCost(replies.flatMap((m) => v1RowsOf(m).flatMap((row) => row.parts.map((part) => ({ part, message: row })))), lookup) ?? null;
165
+ }
166
+ return usageCostOf(replies, lookup);
167
+ }
168
+ export function usageCostOf(replies, lookup) {
169
+ const parts = replies.flatMap((m) => {
170
+ const u = m.usage;
171
+ if (!u)
172
+ return [];
173
+ const part = { type: 'step-finish', cost: u.cost ?? 0, tokens: { input: u.input, output: u.output, reasoning: u.reasoning ?? 0, cache: { read: u.cache_read, write: u.cache_write } } };
174
+ return [{ part, message: { info: { id: m.message_id, role: 'assistant', providerID: m.model?.provider, modelID: m.model?.model }, parts: [part] } }];
175
+ });
176
+ return getTurnCost(parts, lookup) ?? null;
177
+ }
178
+ function compactionOf(user) {
179
+ if (user.kind !== 'compaction')
180
+ return null;
181
+ const block = user.blocks.find((b) => b.type === 'compaction') ?? null;
182
+ return { block, hasContent: !!block?.summary?.trim(), inFlight: user.status === 'streaming' };
183
+ }
184
+ function shellOf(d) {
185
+ const prompt = d.user.blocks;
186
+ if (!prompt.length || !prompt.every((b) => b.type === 'text' && b.synthetic))
187
+ return null;
188
+ const only = d.assistant.length === 1 && d.assistant[0].blocks.length === 1 ? d.assistant[0].blocks[0] : null;
189
+ return only && isCall(only) && only.name === 'bash' ? only : null;
190
+ }
191
+ function threadsOf(d, blocks, heads, known) {
192
+ if (!heads.length)
193
+ return [];
194
+ const replies = new Set(d.assistant.map((m) => m.message_id));
195
+ const out = new Set();
196
+ for (const h of heads)
197
+ if (h.spawned_by && replies.has(h.spawned_by.message_id))
198
+ out.add(h.thread_id);
199
+ for (const b of blocks) {
200
+ const id = b.type === 'subtask' ? b.thread_id : isCall(b) ? getChildSessionId(b) : undefined;
201
+ if (id && known.has(id))
202
+ out.add(id);
203
+ }
204
+ return [...out];
205
+ }
206
+ const writesPlan = (d) => d.assistant.some((m) => m.blocks.some((b) => isCall(b) && toolKind(b.name) === 'todowrite' && shouldShowToolPart(b)));
207
+ const cache = new WeakMap();
208
+ const NONE = [];
209
+ export function sessionLogRetrying(thread) {
210
+ const reply = last(thread.messages, (m) => m.role === 'assistant');
211
+ return !!reply && hasRetryingAssistantTurn(v1RowsOf(reply));
212
+ }
213
+ const inContext = new WeakMap();
214
+ function inContextOnly(thread) {
215
+ let out = inContext.get(thread);
216
+ if (!out) {
217
+ const messages = thread.messages.filter((m) => m.in_context || m.status === 'streaming');
218
+ out = messages.length === thread.messages.length ? thread : { ...thread, messages };
219
+ inContext.set(thread, out);
220
+ }
221
+ return out;
222
+ }
223
+ export function sessionLogTurns(source, options = {}) {
224
+ const thread = options.hideOutOfContext ? inContextOnly(source) : source;
225
+ const held = new Set(options.held ?? NONE);
226
+ const list = drafts(thread.messages, held);
227
+ const lastReply = last(thread.messages, (m) => m.role === 'assistant');
228
+ const retrying = sessionLogRetrying(thread);
229
+ const working = resolveWorkingTurn({
230
+ turns: list.map((d) => ({
231
+ userMessage: { info: { id: d.user.message_id } },
232
+ assistantMessages: d.assistant.map((m) => ({ info: { time: m.status === 'streaming' ? {} : { completed: 1 }, error: m.error ?? undefined } })),
233
+ })),
234
+ hintMessageId: continuedHint(list, options.liveMessageId),
235
+ unrunTurnIds: held,
236
+ });
237
+ const anchor = last(list, writesPlan) ?? list[list.length - 1];
238
+ const v1Thread = isV1Thread(thread);
239
+ const exact = (m) => v1Thread || m.producer.harness === V1_IMPORT;
240
+ const heads = options.threads ?? [];
241
+ const known = new Set(heads.map((h) => h.thread_id));
242
+ return list.map((d) => {
243
+ const live = options.busy === true && working.workingTurnId === d.user.message_id;
244
+ const queued = working.pendingTurnIds.includes(d.user.message_id);
245
+ const retries = retrying && d.assistant.includes(lastReply);
246
+ const key = `${d.partial}|${live}|${queued}|${d === anchor}|${retries}`;
247
+ const prev = cache.get(d.user);
248
+ if (prev && prev.key === key && prev.pricing === options.pricing && prev.heads === options.threads && prev.assistant.length === d.assistant.length && prev.assistant.every((m, i) => m === d.assistant[i]))
249
+ return prev.turn;
250
+ const blocks = d.assistant.flatMap((m) => m.blocks);
251
+ for (const m of d.assistant)
252
+ for (const b of m.blocks)
253
+ messageOfBlock.set(b, m);
254
+ const threads = threadsOf(d, blocks, heads, known);
255
+ const reply = d.assistant[d.assistant.length - 1];
256
+ const turn = {
257
+ id: d.user.message_id,
258
+ user: d.user,
259
+ assistant: d.assistant,
260
+ partial: d.partial,
261
+ continues: d.continues ?? null,
262
+ blocks,
263
+ status: retries ? 'streaming' : reply ? reply.status : d.user.kind === 'compaction' ? d.user.status : 'pending',
264
+ error: errorOf(d),
265
+ cost: costOf([d.user, ...d.assistant], exact, options.pricing),
266
+ compaction: compactionOf(d.user),
267
+ threads,
268
+ plan: d === anchor,
269
+ shell: shellOf(d),
270
+ response: last(blocks, (b) => b.type === 'text' && !!b.text.trim()) ?? null,
271
+ attachments: d.user.blocks.filter((b) => b.type === 'attachment' && (b.mime.startsWith('image/') || b.mime === 'application/pdf')),
272
+ live,
273
+ queued,
274
+ retrying: retries,
275
+ };
276
+ cache.set(d.user, { assistant: d.assistant, key, pricing: options.pricing, heads: options.threads, turn });
277
+ return turn;
278
+ });
279
+ }
@@ -0,0 +1,8 @@
1
+ import type { Part } from '../../runtime/runtime-types.js';
2
+ import { type SessionLogBlock, type SessionLogMessage } from '../types.js';
3
+ import { type V1MessageRow } from '../v1-view.js';
4
+ export declare const messageOfBlock: WeakMap<SessionLogBlock, SessionLogMessage>;
5
+ export declare function partOf(block: SessionLogBlock): Part | undefined;
6
+ export declare const blockOf: (part: object) => SessionLogBlock;
7
+ export declare const partsOf: (list: ReadonlyArray<SessionLogBlock>) => Part[];
8
+ export declare function v1RowsOf(m: SessionLogMessage): V1MessageRow[];
@@ -0,0 +1,43 @@
1
+ import { blockPartOf } from '../tool-call.js';
2
+ import { SESSION_LOG_MINOR, SESSION_LOG_SCHEMA } from '../types.js';
3
+ import { rowsOf } from '../v1-view.js';
4
+ const blocks = new WeakMap();
5
+ export const messageOfBlock = new WeakMap();
6
+ const fallbacks = new WeakMap();
7
+ export function partOf(block) {
8
+ let part;
9
+ const message = messageOfBlock.get(block);
10
+ if (message)
11
+ part = partsById(message).get(block.id);
12
+ if (part)
13
+ return blocks.set(part, block), part;
14
+ if (block.type !== 'harness')
15
+ part = blockPartOf(block);
16
+ else if (typeof block.data?.type === 'string')
17
+ part = block.data;
18
+ else if (block.model_visible && block.fallback_text !== undefined) {
19
+ part = fallbacks.get(block) ?? { id: block.id, type: 'text', text: block.fallback_text, synthetic: true };
20
+ fallbacks.set(block, part);
21
+ }
22
+ if (part)
23
+ blocks.set(part, block);
24
+ return part;
25
+ }
26
+ export const blockOf = (part) => blocks.get(part);
27
+ export const partsOf = (list) => list.flatMap((b) => partOf(b) ?? []);
28
+ const indexes = new WeakMap();
29
+ function partsById(m) {
30
+ let index = indexes.get(m);
31
+ if (!index)
32
+ indexes.set(m, (index = new Map(v1RowsOf(m)[0]?.parts.map((p) => [p.id, p]))));
33
+ return index;
34
+ }
35
+ const heads = new Map();
36
+ export function v1RowsOf(m) {
37
+ let head = heads.get(m.thread_id);
38
+ if (!head) {
39
+ head = { schema: SESSION_LOG_SCHEMA, v: SESSION_LOG_MINOR, thread_id: m.thread_id, parent_thread_id: null, spawned_by: null, agent: null, title: null, created_at: '' };
40
+ heads.set(m.thread_id, head);
41
+ }
42
+ return rowsOf(head, m);
43
+ }
@@ -1,10 +1,13 @@
1
1
  import type { Message, Part } from '../runtime/runtime-types.js';
2
2
  import type { SessionLogState, SessionLogThreadHead } from './store.js';
3
- import { type SessionLog } from './types.js';
3
+ import { type SessionLog, type SessionLogMessage, type SessionLogThread } from './types.js';
4
4
  export interface V1MessageRow {
5
5
  info: Message;
6
6
  parts: Part[];
7
7
  }
8
8
  export declare const isV1Thread: (head: SessionLogThreadHead | undefined) => boolean;
9
- export declare function sessionLogRowsFor<R extends V1MessageRow>(logs: Record<string, SessionLogState>, runtimeSessionId: string, v1Rows: R[]): R[];
9
+ export declare function rowsOf(head: SessionLogThreadHead, message: SessionLogMessage): V1MessageRow[];
10
+ export type OptimisticEchoOf = (id: string) => string | undefined;
11
+ export declare function sessionLogRowsFor<R extends V1MessageRow>(logs: Record<string, SessionLogState>, runtimeSessionId: string, v1Rows: R[], echoOf?: OptimisticEchoOf): R[];
12
+ export declare function sessionLogThreadWithV1Rows(state: SessionLogState, thread: SessionLogThread, v1Rows: readonly V1MessageRow[], echoOf?: OptimisticEchoOf): SessionLogThread;
10
13
  export declare function sessionLogOfV1Rows(sessionId: string, runtimeSessionId: string, rows: readonly V1MessageRow[]): SessionLog;
@@ -21,7 +21,7 @@ const nativeOf = (head) => {
21
21
  return e ? (e.native_id ?? null) : head.thread_id;
22
22
  };
23
23
  const messageRows = new WeakMap();
24
- function rowsOf(head, message) {
24
+ export function rowsOf(head, message) {
25
25
  const native = nativeOf(head);
26
26
  const cached = messageRows.get(message);
27
27
  if (cached && cached.native === native)
@@ -37,7 +37,7 @@ function indexOf(state) {
37
37
  if (!index) {
38
38
  index = new Map();
39
39
  for (const head of Object.values(state.threads)) {
40
- const native = v1Ext(head) ? nativeOf(head) : null;
40
+ const native = nativeOf(head);
41
41
  if (native !== null && !index.has(native))
42
42
  index.set(native, head.thread_id);
43
43
  }
@@ -64,25 +64,64 @@ function insertAt(rows, row) {
64
64
  });
65
65
  return at < 0 ? rows.length : at;
66
66
  }
67
+ function messageInsertAt(messages, message) {
68
+ const created = Date.parse(message.created_at);
69
+ if (!Number.isFinite(created))
70
+ return messages.length;
71
+ const at = messages.findIndex((other) => {
72
+ const t = Date.parse(other.created_at);
73
+ return Number.isFinite(t) && (t > created || (t === created && other.message_id > message.message_id));
74
+ });
75
+ return at < 0 ? messages.length : at;
76
+ }
67
77
  const v1Order = (a, b) => (createdOf(a) ?? -Infinity) - (createdOf(b) ?? -Infinity) || (a.info.id < b.info.id ? -1 : a.info.id > b.info.id ? 1 : 0);
68
78
  const merged = new WeakMap();
69
- export function sessionLogRowsFor(logs, runtimeSessionId, v1Rows) {
79
+ function heldByLog(row, held, revs, echoOf) {
80
+ const id = row.info.id;
81
+ if (held.has(id) || revs[id] !== undefined)
82
+ return true;
83
+ const echo = echoOf?.(id);
84
+ return echo !== undefined && (held.has(echo) || revs[echo] !== undefined);
85
+ }
86
+ export function sessionLogRowsFor(logs, runtimeSessionId, v1Rows, echoOf) {
70
87
  const found = findThread(logs, runtimeSessionId);
71
88
  if (!found)
72
89
  return v1Rows;
73
90
  const { state, head, list } = found;
74
91
  const cached = merged.get(list);
75
92
  const native = nativeOf(head);
76
- if (cached && cached.v1Rows === v1Rows && cached.native === native && cached.revs === state.revs)
93
+ const own = cached && cached.v1Rows === v1Rows && cached.native === native && cached.revs === state.revs ? cached.own : list.flatMap((m) => rowsOf(head, m)).sort(v1Order);
94
+ const shown = new Set(own.map((r) => r.info.id));
95
+ const extra = v1Rows.filter((row) => !heldByLog(row, shown, state.revs, echoOf));
96
+ if (cached && cached.own === own && cached.extra.length === extra.length && cached.extra.every((r, i) => r === extra[i]))
77
97
  return cached.result;
78
- const result = list.flatMap((m) => rowsOf(head, m)).sort(v1Order);
79
- const shown = new Set(result.map((r) => r.info.id));
80
- for (const row of v1Rows) {
81
- if (shown.has(row.info.id) || state.revs[row.info.id] !== undefined)
82
- continue;
98
+ const result = [...own];
99
+ for (const row of extra)
83
100
  result.splice(insertAt(result, row), 0, row);
101
+ merged.set(list, { v1Rows, native, revs: state.revs, own, extra, result });
102
+ return result;
103
+ }
104
+ const extended = new WeakMap();
105
+ export function sessionLogThreadWithV1Rows(state, thread, v1Rows, echoOf) {
106
+ const cached = extended.get(thread);
107
+ const held = cached?.held ?? new Set(thread.messages.flatMap((m) => rowsOf(thread, m).map((r) => r.info.id)));
108
+ const extra = v1Rows.filter((r) => !heldByLog(r, held, state.revs, echoOf));
109
+ if (cached && cached.extra.length === extra.length && cached.extra.every((r, i) => r === extra[i]))
110
+ return cached.result;
111
+ let result = thread;
112
+ if (extra.length) {
113
+ let seq = thread.messages[thread.messages.length - 1]?.seq ?? 0;
114
+ const { paired, used } = pairCompactions(extra);
115
+ const messages = [...thread.messages];
116
+ for (const r of extra) {
117
+ if (used.has(r))
118
+ continue;
119
+ const message = convert(state.session.session_id ?? '', thread.thread_id, r, paired.get(r), ++seq).message;
120
+ messages.splice(messageInsertAt(messages, message), 0, message);
121
+ }
122
+ result = { ...thread, messages };
84
123
  }
85
- merged.set(list, { v1Rows, native, revs: state.revs, result });
124
+ extended.set(thread, { held, extra, result });
86
125
  return result;
87
126
  }
88
127
  const converted = new WeakMap();
@@ -94,13 +133,48 @@ const summaryOf = (row, marker) => {
94
133
  const info = row.info;
95
134
  return info.role === 'assistant' && info.summary === true && info.parentID === marker.info.id;
96
135
  };
136
+ const partBlocks = new WeakMap();
137
+ function reuseBlocks(native, row, message) {
138
+ const info = row.info;
139
+ const at = `${native}|${String(info.id)}|${String(info.time?.created)}`;
140
+ let reused = false;
141
+ const blocks = message.blocks.map((block, i) => {
142
+ const part = row.parts[i];
143
+ if (!isObj(part) || block.type === 'compaction')
144
+ return block;
145
+ const key = `${at}|${i}|${block.id}`;
146
+ const prev = partBlocks.get(part);
147
+ if (prev && prev.key === key) {
148
+ reused = true;
149
+ return prev.block;
150
+ }
151
+ partBlocks.set(part, { key, block });
152
+ return block;
153
+ });
154
+ return reused ? { ...message, blocks } : message;
155
+ }
156
+ function pairCompactions(rows) {
157
+ const paired = new Map();
158
+ const used = new Set();
159
+ for (const row of rows) {
160
+ if (!isMarker(row))
161
+ continue;
162
+ const sum = rows.find((r) => !used.has(r) && summaryOf(r, row));
163
+ if (!sum)
164
+ continue;
165
+ paired.set(row, sum);
166
+ used.add(sum);
167
+ }
168
+ return { paired, used };
169
+ }
97
170
  function convert(sessionId, native, row, sum, seq) {
98
171
  const cached = converted.get(row);
99
172
  if (cached && cached.sessionId === sessionId && cached.native === native && cached.sum === sum && cached.seq === seq)
100
173
  return cached;
101
174
  const unit = sum ? [row, sum] : [row];
102
175
  const log = fromV1({ session_id: sessionId, root_id: native, rows: unit.map((r) => ({ runtime_session_id: native, info: r.info, parts: r.parts })) }, { live: true });
103
- const entry = { sessionId, native, sum, seq, message: { ...log.threads[0].messages[0], seq }, lost: log.grade_counts };
176
+ const message = reuseBlocks(native, row, log.threads[0].messages[0]);
177
+ const entry = { sessionId, native, sum, seq, message: { ...message, seq }, lost: log.grade_counts };
104
178
  converted.set(row, entry);
105
179
  return entry;
106
180
  }
@@ -109,17 +183,7 @@ export function sessionLogOfV1Rows(sessionId, runtimeSessionId, rows) {
109
183
  if (cached && cached.sessionId === sessionId && cached.native === runtimeSessionId)
110
184
  return cached.log;
111
185
  const sorted = [...rows].sort(v1Order);
112
- const paired = new Map();
113
- const used = new Set();
114
- for (const row of sorted) {
115
- if (!isMarker(row))
116
- continue;
117
- const sum = sorted.find((r) => !used.has(r) && summaryOf(r, row));
118
- if (!sum)
119
- continue;
120
- paired.set(row, sum);
121
- used.add(sum);
122
- }
186
+ const { paired, used } = pairCompactions(sorted);
123
187
  const counts = { tool_input: 0, cut_point: 0, attachment: 0 };
124
188
  const messages = [];
125
189
  for (const row of sorted) {
@@ -71,6 +71,12 @@ const extOf = (h, entry) => ({ [h]: { version: BEEUNI_TRANSCRIPT_SCHEMA, ...entr
71
71
  const urlOf = (a, c) => a.url !== undefined ? { url: a.url } : a.ref !== undefined && !c.fromV1 ? { url: a.ref } : {};
72
72
  const textOf = (content) => (content ?? []).flatMap((c) => (c.type === 'text' ? [c.text] : [])).join('');
73
73
  const head = (b, c) => ({ id: b.id, ...(c.sessionID !== null && { sessionID: c.sessionID }), messageID: c.messageID });
74
+ const detailsOf = (b) => {
75
+ if (isObj(b.result?.details))
76
+ return b.result.details;
77
+ const own = Object.values(b.ext ?? {}).find((e) => e.version !== BEEUNI_TRANSCRIPT_SCHEMA && isObj(e.data?.details));
78
+ return own ? own.data.details : {};
79
+ };
74
80
  function toolState(b, c, base) {
75
81
  const r = b.result;
76
82
  const input = b.input === null || b.input === undefined ? {} : { input: b.input };
@@ -86,7 +92,7 @@ function toolState(b, c, base) {
86
92
  const atts = (r?.content ?? []).flatMap((x, i) => x.type === 'attachment' ? [{ ...base, id: `${b.id}-a${i}`, type: 'file', mime: x.mime, ...urlOf(x, c) }] : []);
87
93
  const compacted = msOf(r?.cleared_at);
88
94
  return {
89
- status: 'completed', ...input, output: textOf(r?.content), title: b.title ?? '', metadata: meta,
95
+ status: 'completed', ...input, output: textOf(r?.content), title: b.title ?? '', metadata: { ...detailsOf(b), ...meta },
90
96
  time: { start, end, ...(compacted !== undefined && { compacted }) },
91
97
  ...(atts.length && { attachments: atts }),
92
98
  };
@@ -310,14 +316,15 @@ function toMessage(row, sum, threadId, seq, superseded, c) {
310
316
  const aborted = err?.name === 'MessageAbortedError';
311
317
  const completedAt = src && isObj(src.time) ? iso(src.time.completed) : null;
312
318
  const open = c.live ? 'streaming' : 'interrupted';
313
- const status = !src ? (marker ? open : 'complete') : err ? (aborted ? 'aborted' : 'error') : completedAt ? 'complete' : open;
319
+ const settled = !src ? (marker ? open : 'complete') : err ? (aborted ? 'aborted' : 'error') : completedAt ? 'complete' : open;
314
320
  const createdAt = iso(isObj(info.time) ? info.time.created : undefined) ?? '';
315
321
  const summary = sum ? (Array.isArray(sum.parts) ? sum.parts : []).flatMap((p) => (isObj(p) && p.type === 'text' && typeof p.text === 'string' ? [p.text] : [])).join('') : null;
316
322
  const lost = { tool_input: 0, cut_point: 0, attachment: 0 };
317
323
  const ids = blockIds(parts);
318
324
  const blocks = parts.map((p, i) => blockOf(p, ids[i], marker, summary, c, lost));
319
325
  const visible = blocks.some((b) => b.type === 'text' || b.type === 'attachment' || b.type === 'tool_call' || (b.type === 'harness' && b.model_visible));
320
- const inContext = !superseded && role !== 'system' && (marker ? status === 'complete' : !err || (aborted && visible));
326
+ const inContext = !superseded && role !== 'system' && (marker ? settled === 'complete' : !err || (aborted && visible));
327
+ const status = c.live && inContext && settled !== 'streaming' && blocks.some((b) => b.type === 'tool_call' && (b.status === 'pending' || b.status === 'running')) ? 'streaming' : settled;
321
328
  const hidden = superseded ? 'superseded' : inContext || !err ? undefined : aborted ? 'aborted' : 'failed_attempt';
322
329
  if (marker && isObj(marker) && str(marker.tail_start_id) === undefined)
323
330
  lost.cut_point++;
@@ -1,4 +1,18 @@
1
- import type { SessionTranscriptSyncEnvelope } from '../rest/projects-client/sessions.js';
1
+ import { type SessionTranscriptSyncEnvelope } from '../rest/projects-client/sessions.js';
2
+ export declare const SAVED_HISTORY_SNAPSHOT_WAIT_MS = 2000;
3
+ export declare function loadSavedTranscript(projectId: string, sessionId: string, options?: {
4
+ signal?: AbortSignal;
5
+ snapshotWaitMs?: number;
6
+ }): Promise<SessionTranscriptSyncEnvelope>;
7
+ export interface SavedSessionCopy {
8
+ envelope: SessionTranscriptSyncEnvelope | null;
9
+ empty: boolean;
10
+ }
11
+ export declare function readSavedSessionCopy(input: {
12
+ projectId: string;
13
+ sessionId: string;
14
+ runtimeSessionId: string;
15
+ }): Promise<SavedSessionCopy>;
2
16
  export type SavedTranscript = 'loading' | 'shown' | 'none';
3
17
  export interface SavedTranscriptInput {
4
18
  enabled: boolean;