@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
@@ -1,3 +1,58 @@
1
+ import { getSessionTranscriptSync, getSessionTurn, } from '../rest/projects-client/sessions.js';
2
+ import { OPEN_BUNDLE_TRANSCRIPT_LIMIT, claimOpenBundle, heldSavedWindow, holdSavedWindow, openBundleHistory, } from '../session/open-bundle.js';
3
+ export const SAVED_HISTORY_SNAPSHOT_WAIT_MS = 2_000;
4
+ export async function loadSavedTranscript(projectId, sessionId, options = {}) {
5
+ return heldSavedWindow(projectId, sessionId) ?? readSavedWindow(projectId, sessionId, options);
6
+ }
7
+ async function readSavedWindow(projectId, sessionId, options) {
8
+ const claimed = claimOpenBundle(projectId, sessionId);
9
+ let timer;
10
+ const bundle = claimed
11
+ ? await Promise.race([
12
+ claimed,
13
+ new Promise((resolve) => {
14
+ timer = setTimeout(resolve, options.snapshotWaitMs ?? SAVED_HISTORY_SNAPSHOT_WAIT_MS, null);
15
+ }),
16
+ ]).finally(() => clearTimeout(timer))
17
+ : null;
18
+ return ((bundle && openBundleHistory(bundle)) ??
19
+ getSessionTranscriptSync(projectId, sessionId, {
20
+ limit: OPEN_BUNDLE_TRANSCRIPT_LIMIT,
21
+ history: true,
22
+ signal: options.signal,
23
+ }));
24
+ }
25
+ export async function readSavedSessionCopy(input) {
26
+ const { projectId, sessionId, runtimeSessionId } = input;
27
+ if (!projectId || !sessionId || !runtimeSessionId)
28
+ return { envelope: null, empty: false };
29
+ let envelope;
30
+ try {
31
+ envelope = await readSavedWindow(projectId, sessionId, {});
32
+ }
33
+ catch {
34
+ return { envelope: null, empty: false };
35
+ }
36
+ holdSavedWindow(projectId, sessionId, envelope);
37
+ if (savedCopyEmptyRoot(envelope) !== runtimeSessionId)
38
+ return { envelope, empty: false };
39
+ try {
40
+ const turn = await getSessionTurn(projectId, sessionId);
41
+ return {
42
+ envelope,
43
+ empty: isEmptyConversation({
44
+ savedEmptyRoot: runtimeSessionId,
45
+ rootSessionId: runtimeSessionId,
46
+ turnRead: true,
47
+ hasEndedTurn: turn.last_ended != null,
48
+ hasOpenOrQueuedTurn: turn.turns.length > 0,
49
+ }),
50
+ };
51
+ }
52
+ catch {
53
+ return { envelope, empty: false };
54
+ }
55
+ }
1
56
  export function resolveSavedTranscript(input) {
2
57
  if (input.hasMessages)
3
58
  return 'shown';
@@ -132,6 +132,9 @@ export class SessionSyncController {
132
132
  reconcile(reason = 'manual') {
133
133
  if (this.destroyed)
134
134
  return Promise.resolve();
135
+ if (reason === 'visible' && this.streamReliable && this.snapshot.freshness === 'fresh') {
136
+ return Promise.resolve();
137
+ }
135
138
  if (this.tailRequest)
136
139
  return this.tailRequest;
137
140
  this.update({
@@ -1,4 +1,4 @@
1
- import { getAuthToken, invalidateTokenCache } from '../http/auth.js';
1
+ import { getAuthToken as getSupabaseAccessToken, invalidateTokenCache } from '../http/auth.js';
2
2
  import { getClientForUrl } from '../runtime/client.js';
3
3
  import { isAuthFailure } from '../http/api/errors.js';
4
4
  import { logger } from '../http/logger.js';
@@ -222,8 +222,8 @@ function createLiveStream(client, opts, subscribers) {
222
222
  schedule();
223
223
  if (t.now() - yieldedAt < YIELD_INTERVAL_MS)
224
224
  continue;
225
- yieldedAt = t.now();
226
225
  await new Promise((resolve) => t.setTimeout(resolve, 0));
226
+ yieldedAt = t.now();
227
227
  }
228
228
  stableConnection = streamHadWork;
229
229
  }
@@ -241,7 +241,7 @@ function createLiveStream(client, opts, subscribers) {
241
241
  if (isAuthError) {
242
242
  try {
243
243
  invalidateTokenCache();
244
- await getAuthToken();
244
+ await getSupabaseAccessToken();
245
245
  logger.info('SSE: refreshed auth token after auth error');
246
246
  }
247
247
  catch (refreshErr) {
@@ -1,6 +1,7 @@
1
1
  import { extractGatewayErrorDetails, unwrapError } from './errors.js';
2
2
  import { getChildSessionId } from './parts.js';
3
3
  import { isToolCallBlock, toolPartOf } from '../session-log/tool-call.js';
4
+ import { editBlocks } from './edit-blocks.js';
4
5
  import { inputPath, toolKind } from './tool-kind.js';
5
6
  import { toolInfo } from './tool-registry.js';
6
7
  const MAX_PARSEABLE_OUTPUT_LENGTH = 256 * 1024;
@@ -92,11 +93,12 @@ function toolFiles(kind, input, metadata) {
92
93
  const filediff = record(metadata.filediff);
93
94
  const patch = filediff ? undefined : text(metadata.patch);
94
95
  const counts = patch ? patchLineCounts(patch) : undefined;
96
+ const blocks = filediff || patch ? [] : editBlocks(input);
95
97
  return [
96
98
  defined({
97
99
  path,
98
- before: text(filediff?.before) ?? text(input.oldString),
99
- after: text(filediff?.after) ?? text(input.newString),
100
+ before: text(filediff?.before) ?? (blocks.length ? blocks.map(([before]) => before).join('\n') : undefined),
101
+ after: text(filediff?.after) ?? (blocks.length ? blocks.map(([, after]) => after).join('\n') : text(input.new_source)),
100
102
  patch,
101
103
  additions: count(filediff?.additions) ?? counts?.additions,
102
104
  deletions: count(filediff?.deletions) ?? counts?.deletions,
@@ -0,0 +1 @@
1
+ export declare function editBlocks(input: Record<string, unknown> | undefined): Array<[string, string]>;
@@ -0,0 +1,15 @@
1
+ export function editBlocks(input) {
2
+ const one = pair(input);
3
+ if (one)
4
+ return [one];
5
+ const edits = Array.isArray(input?.edits) ? input.edits : [];
6
+ return edits.flatMap((edit) => {
7
+ const block = edit && typeof edit === 'object' ? pair(edit) : undefined;
8
+ return block ? [block] : [];
9
+ });
10
+ }
11
+ function pair(input) {
12
+ const before = input?.oldString ?? input?.old_string ?? input?.oldText;
13
+ const after = input?.newString ?? input?.new_string ?? input?.newText;
14
+ return typeof before === 'string' && typeof after === 'string' ? [before, after] : undefined;
15
+ }
@@ -7,3 +7,4 @@ export interface BurstSummary {
7
7
  }
8
8
  export declare function burstSummary(parts: ReadonlyArray<Part>): BurstSummary;
9
9
  export declare function burstSummaryLabel(summary: BurstSummary, running: boolean): string;
10
+ export declare function burstWorkLabel(parts: ReadonlyArray<Part>): string;
@@ -1,5 +1,6 @@
1
1
  import { isReasoningPart, isToolPart } from '../parts.js';
2
2
  import { partOutcome } from '../tools/tool-outcome.js';
3
+ import { familyForTool, narrateStep } from './narration.js';
3
4
  import { stepLabel } from './step-label.js';
4
5
  export function burstSummary(parts) {
5
6
  let total = 0;
@@ -43,3 +44,26 @@ export function burstSummaryLabel(summary, running) {
43
44
  return `${steps(total)} failed`;
44
45
  return `Completed ${completed} of ${total} steps · ${failed} failed`;
45
46
  }
47
+ export function burstWorkLabel(parts) {
48
+ const families = new Map();
49
+ let failed = 0;
50
+ for (const part of parts) {
51
+ if (!isToolPart(part) || stepLabel(part).tier === 'plumbing')
52
+ continue;
53
+ const family = familyForTool(part.tool);
54
+ if (family === 'hidden')
55
+ continue;
56
+ families.set(family, [...(families.get(family) ?? []), part]);
57
+ if (partOutcome(part) !== 'ok')
58
+ failed += 1;
59
+ }
60
+ if (families.size === 0)
61
+ return burstSummaryLabel(burstSummary(parts), false);
62
+ const label = [...families]
63
+ .map(([family, calls], i) => {
64
+ const sentence = narrateStep(family, calls);
65
+ return i === 0 ? sentence : sentence.charAt(0).toLowerCase() + sentence.slice(1);
66
+ })
67
+ .join(', ');
68
+ return failed > 0 ? `${label} · ${failed} failed` : label;
69
+ }
@@ -1,11 +1,12 @@
1
1
  import type { ToolPart } from '../../runtime/client.js';
2
+ import type { ToolCallBlock } from '../../session-log/types.js';
2
3
  import { type StepFamily } from './narration.js';
3
- export interface Step {
4
+ export interface Step<P extends ToolPart | ToolCallBlock = ToolPart> {
4
5
  id: string;
5
6
  family: StepFamily;
6
7
  label: string;
7
- parts: ToolPart[];
8
+ parts: P[];
8
9
  status: 'running' | 'error' | 'done';
9
10
  durationMs?: number;
10
11
  }
11
- export declare function groupSteps(parts: ToolPart[]): Step[];
12
+ export declare function groupSteps<P extends ToolPart | ToolCallBlock = ToolPart>(given: P[]): Step<P>[];
@@ -1,3 +1,4 @@
1
+ import { asToolPart } from '../../session-log/tool-call.js';
1
2
  import { isEmptyShowPart, isNoGroupActivityTool } from './session-activity-groups.js';
2
3
  import { familyForTool, narrateFailedStep, narrateStep } from './narration.js';
3
4
  function statusOf(parts) {
@@ -22,18 +23,19 @@ function durationOf(parts) {
22
23
  return undefined;
23
24
  return end - start;
24
25
  }
25
- function finalize(family, parts) {
26
+ function finalize(family, given) {
27
+ const parts = given.map(asToolPart);
26
28
  const status = statusOf(parts);
27
29
  return {
28
30
  id: parts[0].callID,
29
31
  family,
30
32
  label: status === 'error' ? narrateFailedStep(family, parts) : narrateStep(family, parts),
31
- parts,
33
+ parts: given,
32
34
  status,
33
35
  durationMs: status === 'running' ? undefined : durationOf(parts),
34
36
  };
35
37
  }
36
- export function groupSteps(parts) {
38
+ export function groupSteps(given) {
37
39
  const steps = [];
38
40
  let family = null;
39
41
  let buffer = [];
@@ -43,7 +45,8 @@ export function groupSteps(parts) {
43
45
  family = null;
44
46
  buffer = [];
45
47
  };
46
- for (const part of parts) {
48
+ for (const item of given) {
49
+ const part = asToolPart(item);
47
50
  const f = familyForTool(part.tool);
48
51
  if (f === 'hidden')
49
52
  continue;
@@ -51,14 +54,14 @@ export function groupSteps(parts) {
51
54
  continue;
52
55
  if (isNoGroupActivityTool(part.tool)) {
53
56
  flush();
54
- steps.push(finalize(f, [part]));
57
+ steps.push(finalize(f, [item]));
55
58
  continue;
56
59
  }
57
60
  if (f !== family) {
58
61
  flush();
59
62
  family = f;
60
63
  }
61
- buffer.push(part);
64
+ buffer.push(item);
62
65
  }
63
66
  flush();
64
67
  return steps;
@@ -1,9 +1,10 @@
1
1
  import type { ToolPart } from '../../runtime/client.js';
2
- export type StepFamily = 'explore' | 'edit' | 'run' | 'web' | 'create' | 'plan' | 'delegate' | 'sessions' | 'memory' | 'connectors' | 'automations' | 'projects' | 'skills' | 'ask' | 'retired' | 'other';
2
+ import type { ToolCallBlock } from '../../session-log/types.js';
3
+ export type StepFamily = 'explore' | 'edit' | 'run' | 'script' | 'web' | 'create' | 'plan' | 'delegate' | 'sessions' | 'memory' | 'connectors' | 'automations' | 'projects' | 'skills' | 'ask' | 'retired' | 'other';
3
4
  export declare function familyForTool(toolName: string): StepFamily | 'hidden';
4
5
  export declare function narrationToolName(toolName: string): string;
5
6
  export declare function contextLabelForTool(toolName: string): string;
6
7
  export type CreateArtifactKind = 'image' | 'video' | 'presentation';
7
- export declare function createArtifactKind(part: ToolPart): CreateArtifactKind | null;
8
- export declare function narrateStep(family: StepFamily, parts: ToolPart[]): string;
9
- export declare function narrateFailedStep(family: StepFamily, parts: ToolPart[]): string;
8
+ export declare function createArtifactKind(call: ToolPart | ToolCallBlock): CreateArtifactKind | null;
9
+ export declare function narrateStep(family: StepFamily, calls: ReadonlyArray<ToolPart | ToolCallBlock>): string;
10
+ export declare function narrateFailedStep(family: StepFamily, calls: ReadonlyArray<ToolPart | ToolCallBlock>): string;
@@ -1,3 +1,4 @@
1
+ import { asToolPart } from '../../session-log/tool-call.js';
1
2
  import { inputPath, toolKind } from '../tool-kind.js';
2
3
  import { getToolPrimaryArg, normalizeName } from '../tools/tool-meta.js';
3
4
  import { parseWebSearchOutput, wsDomain } from '../tools/web-helpers.js';
@@ -23,6 +24,7 @@ const FAMILY_OF_KIND = {
23
24
  apply_patch: 'edit',
24
25
  bash: 'run',
25
26
  pty: 'run',
27
+ script: 'script',
26
28
  web_search: 'web',
27
29
  webfetch: 'web',
28
30
  media: 'create',
@@ -286,7 +288,8 @@ function createPartKey(part) {
286
288
  return 'shown:result';
287
289
  }
288
290
  const PRESENTATION_GEN_ARTIFACT_ACTIONS = new Set(['create_slide', 'export_pdf', 'export_pptx']);
289
- export function createArtifactKind(part) {
291
+ export function createArtifactKind(call) {
292
+ const part = asToolPart(call);
290
293
  const t = normalizeName(part.tool);
291
294
  if (t === 'image_gen')
292
295
  return 'image';
@@ -337,7 +340,8 @@ function mixedCreateSentence(keys) {
337
340
  });
338
341
  return `Worked on ${joinWithAnd(segments)}`;
339
342
  }
340
- export function narrateStep(family, parts) {
343
+ export function narrateStep(family, calls) {
344
+ const parts = calls.map(asToolPart);
341
345
  const n = parts.length;
342
346
  const arg = firstArg(parts);
343
347
  switch (family) {
@@ -358,6 +362,8 @@ export function narrateStep(family, parts) {
358
362
  }
359
363
  case 'run':
360
364
  return n === 1 ? 'Ran a command' : `Ran ${n} commands`;
365
+ case 'script':
366
+ return n === 1 ? 'Ran a script' : `Ran ${n} scripts`;
361
367
  case 'web': {
362
368
  const isSearch = (p) => {
363
369
  const t = normalizeName(p.tool);
@@ -525,7 +531,8 @@ export function narrateStep(family, parts) {
525
531
  }
526
532
  }
527
533
  }
528
- export function narrateFailedStep(family, parts) {
534
+ export function narrateFailedStep(family, calls) {
535
+ const parts = calls.map(asToolPart);
529
536
  const arg = firstArg(parts);
530
537
  switch (family) {
531
538
  case 'explore':
@@ -539,6 +546,8 @@ export function narrateFailedStep(family, parts) {
539
546
  }
540
547
  case 'run':
541
548
  return 'A command failed';
549
+ case 'script':
550
+ return 'A script failed';
542
551
  case 'web':
543
552
  return "Couldn't finish searching the web";
544
553
  case 'create':
@@ -1,3 +1,4 @@
1
+ import type { ToolCallBlock } from '../../session-log/types.js';
1
2
  export declare function normalizeActivityToolName(toolName: string | undefined): string;
2
3
  export declare function isShellActivityTool(toolName: string | undefined): boolean;
3
4
  export declare function isQuestionTool(toolName: string | undefined): boolean;
@@ -15,6 +16,6 @@ export interface ActivityPartLike {
15
16
  input?: Record<string, unknown> | null;
16
17
  } | null;
17
18
  }
18
- export declare function isEmptyShowPart(part: ActivityPartLike): boolean;
19
+ export declare function isEmptyShowPart(call: ActivityPartLike | ToolCallBlock): boolean;
19
20
  export declare const STANDALONE_TOOLS: ReadonlySet<string>;
20
21
  export declare function isStandaloneActivityTool(toolName: string | undefined): boolean;
@@ -1,4 +1,5 @@
1
1
  import { isShowPayloadEmpty } from '../tools/show-availability.js';
2
+ import { isToolCallBlock, toolPartOf } from '../../session-log/tool-call.js';
2
3
  export function normalizeActivityToolName(toolName) {
3
4
  return (toolName ?? '').replace(/^oc-/, '').replace(/-/g, '_');
4
5
  }
@@ -34,7 +35,8 @@ export function isInvisibleActivityPart(part) {
34
35
  return true;
35
36
  return false;
36
37
  }
37
- export function isEmptyShowPart(part) {
38
+ export function isEmptyShowPart(call) {
39
+ const part = isToolCallBlock(call) ? toolPartOf(call) : call;
38
40
  const name = normalizeActivityToolName(part.tool);
39
41
  if (name !== 'show' && name !== 'show_user')
40
42
  return false;
@@ -1,4 +1,5 @@
1
1
  import type { Part } from '../../runtime/client.js';
2
+ import type { SessionLogBlock, ToolCallBlock } from '../../session-log/types.js';
2
3
  export type StepTier = 'primary' | 'reasoning' | 'plumbing';
3
4
  export interface StepLabel {
4
5
  verb: string;
@@ -7,4 +8,4 @@ export interface StepLabel {
7
8
  tier: StepTier;
8
9
  }
9
10
  export declare const PLUMBING_TOOLS: ReadonlySet<string>;
10
- export declare function stepLabel(part: Part): StepLabel;
11
+ export declare function stepLabel(call: Part | ToolCallBlock | SessionLogBlock): StepLabel;
@@ -1,6 +1,7 @@
1
1
  import { isReasoningPart, isToolPart } from '../parts.js';
2
2
  import { humanizeSearchQuery } from '../tools/search-query.js';
3
3
  import { normalizeActivityToolName } from './session-activity-groups.js';
4
+ import { isToolCallBlock, toolPartOf } from '../../session-log/tool-call.js';
4
5
  export const PLUMBING_TOOLS = new Set([
5
6
  'get_mem',
6
7
  'memory_search',
@@ -63,7 +64,8 @@ function readObject(input, keys) {
63
64
  }
64
65
  return undefined;
65
66
  }
66
- export function stepLabel(part) {
67
+ export function stepLabel(call) {
68
+ const part = (isToolCallBlock(call) ? toolPartOf(call) : call);
67
69
  if (isReasoningPart(part)) {
68
70
  return { verb: 'Thought', running: 'Thinking', object: undefined, tier: 'reasoning' };
69
71
  }
@@ -1,4 +1,5 @@
1
1
  import type { SessionPrompt } from '../../rest/projects-client/sessions.js';
2
+ import type { SessionLogTurn } from '../../session-log/turns/turn.js';
2
3
  interface TurnLike {
3
4
  userMessage: {
4
5
  info: {
@@ -14,6 +15,7 @@ interface TurnLike {
14
15
  };
15
16
  }>;
16
17
  }
18
+ type BlockTurnLike = Pick<SessionLogTurn, 'id' | 'assistant'>;
17
19
  export interface WorkingTurnResolution {
18
20
  workingTurnId: string | null;
19
21
  pendingTurnIds: string[];
@@ -38,7 +40,7 @@ interface DeliveringTurnInput {
38
40
  };
39
41
  }
40
42
  export declare function fallbackBusyRowAfterTurnId(input: QueuedTurnInput & DeliveringTurnInput & {
41
- turns: ReadonlyArray<TurnLike>;
43
+ turns: ReadonlyArray<TurnLike | BlockTurnLike>;
42
44
  }): string | null;
43
45
  export declare function turnIsConfirmedActive(input: {
44
46
  isTurnWorking: boolean;
@@ -61,7 +63,7 @@ export declare function workingTurnDrawsBusyRow(input: {
61
63
  isRetrying: boolean;
62
64
  awaitingUser?: boolean;
63
65
  }): boolean;
64
- export declare function freshSendHint(turns: ReadonlyArray<TurnLike>, isSentTurn: (userMessageId: string) => boolean): string | null;
66
+ export declare function freshSendHint(turns: ReadonlyArray<TurnLike | BlockTurnLike>, isSentTurn: (userMessageId: string) => boolean): string | null;
65
67
  export declare function resolveWorkingTurn(input: {
66
68
  turns: ReadonlyArray<TurnLike>;
67
69
  hintMessageId: string | null | undefined;
@@ -1,4 +1,6 @@
1
1
  import { showTurnBusyIndicator } from './turn-busy-visibility.js';
2
+ const turnIdOf = (turn) => ('id' in turn ? turn.id : turn.userMessage.info.id);
3
+ const replyCountOf = (turn) => ('assistant' in turn ? turn.assistant.length : turn.assistantMessages.length);
2
4
  const completedAt = (info) => info.time?.completed;
3
5
  export function shouldSuppressWorkingTurnBusy(input) {
4
6
  if (!input.hasPendingTurns || !input.newestAssistantCompleted)
@@ -8,18 +10,17 @@ export function shouldSuppressWorkingTurnBusy(input) {
8
10
  (input.activeTurnId !== null && input.activeTurnId !== input.workingTurnId));
9
11
  }
10
12
  function isQueuedTurn(turn, input) {
11
- const id = turn.userMessage.info.id;
12
- return (input.pendingTurnIds.has(id) ||
13
- (turn.assistantMessages.length === 0 && input.pendingPromptIds.has(id)));
13
+ const id = turnIdOf(turn);
14
+ return input.pendingTurnIds.has(id) || (replyCountOf(turn) === 0 && input.pendingPromptIds.has(id));
14
15
  }
15
16
  export function fallbackBusyRowAfterTurnId(input) {
16
- const delivering = input.turns.find((turn) => input.deliveringPromptIds.has(turn.userMessage.info.id));
17
+ const delivering = input.turns.find((turn) => input.deliveringPromptIds.has(turnIdOf(turn)));
17
18
  if (delivering)
18
- return delivering.userMessage.info.id;
19
+ return turnIdOf(delivering);
19
20
  const firstQueued = input.turns.findIndex((turn) => isQueuedTurn(turn, input));
20
21
  if (firstQueued <= 0)
21
22
  return null;
22
- return input.turns[firstQueued - 1].userMessage.info.id;
23
+ return turnIdOf(input.turns[firstQueued - 1]);
23
24
  }
24
25
  export function turnIsConfirmedActive(input) {
25
26
  return input.isTurnWorking && !input.pendingDelivery && input.activeTurnId === input.turnId;
@@ -47,10 +48,10 @@ export function workingTurnDrawsBusyRow(input) {
47
48
  }
48
49
  export function freshSendHint(turns, isSentTurn) {
49
50
  for (let i = turns.length - 1; i >= 0; i--) {
50
- const id = turns[i].userMessage.info.id;
51
+ const id = turnIdOf(turns[i]);
51
52
  if (!isSentTurn(id))
52
53
  continue;
53
- return turns[i].assistantMessages.length === 0 ? id : null;
54
+ return replyCountOf(turns[i]) === 0 ? id : null;
54
55
  }
55
56
  return null;
56
57
  }
@@ -1,3 +1,3 @@
1
- export type ToolKind = 'read' | 'list' | 'glob' | 'grep' | 'write' | 'edit' | 'apply_patch' | 'bash' | 'pty' | 'web_search' | 'webfetch' | 'media' | 'show' | 'task' | 'delegate' | 'sessions' | 'todowrite' | 'question' | 'memory' | 'connectors' | 'automations' | 'projects' | 'skill' | 'context' | 'retired' | 'other';
1
+ export type ToolKind = 'read' | 'list' | 'glob' | 'grep' | 'write' | 'edit' | 'apply_patch' | 'bash' | 'pty' | 'script' | 'web_search' | 'webfetch' | 'media' | 'show' | 'task' | 'delegate' | 'sessions' | 'todowrite' | 'question' | 'memory' | 'connectors' | 'automations' | 'projects' | 'skill' | 'context' | 'retired' | 'other';
2
2
  export declare function toolKind(name: string): ToolKind;
3
3
  export declare function inputPath(input: Record<string, unknown> | undefined): string | undefined;
@@ -8,9 +8,10 @@ kind('list', ['list', 'ls']);
8
8
  kind('glob', ['glob']);
9
9
  kind('grep', ['grep']);
10
10
  kind('write', ['write']);
11
- kind('edit', ['edit', 'multiedit', 'morph_edit']);
11
+ kind('edit', ['edit', 'multiedit', 'morph_edit', 'MultiEdit', 'NotebookEdit']);
12
12
  kind('apply_patch', ['apply_patch', 'patch']);
13
13
  kind('bash', ['bash']);
14
+ kind('script', ['codemode']);
14
15
  kind('web_search', ['web_search', 'websearch', 'image_search']);
15
16
  kind('webfetch', ['webfetch', 'web_fetch', 'scrape_webpage', 'scrapewebpage']);
16
17
  kind('media', ['image_gen', 'video_gen']);
@@ -91,7 +92,7 @@ export function toolKind(name) {
91
92
  return 'other';
92
93
  }
93
94
  export function inputPath(input) {
94
- for (const value of [input?.filePath, input?.file_path, input?.path]) {
95
+ for (const value of [input?.filePath, input?.file_path, input?.path, input?.notebook_path]) {
95
96
  if (typeof value === 'string' && value)
96
97
  return value;
97
98
  }
@@ -47,6 +47,7 @@ const CATEGORY_OF_KIND = {
47
47
  apply_patch: 'edit',
48
48
  bash: 'shell',
49
49
  pty: 'shell',
50
+ script: 'shell',
50
51
  web_search: 'web',
51
52
  webfetch: 'web',
52
53
  media: 'web',
@@ -8,7 +8,7 @@ export declare function contextToolSummary(parts: ToolPart[]): {
8
8
  search: number;
9
9
  list: number;
10
10
  };
11
- export declare function getToolPrimaryArg(part: ToolPart): string;
11
+ export declare function getToolPrimaryArg(call: ToolPart | ToolCallBlock): string;
12
12
  export interface ContextToolTriggerLabels {
13
13
  read: string;
14
14
  search: string;
@@ -1,5 +1,5 @@
1
1
  import { toolKind } from '../tool-kind.js';
2
- import { isToolCallBlock, toolPartOf } from '../../session-log/tool-call.js';
2
+ import { asToolPart, isToolCallBlock, toolPartOf } from '../../session-log/tool-call.js';
3
3
  import { humanizeSearchQuery } from './search-query.js';
4
4
  import { stripTrailingSlashes } from '../text-scan.js';
5
5
  export const CONTEXT_TOOLS = new Set(['read', 'glob', 'grep', 'list']);
@@ -37,7 +37,8 @@ function truncate(s, max = 60) {
37
37
  const trimmed = s.replace(/\s+/g, ' ').trim();
38
38
  return trimmed.length > max ? `${trimmed.slice(0, max)}…` : trimmed;
39
39
  }
40
- export function getToolPrimaryArg(part) {
40
+ export function getToolPrimaryArg(call) {
41
+ const part = asToolPart(call);
41
42
  const state = (part.state ?? {});
42
43
  const input = (state.input ?? {});
43
44
  const key = normalizeName(part.tool);
@@ -1,3 +1,4 @@
1
+ import { editBlocks } from './edit-blocks.js';
1
2
  import { toolKind } from './tool-kind.js';
2
3
  const PRETTY_CAP = 4000;
3
4
  function capText(text, max = PRETTY_CAP) {
@@ -144,19 +145,6 @@ function computeLineDiff(oldStr, newStr) {
144
145
  lines.push({ type: 'unchanged', text: oldLines[i] });
145
146
  return lines;
146
147
  }
147
- function editBlocks(input) {
148
- const oldString = firstString(input?.oldString);
149
- const newString = firstString(input?.newString);
150
- if (oldString !== undefined && newString !== undefined)
151
- return [[oldString, newString]];
152
- const edits = Array.isArray(input?.edits) ? input.edits : [];
153
- return edits.flatMap((edit) => {
154
- const e = asRecord(edit);
155
- const before = e && firstString(e.oldText);
156
- const after = e && firstString(e.newText);
157
- return before !== undefined && after !== undefined ? [[before, after]] : [];
158
- });
159
- }
160
148
  function fileEditViewModel(tool) {
161
149
  const blocks = editBlocks(tool.input);
162
150
  const diffs = blocks.map(([before, after]) => computeLineDiff(before, after));
@@ -0,0 +1,28 @@
1
+ import { type Library } from '@openuidev/lang-core';
2
+ import { z } from 'zod/v4';
3
+ import type { GenuiNode } from './types.js';
4
+ export interface GenuiSlot {
5
+ accepts: readonly string[];
6
+ min: number;
7
+ max: number;
8
+ optional?: boolean;
9
+ lazy?: boolean;
10
+ }
11
+ export type GenuiChildToMarkdown = (node: GenuiNode) => string;
12
+ export interface GenuiComponentSpec {
13
+ name: string;
14
+ block: boolean;
15
+ container: boolean;
16
+ slots: Readonly<Record<string, GenuiSlot>>;
17
+ urls: Readonly<Record<string, 'required' | 'optional'>>;
18
+ strict: z.ZodType;
19
+ streaming: z.ZodType;
20
+ toMarkdown(props: Record<string, any>, child: GenuiChildToMarkdown): string;
21
+ a11y?(props: Record<string, any>): string;
22
+ }
23
+ export declare const GENUI_BLOCKS: readonly ["Stack", "Card", "Stat", "StatRow", "Table", "Compare", "RankedList", "BarChart", "LineChart", "PieChart", "Map", "Steps", "Checklist", "Tabs", "Accordion", "Badge", "Callout", "Image", "Link"];
24
+ export declare const GENUI_SPECS: Readonly<Record<string, GenuiComponentSpec>>;
25
+ export declare const GENUI_LIBRARY: Library<string>;
26
+ export declare const GENUI_MAX_DEPTH = 4;
27
+ export declare const GENUI_MAX_NODES = 500;
28
+ export declare const GENUI_MAX_SOURCE_CHARS: number;