@opengeni/react 0.36.1 → 0.40.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -2
- package/dist/{chunk-J2RVJ6JX.js → chunk-4IJCL7YO.js} +13 -2
- package/dist/chunk-4IJCL7YO.js.map +1 -0
- package/dist/{chunk-7CJOAW3V.js → chunk-EB67J347.js} +1 -135
- package/dist/chunk-EB67J347.js.map +1 -0
- package/dist/chunk-EKZH6IDG.js +141 -0
- package/dist/chunk-EKZH6IDG.js.map +1 -0
- package/dist/{chunk-OKKMZDQF.js → chunk-JALF5FI3.js} +9 -7
- package/dist/{chunk-OKKMZDQF.js.map → chunk-JALF5FI3.js.map} +1 -1
- package/dist/{chunk-Z5FV355Z.js → chunk-KR2SK5GJ.js} +1382 -724
- package/dist/chunk-KR2SK5GJ.js.map +1 -0
- package/dist/{chunk-N4XEBE23.js → chunk-OMCFRWHL.js} +22 -13
- package/dist/{chunk-N4XEBE23.js.map → chunk-OMCFRWHL.js.map} +1 -1
- package/dist/{chunk-FT2TXNGZ.js → chunk-Q2NCKWTK.js} +183 -18
- package/dist/chunk-Q2NCKWTK.js.map +1 -0
- package/dist/{chunk-22RM4GMO.js → chunk-SJKT4TKW.js} +26 -2
- package/dist/chunk-SJKT4TKW.js.map +1 -0
- package/dist/{chunk-ALA3UGWB.js → chunk-SXIQK54Z.js} +8 -6
- package/dist/{chunk-ALA3UGWB.js.map → chunk-SXIQK54Z.js.map} +1 -1
- package/dist/chunk-WZT5G5OR.js +433 -0
- package/dist/chunk-WZT5G5OR.js.map +1 -0
- package/dist/client.d.ts +2 -0
- package/dist/components/chat-composer.d.ts +7 -1
- package/dist/components/human-input-form.d.ts +16 -6
- package/dist/components/human-input-surface.d.ts +19 -0
- package/dist/components/machine-input-display.d.ts +12 -0
- package/dist/components/message-timeline.d.ts +6 -1
- package/dist/components/model-policy-picker.d.ts +78 -0
- package/dist/components/session-chrome.d.ts +2 -1
- package/dist/components/tip-follow.d.ts +30 -0
- package/dist/composer.d.ts +2 -0
- package/dist/composer.js +22 -5
- package/dist/hooks/use-composer.d.ts +10 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +2261 -2230
- package/dist/index.js.map +1 -1
- package/dist/machines.js +4 -3
- package/dist/model-policy.d.ts +12 -4
- package/dist/model-policy.js +5 -1
- package/dist/realtime/dropdown-menu.d.ts +16 -0
- package/dist/realtime/realtime-control.d.ts +126 -0
- package/dist/realtime.d.ts +11 -0
- package/dist/realtime.js +1023 -0
- package/dist/realtime.js.map +1 -0
- package/dist/session-context.d.ts +7 -1
- package/dist/session-ui.d.ts +2 -0
- package/dist/session-ui.js +6 -4
- package/dist/session.js +5 -4
- package/dist/timeline/compute-label.d.ts +2 -0
- package/dist/timeline/index.d.ts +1 -0
- package/dist/timeline/types.d.ts +5 -0
- package/package.json +7 -2
- package/src/client.ts +13 -0
- package/src/components/chat-composer.tsx +19 -5
- package/src/components/composer-transcription-control.tsx +2 -2
- package/src/components/composer.tsx +14 -5
- package/src/components/human-input-form.tsx +506 -186
- package/src/components/human-input-surface.tsx +80 -0
- package/src/components/machine-input-display.ts +83 -0
- package/src/components/message-timeline.tsx +348 -308
- package/src/components/model-policy-picker.tsx +587 -0
- package/src/components/sandbox-files.tsx +1 -1
- package/src/components/session-chrome.tsx +141 -15
- package/src/components/tip-follow.ts +127 -6
- package/src/composer.ts +13 -0
- package/src/hooks/use-composer.ts +229 -29
- package/src/index.ts +19 -0
- package/src/model-policy.ts +51 -7
- package/src/realtime/dropdown-menu.tsx +123 -0
- package/src/realtime/realtime-control.tsx +1178 -0
- package/src/realtime.ts +27 -0
- package/src/session-context.ts +16 -0
- package/src/session-ui.ts +2 -0
- package/src/timeline/compute-label.tsx +18 -0
- package/src/timeline/index.ts +3 -0
- package/src/timeline/projection.ts +21 -1
- package/src/timeline/tool-renderers.tsx +232 -43
- package/src/timeline/types.ts +5 -0
- package/styles/index.css +61 -0
- package/styles/tokens.css +2 -0
- package/dist/chunk-22RM4GMO.js.map +0 -1
- package/dist/chunk-7CJOAW3V.js.map +0 -1
- package/dist/chunk-FT2TXNGZ.js.map +0 -1
- package/dist/chunk-J2RVJ6JX.js.map +0 -1
- package/dist/chunk-Z5FV355Z.js.map +0 -1
package/src/realtime.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batteries-included realtime voice controls and hooks.
|
|
3
|
+
*
|
|
4
|
+
* Import this subpath lazily when the composer action slot is rendered. The
|
|
5
|
+
* base `@opengeni/react` entry remains SSR/browser safe and does not eagerly
|
|
6
|
+
* load microphone, WebRTC, Gateway, or realtime UI code.
|
|
7
|
+
*/
|
|
8
|
+
export {
|
|
9
|
+
CodexRealtimeControl,
|
|
10
|
+
NewSessionRealtimeControl,
|
|
11
|
+
RealtimeModelPickerMenu,
|
|
12
|
+
RealtimeVoiceControl,
|
|
13
|
+
SessionCodexRealtimeControl,
|
|
14
|
+
SessionRealtimeControl,
|
|
15
|
+
codexRealtimeAdmissionAllowed,
|
|
16
|
+
codexRealtimeAdmissionBlocker,
|
|
17
|
+
useRealtimeModelSelection,
|
|
18
|
+
useSessionCodexRealtime,
|
|
19
|
+
useSessionRealtime,
|
|
20
|
+
useWorkspaceRealtimeModelSelection,
|
|
21
|
+
} from "./realtime/realtime-control";
|
|
22
|
+
export type {
|
|
23
|
+
RealtimeModelOption,
|
|
24
|
+
SessionRealtimeControllerFactory,
|
|
25
|
+
} from "./realtime/realtime-control";
|
|
26
|
+
export type { EmbeddedRealtimeSessionClientLike } from "./client";
|
|
27
|
+
export type { EmbeddedRealtimeSessionClientOverride } from "./session-context";
|
package/src/session-context.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
EmbeddedFileAttachmentClientLike,
|
|
5
5
|
EmbeddedGoalClientLike,
|
|
6
6
|
EmbeddedHumanInputSessionClientLike,
|
|
7
|
+
EmbeddedRealtimeSessionClientLike,
|
|
7
8
|
EmbeddedSessionClientLike,
|
|
8
9
|
EmbeddedSessionLineageClientLike,
|
|
9
10
|
EmbeddedSessionMcpApprovalPolicyClientLike,
|
|
@@ -55,6 +56,11 @@ export type EmbeddedSessionReadClientOverride = {
|
|
|
55
56
|
workspaceId?: string | undefined;
|
|
56
57
|
};
|
|
57
58
|
|
|
59
|
+
export type EmbeddedRealtimeSessionClientOverride = {
|
|
60
|
+
client?: EmbeddedRealtimeSessionClientLike | undefined;
|
|
61
|
+
workspaceId?: string | undefined;
|
|
62
|
+
};
|
|
63
|
+
|
|
58
64
|
export type EmbeddedGoalClientOverride = {
|
|
59
65
|
client?: EmbeddedGoalClientLike | undefined;
|
|
60
66
|
workspaceId?: string | undefined;
|
|
@@ -240,6 +246,16 @@ export function useEmbeddedSessionMcpApprovalPolicy(
|
|
|
240
246
|
);
|
|
241
247
|
}
|
|
242
248
|
|
|
249
|
+
/** Resolve the exact browser/API surface required by `@opengeni/react/realtime`. */
|
|
250
|
+
export function useEmbeddedRealtimeSession(
|
|
251
|
+
override: EmbeddedRealtimeSessionClientOverride = {},
|
|
252
|
+
): EmbeddedClientContextValue<EmbeddedRealtimeSessionClientLike> {
|
|
253
|
+
// Preserve the existing lazy capability behavior: proxy/test clients may
|
|
254
|
+
// implement only the methods reached by their selected model and lifecycle.
|
|
255
|
+
// The exported structural type remains the complete embedding contract.
|
|
256
|
+
return useEmbeddedClientRefinement(override, [], "realtime hooks");
|
|
257
|
+
}
|
|
258
|
+
|
|
243
259
|
/**
|
|
244
260
|
* Resolve the client only — for hooks that are not workspace-scoped
|
|
245
261
|
* (`useWorkspaces`, `useBillingUsage`).
|
package/src/session-ui.ts
CHANGED
|
@@ -7,6 +7,8 @@ export type {
|
|
|
7
7
|
HumanInputFormMessages,
|
|
8
8
|
HumanInputFormProps,
|
|
9
9
|
} from "./components/human-input-form";
|
|
10
|
+
export { HumanInputSurface } from "./components/human-input-surface";
|
|
11
|
+
export type { HumanInputSurfaceProps } from "./components/human-input-surface";
|
|
10
12
|
export { MessageTimeline, TimelineRow } from "./components/message-timeline";
|
|
11
13
|
export type { MessageTimelineProps } from "./components/message-timeline";
|
|
12
14
|
export { BUILT_IN_TURN_SUMMARY_FACET_IDS } from "./timeline/turn-summary";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
|
|
3
|
+
/* ----------------------------------------------------------------------------
|
|
4
|
+
Session compute label
|
|
5
|
+
|
|
6
|
+
Optional host-supplied display name for the session's active compute target
|
|
7
|
+
(e.g. "Cloud sandbox" or a Connected Machine name). Used by exec_command
|
|
8
|
+
collapsed previews. The host owns resolution; this package never calls the
|
|
9
|
+
machines API.
|
|
10
|
+
-------------------------------------------------------------------------- */
|
|
11
|
+
|
|
12
|
+
const TimelineComputeLabelContext = createContext<string | null>(null);
|
|
13
|
+
|
|
14
|
+
export const TimelineComputeLabelProvider = TimelineComputeLabelContext.Provider;
|
|
15
|
+
|
|
16
|
+
export function useTimelineComputeLabel(): string | null {
|
|
17
|
+
return useContext(TimelineComputeLabelContext);
|
|
18
|
+
}
|
package/src/timeline/index.ts
CHANGED
|
@@ -95,6 +95,9 @@ export type { FoldRestingState } from "./fold-memory";
|
|
|
95
95
|
// seen activity ids (live tool enter across rail remounts)
|
|
96
96
|
export { SeenActivityIdsProvider, useSeenActivityIds } from "./seen-activity-ids";
|
|
97
97
|
|
|
98
|
+
// session compute label (host-supplied active machine / cloud sandbox name)
|
|
99
|
+
export { TimelineComputeLabelProvider, useTimelineComputeLabel } from "./compute-label";
|
|
100
|
+
|
|
98
101
|
// turn-collapse summary chip
|
|
99
102
|
export { BUILT_IN_TURN_SUMMARY_FACET_IDS, TurnSummary, useTurnSettleOpen } from "./turn-summary";
|
|
100
103
|
export type {
|
|
@@ -124,10 +124,12 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
|
|
|
124
124
|
});
|
|
125
125
|
break;
|
|
126
126
|
}
|
|
127
|
+
const voiceMessage = realtimeVoiceMessage(payload);
|
|
127
128
|
items.push({
|
|
128
129
|
kind: "user-message",
|
|
129
130
|
id: event.id,
|
|
130
|
-
text: stringValue(payload.text),
|
|
131
|
+
text: voiceMessage?.text ?? stringValue(payload.text),
|
|
132
|
+
...(voiceMessage ? { presentation: voiceMessage.presentation } : {}),
|
|
131
133
|
resources: resourceRefs(payload.resources),
|
|
132
134
|
tools: toolRefs(payload.tools),
|
|
133
135
|
occurredAt: event.occurredAt,
|
|
@@ -687,6 +689,24 @@ export function buildTimeline(events: SessionEvent[]): TimelineItem[] {
|
|
|
687
689
|
return items;
|
|
688
690
|
}
|
|
689
691
|
|
|
692
|
+
function realtimeVoiceMessage(payload: Record<string, unknown>): {
|
|
693
|
+
text: string;
|
|
694
|
+
presentation: {
|
|
695
|
+
kind: "realtime_voice" | "realtime_voice_handoff";
|
|
696
|
+
context: string;
|
|
697
|
+
};
|
|
698
|
+
} | null {
|
|
699
|
+
const presentation = asRecord(payload.presentation);
|
|
700
|
+
const visibleText = stringValue(payload.text);
|
|
701
|
+
if (presentation.kind === "realtime_voice" || presentation.kind === "realtime_voice_handoff") {
|
|
702
|
+
const context = stringValue(presentation.context);
|
|
703
|
+
return visibleText && context
|
|
704
|
+
? { text: visibleText, presentation: { kind: presentation.kind, context } }
|
|
705
|
+
: null;
|
|
706
|
+
}
|
|
707
|
+
return null;
|
|
708
|
+
}
|
|
709
|
+
|
|
690
710
|
function providerNativeToolStatus(rawValue: unknown): ToolCallItem["status"] {
|
|
691
711
|
const raw = asRecord(rawValue);
|
|
692
712
|
if (raw.type !== "hosted_tool_call") {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
KeyboardIcon,
|
|
14
14
|
KeyRoundIcon,
|
|
15
15
|
LockIcon,
|
|
16
|
+
MessageCircleQuestionIcon,
|
|
16
17
|
MessagesSquareIcon,
|
|
17
18
|
MessageSquareIcon,
|
|
18
19
|
MousePointer2Icon,
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
} from "lucide-react";
|
|
29
30
|
import type { ReactNode } from "react";
|
|
30
31
|
import { stringifyPayload, tryParseJson } from "../lib/format";
|
|
32
|
+
import { useTimelineComputeLabel } from "./compute-label";
|
|
31
33
|
import {
|
|
32
34
|
applyPatchOpsFromToolItem,
|
|
33
35
|
controlCaret,
|
|
@@ -94,6 +96,14 @@ function RunningPreview({ children }: { children: ReactNode }) {
|
|
|
94
96
|
);
|
|
95
97
|
}
|
|
96
98
|
|
|
99
|
+
/** Prefix a collapsed preview with the host-supplied active compute label. */
|
|
100
|
+
function withComputePreview(label: string | null, preview: string): string {
|
|
101
|
+
if (!label) {
|
|
102
|
+
return preview;
|
|
103
|
+
}
|
|
104
|
+
return `on ${label} · ${preview}`;
|
|
105
|
+
}
|
|
106
|
+
|
|
97
107
|
/* ---- exec_command ---------------------------------------------------------- */
|
|
98
108
|
|
|
99
109
|
function ExecRenderer({ item }: ToolRendererProps) {
|
|
@@ -103,6 +113,7 @@ function ExecRenderer({ item }: ToolRendererProps) {
|
|
|
103
113
|
const running = item.status === "running";
|
|
104
114
|
const out = item.output;
|
|
105
115
|
const title = `$ ${cmd}`;
|
|
116
|
+
const computeLabel = useTimelineComputeLabel();
|
|
106
117
|
|
|
107
118
|
// No output event ever arrived (item.output stays undefined from creation):
|
|
108
119
|
// the turn failed before the output insert — most likely a NUL byte in the
|
|
@@ -116,7 +127,7 @@ function ExecRenderer({ item }: ToolRendererProps) {
|
|
|
116
127
|
title={title}
|
|
117
128
|
titleMono
|
|
118
129
|
chip={{ tone: "bad", text: "failed" }}
|
|
119
|
-
preview="output lost — NUL byte could not be stored"
|
|
130
|
+
preview={withComputePreview(computeLabel, "output lost — NUL byte could not be stored")}
|
|
120
131
|
>
|
|
121
132
|
<BodyNote tone="error">
|
|
122
133
|
output contained a NUL byte and could not be stored; the turn failed on this tool's
|
|
@@ -137,7 +148,7 @@ function ExecRenderer({ item }: ToolRendererProps) {
|
|
|
137
148
|
title={title}
|
|
138
149
|
titleMono
|
|
139
150
|
chip={{ tone: "bad", text: "failed" }}
|
|
140
|
-
preview="tool call failed"
|
|
151
|
+
preview={withComputePreview(computeLabel, "tool call failed")}
|
|
141
152
|
>
|
|
142
153
|
<BodyNote tone="error">the tool call failed with no output.</BodyNote>
|
|
143
154
|
</ActivityDisclosure>
|
|
@@ -146,6 +157,7 @@ function ExecRenderer({ item }: ToolRendererProps) {
|
|
|
146
157
|
|
|
147
158
|
if (running) {
|
|
148
159
|
const streamed = typeof out === "string" ? stripExecBanner(out) : "";
|
|
160
|
+
const runningPreview = streamed ? `${streamed.split("\n").length} lines` : "running…";
|
|
149
161
|
return (
|
|
150
162
|
<ActivityDisclosure
|
|
151
163
|
icon={<TerminalIcon className={ICON_SIZE} />}
|
|
@@ -154,9 +166,7 @@ function ExecRenderer({ item }: ToolRendererProps) {
|
|
|
154
166
|
titleMono
|
|
155
167
|
running
|
|
156
168
|
preview={
|
|
157
|
-
<RunningPreview>
|
|
158
|
-
{streamed ? `${streamed.split("\n").length} lines` : "running…"}
|
|
159
|
-
</RunningPreview>
|
|
169
|
+
<RunningPreview>{withComputePreview(computeLabel, runningPreview)}</RunningPreview>
|
|
160
170
|
}
|
|
161
171
|
>
|
|
162
172
|
{/* The row title is already `$ ${cmd}`; the TermBlock header drops the
|
|
@@ -184,8 +194,9 @@ function ExecRenderer({ item }: ToolRendererProps) {
|
|
|
184
194
|
iconTone = "failed";
|
|
185
195
|
}
|
|
186
196
|
|
|
187
|
-
const
|
|
197
|
+
const peek = binary ? "binary output" : tailPeek(stripped) || "(no output)";
|
|
188
198
|
const truncated = execTruncated(text);
|
|
199
|
+
const preview = withComputePreview(computeLabel, truncated ? `⋯ truncated · ${peek}` : peek);
|
|
189
200
|
// Hand TermBlock the FULL stripped output; it owns the tail/show-more slicing.
|
|
190
201
|
const body = binary ? "(binary output suppressed)" : stripped;
|
|
191
202
|
|
|
@@ -198,7 +209,7 @@ function ExecRenderer({ item }: ToolRendererProps) {
|
|
|
198
209
|
{...(chip ? { chip } : {})}
|
|
199
210
|
failed={item.status === "failed"}
|
|
200
211
|
cancelled={item.status === "cancelled"}
|
|
201
|
-
preview={
|
|
212
|
+
preview={preview}
|
|
202
213
|
>
|
|
203
214
|
<TermBlock
|
|
204
215
|
command={null}
|
|
@@ -1254,6 +1265,179 @@ function MemoryProposeRenderer({ item }: ToolRendererProps) {
|
|
|
1254
1265
|
);
|
|
1255
1266
|
}
|
|
1256
1267
|
|
|
1268
|
+
/* ---- request_human_input --------------------------------------------------- */
|
|
1269
|
+
|
|
1270
|
+
function askToolPreview(args: unknown): string | null {
|
|
1271
|
+
const record = args && typeof args === "object" ? (args as Record<string, unknown>) : null;
|
|
1272
|
+
const questions = Array.isArray(record?.questions) ? record.questions : null;
|
|
1273
|
+
if (!questions || questions.length === 0) {
|
|
1274
|
+
return null;
|
|
1275
|
+
}
|
|
1276
|
+
const first = questions[0];
|
|
1277
|
+
if (!first || typeof first !== "object") {
|
|
1278
|
+
return null;
|
|
1279
|
+
}
|
|
1280
|
+
const q = first as Record<string, unknown>;
|
|
1281
|
+
const text =
|
|
1282
|
+
typeof q.label === "string" && q.label.trim()
|
|
1283
|
+
? q.label.trim()
|
|
1284
|
+
: typeof q.prompt === "string" && q.prompt.trim()
|
|
1285
|
+
? q.prompt.trim()
|
|
1286
|
+
: null;
|
|
1287
|
+
if (!text) {
|
|
1288
|
+
return null;
|
|
1289
|
+
}
|
|
1290
|
+
const preview = truncatePreview(text, 90);
|
|
1291
|
+
return questions.length > 1 ? `${preview} · ${questions.length} questions` : preview;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
function AskRenderer({ item }: ToolRendererProps) {
|
|
1295
|
+
const args = redactSecrets(parseToolArgs(item.arguments));
|
|
1296
|
+
const preview = askToolPreview(args);
|
|
1297
|
+
const icon = <MessageCircleQuestionIcon className={ICON_SIZE} />;
|
|
1298
|
+
const title = "Ask";
|
|
1299
|
+
|
|
1300
|
+
if (item.status === "running") {
|
|
1301
|
+
return (
|
|
1302
|
+
<ActivityDisclosure
|
|
1303
|
+
icon={icon}
|
|
1304
|
+
iconTone="running"
|
|
1305
|
+
title={title}
|
|
1306
|
+
running
|
|
1307
|
+
preview={
|
|
1308
|
+
preview ? (
|
|
1309
|
+
<RunningPreview>{preview}</RunningPreview>
|
|
1310
|
+
) : (
|
|
1311
|
+
<RunningPreview>Waiting…</RunningPreview>
|
|
1312
|
+
)
|
|
1313
|
+
}
|
|
1314
|
+
>
|
|
1315
|
+
<PayloadBlock label="Arguments" value={args} />
|
|
1316
|
+
</ActivityDisclosure>
|
|
1317
|
+
);
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
const { text: outText, isError } = unwrapMcpOutput(item.output);
|
|
1321
|
+
if ((isError || item.status === "failed") && item.status !== "cancelled") {
|
|
1322
|
+
return (
|
|
1323
|
+
<ActivityDisclosure
|
|
1324
|
+
icon={icon}
|
|
1325
|
+
iconTone="failed"
|
|
1326
|
+
title={title}
|
|
1327
|
+
chip={{ tone: "bad", text: "error" }}
|
|
1328
|
+
preview={truncatePreview(outText, 80) || preview || "Error"}
|
|
1329
|
+
>
|
|
1330
|
+
<PayloadBlock label="Arguments" value={args} />
|
|
1331
|
+
<PayloadBlock label="Error" value={outText} failed />
|
|
1332
|
+
</ActivityDisclosure>
|
|
1333
|
+
);
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
return (
|
|
1337
|
+
<ActivityDisclosure
|
|
1338
|
+
icon={icon}
|
|
1339
|
+
iconTone="muted"
|
|
1340
|
+
title={title}
|
|
1341
|
+
cancelled={item.status === "cancelled"}
|
|
1342
|
+
preview={item.status === "cancelled" ? undefined : (preview ?? undefined)}
|
|
1343
|
+
>
|
|
1344
|
+
<PayloadBlock label="Arguments" value={args} />
|
|
1345
|
+
{outText ? <PayloadBlock label="Result" value={outText} /> : null}
|
|
1346
|
+
</ActivityDisclosure>
|
|
1347
|
+
);
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
/* ---- run_on ---------------------------------------------------------------- */
|
|
1351
|
+
|
|
1352
|
+
function runOnTargetName(output: unknown): string | null {
|
|
1353
|
+
const { text } = unwrapMcpOutput(output);
|
|
1354
|
+
const parsed = tryParseJson(text);
|
|
1355
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
1356
|
+
const name = (parsed as { targetName?: unknown }).targetName;
|
|
1357
|
+
if (typeof name === "string" && name.trim()) {
|
|
1358
|
+
return name.trim();
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
return null;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
function runOnOpPreview(args: Record<string, unknown>): string | null {
|
|
1365
|
+
const op = args.op;
|
|
1366
|
+
if (!op || typeof op !== "object" || Array.isArray(op)) {
|
|
1367
|
+
return null;
|
|
1368
|
+
}
|
|
1369
|
+
const record = op as Record<string, unknown>;
|
|
1370
|
+
if (record.kind === "exec" && typeof record.cmd === "string" && record.cmd.trim()) {
|
|
1371
|
+
return `$ ${record.cmd.trim()}`;
|
|
1372
|
+
}
|
|
1373
|
+
if (
|
|
1374
|
+
(record.kind === "read" || record.kind === "write") &&
|
|
1375
|
+
typeof record.path === "string" &&
|
|
1376
|
+
record.path.trim()
|
|
1377
|
+
) {
|
|
1378
|
+
return truncatePreview(record.path.trim(), 72);
|
|
1379
|
+
}
|
|
1380
|
+
return null;
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
function RunOnRenderer({ item }: ToolRendererProps) {
|
|
1384
|
+
const parsedArgs = parseToolArgs(item.arguments);
|
|
1385
|
+
const args = redactSecrets(parsedArgs);
|
|
1386
|
+
const targetName = runOnTargetName(item.output);
|
|
1387
|
+
const title = targetName ? `Run on ${targetName}` : "Run on";
|
|
1388
|
+
const opPreview = runOnOpPreview(parsedArgs);
|
|
1389
|
+
const icon = <ServerIcon className={ICON_SIZE} />;
|
|
1390
|
+
|
|
1391
|
+
if (item.status === "running") {
|
|
1392
|
+
return (
|
|
1393
|
+
<ActivityDisclosure
|
|
1394
|
+
icon={icon}
|
|
1395
|
+
iconTone="running"
|
|
1396
|
+
title={title}
|
|
1397
|
+
running
|
|
1398
|
+
preview={
|
|
1399
|
+
opPreview ? (
|
|
1400
|
+
<RunningPreview>{opPreview}</RunningPreview>
|
|
1401
|
+
) : (
|
|
1402
|
+
<RunningPreview>Running…</RunningPreview>
|
|
1403
|
+
)
|
|
1404
|
+
}
|
|
1405
|
+
>
|
|
1406
|
+
<PayloadBlock label="Arguments" value={args} />
|
|
1407
|
+
</ActivityDisclosure>
|
|
1408
|
+
);
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
const { text: outText, isError } = unwrapMcpOutput(item.output);
|
|
1412
|
+
if ((isError || item.status === "failed") && item.status !== "cancelled") {
|
|
1413
|
+
return (
|
|
1414
|
+
<ActivityDisclosure
|
|
1415
|
+
icon={icon}
|
|
1416
|
+
iconTone="failed"
|
|
1417
|
+
title={title}
|
|
1418
|
+
chip={{ tone: "bad", text: "error" }}
|
|
1419
|
+
preview={truncatePreview(outText, 80) || opPreview || "Error"}
|
|
1420
|
+
>
|
|
1421
|
+
<PayloadBlock label="Arguments" value={args} />
|
|
1422
|
+
<PayloadBlock label="Error" value={outText} failed />
|
|
1423
|
+
</ActivityDisclosure>
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
return (
|
|
1428
|
+
<ActivityDisclosure
|
|
1429
|
+
icon={icon}
|
|
1430
|
+
iconTone="muted"
|
|
1431
|
+
title={title}
|
|
1432
|
+
cancelled={item.status === "cancelled"}
|
|
1433
|
+
preview={item.status === "cancelled" ? undefined : (opPreview ?? undefined)}
|
|
1434
|
+
>
|
|
1435
|
+
<PayloadBlock label="Arguments" value={args} />
|
|
1436
|
+
{outText ? <PayloadBlock label="Result" value={outText} /> : null}
|
|
1437
|
+
</ActivityDisclosure>
|
|
1438
|
+
);
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1257
1441
|
/* ---- generic fallback (first-party MCP, external MCP, unknown) ------------- */
|
|
1258
1442
|
|
|
1259
1443
|
/**
|
|
@@ -1355,42 +1539,45 @@ function truncatePreview(text: string, max: number): string {
|
|
|
1355
1539
|
/** Explicit first-party leaf/prefix → canonical product icons (match nav/pages). */
|
|
1356
1540
|
function GenericToolIcon({ name }: { name: string }) {
|
|
1357
1541
|
const leaf = mcpToolLeaf(name);
|
|
1358
|
-
const Icon =
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
leaf
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1542
|
+
const Icon =
|
|
1543
|
+
leaf === "request_human_input"
|
|
1544
|
+
? MessageCircleQuestionIcon
|
|
1545
|
+
: leaf.startsWith("goal_")
|
|
1546
|
+
? TargetIcon
|
|
1547
|
+
: leaf.startsWith("memory_") ||
|
|
1548
|
+
leaf === "preference_registry_summary" ||
|
|
1549
|
+
leaf === "preference_registry_get"
|
|
1550
|
+
? BrainCircuitIcon
|
|
1551
|
+
: leaf.startsWith("session_") ||
|
|
1552
|
+
leaf === "sessions_list" ||
|
|
1553
|
+
leaf === "set_session_title" ||
|
|
1554
|
+
leaf === "set_other_session_title"
|
|
1555
|
+
? MessagesSquareIcon
|
|
1556
|
+
: leaf.startsWith("sandbox") || leaf === "sandboxes_list" || leaf === "run_on"
|
|
1557
|
+
? ServerIcon
|
|
1558
|
+
: leaf.startsWith("rig_")
|
|
1559
|
+
? ServerCogIcon
|
|
1560
|
+
: leaf.startsWith("scheduled_")
|
|
1561
|
+
? CalendarClockIcon
|
|
1562
|
+
: leaf.startsWith("artifacts_")
|
|
1563
|
+
? PanelsTopLeftIcon
|
|
1564
|
+
: leaf.startsWith("social_")
|
|
1565
|
+
? Share2Icon
|
|
1566
|
+
: leaf.startsWith("slack_")
|
|
1567
|
+
? MessageSquareIcon
|
|
1568
|
+
: leaf.startsWith("github_")
|
|
1569
|
+
? FolderGitIcon
|
|
1570
|
+
: leaf.startsWith("variable_")
|
|
1571
|
+
? BoxIcon
|
|
1572
|
+
: leaf.startsWith("environment_")
|
|
1573
|
+
? KeyRoundIcon
|
|
1574
|
+
: leaf.includes("document") ||
|
|
1575
|
+
leaf.includes("knowledge") ||
|
|
1576
|
+
leaf === "list_document_bases"
|
|
1577
|
+
? FileSearchIcon
|
|
1578
|
+
: leaf === "tool_search" || leaf === "load_skill"
|
|
1579
|
+
? PlugIcon
|
|
1580
|
+
: WrenchIcon;
|
|
1394
1581
|
return <Icon className={ICON_SIZE} />;
|
|
1395
1582
|
}
|
|
1396
1583
|
|
|
@@ -1404,6 +1591,8 @@ const BASE_ENTRIES: ToolRegistryEntry[] = [
|
|
|
1404
1591
|
{ match: "rawType", type: "hosted_tool_call", render: WebSearchRenderer },
|
|
1405
1592
|
// First-party sandbox + MCP tools resolve by name (exact or MCP leaf).
|
|
1406
1593
|
{ match: "name", name: "exec_command", render: ExecRenderer },
|
|
1594
|
+
{ match: "name", name: "request_human_input", render: AskRenderer },
|
|
1595
|
+
{ match: "name", name: "run_on", render: RunOnRenderer },
|
|
1407
1596
|
{ match: "name", name: "write_stdin", render: WriteStdinRenderer },
|
|
1408
1597
|
{ match: "name", name: "apply_patch_call", render: ApplyPatchRenderer },
|
|
1409
1598
|
{ match: "name", name: "apply_patch", render: ApplyPatchRenderer },
|
package/src/timeline/types.ts
CHANGED
|
@@ -13,6 +13,11 @@ export type UserMessageItem = {
|
|
|
13
13
|
kind: "user-message";
|
|
14
14
|
id: string;
|
|
15
15
|
text: string;
|
|
16
|
+
presentation?: {
|
|
17
|
+
kind: "realtime_voice" | "realtime_voice_handoff";
|
|
18
|
+
/** Full bounded execution context sent with this visible voice request. */
|
|
19
|
+
context: string;
|
|
20
|
+
};
|
|
16
21
|
/** Resources attached to this message (file uploads, repositories). */
|
|
17
22
|
resources: ResourceRef[];
|
|
18
23
|
/** Tools requested for the turn this message starts. */
|
package/styles/index.css
CHANGED
|
@@ -19,6 +19,11 @@
|
|
|
19
19
|
@theme inline {
|
|
20
20
|
--font-og-sans: var(--og-font-sans);
|
|
21
21
|
--font-og-mono: var(--og-font-mono);
|
|
22
|
+
/* Compatibility aliases still used by published components and the exact
|
|
23
|
+
dropdown primitives shared with the web app. Keep the public stylesheet
|
|
24
|
+
self-contained instead of requiring consumers to copy the app theme. */
|
|
25
|
+
--font-sans: var(--og-font-sans);
|
|
26
|
+
--font-mono: var(--og-font-mono);
|
|
22
27
|
|
|
23
28
|
/* Type ramp — a real 4-step scale (no half-pixel hand-tuning). Every
|
|
24
29
|
timeline string maps to one of these via `text-og-{xs,sm,base,md}`;
|
|
@@ -31,6 +36,8 @@
|
|
|
31
36
|
--text-og-base--line-height: 1.55;
|
|
32
37
|
--text-og-md: 15px;
|
|
33
38
|
--text-og-md--line-height: 1.6;
|
|
39
|
+
--text-2xs: 0.6875rem;
|
|
40
|
+
--text-2xs--line-height: 1rem;
|
|
34
41
|
|
|
35
42
|
--color-og-bg: var(--og-color-bg);
|
|
36
43
|
--color-og-surface-1: var(--og-color-surface-1);
|
|
@@ -44,6 +51,7 @@
|
|
|
44
51
|
|
|
45
52
|
--color-og-accent: var(--og-color-accent);
|
|
46
53
|
--color-og-accent-strong: var(--og-color-accent-strong);
|
|
54
|
+
--color-og-accent-deep: var(--og-color-accent-deep);
|
|
47
55
|
--color-og-accent-fg: var(--og-color-accent-fg);
|
|
48
56
|
--color-og-accent-soft: var(--og-color-accent-soft);
|
|
49
57
|
|
|
@@ -55,11 +63,64 @@
|
|
|
55
63
|
--color-og-status-cancelled: var(--og-color-status-cancelled);
|
|
56
64
|
--color-og-danger: var(--og-color-danger);
|
|
57
65
|
|
|
66
|
+
--color-bg: var(--og-color-bg);
|
|
67
|
+
--color-surface: var(--og-color-surface-1);
|
|
68
|
+
--color-surface-2: var(--og-color-surface-2);
|
|
69
|
+
--color-surface-3: var(--og-color-surface-3);
|
|
70
|
+
--color-border: var(--og-color-border);
|
|
71
|
+
--color-border-strong: var(--og-color-border-strong);
|
|
72
|
+
--color-fg: var(--og-color-fg);
|
|
73
|
+
--color-fg-muted: var(--og-color-fg-muted);
|
|
74
|
+
--color-fg-subtle: var(--og-color-fg-subtle);
|
|
75
|
+
--color-brand: var(--og-color-accent);
|
|
76
|
+
--color-brand-strong: var(--og-color-accent-deep);
|
|
77
|
+
--color-brand-fg: var(--og-color-accent-fg);
|
|
78
|
+
--color-status-queued: var(--og-color-status-queued);
|
|
79
|
+
--color-status-running: var(--og-color-status-running);
|
|
80
|
+
--color-status-idle: var(--og-color-status-idle);
|
|
81
|
+
--color-status-waiting: var(--og-color-status-waiting);
|
|
82
|
+
--color-status-success: var(--og-color-status-idle);
|
|
83
|
+
--color-status-failed: var(--og-color-status-failed);
|
|
84
|
+
--color-status-cancelled: var(--og-color-status-cancelled);
|
|
85
|
+
--color-danger: var(--og-color-danger);
|
|
86
|
+
|
|
87
|
+
--color-background: var(--color-bg);
|
|
88
|
+
--color-foreground: var(--color-fg);
|
|
89
|
+
--color-card: var(--color-surface);
|
|
90
|
+
--color-card-foreground: var(--color-fg);
|
|
91
|
+
--color-popover: var(--color-surface-3);
|
|
92
|
+
--color-popover-foreground: var(--color-fg);
|
|
93
|
+
--color-primary: var(--color-brand-strong);
|
|
94
|
+
--color-primary-foreground: var(--color-brand-fg);
|
|
95
|
+
--color-secondary: var(--color-surface-2);
|
|
96
|
+
--color-secondary-foreground: var(--color-fg);
|
|
97
|
+
--color-muted: var(--color-surface-2);
|
|
98
|
+
--color-muted-foreground: var(--color-fg-muted);
|
|
99
|
+
--color-accent: var(--color-surface-2);
|
|
100
|
+
--color-accent-foreground: var(--color-fg);
|
|
101
|
+
--color-destructive: var(--og-color-danger);
|
|
102
|
+
--color-destructive-filled: color-mix(in oklch, var(--og-color-danger) 70%, black);
|
|
103
|
+
--color-destructive-foreground: var(--og-color-accent-fg);
|
|
104
|
+
--color-input: var(--color-surface-2);
|
|
105
|
+
--color-ring: var(--color-brand);
|
|
106
|
+
--color-sidebar: var(--color-surface);
|
|
107
|
+
--color-sidebar-foreground: var(--color-fg);
|
|
108
|
+
--color-sidebar-primary: var(--color-brand-strong);
|
|
109
|
+
--color-sidebar-primary-foreground: var(--color-brand-fg);
|
|
110
|
+
--color-sidebar-accent: var(--color-surface-2);
|
|
111
|
+
--color-sidebar-accent-foreground: var(--color-fg);
|
|
112
|
+
--color-sidebar-border: var(--color-border);
|
|
113
|
+
--color-sidebar-ring: var(--color-brand);
|
|
114
|
+
|
|
58
115
|
--radius-og-xs: var(--og-radius-xs);
|
|
59
116
|
--radius-og-sm: var(--og-radius-sm);
|
|
60
117
|
--radius-og-md: var(--og-radius-md);
|
|
61
118
|
--radius-og-lg: var(--og-radius-lg);
|
|
62
119
|
--radius-og-xl: var(--og-radius-xl);
|
|
120
|
+
--radius-sm: var(--og-radius-sm);
|
|
121
|
+
--radius-md: var(--og-radius-md);
|
|
122
|
+
--radius-lg: var(--og-radius-lg);
|
|
123
|
+
--radius-xl: var(--og-radius-xl);
|
|
63
124
|
|
|
64
125
|
--shadow-og-sm: var(--og-shadow-sm);
|
|
65
126
|
--shadow-og-md: var(--og-shadow-md);
|
package/styles/tokens.css
CHANGED
|
@@ -107,6 +107,8 @@
|
|
|
107
107
|
--og-session-chrome-rail-pad: 0.2rem;
|
|
108
108
|
--og-session-chrome-panel-pad-x: 0.5rem;
|
|
109
109
|
--og-session-chrome-panel-pad-y: 0.4rem;
|
|
110
|
+
/* Expanded agents/queue/inbox/goal body — scroll inside, never grow unbound. */
|
|
111
|
+
--og-session-chrome-panel-max-height: min(18rem, 40dvh);
|
|
110
112
|
--og-session-chrome-duration: 220ms;
|
|
111
113
|
--og-session-chrome-crossfade-duration: 180ms;
|
|
112
114
|
--og-session-chrome-ease: var(--og-ease-out);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/model-policy.ts"],"sourcesContent":["import type { ClientModel, ReasoningEffort, WorkspaceModelCatalogModel } from \"@opengeni/sdk\";\n\nexport type PickerBillingClass = \"opengeni_credits\" | \"codex_subscription\" | \"byok\";\n\nexport type PickerModelRow = {\n id: string;\n label: string;\n billingClass: PickerBillingClass;\n billingClassLabel: string;\n selectable: boolean;\n unavailableReason: string | null;\n provider: string;\n providerLabel: string;\n catalog: WorkspaceModelCatalogModel;\n};\n\nexport type LatencyModeId = \"standard\" | \"priority\" | \"fast\";\n\nconst BILLING_CLASS_ORDER: PickerBillingClass[] = [\n \"opengeni_credits\",\n \"codex_subscription\",\n \"byok\",\n];\n\nconst BILLING_CLASS_LABELS: Record<PickerBillingClass, string> = {\n opengeni_credits: \"OpenGeni\",\n codex_subscription: \"Codex\",\n byok: \"Your Gateway\",\n};\n\nconst AVAILABILITY_REASON_LABELS: Record<string, string> = {\n missing_credential: \"Credentials required\",\n needs_reauth: \"Reconnect required\",\n credential_not_ready: \"Credential not ready\",\n not_entitled: \"Not entitled\",\n provider_unhealthy: \"Provider unavailable\",\n policy_blocked: \"Blocked by workspace policy\",\n unsupported: \"Unsupported\",\n};\n\nexport function billingClassForModel(model: ClientModel): PickerBillingClass {\n if (model.source === \"codex\") {\n return \"codex_subscription\";\n }\n if (model.source === \"workspace_gateway\") {\n return \"byok\";\n }\n if (model.credentialSource?.kind === \"connected_subscription\") {\n return \"codex_subscription\";\n }\n if (model.credentialSource?.kind === \"workspace_connection\") {\n return \"byok\";\n }\n if (model.billing?.upstreamPayer === \"connected_subscription\") {\n return \"codex_subscription\";\n }\n if (model.billing?.upstreamPayer === \"workspace\") {\n return \"byok\";\n }\n return \"opengeni_credits\";\n}\n\nexport function billingClassLabel(billingClass: PickerBillingClass): string {\n return BILLING_CLASS_LABELS[billingClass];\n}\n\nexport function availabilityReasonLabel(\n reason: WorkspaceModelCatalogModel[\"availability\"][\"reason\"],\n): string | null {\n if (!reason) {\n return null;\n }\n return AVAILABILITY_REASON_LABELS[reason] ?? \"Unavailable\";\n}\n\nexport function effortOptionsForModel(model: ClientModel): ReasoningEffort[] {\n const efforts = model.capabilities?.reasoning.efforts;\n if (!efforts || efforts.length === 0) {\n return [\"low\"];\n }\n const order: ReasoningEffort[] = [\"none\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"];\n return order.filter((effort) => efforts.includes(effort));\n}\n\nexport function defaultEffortForModel(model: ClientModel): ReasoningEffort {\n const options = effortOptionsForModel(model);\n const configured = model.capabilities?.reasoning.defaultEffort;\n if (configured && options.includes(configured)) {\n return configured;\n }\n return options[0] ?? \"low\";\n}\n\nexport function coerceReasoningEffortForModel(\n model: ClientModel,\n effort: ReasoningEffort,\n): ReasoningEffort {\n const options = effortOptionsForModel(model);\n if (options.includes(effort)) {\n return effort;\n }\n return defaultEffortForModel(model);\n}\n\nexport function runnableLatencyModesForModel(model: ClientModel): LatencyModeId[] {\n const modes = model.capabilities?.latencyModes ?? [];\n return modes.filter((mode) => mode.runnable).map((mode) => mode.id);\n}\n\nexport function labelLatencyMode(mode: LatencyModeId): string {\n if (mode === \"fast\") {\n return \"Fast\";\n }\n if (mode === \"priority\") {\n return \"Priority\";\n }\n return \"Standard\";\n}\n\nexport function payerSummaryForModel(model: ClientModel): string {\n const billing = model.billing;\n if (!billing) {\n return \"Route unknown\";\n }\n if (billing.metering === \"opengeni_credits\") {\n return \"OpenGeni credits · automatic managed route\";\n }\n if (billing.upstreamPayer === \"connected_subscription\") {\n return \"Codex subscription · external billing\";\n }\n if (billing.upstreamPayer === \"workspace\") {\n return \"Billed to your AI Gateway\";\n }\n return \"Deployment route · external billing\";\n}\n\nexport function advancedSourceSummary(model: ClientModel): string | null {\n const source = model.credentialSource;\n if (!source) {\n return null;\n }\n if (source.kind === \"connected_subscription\") {\n return \"Connected Codex subscription\";\n }\n if (source.kind === \"workspace_connection\") {\n return \"Workspace AI Gateway\";\n }\n if (source.kind === \"deployment\") {\n return source.mechanism === \"azure_ad_bearer\"\n ? \"Deployment Azure identity\"\n : \"Deployment API key\";\n }\n return null;\n}\n\nexport function projectPickerRows(models: WorkspaceModelCatalogModel[]): PickerModelRow[] {\n return models\n .filter((catalog) => {\n const billingClass = billingClassForModel(catalog);\n return billingClass === \"opengeni_credits\" || catalog.credentialReadiness.status === \"ready\";\n })\n .map((catalog) => {\n const billingClass = billingClassForModel(catalog);\n return {\n id: catalog.id,\n label: catalog.label,\n billingClass,\n billingClassLabel: billingClassLabel(billingClass),\n selectable: catalog.availability.selectable,\n unavailableReason: catalog.availability.selectable\n ? null\n : availabilityReasonLabel(catalog.availability.reason),\n provider: catalog.provider,\n providerLabel: catalog.providerLabel,\n catalog,\n };\n });\n}\n\nexport function sortPickerRows(rows: PickerModelRow[]): PickerModelRow[] {\n return [...rows].sort((left, right) => {\n const classDelta =\n BILLING_CLASS_ORDER.indexOf(left.billingClass) -\n BILLING_CLASS_ORDER.indexOf(right.billingClass);\n if (classDelta !== 0) {\n return classDelta;\n }\n if (left.selectable !== right.selectable) {\n return left.selectable ? -1 : 1;\n }\n return left.label.localeCompare(right.label);\n });\n}\n\nexport function findPickerRow(rows: PickerModelRow[], modelId: string): PickerModelRow | null {\n return rows.find((row) => row.id === modelId) ?? null;\n}\n\nexport function groupPickerRowsByBillingClass(\n rows: PickerModelRow[],\n): Array<{ billingClass: PickerBillingClass; label: string; rows: PickerModelRow[] }> {\n const sorted = sortPickerRows(rows);\n const groups: Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow[];\n }> = [];\n for (const row of sorted) {\n const existing = groups.find((group) => group.billingClass === row.billingClass);\n if (existing) {\n existing.rows.push(row);\n continue;\n }\n groups.push({\n billingClass: row.billingClass,\n label: row.billingClassLabel,\n rows: [row],\n });\n }\n return groups;\n}\n"],"mappings":"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","names":[]}
|