@opengeni/react 7.6.1 → 7.7.0-canary.37090756480001

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 (142) hide show
  1. package/README.md +19 -2
  2. package/dist/{browser-viewer-5X47I6T2.js → browser-viewer-63TXMINB.js} +6 -5
  3. package/dist/{chunk-UINDK6C3.js → chunk-2QUSQVF2.js} +3 -3
  4. package/dist/{chunk-CHPKSLPN.js → chunk-6ZSWSH4I.js} +3 -1
  5. package/dist/chunk-6ZSWSH4I.js.map +1 -0
  6. package/dist/{chunk-KGENSZKS.js → chunk-AAG4R3QN.js} +4 -3
  7. package/dist/chunk-AAG4R3QN.js.map +1 -0
  8. package/dist/{chunk-Z3DISEQN.js → chunk-CWWKTNKK.js} +35 -18
  9. package/dist/chunk-CWWKTNKK.js.map +1 -0
  10. package/dist/{chunk-5EXGU7UF.js → chunk-DOJWJQ3F.js} +3 -3
  11. package/dist/{chunk-WZ55DVGK.js → chunk-ELCE5SXV.js} +8 -4
  12. package/dist/chunk-ELCE5SXV.js.map +1 -0
  13. package/dist/{chunk-YSMMDOOE.js → chunk-GISEVGS6.js} +10 -2
  14. package/dist/chunk-GISEVGS6.js.map +1 -0
  15. package/dist/{chunk-YRYF2GLG.js → chunk-HNFCAQ5R.js} +39 -31
  16. package/dist/chunk-HNFCAQ5R.js.map +1 -0
  17. package/dist/{chunk-BI57CQUV.js → chunk-I7IWRQLN.js} +2 -2
  18. package/dist/{chunk-XA6R7DJQ.js → chunk-IQUCRAT7.js} +3 -3
  19. package/dist/{chunk-DV2DBNPQ.js → chunk-Q5QBEZIQ.js} +48 -29
  20. package/dist/chunk-Q5QBEZIQ.js.map +1 -0
  21. package/dist/{chunk-FGBCYQOT.js → chunk-RDKBXMWX.js} +120 -74
  22. package/dist/chunk-RDKBXMWX.js.map +1 -0
  23. package/dist/{chunk-45GE35O7.js → chunk-TKB4SB44.js} +10 -2
  24. package/dist/chunk-TKB4SB44.js.map +1 -0
  25. package/dist/{chunk-YCGBREUV.js → chunk-TOAH2BKA.js} +6 -2
  26. package/dist/{chunk-YCGBREUV.js.map → chunk-TOAH2BKA.js.map} +1 -1
  27. package/dist/chunk-UGLEYEMP.js +33 -0
  28. package/dist/chunk-UGLEYEMP.js.map +1 -0
  29. package/dist/{chunk-UJRYEWZI.js → chunk-UTRTG6LH.js} +48 -8
  30. package/dist/chunk-UTRTG6LH.js.map +1 -0
  31. package/dist/{chunk-VGIKFIO2.js → chunk-XOAMRDDK.js} +6 -3
  32. package/dist/chunk-XOAMRDDK.js.map +1 -0
  33. package/dist/{chunk-6NEZPF53.js → chunk-YN7I3STW.js} +153 -32
  34. package/dist/chunk-YN7I3STW.js.map +1 -0
  35. package/dist/{chunk-KZ73RL76.js → chunk-YQEAA6LT.js} +7 -3
  36. package/dist/chunk-YQEAA6LT.js.map +1 -0
  37. package/dist/{chunk-LZ3KHA55.js → chunk-ZYALTAEQ.js} +329 -339
  38. package/dist/chunk-ZYALTAEQ.js.map +1 -0
  39. package/dist/client.d.ts +4 -1
  40. package/dist/commands/types.d.ts +2 -0
  41. package/dist/components/approval-surface.d.ts +15 -0
  42. package/dist/composer.js +8 -7
  43. package/dist/{computer-viewer-7GF35SNY.js → computer-viewer-X2MBRZY4.js} +5 -4
  44. package/dist/connect.js +3 -3
  45. package/dist/hooks/use-browser-session.d.ts +4 -0
  46. package/dist/hooks/use-composer.d.ts +2 -0
  47. package/dist/hooks/use-computer-session.d.ts +2 -0
  48. package/dist/hooks/use-file-attachments.d.ts +2 -0
  49. package/dist/hooks/use-session-events.d.ts +1 -1
  50. package/dist/hooks/use-workspace-sessions.d.ts +15 -5
  51. package/dist/index.d.ts +2 -2
  52. package/dist/index.js +28 -21
  53. package/dist/index.js.map +1 -1
  54. package/dist/interaction.d.ts +1 -1
  55. package/dist/interaction.js +6 -5
  56. package/dist/interaction.js.map +1 -1
  57. package/dist/{latest-question-3BJGKQQ6.js → latest-question-CNEZ5KAN.js} +3 -3
  58. package/dist/lib/error-message.d.ts +7 -0
  59. package/dist/lib/format.d.ts +27 -3
  60. package/dist/lib/interaction-errors.d.ts +3 -0
  61. package/dist/machines.js +5 -4
  62. package/dist/{model-policy-picker-menu-PUTA5JOB.js → model-policy-picker-menu-JSA64TNN.js} +4 -4
  63. package/dist/model-policy.js +1 -1
  64. package/dist/provider.d.ts +5 -1
  65. package/dist/{queue-surface-implementation-2CAQAIHM.js → queue-surface-implementation-HENWYFWA.js} +3 -2
  66. package/dist/{queue-surface-implementation-2CAQAIHM.js.map → queue-surface-implementation-HENWYFWA.js.map} +1 -1
  67. package/dist/realtime.js +2 -2
  68. package/dist/{sandbox-files-AEJTWGT4.js → sandbox-files-BBC47SLD.js} +4 -3
  69. package/dist/session-ui.d.ts +1 -1
  70. package/dist/session-ui.js +13 -12
  71. package/dist/session-ui.js.map +1 -1
  72. package/dist/session.js +7 -6
  73. package/dist/usage.js +2 -1
  74. package/dist/usage.js.map +1 -1
  75. package/package.json +3 -3
  76. package/src/client.ts +5 -1
  77. package/src/commands/registry.ts +18 -15
  78. package/src/commands/types.ts +2 -0
  79. package/src/components/approval-surface.tsx +166 -42
  80. package/src/components/browser-viewer.tsx +38 -9
  81. package/src/components/composer.tsx +9 -2
  82. package/src/components/computer-viewer.tsx +160 -30
  83. package/src/components/generated-video-player.tsx +4 -2
  84. package/src/components/human-input-form.tsx +18 -5
  85. package/src/components/message-timeline.tsx +120 -168
  86. package/src/components/open-geni-chat.tsx +11 -4
  87. package/src/components/queue-surface-state.tsx +3 -1
  88. package/src/components/session-chrome.tsx +5 -2
  89. package/src/components/session-commands-panel.tsx +3 -1
  90. package/src/components/session-conversation.tsx +4 -2
  91. package/src/components/session-list.tsx +7 -5
  92. package/src/components/session-mcp-capability-card.tsx +11 -1
  93. package/src/hooks/internal.ts +3 -2
  94. package/src/hooks/use-browser-session.ts +115 -79
  95. package/src/hooks/use-composer.ts +70 -31
  96. package/src/hooks/use-computer-session.ts +57 -6
  97. package/src/hooks/use-file-attachments.ts +16 -3
  98. package/src/hooks/use-goal.ts +2 -1
  99. package/src/hooks/use-session-capabilities.ts +3 -2
  100. package/src/hooks/use-session-events.ts +15 -8
  101. package/src/hooks/use-slash-commands.ts +6 -11
  102. package/src/hooks/use-turn-queue.ts +2 -1
  103. package/src/hooks/use-workspace-sessions.ts +40 -7
  104. package/src/index.ts +7 -2
  105. package/src/interaction.ts +1 -0
  106. package/src/lib/error-message.ts +37 -0
  107. package/src/lib/format.ts +73 -9
  108. package/src/lib/interaction-errors.ts +15 -0
  109. package/src/model-policy.ts +5 -0
  110. package/src/provider.tsx +12 -4
  111. package/src/session-ui.ts +1 -1
  112. package/src/timeline/projection.ts +12 -1
  113. package/styles/compiled.css +14 -30
  114. package/dist/chunk-45GE35O7.js.map +0 -1
  115. package/dist/chunk-6NEZPF53.js.map +0 -1
  116. package/dist/chunk-CHPKSLPN.js.map +0 -1
  117. package/dist/chunk-DV2DBNPQ.js.map +0 -1
  118. package/dist/chunk-FGBCYQOT.js.map +0 -1
  119. package/dist/chunk-KGENSZKS.js.map +0 -1
  120. package/dist/chunk-KZ73RL76.js.map +0 -1
  121. package/dist/chunk-LZ3KHA55.js.map +0 -1
  122. package/dist/chunk-UJRYEWZI.js.map +0 -1
  123. package/dist/chunk-VGIKFIO2.js.map +0 -1
  124. package/dist/chunk-WZ55DVGK.js.map +0 -1
  125. package/dist/chunk-YRYF2GLG.js.map +0 -1
  126. package/dist/chunk-YSMMDOOE.js.map +0 -1
  127. package/dist/chunk-Z3DISEQN.js.map +0 -1
  128. package/dist/components/timeline-pill-geometry.d.ts +0 -8
  129. package/dist/components/timeline-pill-placement.d.ts +0 -24
  130. package/dist/timeline-pill-geometry-Z23V243M.js +0 -110
  131. package/dist/timeline-pill-geometry-Z23V243M.js.map +0 -1
  132. package/src/components/timeline-pill-geometry.ts +0 -169
  133. package/src/components/timeline-pill-placement.ts +0 -99
  134. /package/dist/{browser-viewer-5X47I6T2.js.map → browser-viewer-63TXMINB.js.map} +0 -0
  135. /package/dist/{chunk-UINDK6C3.js.map → chunk-2QUSQVF2.js.map} +0 -0
  136. /package/dist/{chunk-5EXGU7UF.js.map → chunk-DOJWJQ3F.js.map} +0 -0
  137. /package/dist/{chunk-BI57CQUV.js.map → chunk-I7IWRQLN.js.map} +0 -0
  138. /package/dist/{chunk-XA6R7DJQ.js.map → chunk-IQUCRAT7.js.map} +0 -0
  139. /package/dist/{computer-viewer-7GF35SNY.js.map → computer-viewer-X2MBRZY4.js.map} +0 -0
  140. /package/dist/{latest-question-3BJGKQQ6.js.map → latest-question-CNEZ5KAN.js.map} +0 -0
  141. /package/dist/{model-policy-picker-menu-PUTA5JOB.js.map → model-policy-picker-menu-JSA64TNN.js.map} +0 -0
  142. /package/dist/{sandbox-files-AEJTWGT4.js.map → sandbox-files-BBC47SLD.js.map} +0 -0
@@ -8,7 +8,7 @@ import {
8
8
  TimelineAnnotationsChip,
9
9
  queueItemContent,
10
10
  requestQueueDraftEdit
11
- } from "./chunk-YCGBREUV.js";
11
+ } from "./chunk-TOAH2BKA.js";
12
12
  import {
13
13
  TimelineAnnotationSourceRootContext
14
14
  } from "./chunk-5QHL6BLH.js";
@@ -28,11 +28,11 @@ import {
28
28
  useSessionControl,
29
29
  useSessionEvents,
30
30
  useTurnQueue
31
- } from "./chunk-Z3DISEQN.js";
31
+ } from "./chunk-CWWKTNKK.js";
32
32
  import {
33
33
  buildTimeline,
34
34
  groupTimeline
35
- } from "./chunk-KGENSZKS.js";
35
+ } from "./chunk-AAG4R3QN.js";
36
36
  import {
37
37
  mcpToolLeaf,
38
38
  toolDisplayName
@@ -57,7 +57,7 @@ import {
57
57
  useForcedDefaultOpen,
58
58
  useTimelineSearchNavigation,
59
59
  useTimelineSearchReveal
60
- } from "./chunk-BI57CQUV.js";
60
+ } from "./chunk-I7IWRQLN.js";
61
61
  import {
62
62
  prefersReducedMotion
63
63
  } from "./chunk-GIMRELBW.js";
@@ -95,10 +95,10 @@ import {
95
95
  Status,
96
96
  Surface,
97
97
  useChatComposerController
98
- } from "./chunk-YRYF2GLG.js";
98
+ } from "./chunk-HNFCAQ5R.js";
99
99
  import {
100
100
  useComposer
101
- } from "./chunk-DV2DBNPQ.js";
101
+ } from "./chunk-Q5QBEZIQ.js";
102
102
  import {
103
103
  LightboxProvider,
104
104
  Tooltip,
@@ -108,11 +108,11 @@ import {
108
108
  } from "./chunk-BRM6FVZA.js";
109
109
  import {
110
110
  ModelPolicyPicker
111
- } from "./chunk-UINDK6C3.js";
111
+ } from "./chunk-2QUSQVF2.js";
112
112
  import {
113
113
  projectPickerRows,
114
114
  sortPickerRows
115
- } from "./chunk-CHPKSLPN.js";
115
+ } from "./chunk-6ZSWSH4I.js";
116
116
  import {
117
117
  formatBytes,
118
118
  formatClockTime,
@@ -120,7 +120,7 @@ import {
120
120
  stringifyPayload,
121
121
  truncate,
122
122
  tryParseJson
123
- } from "./chunk-UJRYEWZI.js";
123
+ } from "./chunk-UTRTG6LH.js";
124
124
  import {
125
125
  allowanceLabels,
126
126
  allowanceResetSentence,
@@ -128,7 +128,10 @@ import {
128
128
  } from "./chunk-B3V6TG77.js";
129
129
  import {
130
130
  usePolledValue
131
- } from "./chunk-KZ73RL76.js";
131
+ } from "./chunk-YQEAA6LT.js";
132
+ import {
133
+ useErrorMessage
134
+ } from "./chunk-UGLEYEMP.js";
132
135
  import {
133
136
  useOpenGeni,
134
137
  useOpenGeniClient
@@ -141,6 +144,8 @@ import {
141
144
  import { ChevronDownIcon, ChevronUpIcon, MessageCircleQuestionIcon } from "lucide-react";
142
145
  import { useEffect, useId, useRef, useState } from "react";
143
146
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
147
+ var SkillReviewVerificationError = class extends Error {
148
+ };
144
149
  var defaultHumanInputFormMessages = {
145
150
  title: "Input required",
146
151
  /** Multi-question chrome has no default subtitle; hosts may still override. */
@@ -186,6 +191,7 @@ function HumanInputRequestForm({
186
191
  defaultCollapsed = false,
187
192
  className
188
193
  }) {
194
+ const formatError = useErrorMessage();
189
195
  const messages = { ...defaultHumanInputFormMessages, ...messageOverrides };
190
196
  const singleQuestion = request.questions.length === 1 ? request.questions[0] : null;
191
197
  const resolvedTitle = title === void 0 ? singleQuestion ? singleQuestion.label ?? singleQuestion.prompt : messages.title : title;
@@ -230,12 +236,14 @@ function HumanInputRequestForm({
230
236
  questions.map(async (question) => {
231
237
  if (!loadSkillReview)
232
238
  throw new Error(
233
- "This client cannot preview Skill files. Open this request in Opengeni to review it."
239
+ "This client cannot preview Skill files. Ask your administrator for a review-capable client."
234
240
  );
235
241
  const reference = question.reference;
236
242
  const record = await loadSkillReview(reference);
237
243
  if (record.id !== reference.skillId || record.revisionId !== reference.revisionId || (record.removalOperationId ?? void 0) !== reference.removalOperationId || !record.files.some((file) => file.path === "SKILL.md")) {
238
- throw new Error("The requested Skill revision could not be verified.");
244
+ throw new SkillReviewVerificationError(
245
+ "The requested Skill revision could not be verified."
246
+ );
239
247
  }
240
248
  return [question.id, record];
241
249
  })
@@ -253,13 +261,16 @@ function HumanInputRequestForm({
253
261
  loader: loadSkillReview,
254
262
  identity: reviewIdentity,
255
263
  records: {},
256
- error: cause instanceof Error ? cause.message : "Could not load the Skill files."
264
+ error: formatError(
265
+ cause,
266
+ cause instanceof SkillReviewVerificationError ? cause.message : !loadSkillReview ? "This client cannot preview Skill files. Ask your administrator for a review-capable client." : void 0
267
+ )
257
268
  });
258
269
  });
259
270
  return () => {
260
271
  current = false;
261
272
  };
262
- }, [loadSkillReview, reviewIdentity, reviewReload]);
273
+ }, [loadSkillReview, reviewIdentity, reviewReload, formatError]);
263
274
  const visibleReviews = reviews?.loader === loadSkillReview && reviews?.identity === reviewIdentity ? reviews : null;
264
275
  const preview = (question) => {
265
276
  if (!question.skillReview) return null;
@@ -330,7 +341,7 @@ function HumanInputRequestForm({
330
341
  await onSubmit(response);
331
342
  } catch (cause) {
332
343
  if (generation === submissionGeneration.current) {
333
- setSubmissionError(cause instanceof Error ? cause.message : String(cause));
344
+ setSubmissionError(formatError(cause));
334
345
  }
335
346
  } finally {
336
347
  if (generation === submissionGeneration.current) {
@@ -880,18 +891,22 @@ function HumanInputSurface({
880
891
 
881
892
  // src/components/approval-surface.tsx
882
893
  import { CheckIcon, ShieldCheckIcon, XIcon } from "lucide-react";
883
- import { useEffect as useEffect3, useId as useId2, useRef as useRef3, useState as useState2 } from "react";
884
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
894
+ import { Fragment as Fragment2, useEffect as useEffect3, useId as useId2, useRef as useRef3, useState as useState2 } from "react";
895
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
885
896
  var defaultApprovalSurfaceMessages = {
886
- title: "Approval required",
897
+ title: "Approval needed",
887
898
  description: "Review the requested action before the agent continues.",
888
899
  approve: "Approve",
889
900
  reject: "Reject",
890
901
  approving: "Approving\u2026",
891
902
  rejecting: "Rejecting\u2026",
892
- formatToolName: (name) => name.includes("__") || /^[a-f0-9]{64}$/.test(name) ? toolDisplayName(name) : name.replaceAll("_", " ").replaceAll(".", " \u203A ")
903
+ formatToolName: (name) => name.includes("__") || /^[a-f0-9]{64}$/.test(name) ? toolDisplayName(name) : name.replaceAll("_", " ").replaceAll(".", " \u203A "),
904
+ showDetails: "Show exact arguments",
905
+ hideDetails: "Hide exact arguments"
893
906
  };
894
907
  var APPROVAL_ARGUMENT_PREVIEW_CHARACTERS = 4e3;
908
+ var APPROVAL_FIELD_LIMIT = 12;
909
+ var APPROVAL_LIST_LIMIT = 10;
895
910
  function approvalArgumentsPreview(value) {
896
911
  if (value === void 0) return null;
897
912
  let serialized;
@@ -905,6 +920,46 @@ function approvalArgumentsPreview(value) {
905
920
  return `${characters.slice(0, APPROVAL_ARGUMENT_PREVIEW_CHARACTERS).join("")}
906
921
  \u2026 ${characters.length - APPROVAL_ARGUMENT_PREVIEW_CHARACTERS} characters omitted`;
907
922
  }
923
+ var ACRONYMS = /* @__PURE__ */ new Set(["id", "ids", "url", "uri", "api", "ip", "sku", "utc", "iban", "vat"]);
924
+ function fieldLabel(key) {
925
+ const words = key.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[\s_.-]+/).filter(Boolean).map((word) => ACRONYMS.has(word.toLowerCase()) ? word.toUpperCase() : word.toLowerCase());
926
+ const label = words.join(" ");
927
+ return label ? label.charAt(0).toUpperCase() + label.slice(1) : key;
928
+ }
929
+ function scalarText(value) {
930
+ if (typeof value === "string") return value;
931
+ if (typeof value === "number" || typeof value === "bigint") return String(value);
932
+ if (typeof value === "boolean") return value ? "Yes" : "No";
933
+ if (value === null) return "None";
934
+ return null;
935
+ }
936
+ function approvalArgumentFields(value) {
937
+ let record = value;
938
+ if (typeof record === "string") {
939
+ try {
940
+ record = JSON.parse(record);
941
+ } catch {
942
+ return null;
943
+ }
944
+ }
945
+ if (!record || typeof record !== "object" || Array.isArray(record)) return null;
946
+ const entries = Object.entries(record);
947
+ if (entries.length === 0 || entries.length > APPROVAL_FIELD_LIMIT) return null;
948
+ const fields = [];
949
+ for (const [key, entry] of entries) {
950
+ let text = scalarText(entry);
951
+ if (text === null && Array.isArray(entry) && entry.length <= APPROVAL_LIST_LIMIT) {
952
+ const items = entry.map(scalarText);
953
+ if (items.every((item) => item !== null)) text = items.join(", ");
954
+ }
955
+ if (text === null || text.length > APPROVAL_ARGUMENT_PREVIEW_CHARACTERS) return null;
956
+ fields.push({ key, label: fieldLabel(key), value: text });
957
+ }
958
+ return fields;
959
+ }
960
+ function isEmptyArguments(value) {
961
+ return value === void 0 || value === null || typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 0;
962
+ }
908
963
  function approvalOwnershipKey(approval) {
909
964
  return `${approval.id}\0${approval.name}\0${approvalArgumentsPreview(approval.arguments) ?? ""}`;
910
965
  }
@@ -919,6 +974,8 @@ function ApprovalSurface({
919
974
  className
920
975
  }) {
921
976
  const titleId = useId2();
977
+ const formatError = useErrorMessage();
978
+ const descriptionId = useId2();
922
979
  const messages = { ...defaultApprovalSurfaceMessages, ...overrides };
923
980
  const [pending, setPending] = useState2(null);
924
981
  const pendingRef = useRef3(null);
@@ -946,50 +1003,45 @@ function ApprovalSurface({
946
1003
  if (pendingRef.current?.token === token) {
947
1004
  pendingRef.current = null;
948
1005
  setPending((current) => current?.token === token ? null : current);
949
- setDecisionError(cause instanceof Error ? cause : new Error(String(cause)));
1006
+ setDecisionError({ cause });
950
1007
  }
951
1008
  }
952
1009
  };
953
- const errorMessage = decisionError?.message ?? (error instanceof Error ? error.message : error);
1010
+ const errorMessage = decisionError ? formatError(decisionError.cause) : error instanceof Error ? formatError(error) : error;
954
1011
  return /* @__PURE__ */ jsxs2(
955
1012
  "section",
956
1013
  {
957
1014
  className: cn(
958
- "og-root flex w-full flex-col gap-3 rounded-og-lg border border-og-status-waiting/35 bg-og-status-waiting/5 p-4 shadow-og-sm",
1015
+ "og-root box-border flex w-full flex-col rounded-og-lg border border-og-status-waiting/35 bg-og-status-waiting/5 shadow-og-sm",
959
1016
  className
960
1017
  ),
961
1018
  "aria-labelledby": titleId,
1019
+ "aria-describedby": descriptionId,
1020
+ "data-og-approval-surface": "",
962
1021
  children: [
963
- /* @__PURE__ */ jsxs2("header", { className: "flex items-start gap-3", children: [
964
- /* @__PURE__ */ jsx3("span", { className: "mt-0.5 inline-flex size-8 shrink-0 items-center justify-center rounded-og-md bg-og-status-waiting/12 text-og-status-waiting", children: /* @__PURE__ */ jsx3(ShieldCheckIcon, { "aria-hidden": "true", className: "size-4" }) }),
965
- /* @__PURE__ */ jsxs2("div", { className: "min-w-0", children: [
966
- /* @__PURE__ */ jsx3("h2", { id: titleId, className: "text-og-md font-semibold text-og-fg", children: messages.title }),
967
- /* @__PURE__ */ jsx3("p", { className: "mt-0.5 text-og-sm text-og-fg-muted", children: messages.description })
968
- ] })
969
- ] }),
970
- /* @__PURE__ */ jsx3("div", { className: "flex flex-col gap-2", children: approvals.map((approval) => {
1022
+ /* @__PURE__ */ jsx3("h2", { id: titleId, className: "sr-only", children: messages.title }),
1023
+ /* @__PURE__ */ jsx3("p", { id: descriptionId, className: "sr-only", children: messages.description }),
1024
+ /* @__PURE__ */ jsx3("div", { className: "flex flex-col divide-y divide-og-status-waiting/20", children: approvals.map((approval) => {
971
1025
  const approvalKey = approvalOwnershipKey(approval);
972
1026
  const active = pending?.approvalKey === approvalKey ? pending.decision : null;
973
- const argumentsPreview = approvalArgumentsPreview(approval.arguments);
974
1027
  return /* @__PURE__ */ jsxs2(
975
1028
  "article",
976
1029
  {
977
1030
  "data-approval-id": approval.id,
978
- className: "rounded-og-md border border-og-border bg-og-surface-1 p-3",
1031
+ className: "flex flex-col gap-3 p-4",
979
1032
  children: [
980
- renderApproval ? renderApproval(approval) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
981
- /* @__PURE__ */ jsx3("p", { className: "text-og-sm font-medium text-og-fg", children: approval.display?.title ?? messages.formatToolName(approval.display?.toolName ?? approval.name) }),
982
- approval.display?.accountLabel ? /* @__PURE__ */ jsx3("p", { className: "mt-1 break-words text-og-xs text-og-fg-muted", children: approval.display.accountLabel }) : null,
983
- argumentsPreview !== null ? /* @__PURE__ */ jsx3("pre", { className: "mt-2 max-h-48 overflow-auto whitespace-pre-wrap break-words rounded-og-sm bg-og-surface-2 p-2 font-mono text-og-xs text-og-fg-muted", children: argumentsPreview }) : null
984
- ] }),
985
- /* @__PURE__ */ jsxs2("div", { className: "mt-3 flex flex-wrap justify-end gap-2", children: [
1033
+ renderApproval ? /* @__PURE__ */ jsxs2("div", { className: "min-w-0", children: [
1034
+ /* @__PURE__ */ jsx3("p", { className: "mb-1 text-og-xs font-medium text-og-status-waiting", "aria-hidden": true, children: messages.title }),
1035
+ renderApproval(approval)
1036
+ ] }) : /* @__PURE__ */ jsx3(ApprovalDetails, { approval, messages }),
1037
+ /* @__PURE__ */ jsxs2("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [
986
1038
  /* @__PURE__ */ jsxs2(
987
1039
  "button",
988
1040
  {
989
1041
  type: "button",
990
1042
  disabled: busy,
991
1043
  onClick: () => void decide(approval, "reject"),
992
- className: "inline-flex min-h-9 items-center gap-1.5 rounded-og-md border border-og-border px-3 py-1.5 text-og-sm font-medium text-og-fg-muted transition-colors hover:bg-og-surface-2 hover:text-og-fg disabled:opacity-50",
1044
+ className: "inline-flex min-h-8 items-center gap-1.5 rounded-og-md border border-og-border bg-og-surface-1 px-3 py-1 text-og-sm font-medium text-og-fg transition-colors hover:border-og-border-strong disabled:opacity-50",
993
1045
  children: [
994
1046
  /* @__PURE__ */ jsx3(XIcon, { "aria-hidden": "true", className: "size-3.5" }),
995
1047
  active === "reject" ? messages.rejecting : messages.reject
@@ -1002,7 +1054,7 @@ function ApprovalSurface({
1002
1054
  type: "button",
1003
1055
  disabled: busy,
1004
1056
  onClick: () => void decide(approval, "approve"),
1005
- className: "inline-flex min-h-9 items-center gap-1.5 rounded-og-md border border-og-primary-border bg-og-primary text-og-primary-fg px-3 py-1.5 text-og-sm font-medium transition-colors hover:bg-og-primary-hover disabled:opacity-50",
1057
+ className: "inline-flex min-h-8 items-center gap-1.5 rounded-og-md border border-og-primary-border bg-og-primary px-3 py-1 text-og-sm font-medium text-og-primary-fg transition-colors hover:bg-og-primary-hover disabled:opacity-50",
1006
1058
  children: [
1007
1059
  /* @__PURE__ */ jsx3(CheckIcon, { "aria-hidden": "true", className: "size-3.5" }),
1008
1060
  active === "approve" ? messages.approving : messages.approve
@@ -1015,11 +1067,42 @@ function ApprovalSurface({
1015
1067
  approval.id
1016
1068
  );
1017
1069
  }) }),
1018
- errorMessage ? /* @__PURE__ */ jsx3("p", { role: "alert", className: "text-og-sm text-og-status-failed", children: errorMessage }) : null
1070
+ errorMessage ? /* @__PURE__ */ jsx3("p", { role: "alert", className: "px-4 pb-3 text-og-sm text-og-status-failed", children: errorMessage }) : null
1019
1071
  ]
1020
1072
  }
1021
1073
  );
1022
1074
  }
1075
+ function ApprovalDetails({
1076
+ approval,
1077
+ messages
1078
+ }) {
1079
+ const [showExact, setShowExact] = useState2(false);
1080
+ const fields = approvalArgumentFields(approval.arguments);
1081
+ const exact = isEmptyArguments(approval.arguments) ? null : approvalArgumentsPreview(approval.arguments);
1082
+ return /* @__PURE__ */ jsxs2("div", { className: "flex min-w-0 items-start gap-3", children: [
1083
+ /* @__PURE__ */ jsx3("span", { className: "mt-0.5 inline-flex size-8 shrink-0 items-center justify-center rounded-og-md bg-og-status-waiting/12 text-og-status-waiting", children: /* @__PURE__ */ jsx3(ShieldCheckIcon, { "aria-hidden": "true", className: "size-4" }) }),
1084
+ /* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex-1", children: [
1085
+ /* @__PURE__ */ jsx3("p", { className: "text-og-xs font-medium text-og-status-waiting", children: messages.title }),
1086
+ /* @__PURE__ */ jsx3("p", { className: "mt-0.5 break-words text-og-md font-semibold text-og-fg", children: approval.display?.title ?? messages.formatToolName(approval.display?.toolName ?? approval.name) }),
1087
+ approval.display?.accountLabel ? /* @__PURE__ */ jsx3("p", { className: "mt-0.5 break-words text-og-xs text-og-fg-muted", children: approval.display.accountLabel }) : null,
1088
+ fields ? /* @__PURE__ */ jsx3("dl", { className: "m-0 mt-3 grid grid-cols-[minmax(5.5rem,max-content)_minmax(0,1fr)] gap-x-5 gap-y-1.5 text-og-sm", children: fields.map((field) => /* @__PURE__ */ jsxs2(Fragment2, { children: [
1089
+ /* @__PURE__ */ jsx3("dt", { className: "m-0 text-og-fg-muted", children: field.label }),
1090
+ /* @__PURE__ */ jsx3("dd", { className: "m-0 max-h-32 min-w-0 overflow-auto whitespace-pre-wrap break-words text-og-fg", children: field.value })
1091
+ ] }, field.key)) }) : null,
1092
+ exact !== null && (!fields || showExact) ? /* @__PURE__ */ jsx3("pre", { className: "mt-3 max-h-48 overflow-auto whitespace-pre-wrap break-words rounded-og-sm bg-og-fg/5 p-2.5 font-mono text-og-xs text-og-fg-muted", children: exact }) : null,
1093
+ fields && exact !== null ? /* @__PURE__ */ jsx3(
1094
+ "button",
1095
+ {
1096
+ type: "button",
1097
+ "aria-expanded": showExact,
1098
+ onClick: () => setShowExact((value) => !value),
1099
+ className: "mt-2 text-og-xs text-og-fg-muted underline-offset-2 hover:text-og-fg hover:underline",
1100
+ children: showExact ? messages.hideDetails ?? defaultApprovalSurfaceMessages.hideDetails : messages.showDetails ?? defaultApprovalSurfaceMessages.showDetails
1101
+ }
1102
+ ) : null
1103
+ ] })
1104
+ ] });
1105
+ }
1023
1106
 
1024
1107
  // src/timeline/knowledge-receipt.tsx
1025
1108
  import { createContext, useContext, useState as useState3 } from "react";
@@ -5289,6 +5372,7 @@ function GeneratedVideoPlayer({
5289
5372
  className,
5290
5373
  label = "Generated video"
5291
5374
  }) {
5375
+ const formatError = useErrorMessage();
5292
5376
  const [retry, setRetry] = useState11(0);
5293
5377
  const [state, setState] = useState11({ kind: "loading" });
5294
5378
  useEffect7(() => {
@@ -5302,12 +5386,12 @@ function GeneratedVideoPlayer({
5302
5386
  if (controller.signal.aborted) return;
5303
5387
  setState({
5304
5388
  kind: "error",
5305
- message: error instanceof Error ? error.message : "Playback is unavailable."
5389
+ message: formatError(error)
5306
5390
  });
5307
5391
  }
5308
5392
  );
5309
5393
  return () => controller.abort();
5310
- }, [loadPlaybackSource, receipt.artifact.artifactId, retry]);
5394
+ }, [loadPlaybackSource, receipt.artifact.artifactId, retry, formatError]);
5311
5395
  if (state.kind === "loading") {
5312
5396
  return /* @__PURE__ */ jsx13(
5313
5397
  "div",
@@ -5577,11 +5661,11 @@ import {
5577
5661
  lazy as lazy3,
5578
5662
  memo,
5579
5663
  useCallback as useCallback3,
5580
- useEffect as useEffect10,
5664
+ useEffect as useEffect9,
5581
5665
  useLayoutEffect as useLayoutEffect4,
5582
5666
  useMemo as useMemo5,
5583
5667
  useRef as useRef9,
5584
- useState as useState15
5668
+ useState as useState14
5585
5669
  } from "react";
5586
5670
 
5587
5671
  // src/components/timeline-anchor.tsx
@@ -5723,76 +5807,6 @@ function useReadingProgress(projected, pinned, scroller) {
5723
5807
  return { groups, release };
5724
5808
  }
5725
5809
 
5726
- // src/components/timeline-pill-placement.ts
5727
- import { useEffect as useEffect9, useState as useState14 } from "react";
5728
- var RECHECK_MS = 1e3;
5729
- function useTimelinePillPlacement({
5730
- pillRef,
5731
- scrollerRef,
5732
- active,
5733
- preference,
5734
- allowDownwardFallback = false
5735
- }) {
5736
- const [position, setPosition] = useState14({
5737
- placement: preference[0],
5738
- offsetY: 0
5739
- });
5740
- const key = preference.join(",");
5741
- useEffect9(() => {
5742
- if (!active) {
5743
- setPosition({ placement: preference[0], offsetY: 0 });
5744
- return;
5745
- }
5746
- const scroller = scrollerRef.current;
5747
- if (!scroller) return;
5748
- let frame = 0;
5749
- let current = { placement: preference[0], offsetY: 0 };
5750
- let geometry = null;
5751
- let disposed = false;
5752
- void import("./timeline-pill-geometry-Z23V243M.js").then((loaded) => {
5753
- if (disposed) return;
5754
- geometry = loaded;
5755
- schedule();
5756
- });
5757
- const evaluate = () => {
5758
- frame = 0;
5759
- const pill = pillRef.current;
5760
- const frameElement = pill?.offsetParent;
5761
- if (!geometry || !pill || !(frameElement instanceof HTMLElement)) return;
5762
- const next = allowDownwardFallback ? geometry.chooseQuestionPosition(pill, frameElement, scroller, preference, current) : {
5763
- placement: geometry.choosePlacement(
5764
- pill,
5765
- frameElement,
5766
- scroller,
5767
- preference,
5768
- current.placement
5769
- ),
5770
- offsetY: 0
5771
- };
5772
- if (next.placement !== current.placement || next.offsetY !== current.offsetY) {
5773
- current = next;
5774
- setPosition(next);
5775
- }
5776
- };
5777
- const schedule = () => {
5778
- if (frame === 0) frame = requestAnimationFrame(evaluate);
5779
- };
5780
- schedule();
5781
- const view = scroller.ownerDocument.defaultView;
5782
- scroller.addEventListener("scroll", schedule, { passive: true });
5783
- view?.addEventListener("resize", schedule);
5784
- const timer = setInterval(schedule, RECHECK_MS);
5785
- return () => {
5786
- disposed = true;
5787
- if (frame !== 0) cancelAnimationFrame(frame);
5788
- scroller.removeEventListener("scroll", schedule);
5789
- view?.removeEventListener("resize", schedule);
5790
- clearInterval(timer);
5791
- };
5792
- }, [active, key, pillRef, scrollerRef, allowDownwardFallback]);
5793
- return active ? position : { placement: preference[0], offsetY: 0 };
5794
- }
5795
-
5796
5810
  // src/components/timeline-settlement.ts
5797
5811
  function captureTimelineSettlement(scroller, groups) {
5798
5812
  if (timelineHasReader(scroller)) return null;
@@ -6267,17 +6281,12 @@ var TimelineAnnotationMarkers = lazy3(() => import("./timeline-annotation-marker
6267
6281
  var PIN_THRESHOLD_PX = 48;
6268
6282
  var JUMP_TO_LATEST_CATCHUP_DEBT_PX = 240;
6269
6283
  var QUESTION_NAV_MARGIN_PX = 12;
6270
- var JUMP_PILL_PLACEMENTS = ["center", "end", "start"];
6271
- var QUESTION_PILL_PLACEMENTS = ["end", "center", "start"];
6272
- var JUMP_PILL_PLACEMENT_CLASS = {
6273
- center: "inset-x-0 mx-auto",
6274
- end: "right-4 sm:right-6",
6275
- start: "left-4 sm:left-6"
6276
- };
6277
- var QUESTION_PILL_PLACEMENT_CLASS = {
6278
- center: "justify-center",
6279
- end: "justify-end",
6280
- start: "justify-start"
6284
+ var NAV_PILL_CLASS = "pointer-events-auto inline-flex max-w-full items-center gap-1.5 whitespace-nowrap rounded-full border border-og-border bg-og-surface-3/90 px-3 py-1.5 text-og-control font-medium text-og-fg shadow-og-md backdrop-blur hover:border-og-border-strong focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-og-accent pointer-coarse:min-h-11";
6285
+ var NAV_PILL_MOTION = {
6286
+ initial: { opacity: 0, y: 8 },
6287
+ animate: { opacity: 1, y: 0 },
6288
+ exit: { opacity: 0, y: 8 },
6289
+ transition: { duration: 0.15, ease: "easeOut" }
6281
6290
  };
6282
6291
  var OLDER_PREFETCH_MARGIN_PX = 400;
6283
6292
  var OLDER_PREFETCH_ROOT_MARGIN = `${OLDER_PREFETCH_MARGIN_PX}px 0px 0px 0px`;
@@ -6416,6 +6425,7 @@ function MessageTimeline({
6416
6425
  emptyState,
6417
6426
  className
6418
6427
  }) {
6428
+ const formatError = useErrorMessage();
6419
6429
  const resolvedItems = useMemo5(() => {
6420
6430
  const projectedItems = items ?? buildTimeline(events ?? []);
6421
6431
  if (!shouldRenderAuthNeeded) {
@@ -6458,9 +6468,9 @@ function MessageTimeline({
6458
6468
  newerScopeRef.current = newerBoundaryKey;
6459
6469
  const newerAttemptRef = useRef9(null);
6460
6470
  const newerRetryButtonRef = useRef9(null);
6461
- const [newerRetryPending, setNewerRetryPending] = useState15(false);
6462
- const [newerFailure, setNewerFailure] = useState15(null);
6463
- useEffect10(() => {
6471
+ const [newerRetryPending, setNewerRetryPending] = useState14(false);
6472
+ const [newerFailure, setNewerFailure] = useState14(null);
6473
+ useEffect9(() => {
6464
6474
  newerScopeRef.current = newerBoundaryKey;
6465
6475
  newerAttemptRef.current = null;
6466
6476
  setNewerFailure(null);
@@ -6495,12 +6505,12 @@ function MessageTimeline({
6495
6505
  setNewerRetryPending(false);
6496
6506
  setNewerFailure({
6497
6507
  key: newerBoundaryKey,
6498
- message: reason instanceof Error ? reason.message : String(reason)
6508
+ message: formatError(reason)
6499
6509
  });
6500
6510
  }
6501
6511
  );
6502
6512
  },
6503
- [onLoadNewer, loadingNewer, newerBoundaryKey]
6513
+ [onLoadNewer, loadingNewer, newerBoundaryKey, formatError]
6504
6514
  );
6505
6515
  const previousSourceIdsRef = useRef9(/* @__PURE__ */ new Set());
6506
6516
  const previousSourceBoundaryRef = useRef9(void 0);
@@ -6512,7 +6522,7 @@ function MessageTimeline({
6512
6522
  settlementAnimationRef.current = null;
6513
6523
  }, []);
6514
6524
  const olderPageBudgetRef = useRef9(0);
6515
- const [olderDemand, setOlderDemand] = useState15(0);
6525
+ const [olderDemand, setOlderDemand] = useState14(0);
6516
6526
  const readableTurns = turnSummary?.rolling === true;
6517
6527
  const projectedGroups = useMemo5(
6518
6528
  () => groupTimeline(resolvedItems, { readableTurns }),
@@ -6532,43 +6542,28 @@ function MessageTimeline({
6532
6542
  const topSentinelRef = useRef9(null);
6533
6543
  const bottomSentinelRef = useRef9(null);
6534
6544
  const previousBulkFirstKeyRef = useRef9(void 0);
6535
- const [pinned, setPinned] = useState15(true);
6545
+ const [pinned, setPinned] = useState14(true);
6536
6546
  const { groups: allGroups, release: releaseProgress } = useReadingProgress(
6537
6547
  projectedGroups,
6538
6548
  autoFollow && pinned && !hasNewer,
6539
6549
  scrollRef.current
6540
6550
  );
6541
- const [canSkipTipCatchup, setCanSkipTipCatchup] = useState15(false);
6551
+ const [canSkipTipCatchup, setCanSkipTipCatchup] = useState14(false);
6542
6552
  const canSkipTipCatchupRef = useRef9(false);
6543
- const [bulkActive, setBulkActive] = useState15(true);
6553
+ const [bulkActive, setBulkActive] = useState14(true);
6544
6554
  const olderPrefetchArmedRef = useRef9(false);
6545
- const [olderPrefetchArmed, setOlderPrefetchArmed] = useState15(false);
6555
+ const [olderPrefetchArmed, setOlderPrefetchArmed] = useState14(false);
6546
6556
  const olderLoadAttemptRef = useRef9(null);
6547
- const [underfillSettledAttempt, setUnderfillSettledAttempt] = useState15(
6557
+ const [underfillSettledAttempt, setUnderfillSettledAttempt] = useState14(
6548
6558
  null
6549
6559
  );
6550
6560
  const underfillRetryReadyRef = useRef9(false);
6551
6561
  const resizeFollowRafRef = useRef9(null);
6552
6562
  const questionNavFrameRef = useRef9(null);
6553
- const [questionNav, setQuestionNav] = useState15(null);
6554
- const jumpPillRef = useRef9(null);
6555
- const questionPillRef = useRef9(null);
6563
+ const [questionNav, setQuestionNav] = useState14(null);
6556
6564
  const jumpPillShown = autoFollow && (!pinned || hasNewer || canSkipTipCatchup);
6557
- const jumpPillPlacement = useTimelinePillPlacement({
6558
- pillRef: jumpPillRef,
6559
- scrollerRef: scrollRef,
6560
- active: jumpPillShown,
6561
- preference: JUMP_PILL_PLACEMENTS
6562
- });
6563
- const questionPillPlacement = useTimelinePillPlacement({
6564
- pillRef: questionPillRef,
6565
- scrollerRef: scrollRef,
6566
- active: questionNav !== null,
6567
- preference: QUESTION_PILL_PLACEMENTS,
6568
- allowDownwardFallback: true
6569
- });
6570
6565
  const firstGroupKey = allGroups[0] ? timelineGroupKey(allGroups[0]) : null;
6571
- const [revealed, setRevealed] = useState15(resolvedItems[0]?.id === "c");
6566
+ const [revealed, setRevealed] = useState14(resolvedItems[0]?.id === "c");
6572
6567
  const pinnedRef = useRef9(true);
6573
6568
  const hasNewerRef = useRef9(hasNewer);
6574
6569
  hasNewerRef.current = hasNewer;
@@ -6694,7 +6689,7 @@ function MessageTimeline({
6694
6689
  setOlderPrefetchArmed(true);
6695
6690
  }
6696
6691
  }, [autoFollow, applyPinned, clearPendingReaderLeave, clearReaderIntent, stopFollow]);
6697
- useEffect10(() => {
6692
+ useEffect9(() => {
6698
6693
  if (!readableTurns) return;
6699
6694
  const node = scrollRef.current;
6700
6695
  if (!node) return;
@@ -6962,7 +6957,7 @@ function MessageTimeline({
6962
6957
  setQuestionNav((current) => sameQuestionNav(current, next) ? current : next);
6963
6958
  });
6964
6959
  }, [readableTurns]);
6965
- useEffect10(
6960
+ useEffect9(
6966
6961
  () => () => {
6967
6962
  if (questionNavFrameRef.current != null) {
6968
6963
  cancelFrame(questionNavFrameRef.current);
@@ -7088,8 +7083,8 @@ function MessageTimeline({
7088
7083
  [applyCanSkipTipCatchup, cancelLeaveFallback, stopFollow, syncScrollBaseline, writeScrollTop]
7089
7084
  );
7090
7085
  driveFollowRef.current = driveFollow;
7091
- useEffect10(() => stopFollow, [stopFollow]);
7092
- useEffect10(() => () => cancelLeaveFallback(), [cancelLeaveFallback]);
7086
+ useEffect9(() => stopFollow, [stopFollow]);
7087
+ useEffect9(() => () => cancelLeaveFallback(), [cancelLeaveFallback]);
7093
7088
  useLayoutEffect4(() => {
7094
7089
  const node = scrollRef.current;
7095
7090
  if (!node) {
@@ -7308,7 +7303,7 @@ function MessageTimeline({
7308
7303
  seenActivityIdsRef.current.clear();
7309
7304
  applyPinned(true);
7310
7305
  }, [allGroups.length, revealed, applyPinned, clearReaderIntent]);
7311
- useEffect10(() => {
7306
+ useEffect9(() => {
7312
7307
  const node = scrollRef.current;
7313
7308
  if (node) {
7314
7309
  requestOlderIfUnderfilled(node);
@@ -7323,7 +7318,7 @@ function MessageTimeline({
7323
7318
  const frame = requestFrame(() => setBulkActive(false));
7324
7319
  return () => cancelFrame(frame);
7325
7320
  }, [bulkRender, firstGroupKey]);
7326
- useEffect10(() => {
7321
+ useEffect9(() => {
7327
7322
  const root = scrollRef.current;
7328
7323
  const target = topSentinelRef.current;
7329
7324
  if (!root || !target || !olderPrefetchArmed || !hasOlder || loadingOlder || !onLoadOlder || typeof IntersectionObserver === "undefined") {
@@ -7374,7 +7369,7 @@ function MessageTimeline({
7374
7369
  onLoadOlder,
7375
7370
  requestOlderIfUnderfilled
7376
7371
  ]);
7377
- useEffect10(() => {
7372
+ useEffect9(() => {
7378
7373
  const root = scrollRef.current;
7379
7374
  const target = bottomSentinelRef.current;
7380
7375
  if (!root || !target || !hasNewer || loadingNewer || !onLoadNewer || typeof IntersectionObserver === "undefined") {
@@ -7391,7 +7386,7 @@ function MessageTimeline({
7391
7386
  observer.observe(target);
7392
7387
  return () => observer.disconnect();
7393
7388
  }, [hasNewer, loadingNewer, onLoadNewer, requestNewer, firstGroupKey]);
7394
- useEffect10(() => {
7389
+ useEffect9(() => {
7395
7390
  const node = scrollRef.current;
7396
7391
  const inner = node?.firstElementChild;
7397
7392
  if (!node || !inner || typeof ResizeObserver === "undefined") {
@@ -7428,7 +7423,7 @@ function MessageTimeline({
7428
7423
  }
7429
7424
  };
7430
7425
  }, [autoFollow, driveFollow, requestOlderIfUnderfilled, snapToBottom]);
7431
- useEffect10(() => {
7426
+ useEffect9(() => {
7432
7427
  if (searchTargetRef.current) return;
7433
7428
  if (hasNewer) {
7434
7429
  stopFollow();
@@ -7688,12 +7683,7 @@ function MessageTimeline({
7688
7683
  transition: { duration: 0.15, ease: "easeOut" },
7689
7684
  "data-og-loading-older": "",
7690
7685
  "aria-live": "polite",
7691
- className: cn(
7692
- "pointer-events-none absolute inset-x-0 -top-11 z-10 flex",
7693
- // The scrolling history control and fixed question
7694
- // action must never share the same pointer region.
7695
- questionNav ? "max-w-[calc(50%-0.5rem)] justify-start" : "justify-center"
7696
- ),
7686
+ className: "pointer-events-none absolute inset-x-0 -top-11 z-10 flex justify-center",
7697
7687
  children: [
7698
7688
  loadingOlder || loadingOldest ? /* @__PURE__ */ jsx18("span", { className: LOADING_CHIP_CLASS, children: /* @__PURE__ */ jsx18("span", { className: "og-shimmer-text", children: loadingOldest ? "Jumping to start\u2026" : "Loading earlier activity\u2026" }) }) : null,
7699
7689
  hasOlder && !loadingOlder && !loadingOldest && (underfillRetryReady || onJumpToStart) ? /* @__PURE__ */ jsx18(
@@ -7833,117 +7823,93 @@ function MessageTimeline({
7833
7823
  onSelect: onDraftAnnotationSelect
7834
7824
  }
7835
7825
  ) }) : null,
7836
- /* @__PURE__ */ jsx18(AnimatePresence3, { children: questionNav ? /* @__PURE__ */ jsx18(
7837
- motion3.div,
7838
- {
7839
- initial: { opacity: 0, y: -6 },
7840
- animate: { opacity: 1, y: 0 },
7841
- exit: { opacity: 0, y: -6 },
7842
- transition: { duration: 0.15, ease: "easeOut" },
7843
- "data-og-question-nav": "",
7844
- "data-og-pill-placement": questionPillPlacement.placement,
7845
- style: { marginTop: questionPillPlacement.offsetY },
7846
- className: cn(
7847
- "pointer-events-none absolute inset-x-0 top-11 z-10 flex px-4 sm:px-6 pointer-coarse:top-14",
7848
- QUESTION_PILL_PLACEMENT_CLASS[questionPillPlacement.placement]
7849
- ),
7850
- children: /* @__PURE__ */ jsx18(
7851
- motion3.div,
7852
- {
7853
- ref: questionPillRef,
7854
- layout: "position",
7855
- transition: { duration: 0.18, ease: "easeOut" },
7856
- className: "pointer-events-auto inline-flex max-w-full items-center rounded-full border border-og-border bg-og-surface-3/90 text-og-control font-medium text-og-fg shadow-og-md backdrop-blur",
7857
- children: /* @__PURE__ */ jsxs13(
7858
- "button",
7859
- {
7860
- type: "button",
7861
- "data-og-jump-to-question": "",
7862
- onClick: () => jumpToQuestion(questionNav.key),
7863
- className: "inline-flex min-w-0 items-center gap-1.5 whitespace-nowrap px-3 py-1.5 hover:text-og-fg pointer-coarse:min-h-11",
7864
- children: [
7865
- /* @__PURE__ */ jsx18(ArrowUpIcon, { "aria-hidden": true, className: "size-3.5" }),
7866
- "Back to your message"
7867
- ]
7868
- }
7869
- )
7870
- }
7871
- )
7872
- },
7873
- "question-nav"
7874
- ) : null }),
7875
- /* @__PURE__ */ jsx18(AnimatePresence3, { children: loadingNewer ? /* @__PURE__ */ jsx18(
7876
- motion3.div,
7877
- {
7878
- initial: { opacity: 0, y: 6 },
7879
- animate: { opacity: 1, y: 0 },
7880
- exit: { opacity: 0, y: 6 },
7881
- transition: { duration: 0.15, ease: "easeOut" },
7882
- "data-og-loading-newer": "",
7883
- "aria-live": "polite",
7884
- className: "pointer-events-none absolute inset-x-0 bottom-14 z-10 flex justify-center",
7885
- children: /* @__PURE__ */ jsx18("span", { className: LOADING_CHIP_CLASS, children: /* @__PURE__ */ jsx18("span", { className: "og-shimmer-text", children: "Loading later activity\u2026" }) })
7886
- }
7887
- ) : null }),
7888
- /* @__PURE__ */ jsx18(AnimatePresence3, { children: jumpPillShown ? /* @__PURE__ */ jsxs13(
7889
- motion3.button,
7826
+ /* @__PURE__ */ jsx18(
7827
+ "div",
7890
7828
  {
7891
- ref: jumpPillRef,
7892
- type: "button",
7893
- "data-og-jump-to-latest": "",
7894
- "data-og-pill-placement": jumpPillPlacement.placement,
7895
- layout: "position",
7896
- initial: { opacity: 0, y: 8 },
7897
- animate: { opacity: 1, y: 0 },
7898
- exit: { opacity: 0, y: 8 },
7899
- transition: { duration: 0.15, ease: "easeOut" },
7900
- onClick: () => {
7901
- const viewport = scrollRef.current;
7902
- const selection = viewport?.ownerDocument.getSelection();
7903
- if (selection && !selection.isCollapsed && (viewport?.contains(selection.anchorNode) || viewport?.contains(selection.focusNode)))
7904
- selection.removeAllRanges();
7905
- disclosureKeepsUnpinnedRef.current = false;
7906
- if (hasNewer) {
7907
- wantPinRef.current = true;
7908
- const node2 = scrollRef.current;
7909
- if (onJumpToLatest) {
7910
- void Promise.resolve(onJumpToLatest()).then(
7911
- () => {
7912
- const current = scrollRef.current;
7913
- if (current && wantPinRef.current && !hasNewerRef.current) {
7914
- wantPinRef.current = false;
7915
- applyPinned(true);
7916
- snapToBottom(current);
7829
+ "data-og-timeline-nav": "",
7830
+ className: "pointer-events-none absolute inset-x-0 bottom-4 z-10 flex flex-col items-center gap-2 px-4 sm:px-6",
7831
+ children: /* @__PURE__ */ jsxs13(AnimatePresence3, { mode: "popLayout", children: [
7832
+ loadingNewer ? /* @__PURE__ */ jsx18(
7833
+ motion3.div,
7834
+ {
7835
+ layout: "position",
7836
+ ...NAV_PILL_MOTION,
7837
+ "data-og-loading-newer": "",
7838
+ "aria-live": "polite",
7839
+ className: "flex max-w-full justify-center",
7840
+ children: /* @__PURE__ */ jsx18("span", { className: LOADING_CHIP_CLASS, children: /* @__PURE__ */ jsx18("span", { className: "og-shimmer-text", children: "Loading later activity\u2026" }) })
7841
+ },
7842
+ "loading-newer"
7843
+ ) : null,
7844
+ questionNav ? /* @__PURE__ */ jsxs13(
7845
+ motion3.button,
7846
+ {
7847
+ layout: "position",
7848
+ ...NAV_PILL_MOTION,
7849
+ type: "button",
7850
+ "data-og-question-nav": "",
7851
+ "data-og-jump-to-question": "",
7852
+ onClick: () => jumpToQuestion(questionNav.key),
7853
+ className: NAV_PILL_CLASS,
7854
+ children: [
7855
+ /* @__PURE__ */ jsx18(ArrowUpIcon, { "aria-hidden": true, className: "size-3.5 shrink-0" }),
7856
+ "Back to your message"
7857
+ ]
7858
+ },
7859
+ "question-nav"
7860
+ ) : null,
7861
+ jumpPillShown ? /* @__PURE__ */ jsxs13(
7862
+ motion3.button,
7863
+ {
7864
+ layout: "position",
7865
+ ...NAV_PILL_MOTION,
7866
+ type: "button",
7867
+ "data-og-jump-to-latest": "",
7868
+ onClick: () => {
7869
+ const viewport = scrollRef.current;
7870
+ const selection = viewport?.ownerDocument.getSelection();
7871
+ if (selection && !selection.isCollapsed && (viewport?.contains(selection.anchorNode) || viewport?.contains(selection.focusNode)))
7872
+ selection.removeAllRanges();
7873
+ disclosureKeepsUnpinnedRef.current = false;
7874
+ if (hasNewer) {
7875
+ wantPinRef.current = true;
7876
+ const node2 = scrollRef.current;
7877
+ if (onJumpToLatest) {
7878
+ void Promise.resolve(onJumpToLatest()).then(
7879
+ () => {
7880
+ const current = scrollRef.current;
7881
+ if (current && wantPinRef.current && !hasNewerRef.current) {
7882
+ wantPinRef.current = false;
7883
+ applyPinned(true);
7884
+ snapToBottom(current);
7885
+ }
7886
+ },
7887
+ () => {
7888
+ wantPinRef.current = false;
7889
+ }
7890
+ );
7891
+ } else if (node2) {
7892
+ snapToBottom(node2);
7917
7893
  }
7918
- },
7919
- () => {
7920
- wantPinRef.current = false;
7894
+ return;
7921
7895
  }
7922
- );
7923
- } else if (node2) {
7924
- snapToBottom(node2);
7925
- }
7926
- return;
7927
- }
7928
- const node = scrollRef.current;
7929
- if (node) {
7930
- applyPinned(true);
7931
- snapToBottom(node);
7932
- }
7933
- },
7934
- className: cn(
7935
- "absolute bottom-4 w-fit",
7936
- JUMP_PILL_PLACEMENT_CLASS[jumpPillPlacement.placement],
7937
- "inline-flex items-center gap-1.5 rounded-full border border-og-border bg-og-surface-3/90 px-3 py-1.5",
7938
- "text-og-control font-medium text-og-fg shadow-og-md backdrop-blur",
7939
- "hover:border-og-border-strong"
7940
- ),
7941
- children: [
7942
- /* @__PURE__ */ jsx18(ArrowDownIcon, { className: "size-3.5" }),
7943
- "Jump to latest"
7944
- ]
7896
+ const node = scrollRef.current;
7897
+ if (node) {
7898
+ applyPinned(true);
7899
+ snapToBottom(node);
7900
+ }
7901
+ },
7902
+ className: NAV_PILL_CLASS,
7903
+ children: [
7904
+ /* @__PURE__ */ jsx18(ArrowDownIcon, { "aria-hidden": true, className: "size-3.5 shrink-0" }),
7905
+ "Jump to latest"
7906
+ ]
7907
+ },
7908
+ "jump-to-latest"
7909
+ ) : null
7910
+ ] })
7945
7911
  }
7946
- ) : null })
7912
+ )
7947
7913
  ]
7948
7914
  }
7949
7915
  ) }) }) }) }) }) }) })
@@ -8952,7 +8918,7 @@ function WorkerCompletionRow({
8952
8918
  onOpenSession
8953
8919
  }) {
8954
8920
  const enter = useEntranceAnimation();
8955
- const [open, setOpen] = useState15(false);
8921
+ const [open, setOpen] = useState14(false);
8956
8922
  const meta = workerCompletionMeta(item);
8957
8923
  const Icon = meta.icon;
8958
8924
  const showPausedReason = item.childStatus !== "failed" && item.goalStatus === "paused" && !!item.pausedReason?.trim();
@@ -9359,8 +9325,8 @@ function AuthNeededRow({
9359
9325
  resolveProviderLogo
9360
9326
  }) {
9361
9327
  const enter = useEntranceAnimation();
9362
- const [busy, setBusy] = useState15(false);
9363
- const [failed, setFailed] = useState15(false);
9328
+ const [busy, setBusy] = useState14(false);
9329
+ const [failed, setFailed] = useState14(false);
9364
9330
  const recommendation = item.capability ?? null;
9365
9331
  const provider = recommendation?.name ?? (item.serverId === "codex_apps" ? "Codex Apps" : providerLabel(item.providerDomain));
9366
9332
  const unavailable = item.reason === "personal_authority_unavailable" || item.reason === "unsupported_auth" || item.reason === "resource_scope_unavailable";
@@ -9464,8 +9430,8 @@ function AuthNeededRow({
9464
9430
  ] });
9465
9431
  }
9466
9432
  function AuthProviderLogo({ src, label }) {
9467
- const [failed, setFailed] = useState15(false);
9468
- useEffect10(() => setFailed(false), [src]);
9433
+ const [failed, setFailed] = useState14(false);
9434
+ useEffect9(() => setFailed(false), [src]);
9469
9435
  const showImage = src && !failed;
9470
9436
  return /* @__PURE__ */ jsx18(
9471
9437
  "span",
@@ -9528,7 +9494,7 @@ function authReasonLine(reason) {
9528
9494
  import { Loader2Icon } from "lucide-react";
9529
9495
  import { lazy as lazy4, Suspense as Suspense5 } from "react";
9530
9496
  import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
9531
- var loadQueueSurface = () => import("./queue-surface-implementation-2CAQAIHM.js");
9497
+ var loadQueueSurface = () => import("./queue-surface-implementation-HENWYFWA.js");
9532
9498
  var QueueSurface = createQueueSurface(loadQueueSurface);
9533
9499
  function createQueueSurface(loadImplementation) {
9534
9500
  const LazyQueueSurface = lazy4(async () => ({
@@ -9794,7 +9760,7 @@ import {
9794
9760
  TargetIcon as TargetIcon3
9795
9761
  } from "lucide-react";
9796
9762
  import { AnimatePresence as AnimatePresence4, motion as motion5, useReducedMotion as useReducedMotion4 } from "motion/react";
9797
- import { useEffect as useEffect11, useId as useId4, useMemo as useMemo6, useRef as useRef10, useState as useState16 } from "react";
9763
+ import { useEffect as useEffect10, useId as useId4, useMemo as useMemo6, useRef as useRef10, useState as useState15 } from "react";
9798
9764
  import { Fragment as Fragment8, jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
9799
9765
  var GOAL_LABEL = {
9800
9766
  pursuing: "Pursuing",
@@ -9910,8 +9876,8 @@ function formatCoarseElapsed(ms) {
9910
9876
  }
9911
9877
  function useLiveElapsed(startIso, live, endIso) {
9912
9878
  const start = startIso ? Date.parse(startIso) : Number.NaN;
9913
- const [now, setNow] = useState16(() => Date.now());
9914
- useEffect11(() => {
9879
+ const [now, setNow] = useState15(() => Date.now());
9880
+ useEffect10(() => {
9915
9881
  if (!live) return;
9916
9882
  const id = setInterval(() => setNow(Date.now()), 1e3);
9917
9883
  return () => clearInterval(id);
@@ -9983,7 +9949,8 @@ function SessionChrome({
9983
9949
  defaultActive = null,
9984
9950
  onActiveChange
9985
9951
  }) {
9986
- const [activityRequested, setActivityOpen] = useState16(
9952
+ const formatError = useErrorMessage();
9953
+ const [activityRequested, setActivityOpen] = useState15(
9987
9954
  Boolean(defaultActive && ["incoming", "agents", "commands"].includes(defaultActive))
9988
9955
  );
9989
9956
  const reactId = useId4();
@@ -10013,7 +9980,7 @@ function SessionChrome({
10013
9980
  queue.queue,
10014
9981
  queue.mutationFor
10015
9982
  );
10016
- const [activeUncontrolled, setActiveUncontrolled] = useState16(
9983
+ const [activeUncontrolled, setActiveUncontrolled] = useState15(
10017
9984
  () => sessionChromeInitialActive({
10018
9985
  defaultActive,
10019
9986
  authoritativeQueuedCount: initialAuthoritativeQueuedCount
@@ -10024,13 +9991,13 @@ function SessionChrome({
10024
9991
  const openedQueueTargetRef = useRef10(null);
10025
9992
  const focusedQueueTargetRef = useRef10(null);
10026
9993
  const queueTargetKey = queueFocusTarget ? `${queueFocusTarget.turnId}:${queueFocusTarget.requestId}` : null;
10027
- useEffect11(() => {
9994
+ useEffect10(() => {
10028
9995
  if (!queueTargetKey || openedQueueTargetRef.current === queueTargetKey) return;
10029
9996
  openedQueueTargetRef.current = queueTargetKey;
10030
9997
  if (activeControlled === void 0) setActiveUncontrolled("queue");
10031
9998
  onActiveChange?.("queue");
10032
9999
  }, [queueTargetKey, activeControlled, onActiveChange]);
10033
- useEffect11(() => {
10000
+ useEffect10(() => {
10034
10001
  if (!queueFocusTarget || active !== "queue" || focusedQueueTargetRef.current === queueTargetKey)
10035
10002
  return;
10036
10003
  const root = rootRef.current;
@@ -10150,8 +10117,8 @@ function SessionChrome({
10150
10117
  ]);
10151
10118
  const optimisticQueueKeys = optimisticQueued.map((message) => message.clientEventId).join(",");
10152
10119
  const previousOptimisticQueueKeys = useRef10(optimisticQueueKeys);
10153
- const [queueArrivalNonce, setQueueArrivalNonce] = useState16(0);
10154
- useEffect11(() => {
10120
+ const [queueArrivalNonce, setQueueArrivalNonce] = useState15(0);
10121
+ useEffect10(() => {
10155
10122
  const previous = new Set(previousOptimisticQueueKeys.current.split(",").filter(Boolean));
10156
10123
  const arrived = optimisticQueued.some((message) => !previous.has(message.clientEventId));
10157
10124
  previousOptimisticQueueKeys.current = optimisticQueueKeys;
@@ -10162,13 +10129,13 @@ function SessionChrome({
10162
10129
  }
10163
10130
  }, [active, activeControlled, optimisticQueueKeys, optimisticQueued]);
10164
10131
  const queueOccupied = queuedTurns.length > 0 || optimisticQueued.length > 0;
10165
- useEffect11(() => {
10132
+ useEffect10(() => {
10166
10133
  if (queueOccupied) return;
10167
10134
  queueOfferAdmissionSuppressedRef.current = false;
10168
10135
  queueOfferDismissedSessionIdsRef.current.clear();
10169
10136
  }, [queueOccupied]);
10170
10137
  const queueOfferSuppressed = queueOfferAdmissionSuppressedRef.current || occupancySessionId != null && queueOfferDismissedSessionIdsRef.current.has(occupancySessionId);
10171
- useEffect11(() => {
10138
+ useEffect10(() => {
10172
10139
  if (!sessionChromeShouldOfferQueue({
10173
10140
  controlled: activeControlled !== void 0,
10174
10141
  active,
@@ -10189,28 +10156,28 @@ function SessionChrome({
10189
10156
  queueOfferSuppressed,
10190
10157
  queuedTurns.length
10191
10158
  ]);
10192
- const [replaceDraftFor, setReplaceDraftFor] = useState16(null);
10159
+ const [replaceDraftFor, setReplaceDraftFor] = useState15(null);
10193
10160
  const chipRefs = useRef10({});
10194
10161
  const railRef = useRef10(null);
10195
- const [pill, setPill] = useState16({ left: 0, top: 0, width: 0, height: 0, opacity: 0 });
10162
+ const [pill, setPill] = useState15({ left: 0, top: 0, width: 0, height: 0, opacity: 0 });
10196
10163
  const signalIds = signals.map((signal) => signal.id).join(",");
10197
- useEffect11(() => {
10164
+ useEffect10(() => {
10198
10165
  if (!signals.some((signal) => ["incoming", "agents", "commands"].includes(signal.id)))
10199
10166
  setActivityOpen(false);
10200
10167
  }, [signals]);
10201
- useEffect11(() => {
10168
+ useEffect10(() => {
10202
10169
  if (active && !signalIds.split(",").includes(active)) {
10203
10170
  if (activeControlled === void 0) setActiveUncontrolled(null);
10204
10171
  onActiveChange?.(null);
10205
10172
  }
10206
10173
  }, [active, activeControlled, onActiveChange, signalIds]);
10207
- useEffect11(() => {
10174
+ useEffect10(() => {
10208
10175
  if (active !== "queue" || !replaceDraftFor) return;
10209
10176
  if (!queuedTurns.some((turn) => turn.id === replaceDraftFor)) {
10210
10177
  setReplaceDraftFor(null);
10211
10178
  }
10212
10179
  }, [active, queuedTurns, replaceDraftFor]);
10213
- useEffect11(() => {
10180
+ useEffect10(() => {
10214
10181
  const rail = railRef.current;
10215
10182
  const measure = () => {
10216
10183
  if (!rail || !active) {
@@ -10578,7 +10545,7 @@ function SessionChrome({
10578
10545
  ) : null }),
10579
10546
  goal?.mutationError ? /* @__PURE__ */ jsxs16("p", { role: "alert", className: "px-3 pb-2 text-og-xs text-og-danger", children: [
10580
10547
  "Goal action not confirmed. ",
10581
- goal.mutationError.message
10548
+ formatError(goal.mutationError)
10582
10549
  ] }) : null,
10583
10550
  /* @__PURE__ */ jsx21(
10584
10551
  "div",
@@ -10727,10 +10694,10 @@ function QueuePanel({
10727
10694
  }) {
10728
10695
  const reduceMotion = useReducedMotion4();
10729
10696
  const turnIdsKey = turns.map((turn) => turn.id).join(",");
10730
- const [interactiveTurnIds, setInteractiveTurnIds] = useState16(
10697
+ const [interactiveTurnIds, setInteractiveTurnIds] = useState15(
10731
10698
  () => /* @__PURE__ */ new Set()
10732
10699
  );
10733
- useEffect11(() => {
10700
+ useEffect10(() => {
10734
10701
  const visibleTurnIds = new Set(turnIdsKey ? turnIdsKey.split(",") : []);
10735
10702
  setInteractiveTurnIds((current) => {
10736
10703
  const retained = new Set([...current].filter((turnId) => visibleTurnIds.has(turnId)));
@@ -10987,6 +10954,7 @@ function GoalPanel({
10987
10954
  elapsed,
10988
10955
  readOnly
10989
10956
  }) {
10957
+ const formatError = useErrorMessage();
10990
10958
  const record = goal.goal;
10991
10959
  if (!record) return null;
10992
10960
  const canToggle = !readOnly && (record.status === "active" || record.status === "paused");
@@ -11018,7 +10986,7 @@ function GoalPanel({
11018
10986
  children: explanation
11019
10987
  }
11020
10988
  ) : null,
11021
- record.continuation?.lastError ? /* @__PURE__ */ jsx21("p", { className: "rounded-og-sm bg-og-status-waiting/10 px-1.5 py-1 text-og-xs leading-4 text-og-status-waiting", children: record.continuation.lastError }) : null,
10989
+ record.continuation?.lastError ? /* @__PURE__ */ jsx21("p", { className: "rounded-og-sm bg-og-status-waiting/10 px-1.5 py-1 text-og-xs leading-4 text-og-status-waiting", children: formatError(record.continuation.lastError) }) : null,
11022
10990
  /* @__PURE__ */ jsxs16("div", { className: "flex flex-wrap items-center justify-between gap-1.5 pt-0.5", children: [
11023
10991
  /* @__PURE__ */ jsxs16("div", { className: "flex flex-wrap gap-1 text-[10px] text-og-fg-muted", children: [
11024
10992
  /* @__PURE__ */ jsxs16("span", { className: "rounded bg-og-surface-3/70 px-1 py-px", children: [
@@ -11110,10 +11078,10 @@ import {
11110
11078
  lazy as lazy5,
11111
11079
  Suspense as Suspense6,
11112
11080
  useCallback as useCallback5,
11113
- useEffect as useEffect12,
11081
+ useEffect as useEffect11,
11114
11082
  useMemo as useMemo7,
11115
11083
  useRef as useRef11,
11116
- useState as useState17
11084
+ useState as useState16
11117
11085
  } from "react";
11118
11086
  import { Fragment as Fragment9, jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
11119
11087
  function SessionConversation(props) {
@@ -11140,6 +11108,7 @@ function Conversation({
11140
11108
  }) {
11141
11109
  const scope = { client, workspaceId };
11142
11110
  const context = useOpenGeni(scope);
11111
+ const formatError = useErrorMessage();
11143
11112
  const config = useClientConfigFlags(context.client);
11144
11113
  const showModelPicker = modelPicker ?? config.modelSelection;
11145
11114
  const catalog = useWorkspaceModelCatalog({
@@ -11217,7 +11186,7 @@ function Conversation({
11217
11186
  style: { height },
11218
11187
  "data-og-conversation": "",
11219
11188
  children: [
11220
- error && /* @__PURE__ */ jsx22("p", { role: "alert", children: error.message }),
11189
+ error && /* @__PURE__ */ jsx22("p", { role: "alert", children: formatError(error) }),
11221
11190
  /* @__PURE__ */ jsx22(
11222
11191
  MessageTimeline,
11223
11192
  {
@@ -11278,7 +11247,7 @@ function Conversation({
11278
11247
  await human.respond(id, response);
11279
11248
  },
11280
11249
  respondingRequestId: human.respondingRequestId,
11281
- error: human.mutationError?.message,
11250
+ error: human.mutationError ? formatError(human.mutationError) : null,
11282
11251
  autoFocus: false
11283
11252
  }
11284
11253
  ),
@@ -11356,8 +11325,8 @@ function useDefaultInteractiveBlock(client, workspaceId, sessionId) {
11356
11325
  );
11357
11326
  }
11358
11327
  function useClientConfigFlags(client) {
11359
- const [flags, setFlags] = useState17({ uploads: false, modelSelection: true, sandboxFiles: false });
11360
- useEffect12(() => {
11328
+ const [flags, setFlags] = useState16({ uploads: false, modelSelection: true, sandboxFiles: false });
11329
+ useEffect11(() => {
11361
11330
  let live = true;
11362
11331
  client.getClientConfig().then(
11363
11332
  (config) => {
@@ -11379,14 +11348,16 @@ function useClientConfigFlags(client) {
11379
11348
  }
11380
11349
 
11381
11350
  // src/hooks/use-workspace-sessions.ts
11382
- import { useCallback as useCallback6, useEffect as useEffect13, useRef as useRef12 } from "react";
11351
+ import { useCallback as useCallback6, useEffect as useEffect12, useRef as useRef12 } from "react";
11383
11352
  function useWorkspaceSessions(options = {}) {
11384
11353
  const { client, workspaceId } = useOpenGeni(options);
11354
+ const projection = options.projection;
11385
11355
  const limit = options.limit;
11386
11356
  const parentSessionId = options.parentSessionId;
11387
11357
  const cursor = options.cursor;
11388
11358
  const search = options.search;
11389
11359
  const pinsOnly = options.pinsOnly;
11360
+ const includePinned = options.includePinned;
11390
11361
  const archivedOnly = options.archivedOnly;
11391
11362
  const sortBy = options.sortBy;
11392
11363
  const archiveStatus = options.archiveStatus;
@@ -11396,34 +11367,45 @@ function useWorkspaceSessions(options = {}) {
11396
11367
  const beginRead = options.beginRead;
11397
11368
  const queryKey = [
11398
11369
  workspaceId,
11370
+ projection ?? "full",
11399
11371
  limit ?? "",
11400
11372
  parentSessionId === null ? "null" : parentSessionId ?? "",
11401
11373
  cursor ?? "",
11402
11374
  search ?? "",
11403
11375
  pinsOnly ? "1" : "",
11376
+ includePinned === false ? "no-pins" : "",
11404
11377
  archivedOnly ? "archived" : "active",
11405
11378
  sortBy ?? "",
11406
11379
  archiveStatus ?? ""
11407
11380
  ].join("\0");
11408
11381
  const previousQueryKey = useRef12(queryKey);
11409
11382
  const queryKeyTransition = previousQueryKey.current !== queryKey;
11410
- useEffect13(() => {
11383
+ useEffect12(() => {
11411
11384
  previousQueryKey.current = queryKey;
11412
11385
  }, [queryKey]);
11413
11386
  const load = useCallback6(
11414
11387
  async (signal) => {
11415
11388
  const readGeneration = beginRead?.() ?? ++nextReadGeneration.current;
11416
- const page2 = await client.listSessionPage(workspaceId, {
11389
+ const query = {
11417
11390
  ...limit !== void 0 ? { limit } : {},
11418
11391
  ...parentSessionId !== void 0 ? { parentSessionId } : {},
11419
11392
  ...cursor !== void 0 ? { cursor } : {},
11420
11393
  ...search !== void 0 ? { search } : {},
11421
11394
  ...pinsOnly ? { pinsOnly: true } : {},
11395
+ ...includePinned === false ? { includePinned: false } : {},
11422
11396
  ...archivedOnly ? { archivedOnly: true } : {},
11423
11397
  ...sortBy ? { sortBy } : {},
11424
11398
  ...archiveStatus ? { archiveStatus } : {},
11425
11399
  signal
11426
- });
11400
+ };
11401
+ const page2 = projection === "summary" ? client.listSessionSummaryPage ? await client.listSessionSummaryPage(workspaceId, query) : await client.listSessionPage(workspaceId, query).then(async (full) => {
11402
+ const { sessionListEntry } = await import("@opengeni/sdk/session-list-entries");
11403
+ return {
11404
+ ...full,
11405
+ pinned: full.pinned.map(sessionListEntry),
11406
+ sessions: full.sessions.map(sessionListEntry)
11407
+ };
11408
+ }) : await client.listSessionPage(workspaceId, query);
11427
11409
  return {
11428
11410
  queryKey,
11429
11411
  page: page2,
@@ -11435,11 +11417,13 @@ function useWorkspaceSessions(options = {}) {
11435
11417
  beginRead,
11436
11418
  client,
11437
11419
  workspaceId,
11420
+ projection,
11438
11421
  limit,
11439
11422
  parentSessionId,
11440
11423
  cursor,
11441
11424
  search,
11442
11425
  pinsOnly,
11426
+ includePinned,
11443
11427
  archivedOnly,
11444
11428
  sortBy,
11445
11429
  archiveStatus,
@@ -11476,7 +11460,7 @@ function useWorkspaceSessions(options = {}) {
11476
11460
  // src/components/session-list.tsx
11477
11461
  import { deriveSessionDisplayTitle } from "@opengeni/sdk";
11478
11462
  import { ArchiveIcon, PencilIcon as PencilIcon2, PlusIcon } from "lucide-react";
11479
- import { useEffect as useEffect14, useRef as useRef13, useState as useState18 } from "react";
11463
+ import { useEffect as useEffect13, useRef as useRef13, useState as useState17 } from "react";
11480
11464
  import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
11481
11465
  var DEFAULT_LABELS = {
11482
11466
  heading: "Chats",
@@ -11506,7 +11490,7 @@ function SessionList({
11506
11490
  const labels = { ...DEFAULT_LABELS, ...labelOverrides };
11507
11491
  const scope = { client, workspaceId };
11508
11492
  const context = useOpenGeni(scope);
11509
- const [limit, setLimit] = useState18(pageSize);
11493
+ const [limit, setLimit] = useState17(pageSize);
11510
11494
  const list = useWorkspaceSessions({
11511
11495
  ...scope,
11512
11496
  parentSessionId: null,
@@ -11516,14 +11500,15 @@ function SessionList({
11516
11500
  });
11517
11501
  const refresh = list.refresh;
11518
11502
  const firstRefreshKey = useRef13(refreshKey);
11519
- useEffect14(() => {
11503
+ useEffect13(() => {
11520
11504
  if (Object.is(refreshKey, firstRefreshKey.current)) return;
11521
11505
  firstRefreshKey.current = refreshKey;
11522
11506
  void refresh();
11523
11507
  }, [refresh, refreshKey]);
11524
- const [editing, setEditing] = useState18(null);
11525
- const [busy, setBusy] = useState18(null);
11526
- const [error, setError] = useState18(null);
11508
+ const [editing, setEditing] = useState17(null);
11509
+ const [busy, setBusy] = useState17(null);
11510
+ const [error, setError] = useState17(null);
11511
+ const formatError = useErrorMessage();
11527
11512
  const archiveClient = context.client;
11528
11513
  const canArchive = archive && typeof archiveClient.updateSessionArchive === "function";
11529
11514
  const run = async (id, action) => {
@@ -11533,7 +11518,7 @@ function SessionList({
11533
11518
  await action();
11534
11519
  await list.refresh();
11535
11520
  } catch (cause) {
11536
- setError(cause instanceof Error ? cause.message : String(cause));
11521
+ setError({ cause });
11537
11522
  } finally {
11538
11523
  setBusy(null);
11539
11524
  }
@@ -11580,10 +11565,10 @@ function SessionList({
11580
11565
  }
11581
11566
  ) : null
11582
11567
  ] }),
11583
- error ? /* @__PURE__ */ jsx23("p", { role: "alert", className: "px-2 text-og-xs text-og-status-failed", children: error }) : null,
11568
+ error || list.error ? /* @__PURE__ */ jsx23("p", { role: "alert", className: "px-2 text-og-xs text-og-status-failed", children: formatError(error ? error.cause : list.error) }) : null,
11584
11569
  /* @__PURE__ */ jsxs18("ul", { className: "flex min-h-0 flex-1 flex-col gap-0.5 overflow-y-auto px-1 pb-2", children: [
11585
11570
  list.loading && sessions.length === 0 ? /* @__PURE__ */ jsx23("li", { className: "px-2 py-2 text-og-xs text-og-fg-subtle", children: labels.loading }) : null,
11586
- !list.loading && sessions.length === 0 ? /* @__PURE__ */ jsx23("li", { className: "px-2 py-2 text-og-xs text-og-fg-subtle", children: labels.empty }) : null,
11571
+ !list.loading && !list.error && sessions.length === 0 ? /* @__PURE__ */ jsx23("li", { className: "px-2 py-2 text-og-xs text-og-fg-subtle", children: labels.empty }) : null,
11587
11572
  sessions.map((session) => {
11588
11573
  const selected = session.id === selectedSessionId;
11589
11574
  const title = deriveSessionDisplayTitle(session);
@@ -11673,7 +11658,7 @@ function SessionList({
11673
11658
 
11674
11659
  // src/components/open-geni-chat.tsx
11675
11660
  import { MenuIcon, SendIcon, XIcon as XIcon3 } from "lucide-react";
11676
- import { useCallback as useCallback7, useRef as useRef14, useState as useState19 } from "react";
11661
+ import { useCallback as useCallback7, useRef as useRef14, useState as useState18 } from "react";
11677
11662
  import { jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
11678
11663
  var DEFAULT_LABELS2 = {
11679
11664
  openChats: "Open chats",
@@ -11699,10 +11684,10 @@ function OpenGeniChat({
11699
11684
  const labels = { ...DEFAULT_LABELS2, ...labelOverrides };
11700
11685
  const scope = { client, workspaceId };
11701
11686
  const context = useOpenGeni(scope);
11702
- const [uncontrolled, setUncontrolled] = useState19(defaultSessionId);
11687
+ const [uncontrolled, setUncontrolled] = useState18(defaultSessionId);
11703
11688
  const selected = controlledSessionId !== void 0 ? controlledSessionId : uncontrolled;
11704
- const [drawerOpen, setDrawerOpen] = useState19(false);
11705
- const [listRevision, setListRevision] = useState19(0);
11689
+ const [drawerOpen, setDrawerOpen] = useState18(false);
11690
+ const [listRevision, setListRevision] = useState18(0);
11706
11691
  const select = useCallback7(
11707
11692
  (next) => {
11708
11693
  if (controlledSessionId === void 0) setUncontrolled(next);
@@ -11824,9 +11809,10 @@ function NewChat({
11824
11809
  create,
11825
11810
  onCreated
11826
11811
  }) {
11827
- const [text, setText] = useState19("");
11828
- const [sending, setSending] = useState19(false);
11829
- const [error, setError] = useState19(null);
11812
+ const [text, setText] = useState18("");
11813
+ const [sending, setSending] = useState18(false);
11814
+ const [error, setError] = useState18(null);
11815
+ const formatError = useErrorMessage();
11830
11816
  const idempotencyKey = useRef14(crypto.randomUUID());
11831
11817
  const submit = async (event) => {
11832
11818
  event.preventDefault();
@@ -11840,7 +11826,7 @@ function NewChat({
11840
11826
  setText("");
11841
11827
  onCreated(id);
11842
11828
  } catch (cause) {
11843
- setError(cause instanceof Error ? cause.message : String(cause));
11829
+ setError({ cause });
11844
11830
  } finally {
11845
11831
  setSending(false);
11846
11832
  }
@@ -11849,10 +11835,13 @@ function NewChat({
11849
11835
  "form",
11850
11836
  {
11851
11837
  onSubmit: (event) => void submit(event),
11852
- className: "flex h-full flex-col justify-end gap-2 p-3",
11838
+ className: "box-border flex h-full flex-col justify-end gap-2 p-3",
11853
11839
  "data-og-new-chat-composer": "",
11854
11840
  children: [
11855
- error ? /* @__PURE__ */ jsx24("p", { role: "alert", className: "text-og-xs text-og-status-failed", children: error }) : null,
11841
+ error ? /* @__PURE__ */ jsx24("p", { role: "alert", className: "text-og-xs text-og-status-failed", children: formatError(
11842
+ error.cause,
11843
+ error.cause instanceof Error && error.cause.message === labels.newChatUnavailable ? labels.newChatUnavailable : void 0
11844
+ ) }) : null,
11856
11845
  /* @__PURE__ */ jsxs19("div", { className: "flex items-end gap-2 rounded-lg border border-og-border bg-og-surface-1 p-2", children: [
11857
11846
  /* @__PURE__ */ jsx24(
11858
11847
  "textarea",
@@ -11890,14 +11879,15 @@ function NewChat({
11890
11879
 
11891
11880
  // src/components/session-commands-panel.tsx
11892
11881
  import { ChevronRightIcon as ChevronRightIcon3, Loader2Icon as Loader2Icon3, SquareIcon } from "lucide-react";
11893
- import { useState as useState20 } from "react";
11882
+ import { useState as useState19 } from "react";
11894
11883
  import { jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
11895
11884
  function SessionCommandsPanel({
11896
11885
  commands: state,
11897
11886
  readOnly = false
11898
11887
  }) {
11899
- const [pending, setPending] = useState20(null);
11900
- const [error, setError] = useState20(null);
11888
+ const formatError = useErrorMessage();
11889
+ const [pending, setPending] = useState19(null);
11890
+ const [error, setError] = useState19(null);
11901
11891
  const active = state.commands.filter(
11902
11892
  (command) => command.state === "running" || command.state === "stopping"
11903
11893
  );
@@ -11907,7 +11897,7 @@ function SessionCommandsPanel({
11907
11897
  try {
11908
11898
  await state.cancel(id);
11909
11899
  } catch (cause) {
11910
- setError(cause instanceof Error ? cause.message : "Stop was not confirmed. Try again.");
11900
+ setError(formatError(cause));
11911
11901
  } finally {
11912
11902
  setPending(null);
11913
11903
  }
@@ -11986,7 +11976,7 @@ function SessionCommandsPanel({
11986
11976
  }
11987
11977
 
11988
11978
  // src/hooks/use-session-background-commands.ts
11989
- import { useCallback as useCallback8, useEffect as useEffect15, useRef as useRef15 } from "react";
11979
+ import { useCallback as useCallback8, useEffect as useEffect14, useRef as useRef15 } from "react";
11990
11980
  function useSessionBackgroundCommands(sessionId, options = {}) {
11991
11981
  const { client, workspaceId } = useOpenGeni(options);
11992
11982
  const enabled = (options.enabled ?? true) && Boolean(sessionId);
@@ -12006,7 +11996,7 @@ function useSessionBackgroundCommands(sessionId, options = {}) {
12006
11996
  });
12007
11997
  const refresh = state.refresh;
12008
11998
  const generation = useRef15(0);
12009
- useEffect15(() => {
11999
+ useEffect14(() => {
12010
12000
  generation.current += 1;
12011
12001
  return () => {
12012
12002
  generation.current += 1;
@@ -12210,4 +12200,4 @@ export {
12210
12200
  SessionCommands,
12211
12201
  StartupTimings
12212
12202
  };
12213
- //# sourceMappingURL=chunk-LZ3KHA55.js.map
12203
+ //# sourceMappingURL=chunk-ZYALTAEQ.js.map