@opengeni/react 0.34.1 → 0.34.3

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 (60) hide show
  1. package/dist/{chunk-A2WITZTI.js → chunk-4NMH6UJ3.js} +2 -2
  2. package/dist/{chunk-GZ4KR67U.js → chunk-ALA3UGWB.js} +2 -2
  3. package/dist/chunk-ATSTR5P3.js +138 -0
  4. package/dist/chunk-ATSTR5P3.js.map +1 -0
  5. package/dist/{chunk-KZRUYCL4.js → chunk-FT2TXNGZ.js} +5 -2
  6. package/dist/chunk-FT2TXNGZ.js.map +1 -0
  7. package/dist/{chunk-4QOQ2DSR.js → chunk-LAKLF4PA.js} +14 -1
  8. package/dist/chunk-LAKLF4PA.js.map +1 -0
  9. package/dist/{chunk-TCCE5ZU5.js → chunk-MEGI4FS6.js} +38 -9
  10. package/dist/chunk-MEGI4FS6.js.map +1 -0
  11. package/dist/{chunk-MS3FBZ6A.js → chunk-PVW56EVR.js} +105 -62
  12. package/dist/chunk-PVW56EVR.js.map +1 -0
  13. package/dist/{chunk-L7R5RK6A.js → chunk-QRYJCWGD.js} +1199 -897
  14. package/dist/chunk-QRYJCWGD.js.map +1 -0
  15. package/dist/components/chat-composer.d.ts +2 -1
  16. package/dist/components/composer.d.ts +8 -2
  17. package/dist/components/copy-button.d.ts +4 -2
  18. package/dist/components/tip-follow.d.ts +3 -0
  19. package/dist/composer.d.ts +2 -1
  20. package/dist/composer.js +4 -3
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.js +106 -101
  23. package/dist/index.js.map +1 -1
  24. package/dist/lib/format.d.ts +2 -0
  25. package/dist/machines.js +2 -2
  26. package/dist/session-ui.js +4 -3
  27. package/dist/session.js +4 -4
  28. package/dist/timeline/index.d.ts +1 -1
  29. package/dist/timeline/parsers.d.ts +5 -0
  30. package/dist/timeline/projection.d.ts +1 -12
  31. package/dist/timeline/tool-display-name.d.ts +17 -6
  32. package/dist/workstream-control-event.d.ts +6 -0
  33. package/package.json +1 -1
  34. package/src/components/chat-composer.tsx +1 -1
  35. package/src/components/composer-transcription-control.tsx +70 -57
  36. package/src/components/composer.tsx +197 -126
  37. package/src/components/copy-button.tsx +27 -8
  38. package/src/components/message-timeline.tsx +236 -39
  39. package/src/components/tip-follow.ts +15 -0
  40. package/src/composer.ts +1 -1
  41. package/src/hooks/use-composer.ts +7 -1
  42. package/src/hooks/use-workspace-capture.ts +6 -0
  43. package/src/index.ts +2 -1
  44. package/src/lib/format.ts +14 -0
  45. package/src/timeline/index.ts +2 -0
  46. package/src/timeline/parsers.ts +18 -1
  47. package/src/timeline/projection.ts +50 -20
  48. package/src/timeline/registry.ts +15 -2
  49. package/src/timeline/shared.tsx +30 -28
  50. package/src/timeline/tool-display-name.ts +30 -11
  51. package/src/timeline/tool-renderers.tsx +347 -16
  52. package/src/timeline/turn-summary.tsx +5 -2
  53. package/src/workstream-control-event.ts +6 -0
  54. package/dist/chunk-4QOQ2DSR.js.map +0 -1
  55. package/dist/chunk-KZRUYCL4.js.map +0 -1
  56. package/dist/chunk-L7R5RK6A.js.map +0 -1
  57. package/dist/chunk-MS3FBZ6A.js.map +0 -1
  58. package/dist/chunk-TCCE5ZU5.js.map +0 -1
  59. /package/dist/{chunk-A2WITZTI.js.map → chunk-4NMH6UJ3.js.map} +0 -0
  60. /package/dist/{chunk-GZ4KR67U.js.map → chunk-ALA3UGWB.js.map} +0 -0
@@ -4,7 +4,8 @@ import type { SlashCommand } from "../commands/types";
4
4
  import type { ComposerState } from "../hooks/use-composer";
5
5
  import type { UseFileAttachmentsResult } from "../hooks/use-file-attachments";
6
6
  import type { SlashCommandContext } from "../hooks/use-slash-commands";
7
- import { OPEN_WORKSTREAM_CONTROL_EVENT, type ChatComposerMessages, type ComposerControlLinks } from "./composer";
7
+ import { OPEN_WORKSTREAM_CONTROL_EVENT } from "../workstream-control-event";
8
+ import { type ChatComposerMessages, type ComposerControlLinks } from "./composer";
8
9
  import { type ComposerTranscriptionControlProps } from "./composer-transcription-control";
9
10
  export { OPEN_WORKSTREAM_CONTROL_EVENT };
10
11
  export type ChatComposerProps = {
@@ -5,7 +5,8 @@ import type { ComposerState } from "../hooks/use-composer";
5
5
  import type { UseFileAttachmentsResult } from "../hooks/use-file-attachments";
6
6
  import { type ConfirmState, type SlashCommandContext } from "../hooks/use-slash-commands";
7
7
  import type { PickerModelRow } from "../model-policy";
8
- export declare const OPEN_WORKSTREAM_CONTROL_EVENT = "opengeni:open-workstream-control";
8
+ import { OPEN_WORKSTREAM_CONTROL_EVENT } from "../workstream-control-event";
9
+ export { OPEN_WORKSTREAM_CONTROL_EVENT };
9
10
  export type ComposerDelivery = Pick<ComposerState, "value" | "setValue" | "send" | "steer" | "sending" | "canSend" | "error" | "clearError">;
10
11
  export type ComposerDraftState = Pick<ComposerState, "draftConflict" | "draftSaving" | "resolveDraftConflict" | "restoredResources" | "removeRestoredResource">;
11
12
  export type ComposerControlState = Pick<ComposerState, "pause" | "pausing" | "resume" | "resumeScope" | "resuming">;
@@ -91,6 +92,12 @@ export type UseChatComposerControllerOptions = {
91
92
  onPaste?: ((event: ClipboardEvent<HTMLTextAreaElement>) => void) | undefined;
92
93
  messages?: Partial<ChatComposerMessages> | undefined;
93
94
  };
95
+ /**
96
+ * Autosize a composer textarea up to `maxPx` without the classic height→0
97
+ * measure collapse (that flash expands the timeline flex sibling and yanks
98
+ * tip-follow while a stream is pinned).
99
+ */
100
+ export declare function applyComposerTextareaHeight(textarea: HTMLTextAreaElement, maxPx?: number): void;
94
101
  /**
95
102
  * Headless interaction layer for a chat composer. It is the single owner of
96
103
  * delivery guards, keyboard routing, command interception, drag/drop, focus,
@@ -274,4 +281,3 @@ export type ComposerSendButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElemen
274
281
  export declare const SendButton: import("react").ForwardRefExoticComponent<ComposerSendButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
275
282
  export declare function Help(): import("react/jsx-runtime").JSX.Element;
276
283
  export declare function Status(): import("react/jsx-runtime").JSX.Element;
277
- export {};
@@ -7,7 +7,7 @@ export type CopyButtonProps = {
7
7
  className?: string | undefined;
8
8
  /**
9
9
  * `always` — visible control.
10
- * `group-hover` — parent must use `group/copy`; fades in on hover/focus.
10
+ * `group-hover` — parent must use `group/copy`; fades in on hover/focus-visible.
11
11
  */
12
12
  reveal?: "always" | "group-hover" | undefined;
13
13
  };
@@ -17,10 +17,12 @@ export type CopyButtonProps = {
17
17
  */
18
18
  export declare function CopyButton({ text, label, className, reveal, }: CopyButtonProps): import("react/jsx-runtime").JSX.Element;
19
19
  /** Hover-reveal chrome around a message / turn so {@link CopyButton} can fade in. */
20
- export declare function CopyHoverFrame({ children, className, copyText, label, align, }: {
20
+ export declare function CopyHoverFrame({ children, className, copyText, label, align, trailing, }: {
21
21
  children: ReactNode;
22
22
  className?: string | undefined;
23
23
  copyText: string;
24
24
  label: string;
25
25
  align?: "start" | "end" | undefined;
26
+ /** Optional footer meta (e.g. sent/finished clock) — immediately after the copy control. */
27
+ trailing?: ReactNode | undefined;
26
28
  }): import("react/jsx-runtime").JSX.Element;
@@ -56,6 +56,9 @@ export declare const TIP_FOLLOW_VELOCITY_ARM_DEBT_PX = 72;
56
56
  export declare const TIP_FOLLOW_VELOCITY_DECAY_MS: number;
57
57
  /** Reader-up pixels above clamp budget that count as leaving the tip. */
58
58
  export declare const TIP_FOLLOW_READER_UP_EPS_PX = 2;
59
+ /** @internal */ export declare function setScrollEndSupportForTests(value: boolean | null): void;
60
+ /** True when the engine exposes element `scrollend` (prefer over rAF leave). */
61
+ export declare function supportsScrollEndEvent(): boolean;
59
62
  /** @deprecated Shrink lock removed; kept so old imports do not break. */
60
63
  export declare const TIP_FOLLOW_SHRINK_LOCK_MS = 0;
61
64
  /** @deprecated Absorb thresholds removed — growth track is continuous. */
@@ -3,7 +3,8 @@
3
3
  *
4
4
  * `import * as Composer from "@opengeni/react/composer"`.
5
5
  */
6
- export { Actions, AttachButton, Attachments, CommandPalette, Confirmation, Controls, Footer, Frame, Help, Hint, Input, ModelPicker, OPEN_WORKSTREAM_CONTROL_EVENT, PauseButton, PausedState, RestoredResources, Root, SendButton, Status, Surface, defaultChatComposerMessages, useChatComposer, useChatComposerController, } from "./components/composer";
6
+ export { OPEN_WORKSTREAM_CONTROL_EVENT } from "./workstream-control-event";
7
+ export { Actions, AttachButton, Attachments, CommandPalette, Confirmation, Controls, Footer, Frame, Help, Hint, Input, ModelPicker, PauseButton, PausedState, RestoredResources, Root, SendButton, Status, Surface, defaultChatComposerMessages, useChatComposer, useChatComposerController, } from "./components/composer";
7
8
  export type { ChatComposerController, ChatComposerContextValue, ChatComposerMessages, ComposerActionsProps, ComposerAttachButtonProps, ComposerCommandPaletteProps, ComposerControlLinks, ComposerControlState, ComposerControlsProps, ComposerDelivery, ComposerDraftState, ComposerFooterProps, ComposerFrameProps, ComposerHintProps, ComposerInputProps, ComposerModelPickerProps, ComposerPauseButtonProps, ComposerRootProps, ComposerSendButtonProps, ComposerSubmitBlocker, ComposerSubmitMode, ComposerSurfaceProps, UseChatComposerControllerOptions, } from "./components/composer";
8
9
  export { ComposerTranscriptionControl } from "./components/composer-transcription-control";
9
10
  export type { ComposerTranscriptionControlProps, ComposerTranscriptionMessages, } from "./components/composer-transcription-control";
package/dist/composer.js CHANGED
@@ -24,12 +24,13 @@ import {
24
24
  useChatComposer,
25
25
  useChatComposerController,
26
26
  useVoiceInput
27
- } from "./chunk-MS3FBZ6A.js";
28
- import "./chunk-KZRUYCL4.js";
27
+ } from "./chunk-PVW56EVR.js";
28
+ import "./chunk-FT2TXNGZ.js";
29
29
  import "./chunk-7CJOAW3V.js";
30
30
  import "./chunk-U255M5EZ.js";
31
+ import "./chunk-ATSTR5P3.js";
31
32
  import "./chunk-TK7G6XLT.js";
32
- import "./chunk-4QOQ2DSR.js";
33
+ import "./chunk-LAKLF4PA.js";
33
34
  export {
34
35
  Actions,
35
36
  AttachButton,
package/dist/index.d.ts CHANGED
@@ -25,7 +25,7 @@ export type { QueueSurfaceProps } from "./components/queue-surface";
25
25
  export { SessionChrome, sessionChromeGoalPillState } from "./components/session-chrome";
26
26
  export type { SessionChromeAgentsSignal, SessionChromeProps, SessionChromeSignalId, SessionChromeSignalTone, } from "./components/session-chrome";
27
27
  export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./components/tooltip";
28
- export { OPEN_WORKSTREAM_CONTROL_EVENT } from "./components/chat-composer";
28
+ export { OPEN_WORKSTREAM_CONTROL_EVENT } from "./workstream-control-event";
29
29
  export { useGoal, isGoalEvent } from "./hooks/use-goal";
30
30
  export type { UseGoalOptions, UseGoalResult } from "./hooks/use-goal";
31
31
  export { useSessionControl } from "./hooks/use-session-control";
@@ -141,4 +141,4 @@ export type { CodexAccountsClientLike, UseCodexAccountsOptions, UseCodexAccounts
141
141
  export { gitFileDiffToPatch } from "./lib/git-patch";
142
142
  export { xtermThemeFromTokens } from "./lib/xterm-theme";
143
143
  export { cn } from "./lib/cn";
144
- export { CREDIT_EXHAUSTION_MESSAGE, formatBytes, formatRelativeTime, humanizeFailureReason, isCreditExhaustion, stringifyPayload, truncate, tryParseJson, } from "./lib/format";
144
+ export { CREDIT_EXHAUSTION_MESSAGE, formatBytes, formatClockTime, formatRelativeTime, humanizeFailureReason, isCreditExhaustion, stringifyPayload, truncate, tryParseJson, } from "./lib/format";
package/dist/index.js CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  healthPulses,
26
26
  pointsFor,
27
27
  useMachines
28
- } from "./chunk-GZ4KR67U.js";
28
+ } from "./chunk-ALA3UGWB.js";
29
29
  import {
30
30
  SESSION_EVENT_BROWSER_MAX_BYTES,
31
31
  SESSION_EVENT_BROWSER_MAX_COUNT,
@@ -52,7 +52,7 @@ import {
52
52
  useSessionLineage,
53
53
  useSessionMcpApprovalPolicy,
54
54
  useTurnQueue
55
- } from "./chunk-A2WITZTI.js";
55
+ } from "./chunk-4NMH6UJ3.js";
56
56
  import {
57
57
  ActivityDisclosure,
58
58
  ActivityRail,
@@ -78,10 +78,6 @@ import {
78
78
  TermBlock,
79
79
  Thumbnail,
80
80
  TimelineRow,
81
- Tooltip,
82
- TooltipContent,
83
- TooltipProvider,
84
- TooltipTrigger,
85
81
  TurnSummary,
86
82
  answersFromDrafts,
87
83
  applyPatchOps,
@@ -108,10 +104,9 @@ import {
108
104
  unwrapMcpOutput,
109
105
  useLightbox,
110
106
  useLightboxOptional,
111
- usePortalTokenStyle,
112
107
  useThemeType,
113
108
  v4aToGitFileDiff
114
- } from "./chunk-L7R5RK6A.js";
109
+ } from "./chunk-QRYJCWGD.js";
115
110
  import {
116
111
  buildTimeline,
117
112
  creditExhaustedFromEvents,
@@ -119,7 +114,7 @@ import {
119
114
  groupTimeline,
120
115
  sessionStatusFromEvents,
121
116
  toolDisplayName
122
- } from "./chunk-TCCE5ZU5.js";
117
+ } from "./chunk-MEGI4FS6.js";
123
118
  import {
124
119
  Actions,
125
120
  AttachButton,
@@ -159,14 +154,14 @@ import {
159
154
  useSlashCommands,
160
155
  useTranscription,
161
156
  useVoiceInput
162
- } from "./chunk-MS3FBZ6A.js";
157
+ } from "./chunk-PVW56EVR.js";
163
158
  import {
164
159
  FILE_ONLY_MESSAGE_TEXT,
165
160
  composeSendInput,
166
161
  shouldSteerOnKey,
167
162
  shouldSubmitOnKey,
168
163
  useComposer
169
- } from "./chunk-KZRUYCL4.js";
164
+ } from "./chunk-FT2TXNGZ.js";
170
165
  import {
171
166
  useMutationRunner,
172
167
  useOpenGeni,
@@ -190,6 +185,13 @@ import {
190
185
  runnableLatencyModesForModel,
191
186
  sortPickerRows
192
187
  } from "./chunk-U255M5EZ.js";
188
+ import {
189
+ Tooltip,
190
+ TooltipContent,
191
+ TooltipProvider,
192
+ TooltipTrigger,
193
+ usePortalTokenStyle
194
+ } from "./chunk-ATSTR5P3.js";
193
195
  import {
194
196
  cn
195
197
  } from "./chunk-TK7G6XLT.js";
@@ -198,13 +200,14 @@ import {
198
200
  CREDIT_EXHAUSTION_MESSAGE,
199
201
  composerSubmissionErrorMessage,
200
202
  formatBytes,
203
+ formatClockTime,
201
204
  formatRelativeTime,
202
205
  humanizeFailureReason,
203
206
  isCreditExhaustion,
204
207
  stringifyPayload,
205
208
  truncate,
206
209
  tryParseJson
207
- } from "./chunk-4QOQ2DSR.js";
210
+ } from "./chunk-LAKLF4PA.js";
208
211
  import "./chunk-YDNWMKXO.js";
209
212
 
210
213
  // src/hooks/use-last-started-turn-policy.ts
@@ -259,77 +262,6 @@ function useLastStartedTurnPolicy(sessionId, options = {}) {
259
262
  };
260
263
  }
261
264
 
262
- // src/components/chat-composer.tsx
263
- import { jsx, jsxs } from "react/jsx-runtime";
264
- function ChatComposer({
265
- composer,
266
- effectiveControl,
267
- queuedAheadCount,
268
- canControlWorkspace,
269
- controlLinks,
270
- placeholder,
271
- disabled,
272
- autoFocus,
273
- hint,
274
- controlsStart,
275
- transcription,
276
- header,
277
- onPaste,
278
- attachments,
279
- models,
280
- selectedModel,
281
- onSelectModel,
282
- className,
283
- commands,
284
- commandContext,
285
- onClearView,
286
- messages
287
- }) {
288
- const controller = useChatComposerController({
289
- delivery: composer,
290
- draft: composer,
291
- control: composer,
292
- effectiveControl,
293
- queuedAheadCount,
294
- canControlWorkspace,
295
- controlLinks,
296
- disabled,
297
- attachments,
298
- commands,
299
- commandContext,
300
- onClearView,
301
- onPaste,
302
- messages
303
- });
304
- const hasControls = Boolean(attachments || models || controlsStart || transcription);
305
- return /* @__PURE__ */ jsxs(Root, { controller, className, children: [
306
- /* @__PURE__ */ jsxs(Frame, { children: [
307
- /* @__PURE__ */ jsx(CommandPalette2, {}),
308
- /* @__PURE__ */ jsxs(Surface, { children: [
309
- /* @__PURE__ */ jsx(PausedState, {}),
310
- /* @__PURE__ */ jsx(RestoredResources, {}),
311
- /* @__PURE__ */ jsx(Attachments, {}),
312
- header,
313
- /* @__PURE__ */ jsx(Input, { placeholder, autoFocus }),
314
- controller.confirmState ? /* @__PURE__ */ jsx(Confirmation, {}) : /* @__PURE__ */ jsxs(Footer, { children: [
315
- hasControls ? /* @__PURE__ */ jsxs(Controls, { children: [
316
- /* @__PURE__ */ jsx(AttachButton, {}),
317
- transcription ? /* @__PURE__ */ jsx(ComposerTranscriptionControl, { ...transcription }) : null,
318
- models ? /* @__PURE__ */ jsx(ModelPicker2, { models, value: selectedModel, onChange: onSelectModel }) : null,
319
- controlsStart
320
- ] }) : /* @__PURE__ */ jsx(Hint, { children: hint }),
321
- /* @__PURE__ */ jsxs(Actions, { children: [
322
- /* @__PURE__ */ jsx(PauseButton, {}),
323
- /* @__PURE__ */ jsx(SendButton, {})
324
- ] })
325
- ] })
326
- ] })
327
- ] }),
328
- /* @__PURE__ */ jsx(Help, {}),
329
- /* @__PURE__ */ jsx(Status, {})
330
- ] });
331
- }
332
-
333
265
  // src/hooks/use-scheduled-tasks.ts
334
266
  import { useCallback as useCallback2 } from "react";
335
267
  function useScheduledTasks(options = {}) {
@@ -2999,6 +2931,7 @@ function useWorkspaceCapture(sessionId, options = {}) {
2999
2931
  if (!enabled) return;
3000
2932
  if (visibleAnnouncedRevision === null) return;
3001
2933
  if (loadedRevision !== null && visibleAnnouncedRevision <= loadedRevision) return;
2934
+ if (requestAbortRef.current) return;
3002
2935
  void refresh();
3003
2936
  }, [enabled, visibleAnnouncedRevision, loadedRevision, refresh]);
3004
2937
  const isStale = loadedRevision !== null && visibleAnnouncedRevision !== null && visibleAnnouncedRevision > loadedRevision;
@@ -3240,7 +3173,7 @@ function useMachineChip(input) {
3240
3173
  // src/components/approval-surface.tsx
3241
3174
  import { CheckIcon, ShieldCheckIcon, XIcon } from "lucide-react";
3242
3175
  import { useEffect as useEffect12, useId, useRef as useRef11, useState as useState10 } from "react";
3243
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
3176
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3244
3177
  var defaultApprovalSurfaceMessages = {
3245
3178
  title: "Approval required",
3246
3179
  description: "Review the requested action before the agent continues.",
@@ -3310,7 +3243,7 @@ function ApprovalSurface({
3310
3243
  }
3311
3244
  };
3312
3245
  const errorMessage = decisionError?.message ?? (error instanceof Error ? error.message : error);
3313
- return /* @__PURE__ */ jsxs2(
3246
+ return /* @__PURE__ */ jsxs(
3314
3247
  "section",
3315
3248
  {
3316
3249
  className: cn(
@@ -3319,29 +3252,29 @@ function ApprovalSurface({
3319
3252
  ),
3320
3253
  "aria-labelledby": titleId,
3321
3254
  children: [
3322
- /* @__PURE__ */ jsxs2("header", { className: "flex items-start gap-3", children: [
3323
- /* @__PURE__ */ jsx2("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__ */ jsx2(ShieldCheckIcon, { "aria-hidden": "true", className: "size-4" }) }),
3324
- /* @__PURE__ */ jsxs2("div", { className: "min-w-0", children: [
3325
- /* @__PURE__ */ jsx2("h2", { id: titleId, className: "text-og-md font-semibold text-og-fg", children: messages.title }),
3326
- /* @__PURE__ */ jsx2("p", { className: "mt-0.5 text-og-sm text-og-fg-muted", children: messages.description })
3255
+ /* @__PURE__ */ jsxs("header", { className: "flex items-start gap-3", children: [
3256
+ /* @__PURE__ */ jsx("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__ */ jsx(ShieldCheckIcon, { "aria-hidden": "true", className: "size-4" }) }),
3257
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
3258
+ /* @__PURE__ */ jsx("h2", { id: titleId, className: "text-og-md font-semibold text-og-fg", children: messages.title }),
3259
+ /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-og-sm text-og-fg-muted", children: messages.description })
3327
3260
  ] })
3328
3261
  ] }),
3329
- /* @__PURE__ */ jsx2("div", { className: "flex flex-col gap-2", children: approvals.map((approval) => {
3262
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: approvals.map((approval) => {
3330
3263
  const approvalKey = approvalOwnershipKey(approval);
3331
3264
  const active = pending?.approvalKey === approvalKey ? pending.decision : null;
3332
3265
  const argumentsPreview = approvalArgumentsPreview(approval.arguments);
3333
- return /* @__PURE__ */ jsxs2(
3266
+ return /* @__PURE__ */ jsxs(
3334
3267
  "article",
3335
3268
  {
3336
3269
  "data-approval-id": approval.id,
3337
3270
  className: "rounded-og-md border border-og-border bg-og-surface-1 p-3",
3338
3271
  children: [
3339
- renderApproval ? renderApproval(approval) : /* @__PURE__ */ jsxs2(Fragment, { children: [
3340
- /* @__PURE__ */ jsx2("p", { className: "text-og-sm font-medium text-og-fg", children: messages.formatToolName(approval.name) }),
3341
- argumentsPreview !== null ? /* @__PURE__ */ jsx2("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
3272
+ renderApproval ? renderApproval(approval) : /* @__PURE__ */ jsxs(Fragment, { children: [
3273
+ /* @__PURE__ */ jsx("p", { className: "text-og-sm font-medium text-og-fg", children: messages.formatToolName(approval.name) }),
3274
+ argumentsPreview !== null ? /* @__PURE__ */ jsx("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
3342
3275
  ] }),
3343
- /* @__PURE__ */ jsxs2("div", { className: "mt-3 flex flex-wrap justify-end gap-2", children: [
3344
- /* @__PURE__ */ jsxs2(
3276
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 flex flex-wrap justify-end gap-2", children: [
3277
+ /* @__PURE__ */ jsxs(
3345
3278
  "button",
3346
3279
  {
3347
3280
  type: "button",
@@ -3349,12 +3282,12 @@ function ApprovalSurface({
3349
3282
  onClick: () => void decide(approval, "reject"),
3350
3283
  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",
3351
3284
  children: [
3352
- /* @__PURE__ */ jsx2(XIcon, { "aria-hidden": "true", className: "size-3.5" }),
3285
+ /* @__PURE__ */ jsx(XIcon, { "aria-hidden": "true", className: "size-3.5" }),
3353
3286
  active === "reject" ? messages.rejecting : messages.reject
3354
3287
  ]
3355
3288
  }
3356
3289
  ),
3357
- /* @__PURE__ */ jsxs2(
3290
+ /* @__PURE__ */ jsxs(
3358
3291
  "button",
3359
3292
  {
3360
3293
  type: "button",
@@ -3362,7 +3295,7 @@ function ApprovalSurface({
3362
3295
  onClick: () => void decide(approval, "approve"),
3363
3296
  className: "inline-flex min-h-9 items-center gap-1.5 rounded-og-md bg-og-accent px-3 py-1.5 text-og-sm font-medium text-og-accent-fg transition-colors hover:bg-og-accent-strong disabled:opacity-50",
3364
3297
  children: [
3365
- /* @__PURE__ */ jsx2(CheckIcon, { "aria-hidden": "true", className: "size-3.5" }),
3298
+ /* @__PURE__ */ jsx(CheckIcon, { "aria-hidden": "true", className: "size-3.5" }),
3366
3299
  active === "approve" ? messages.approving : messages.approve
3367
3300
  ]
3368
3301
  }
@@ -3373,12 +3306,83 @@ function ApprovalSurface({
3373
3306
  approval.id
3374
3307
  );
3375
3308
  }) }),
3376
- errorMessage ? /* @__PURE__ */ jsx2("p", { role: "alert", className: "text-og-sm text-og-status-failed", children: errorMessage }) : null
3309
+ errorMessage ? /* @__PURE__ */ jsx("p", { role: "alert", className: "text-og-sm text-og-status-failed", children: errorMessage }) : null
3377
3310
  ]
3378
3311
  }
3379
3312
  );
3380
3313
  }
3381
3314
 
3315
+ // src/components/chat-composer.tsx
3316
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
3317
+ function ChatComposer({
3318
+ composer,
3319
+ effectiveControl,
3320
+ queuedAheadCount,
3321
+ canControlWorkspace,
3322
+ controlLinks,
3323
+ placeholder,
3324
+ disabled,
3325
+ autoFocus,
3326
+ hint,
3327
+ controlsStart,
3328
+ transcription,
3329
+ header,
3330
+ onPaste,
3331
+ attachments,
3332
+ models,
3333
+ selectedModel,
3334
+ onSelectModel,
3335
+ className,
3336
+ commands,
3337
+ commandContext,
3338
+ onClearView,
3339
+ messages
3340
+ }) {
3341
+ const controller = useChatComposerController({
3342
+ delivery: composer,
3343
+ draft: composer,
3344
+ control: composer,
3345
+ effectiveControl,
3346
+ queuedAheadCount,
3347
+ canControlWorkspace,
3348
+ controlLinks,
3349
+ disabled,
3350
+ attachments,
3351
+ commands,
3352
+ commandContext,
3353
+ onClearView,
3354
+ onPaste,
3355
+ messages
3356
+ });
3357
+ const hasControls = Boolean(attachments || models || controlsStart || transcription);
3358
+ return /* @__PURE__ */ jsxs2(Root, { controller, className, children: [
3359
+ /* @__PURE__ */ jsxs2(Frame, { children: [
3360
+ /* @__PURE__ */ jsx2(CommandPalette2, {}),
3361
+ /* @__PURE__ */ jsxs2(Surface, { children: [
3362
+ /* @__PURE__ */ jsx2(PausedState, {}),
3363
+ /* @__PURE__ */ jsx2(RestoredResources, {}),
3364
+ /* @__PURE__ */ jsx2(Attachments, {}),
3365
+ header,
3366
+ /* @__PURE__ */ jsx2(Input, { placeholder, autoFocus }),
3367
+ controller.confirmState ? /* @__PURE__ */ jsx2(Confirmation, {}) : /* @__PURE__ */ jsxs2(Footer, { children: [
3368
+ hasControls ? /* @__PURE__ */ jsxs2(Controls, { children: [
3369
+ /* @__PURE__ */ jsx2(AttachButton, {}),
3370
+ transcription ? /* @__PURE__ */ jsx2(ComposerTranscriptionControl, { ...transcription }) : null,
3371
+ models ? /* @__PURE__ */ jsx2(ModelPicker2, { models, value: selectedModel, onChange: onSelectModel }) : null,
3372
+ controlsStart
3373
+ ] }) : /* @__PURE__ */ jsx2(Hint, { children: hint }),
3374
+ /* @__PURE__ */ jsxs2(Actions, { children: [
3375
+ /* @__PURE__ */ jsx2(PauseButton, {}),
3376
+ /* @__PURE__ */ jsx2(SendButton, {})
3377
+ ] })
3378
+ ] })
3379
+ ] })
3380
+ ] }),
3381
+ /* @__PURE__ */ jsx2(Help, {}),
3382
+ /* @__PURE__ */ jsx2(Status, {})
3383
+ ] });
3384
+ }
3385
+
3382
3386
  // src/components/fleet-tile.tsx
3383
3387
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
3384
3388
  function sessionDisplayTitle(session) {
@@ -8487,6 +8491,7 @@ export {
8487
8491
  firstMissingRequiredArg,
8488
8492
  formatAsOf,
8489
8493
  formatBytes,
8494
+ formatClockTime,
8490
8495
  formatRelativeTime,
8491
8496
  gitFileDiffToPatch,
8492
8497
  groupPickerRowsByBillingClass,