@opengeni/react 0.34.2 → 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 (59) 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 +105 -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/index.ts +2 -1
  43. package/src/lib/format.ts +14 -0
  44. package/src/timeline/index.ts +2 -0
  45. package/src/timeline/parsers.ts +18 -1
  46. package/src/timeline/projection.ts +50 -20
  47. package/src/timeline/registry.ts +15 -2
  48. package/src/timeline/shared.tsx +30 -28
  49. package/src/timeline/tool-display-name.ts +30 -11
  50. package/src/timeline/tool-renderers.tsx +347 -16
  51. package/src/timeline/turn-summary.tsx +5 -2
  52. package/src/workstream-control-event.ts +6 -0
  53. package/dist/chunk-4QOQ2DSR.js.map +0 -1
  54. package/dist/chunk-KZRUYCL4.js.map +0 -1
  55. package/dist/chunk-L7R5RK6A.js.map +0 -1
  56. package/dist/chunk-MS3FBZ6A.js.map +0 -1
  57. package/dist/chunk-TCCE5ZU5.js.map +0 -1
  58. /package/dist/{chunk-A2WITZTI.js.map → chunk-4NMH6UJ3.js.map} +0 -0
  59. /package/dist/{chunk-GZ4KR67U.js.map → chunk-ALA3UGWB.js.map} +0 -0
@@ -1,3 +1,5 @@
1
+ /** Local finished-at stamp for message footers: "Aug 2, 3:42 PM" / locale-equivalent. */
2
+ export declare function formatClockTime(iso: string): string;
1
3
  /** Compact relative time: "now", "42s", "7m", "3h", "2d", then a date. */
2
4
  export declare function formatRelativeTime(iso: string, now?: Date): string;
3
5
  /** Human-readable byte size: "512 B", "8.0 KB", "1.4 MB", "3 GB". */
package/dist/machines.js CHANGED
@@ -24,10 +24,10 @@ import {
24
24
  healthPulses,
25
25
  pointsFor,
26
26
  useMachines
27
- } from "./chunk-GZ4KR67U.js";
27
+ } from "./chunk-ALA3UGWB.js";
28
28
  import "./chunk-7CJOAW3V.js";
29
29
  import "./chunk-TK7G6XLT.js";
30
- import "./chunk-4QOQ2DSR.js";
30
+ import "./chunk-LAKLF4PA.js";
31
31
  export {
32
32
  CONNECTION_STATUS_META,
33
33
  ConnectionDot,
@@ -6,10 +6,11 @@ import {
6
6
  SessionChrome,
7
7
  TimelineRow,
8
8
  sessionChromeGoalPillState
9
- } from "./chunk-L7R5RK6A.js";
10
- import "./chunk-TCCE5ZU5.js";
9
+ } from "./chunk-QRYJCWGD.js";
10
+ import "./chunk-MEGI4FS6.js";
11
+ import "./chunk-ATSTR5P3.js";
11
12
  import "./chunk-TK7G6XLT.js";
12
- import "./chunk-4QOQ2DSR.js";
13
+ import "./chunk-LAKLF4PA.js";
13
14
  import "./chunk-YDNWMKXO.js";
14
15
  export {
15
16
  BUILT_IN_TURN_SUMMARY_FACET_IDS,
package/dist/session.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  useSessionLineage,
19
19
  useSessionMcpApprovalPolicy,
20
20
  useTurnQueue
21
- } from "./chunk-A2WITZTI.js";
21
+ } from "./chunk-4NMH6UJ3.js";
22
22
  import {
23
23
  buildTimeline,
24
24
  creditExhaustedFromEvents,
@@ -26,16 +26,16 @@ import {
26
26
  groupTimeline,
27
27
  sessionStatusFromEvents,
28
28
  toolDisplayName
29
- } from "./chunk-TCCE5ZU5.js";
29
+ } from "./chunk-MEGI4FS6.js";
30
30
  import {
31
31
  FILE_ONLY_MESSAGE_TEXT,
32
32
  composeSendInput,
33
33
  shouldSteerOnKey,
34
34
  shouldSubmitOnKey,
35
35
  useComposer
36
- } from "./chunk-KZRUYCL4.js";
36
+ } from "./chunk-FT2TXNGZ.js";
37
37
  import "./chunk-7CJOAW3V.js";
38
- import "./chunk-4QOQ2DSR.js";
38
+ import "./chunk-LAKLF4PA.js";
39
39
  export {
40
40
  FILE_ONLY_MESSAGE_TEXT,
41
41
  approvalsFromRequiresAction,
@@ -1,4 +1,4 @@
1
- export { buildTimeline, creditExhaustedFromEvents, extractSessionRef, groupTimeline, sessionStatusFromEvents, toolDisplayName, } from "./projection";
1
+ export { buildTimeline, creditExhaustedFromEvents, extractSessionRef, groupTimeline, sessionStatusFromEvents, mcpToolLeaf, toolDisplayName, toolMatchesLeaf, } from "./projection";
2
2
  export type { ActivityItem, AgentMessageItem, AuthNeededItem, ContextCompactionItem, FleetDecisionItem, FleetDecisionScoreItem, GoalItem, MachineInputBatchItem, MachineInputMember, MemoryItem, NoticeItem, ReasoningItem, SandboxItem, SessionStatusItem, TimelineGroup, TimelineItem, TurnEndItem, ToolCallItem, UserMessageItem, WorkerCompletionItem, WorkerItem, } from "./types";
3
3
  export { createToolRegistry, rawTypeOf } from "./registry";
4
4
  export type { CreateToolRegistryOptions, ToolRegistry, ToolRegistryEntry, ToolRenderer, ToolRendererProps, } from "./registry";
@@ -49,6 +49,11 @@ export declare function v4aToGitFileDiff(op: ApplyPatchOperation): GitFileDiff;
49
49
  * renderer and the turn-summary facet counter never drift.
50
50
  */
51
51
  export declare function applyPatchOps(raw: unknown): ApplyPatchOperation[];
52
+ /** Ops from provider `raw`, or from function-tool arguments when raw is empty. */
53
+ export declare function applyPatchOpsFromToolItem(item: {
54
+ raw: unknown;
55
+ arguments: unknown;
56
+ }): ApplyPatchOperation[];
52
57
  /**
53
58
  * True when a tool item is an `apply_patch_call` — by its provider-native
54
59
  * `raw.type` (the live-wire source of truth) or by tool `name` (first-party
@@ -1,7 +1,6 @@
1
1
  import type { SessionEvent, SessionStatus } from "@opengeni/sdk";
2
2
  import type { TimelineGroup, TimelineItem } from "./types";
3
- /** Readable label for a tool call, without leaking an MCP server prefix. */
4
- export declare function toolDisplayName(name: string): string;
3
+ export { toolDisplayName, mcpToolLeaf, toolMatchesLeaf } from "./tool-display-name";
5
4
  export declare function buildTimeline(events: SessionEvent[]): TimelineItem[];
6
5
  /**
7
6
  * Codex subscription web search can return private citation handles without
@@ -26,13 +25,3 @@ export declare function groupTimeline(items: TimelineItem[]): TimelineGroup[];
26
25
  * text: "{...}" }], structuredContent? }`).
27
26
  */
28
27
  export declare function extractSessionRef(value: unknown, depth?: number): string | null;
29
- /**
30
- * Readable label for a tool call ("session_create" -> "session create").
31
- *
32
- * MCP tools are namespaced `<serverId>__<toolName>` (see prefixedMcpToolName),
33
- * and for catalog-imported servers that serverId is an opaque slug+hash
34
- * ("mcp-integrations-sh-supabase-com-34ed9dcf1390-0i6tcf8"). De-slugging the
35
- * whole thing leaked that id into the timeline; strip the server prefix and show
36
- * just the tool ("list organizations"). Names without the `__` boundary (plain
37
- * built-ins like "session_create") are unaffected.
38
- */
@@ -1,10 +1,21 @@
1
1
  /**
2
- * Readable label for a tool call ("session_create" -> "session create").
2
+ * MCP / first-party tool naming helpers.
3
3
  *
4
- * MCP tools are namespaced `<serverId>__<toolName>` (see prefixedMcpToolName),
5
- * and for catalog-imported servers that serverId is an opaque slug+hash.
6
- * De-slugging the whole thing leaked that id into the timeline; strip the
7
- * server prefix and show just the tool. Names without the `__` boundary (plain
8
- * built-ins like "session_create") are unaffected.
4
+ * Wire names are often `<serverId>__<toolName>` (see prefixedMcpToolName).
5
+ * Matching and titles must use the leaf tool name so `opengeni__session_create`
6
+ * and bare `session_create` resolve the same UI without inventing previews
7
+ * from argument JSON.
8
+ */
9
+ /** Leaf tool name after the first `__` server boundary (or the whole name). */
10
+ export declare function mcpToolLeaf(name: string): string;
11
+ /**
12
+ * True when `wireName` is exactly `leaf` or ends with `__${leaf}` (MCP prefix).
13
+ * Does not treat arbitrary suffixes as matches — the leaf must be the full
14
+ * right-hand side after `__`.
15
+ */
16
+ export declare function toolMatchesLeaf(wireName: string, leaf: string): boolean;
17
+ /**
18
+ * Readable label for a tool call ("session_create" / "opengeni__session_create"
19
+ * → "Session create"). Title-cases the first character of the leaf phrase.
9
20
  */
10
21
  export declare function toolDisplayName(name: string): string;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Document event hosts dispatch to open the workstream Pause/Resume surface.
3
+ * Kept in a leaf module so session chrome can import the name without pulling
4
+ * the ChatComposer / Radix tooltip graph into the app shell.
5
+ */
6
+ export declare const OPEN_WORKSTREAM_CONTROL_EVENT = "opengeni:open-workstream-control";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/react",
3
- "version": "0.34.2",
3
+ "version": "0.34.3",
4
4
  "description": "React hooks and styled components for OpenGeni: live session streaming, chat composer, message timeline, session status, and fleet views — token-themed (CSS variables), dark-first, built on Tailwind v4 + Radix + Motion.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -4,6 +4,7 @@ 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 } from "../workstream-control-event";
7
8
  import {
8
9
  Actions,
9
10
  AttachButton,
@@ -17,7 +18,6 @@ import {
17
18
  Hint,
18
19
  Input,
19
20
  ModelPicker,
20
- OPEN_WORKSTREAM_CONTROL_EVENT,
21
21
  PauseButton,
22
22
  PausedState,
23
23
  RestoredResources,
@@ -6,10 +6,20 @@ import type {
6
6
  } from "@opengeni/sdk";
7
7
  import { LoaderCircleIcon, MicIcon, SquareIcon, XIcon } from "lucide-react";
8
8
  import { AnimatePresence, motion } from "motion/react";
9
- import { useEffect, useState, type MouseEvent } from "react";
9
+ import { useEffect, useState, type MouseEvent, type ReactElement } from "react";
10
10
  import { cn } from "../lib/cn";
11
11
  import { useVoiceInput } from "../hooks/use-voice-input";
12
12
  import { useChatComposer } from "./composer";
13
+ import { Tooltip, TooltipContent, TooltipTrigger } from "./tooltip";
14
+
15
+ function Tip({ tip, children }: { tip: string; children: ReactElement }) {
16
+ return (
17
+ <Tooltip>
18
+ <TooltipTrigger asChild>{children}</TooltipTrigger>
19
+ <TooltipContent side="top">{tip}</TooltipContent>
20
+ </Tooltip>
21
+ );
22
+ }
13
23
 
14
24
  export type ComposerTranscriptionMessages = {
15
25
  start: string;
@@ -161,33 +171,35 @@ export function ComposerTranscriptionControl({
161
171
  )}
162
172
  {status === "recording" ? (
163
173
  <>
164
- <button
165
- type="button"
166
- onClick={() => transcription.cancel()}
167
- aria-label={messages.cancel}
168
- aria-keyshortcuts="Escape"
169
- title={messages.cancel}
170
- className={cn(
171
- "inline-flex size-7 shrink-0 items-center justify-center rounded-og-sm",
172
- "text-og-fg-muted transition-colors duration-150 motion-reduce:transition-none",
173
- "hover:bg-og-surface-3 hover:text-og-fg pointer-coarse:size-9",
174
- )}
175
- >
176
- <XIcon className="size-3.5" />
177
- </button>
178
- <button
179
- type="button"
180
- onClick={() => transcription.stop()}
181
- aria-label={messages.stop}
182
- title={messages.stop}
183
- className={cn(
184
- "inline-flex size-7 shrink-0 items-center justify-center rounded-og-sm",
185
- "bg-og-fg text-og-bg transition-colors duration-150 motion-reduce:transition-none",
186
- "hover:bg-og-fg-muted pointer-coarse:size-9",
187
- )}
188
- >
189
- <SquareIcon className="size-2.5 fill-current" />
190
- </button>
174
+ <Tip tip={messages.cancel}>
175
+ <button
176
+ type="button"
177
+ onClick={() => transcription.cancel()}
178
+ aria-label={messages.cancel}
179
+ aria-keyshortcuts="Escape"
180
+ className={cn(
181
+ "inline-flex size-7 shrink-0 items-center justify-center rounded-og-sm",
182
+ "text-og-fg-muted transition-colors duration-150 motion-reduce:transition-none",
183
+ "hover:bg-og-surface-3 hover:text-og-fg pointer-coarse:size-9",
184
+ )}
185
+ >
186
+ <XIcon className="size-3.5" />
187
+ </button>
188
+ </Tip>
189
+ <Tip tip={messages.stop}>
190
+ <button
191
+ type="button"
192
+ onClick={() => transcription.stop()}
193
+ aria-label={messages.stop}
194
+ className={cn(
195
+ "inline-flex size-7 shrink-0 items-center justify-center rounded-og-sm",
196
+ "bg-og-fg text-og-bg transition-colors duration-150 motion-reduce:transition-none",
197
+ "hover:bg-og-fg-muted pointer-coarse:size-9",
198
+ )}
199
+ >
200
+ <SquareIcon className="size-2.5 fill-current" />
201
+ </button>
202
+ </Tip>
191
203
  </>
192
204
  ) : status === "transcribing" ? (
193
205
  <span className="og-shimmer-text px-1.5 text-og-xs font-medium whitespace-nowrap">
@@ -200,38 +212,39 @@ export function ComposerTranscriptionControl({
200
212
  )}
201
213
  </motion.span>
202
214
  ) : (
203
- <motion.button
204
- key="idle"
205
- type="button"
206
- initial={{ opacity: 0, scale: 0.96 }}
207
- animate={{ opacity: 1, scale: 1 }}
208
- exit={{ opacity: 0, scale: 0.96 }}
209
- transition={{ duration: 0.14, ease: [0.22, 1, 0.36, 1] }}
210
- onClick={start}
211
- aria-label={idleLabel}
212
- aria-pressed={false}
213
- aria-disabled={unavailableMessage !== null}
214
- title={idleLabel}
215
- className={cn(
216
- "inline-flex size-8 shrink-0 items-center justify-center rounded-og-md pointer-coarse:size-11",
217
- "text-og-fg-muted transition-colors duration-150 motion-reduce:transition-none",
218
- unavailableMessage
219
- ? "cursor-not-allowed opacity-45"
220
- : "hover:bg-og-surface-2 hover:text-og-fg",
221
- )}
222
- >
223
- <MicIcon className="size-4" />
224
- </motion.button>
215
+ <Tip key="idle" tip={idleLabel}>
216
+ <motion.button
217
+ type="button"
218
+ initial={{ opacity: 0, scale: 0.96 }}
219
+ animate={{ opacity: 1, scale: 1 }}
220
+ exit={{ opacity: 0, scale: 0.96 }}
221
+ transition={{ duration: 0.14, ease: [0.22, 1, 0.36, 1] }}
222
+ onClick={start}
223
+ aria-label={idleLabel}
224
+ aria-pressed={false}
225
+ aria-disabled={unavailableMessage !== null}
226
+ className={cn(
227
+ "inline-flex size-8 shrink-0 items-center justify-center rounded-og-md pointer-coarse:size-11",
228
+ "text-og-fg-muted transition-colors duration-150 motion-reduce:transition-none",
229
+ unavailableMessage
230
+ ? "cursor-not-allowed opacity-45"
231
+ : "hover:bg-og-surface-2 hover:text-og-fg",
232
+ )}
233
+ >
234
+ <MicIcon className="size-4" />
235
+ </motion.button>
236
+ </Tip>
225
237
  )}
226
238
  </AnimatePresence>
227
239
  {status === "error" && errorMessage ? (
228
- <span
229
- aria-hidden="true"
230
- title={errorMessage}
231
- className="max-w-40 truncate text-og-xs text-og-status-failed max-sm:max-w-24"
232
- >
233
- {errorMessage}
234
- </span>
240
+ <Tip tip={errorMessage}>
241
+ <span
242
+ aria-hidden="true"
243
+ className="max-w-40 truncate text-og-xs text-og-status-failed max-sm:max-w-24"
244
+ >
245
+ {errorMessage}
246
+ </span>
247
+ </Tip>
235
248
  ) : null}
236
249
  <span className="sr-only" role={status === "error" ? "alert" : "status"} aria-live="polite">
237
250
  {announcement}