@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
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
-
useEmbeddedSession,
|
|
3
2
|
useSessionEventTrigger
|
|
4
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EB67J347.js";
|
|
4
|
+
import {
|
|
5
|
+
useEmbeddedSession
|
|
6
|
+
} from "./chunk-EKZH6IDG.js";
|
|
5
7
|
|
|
6
8
|
// src/hooks/use-composer.ts
|
|
9
|
+
import {
|
|
10
|
+
DEFAULT_FILE_RESOURCE_MOUNT_ROOT
|
|
11
|
+
} from "@opengeni/sdk";
|
|
7
12
|
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
8
13
|
var PENDING_COMPOSER_STORAGE_PREFIX = "opengeni.pending-composer.v1:";
|
|
9
14
|
var pendingComposerOperations = /* @__PURE__ */ new Map();
|
|
@@ -103,6 +108,32 @@ function updatePendingComposerShadow(key, operation, shadow) {
|
|
|
103
108
|
rememberPendingComposerOperation(key, next);
|
|
104
109
|
return next;
|
|
105
110
|
}
|
|
111
|
+
var STEERING_SETTLEMENT_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
112
|
+
"turn.started",
|
|
113
|
+
"turn.completed",
|
|
114
|
+
"turn.failed",
|
|
115
|
+
"turn.cancelled",
|
|
116
|
+
"turn.superseded"
|
|
117
|
+
]);
|
|
118
|
+
function isSteeringSettlementEvent(event) {
|
|
119
|
+
return STEERING_SETTLEMENT_EVENT_TYPES.has(event.type);
|
|
120
|
+
}
|
|
121
|
+
function steeringAcceptedEvent(steering, events) {
|
|
122
|
+
return events.find(
|
|
123
|
+
(event) => event.type === "user.message" && steering.clientEventId !== null && event.clientEventId === steering.clientEventId
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
function steeringSettledByEvents(steering, events) {
|
|
127
|
+
const acceptedEventId = steering.triggerEventId ?? steeringAcceptedEvent(steering, events)?.id ?? null;
|
|
128
|
+
return events.some((event) => {
|
|
129
|
+
if (steering.turnId && event.turnId === steering.turnId && isSteeringSettlementEvent(event)) {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
if (event.type !== "turn.started" || !acceptedEventId) return false;
|
|
133
|
+
const payload = event.payload;
|
|
134
|
+
return typeof payload === "object" && payload !== null && "triggerEventId" in payload && payload.triggerEventId === acceptedEventId;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
106
137
|
function useComposer(sessionId, options = {}) {
|
|
107
138
|
const { client, workspaceId, registerSessionReconciler } = useEmbeddedSession(options);
|
|
108
139
|
const durableDrafts = options.draftPersistence !== "disabled";
|
|
@@ -113,6 +144,15 @@ function useComposer(sessionId, options = {}) {
|
|
|
113
144
|
const [value, setValue] = useState(() => initialShadow?.text ?? "");
|
|
114
145
|
const [stateTargetKey, setStateTargetKey] = useState(targetKey);
|
|
115
146
|
const [sending, setSending] = useState(false);
|
|
147
|
+
const [steering, setSteering] = useState(
|
|
148
|
+
() => initialPendingOperation?.delivery === "steer" ? {
|
|
149
|
+
phase: "submitting",
|
|
150
|
+
text: initialPendingOperation.input.text,
|
|
151
|
+
clientEventId: initialPendingOperation.input.clientEventId ?? null,
|
|
152
|
+
triggerEventId: null,
|
|
153
|
+
turnId: null
|
|
154
|
+
} : null
|
|
155
|
+
);
|
|
116
156
|
const [pausing, setPausing] = useState(false);
|
|
117
157
|
const [resuming, setResuming] = useState(false);
|
|
118
158
|
const [error, setError] = useState(null);
|
|
@@ -124,6 +164,8 @@ function useComposer(sessionId, options = {}) {
|
|
|
124
164
|
() => initialShadow?.resources ?? []
|
|
125
165
|
);
|
|
126
166
|
const pendingOperationRef = useRef(initialPendingOperation);
|
|
167
|
+
const steeringSettlementEventsRef = useRef([]);
|
|
168
|
+
const steeringRef = useRef(steering);
|
|
127
169
|
const pendingClientEventId = useRef(
|
|
128
170
|
initialPendingOperation?.input.clientEventId ?? null
|
|
129
171
|
);
|
|
@@ -141,6 +183,9 @@ function useComposer(sessionId, options = {}) {
|
|
|
141
183
|
useLayoutEffect(() => {
|
|
142
184
|
onDraftAppliedRef.current = onDraftApplied;
|
|
143
185
|
}, [onDraftApplied]);
|
|
186
|
+
useLayoutEffect(() => {
|
|
187
|
+
steeringRef.current = steering;
|
|
188
|
+
}, [steering]);
|
|
144
189
|
const sendExtrasRef = useRef(options.sendExtras);
|
|
145
190
|
sendExtrasRef.current = options.sendExtras;
|
|
146
191
|
const sendBlockedRef = useRef(options.sendBlocked);
|
|
@@ -153,6 +198,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
153
198
|
targetGeneration.current += 1;
|
|
154
199
|
draftReadGeneration.current += 1;
|
|
155
200
|
pendingOperationRef.current = restorePendingComposerOperation(pendingOperationKey);
|
|
201
|
+
steeringSettlementEventsRef.current = [];
|
|
156
202
|
pendingClientEventId.current = pendingOperationRef.current?.input.clientEventId ?? null;
|
|
157
203
|
const shadow = pendingOperationRef.current?.newerShadow;
|
|
158
204
|
localEditRevision.current = shadow ? 1 : 0;
|
|
@@ -164,6 +210,15 @@ function useComposer(sessionId, options = {}) {
|
|
|
164
210
|
setStateTargetKey(targetKey);
|
|
165
211
|
setValue(shadow?.text ?? "");
|
|
166
212
|
setSending(false);
|
|
213
|
+
setSteering(
|
|
214
|
+
pendingOperationRef.current?.delivery === "steer" ? {
|
|
215
|
+
phase: "submitting",
|
|
216
|
+
text: pendingOperationRef.current.input.text,
|
|
217
|
+
clientEventId: pendingOperationRef.current.input.clientEventId ?? null,
|
|
218
|
+
triggerEventId: null,
|
|
219
|
+
turnId: null
|
|
220
|
+
} : null
|
|
221
|
+
);
|
|
167
222
|
setPausing(false);
|
|
168
223
|
setResuming(false);
|
|
169
224
|
setError(null);
|
|
@@ -267,7 +322,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
267
322
|
setRestoredResources(shadow.resources);
|
|
268
323
|
} else if (replaceLocal || !localWasDirtyAtStart && localAtStart === localEditRevision.current) {
|
|
269
324
|
const extrasNow = resolveSendExtras(sendExtrasRef.current);
|
|
270
|
-
const pickerChangedDuringFetch = extrasNow.model !== extrasAtStart.model || extrasNow.reasoningEffort !== extrasAtStart.reasoningEffort;
|
|
325
|
+
const pickerChangedDuringFetch = extrasNow.model !== extrasAtStart.model || extrasNow.reasoningEffort !== extrasAtStart.reasoningEffort || extrasNow.latencyMode !== extrasAtStart.latencyMode;
|
|
271
326
|
valueRef.current = fetched.text;
|
|
272
327
|
restoredResourcesRef.current = fetched.resources;
|
|
273
328
|
lastSavedSignature.current = draftSignature(draftPayload(fetched));
|
|
@@ -301,17 +356,73 @@ function useComposer(sessionId, options = {}) {
|
|
|
301
356
|
if (!sessionId || !durableDrafts) return;
|
|
302
357
|
return registerSessionReconciler(sessionId, "composer", async () => await loadDraft(false));
|
|
303
358
|
}, [durableDrafts, loadDraft, registerSessionReconciler, sessionId]);
|
|
359
|
+
const reconcileSteering = useCallback(async () => {
|
|
360
|
+
if (!sessionId || !steeringRef.current) return;
|
|
361
|
+
const ownedTargetKey = targetKey;
|
|
362
|
+
let events;
|
|
363
|
+
try {
|
|
364
|
+
events = await client.listEvents(workspaceId, sessionId, {
|
|
365
|
+
includeTypes: [
|
|
366
|
+
"user.message",
|
|
367
|
+
"turn.started",
|
|
368
|
+
"turn.completed",
|
|
369
|
+
"turn.failed",
|
|
370
|
+
"turn.cancelled",
|
|
371
|
+
"turn.superseded"
|
|
372
|
+
],
|
|
373
|
+
limit: 250,
|
|
374
|
+
payloadMode: "full"
|
|
375
|
+
});
|
|
376
|
+
} catch {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
if (targetKeyRef.current !== ownedTargetKey) return;
|
|
380
|
+
setSteering((current) => {
|
|
381
|
+
if (!current) return current;
|
|
382
|
+
if (steeringSettledByEvents(current, events)) {
|
|
383
|
+
steeringSettlementEventsRef.current = [];
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
386
|
+
const accepted = steeringAcceptedEvent(current, events);
|
|
387
|
+
if (!accepted || current.triggerEventId) return current;
|
|
388
|
+
return {
|
|
389
|
+
...current,
|
|
390
|
+
phase: "accepted",
|
|
391
|
+
triggerEventId: accepted.id
|
|
392
|
+
};
|
|
393
|
+
});
|
|
394
|
+
}, [client, sessionId, targetKey, workspaceId]);
|
|
304
395
|
useSessionEventTrigger(
|
|
305
396
|
client,
|
|
306
397
|
workspaceId,
|
|
307
398
|
sessionId,
|
|
308
|
-
isComposerDraftEvent,
|
|
309
|
-
() =>
|
|
399
|
+
(event) => isComposerDraftEvent(event) || isSteeringSettlementEvent(event),
|
|
400
|
+
(event) => {
|
|
401
|
+
if (isComposerDraftEvent(event)) void loadDraft(false);
|
|
402
|
+
if (!isSteeringSettlementEvent(event)) return;
|
|
403
|
+
steeringSettlementEventsRef.current = [
|
|
404
|
+
...steeringSettlementEventsRef.current.slice(-15),
|
|
405
|
+
event
|
|
406
|
+
];
|
|
407
|
+
setSteering((current) => {
|
|
408
|
+
if (!current || !steeringSettledByEvents(current, [event])) return current;
|
|
409
|
+
steeringSettlementEventsRef.current = [];
|
|
410
|
+
return null;
|
|
411
|
+
});
|
|
412
|
+
},
|
|
310
413
|
{
|
|
311
|
-
enabled: Boolean(sessionId) && durableDrafts,
|
|
414
|
+
enabled: Boolean(sessionId) && (durableDrafts || steering !== null),
|
|
312
415
|
...options.events !== void 0 ? { events: options.events } : {}
|
|
313
|
-
}
|
|
416
|
+
},
|
|
417
|
+
reconcileSteering
|
|
314
418
|
);
|
|
419
|
+
useEffect(() => {
|
|
420
|
+
if (!steering) return;
|
|
421
|
+
const observed = [...options.events ?? [], ...steeringSettlementEventsRef.current];
|
|
422
|
+
if (!steeringSettledByEvents(steering, observed)) return;
|
|
423
|
+
steeringSettlementEventsRef.current = [];
|
|
424
|
+
setSteering(null);
|
|
425
|
+
}, [options.events, steering]);
|
|
315
426
|
const currentDraftPayload = useCallback(() => {
|
|
316
427
|
if (!durableDrafts || targetKeyRef.current !== targetKey) return null;
|
|
317
428
|
const base = draftRef.current;
|
|
@@ -427,6 +538,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
427
538
|
pendingClientEventId.current = null;
|
|
428
539
|
forgetPendingComposerOperation(operationKey);
|
|
429
540
|
};
|
|
541
|
+
let keepSteering = pending?.delivery === "steer";
|
|
430
542
|
const settleAccepted = (operation) => {
|
|
431
543
|
clearPending();
|
|
432
544
|
const draftWasUnchanged = valueRef.current === operation.draftAtSend;
|
|
@@ -458,25 +570,34 @@ function useComposer(sessionId, options = {}) {
|
|
|
458
570
|
};
|
|
459
571
|
const deliver = async (operation) => {
|
|
460
572
|
if (operation.delivery === "steer") {
|
|
461
|
-
await client.steerMessage(workspaceId, sessionId, operation.input);
|
|
462
|
-
} else {
|
|
463
|
-
await client.sendMessage(workspaceId, sessionId, operation.input);
|
|
573
|
+
return await client.steerMessage(workspaceId, sessionId, operation.input);
|
|
464
574
|
}
|
|
575
|
+
await client.sendMessage(workspaceId, sessionId, operation.input);
|
|
576
|
+
return null;
|
|
465
577
|
};
|
|
578
|
+
if (delivery === "steer") {
|
|
579
|
+
setSteering({
|
|
580
|
+
phase: "submitting",
|
|
581
|
+
text: rawText,
|
|
582
|
+
clientEventId: pending?.input.clientEventId ?? pendingClientEventId.current,
|
|
583
|
+
triggerEventId: null,
|
|
584
|
+
turnId: null
|
|
585
|
+
});
|
|
586
|
+
}
|
|
466
587
|
setSending(true);
|
|
467
588
|
setError(null);
|
|
468
589
|
try {
|
|
469
590
|
if (pending) {
|
|
470
|
-
let
|
|
591
|
+
let acceptedEvent = null;
|
|
471
592
|
try {
|
|
472
593
|
const events = await client.listEvents(workspaceId, sessionId, {
|
|
473
594
|
includeTypes: ["user.message"],
|
|
474
595
|
limit: 100,
|
|
475
596
|
payloadMode: "none"
|
|
476
597
|
});
|
|
477
|
-
|
|
598
|
+
acceptedEvent = events.find(
|
|
478
599
|
(event) => event.type === "user.message" && event.clientEventId === pending.input.clientEventId
|
|
479
|
-
);
|
|
600
|
+
) ?? null;
|
|
480
601
|
} catch (cause) {
|
|
481
602
|
if (targetKeyRef.current === ownedTargetKey && targetGeneration.current === ownedGeneration) {
|
|
482
603
|
setError(asError(cause));
|
|
@@ -486,7 +607,17 @@ function useComposer(sessionId, options = {}) {
|
|
|
486
607
|
if (targetKeyRef.current !== ownedTargetKey || targetGeneration.current !== ownedGeneration) {
|
|
487
608
|
return false;
|
|
488
609
|
}
|
|
489
|
-
if (
|
|
610
|
+
if (acceptedEvent) {
|
|
611
|
+
if (pending.delivery === "steer") {
|
|
612
|
+
keepSteering = true;
|
|
613
|
+
setSteering({
|
|
614
|
+
phase: "accepted",
|
|
615
|
+
text: pending.input.text,
|
|
616
|
+
clientEventId: pending.input.clientEventId ?? null,
|
|
617
|
+
triggerEventId: acceptedEvent.id,
|
|
618
|
+
turnId: null
|
|
619
|
+
});
|
|
620
|
+
}
|
|
490
621
|
settleAccepted(pending);
|
|
491
622
|
return true;
|
|
492
623
|
}
|
|
@@ -499,8 +630,19 @@ function useComposer(sessionId, options = {}) {
|
|
|
499
630
|
return false;
|
|
500
631
|
}
|
|
501
632
|
try {
|
|
502
|
-
await deliver(pending);
|
|
633
|
+
const result = await deliver(pending);
|
|
634
|
+
if (pending.delivery === "steer" && result) {
|
|
635
|
+
keepSteering = true;
|
|
636
|
+
setSteering({
|
|
637
|
+
phase: "accepted",
|
|
638
|
+
text: pending.input.text,
|
|
639
|
+
clientEventId: pending.input.clientEventId ?? null,
|
|
640
|
+
triggerEventId: result.accepted.id,
|
|
641
|
+
turnId: result.turn.id
|
|
642
|
+
});
|
|
643
|
+
}
|
|
503
644
|
} catch (cause) {
|
|
645
|
+
if (pending.delivery === "steer") keepSteering = true;
|
|
504
646
|
if (targetKeyRef.current === ownedTargetKey && targetGeneration.current === ownedGeneration) {
|
|
505
647
|
setError(asError(cause));
|
|
506
648
|
}
|
|
@@ -539,11 +681,32 @@ function useComposer(sessionId, options = {}) {
|
|
|
539
681
|
};
|
|
540
682
|
pendingOperationRef.current = operation;
|
|
541
683
|
rememberPendingComposerOperation(operationKey, operation);
|
|
684
|
+
if (delivery === "steer") {
|
|
685
|
+
setSteering({
|
|
686
|
+
phase: "submitting",
|
|
687
|
+
text: sendText,
|
|
688
|
+
clientEventId: input.clientEventId ?? null,
|
|
689
|
+
triggerEventId: null,
|
|
690
|
+
turnId: null
|
|
691
|
+
});
|
|
692
|
+
}
|
|
542
693
|
try {
|
|
543
|
-
await deliver(operation);
|
|
694
|
+
const result = await deliver(operation);
|
|
695
|
+
if (delivery === "steer" && result) {
|
|
696
|
+
keepSteering = true;
|
|
697
|
+
setSteering({
|
|
698
|
+
phase: "accepted",
|
|
699
|
+
text: sendText,
|
|
700
|
+
clientEventId: input.clientEventId ?? null,
|
|
701
|
+
triggerEventId: result.accepted.id,
|
|
702
|
+
turnId: result.turn.id
|
|
703
|
+
});
|
|
704
|
+
}
|
|
544
705
|
} catch (cause) {
|
|
545
706
|
if (!isOutcomeUnknownError(cause)) {
|
|
546
707
|
clearPending();
|
|
708
|
+
} else if (delivery === "steer") {
|
|
709
|
+
keepSteering = true;
|
|
547
710
|
}
|
|
548
711
|
if (targetKeyRef.current === ownedTargetKey && targetGeneration.current === ownedGeneration) {
|
|
549
712
|
setError(asError(cause));
|
|
@@ -558,6 +721,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
558
721
|
} finally {
|
|
559
722
|
if (targetKeyRef.current === ownedTargetKey && targetGeneration.current === ownedGeneration) {
|
|
560
723
|
setSending(false);
|
|
724
|
+
if (delivery === "steer" && !keepSteering) setSteering(null);
|
|
561
725
|
}
|
|
562
726
|
}
|
|
563
727
|
},
|
|
@@ -763,6 +927,7 @@ function useComposer(sessionId, options = {}) {
|
|
|
763
927
|
hasDraftContent,
|
|
764
928
|
send,
|
|
765
929
|
steer,
|
|
930
|
+
steering: identityMatches ? steering : null,
|
|
766
931
|
sending: identityMatches ? sending : false,
|
|
767
932
|
canSend: identityMatches && Boolean(sessionId) && !sending && sendBlockedRef.current?.() !== true && (hasPendingOperation || value.trim().length > 0 || hasReadyResources),
|
|
768
933
|
pause,
|
|
@@ -844,7 +1009,7 @@ function draftSignature(payload) {
|
|
|
844
1009
|
function mergeResources(base, additions) {
|
|
845
1010
|
const seen = /* @__PURE__ */ new Set();
|
|
846
1011
|
return [...base, ...additions].filter((resource) => {
|
|
847
|
-
const key = resource.kind === "file" ? `file:${resource.fileId}\0${resource.mountPath ??
|
|
1012
|
+
const key = resource.kind === "file" ? `file:${resource.fileId}\0${resource.mountPath ?? `${DEFAULT_FILE_RESOURCE_MOUNT_ROOT}/${resource.fileId}`}` : JSON.stringify(resource);
|
|
848
1013
|
if (seen.has(key)) return false;
|
|
849
1014
|
seen.add(key);
|
|
850
1015
|
return true;
|
|
@@ -858,4 +1023,4 @@ export {
|
|
|
858
1023
|
shouldSubmitOnKey,
|
|
859
1024
|
shouldSteerOnKey
|
|
860
1025
|
};
|
|
861
|
-
//# sourceMappingURL=chunk-
|
|
1026
|
+
//# sourceMappingURL=chunk-Q2NCKWTK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/use-composer.ts"],"sourcesContent":["import {\n DEFAULT_FILE_RESOURCE_MOUNT_ROOT,\n type ComposerDraft,\n type EffectiveControlResumeOption,\n type EffectiveSessionControl,\n type OpenGeniApiError,\n type ResourceRef,\n type SaveComposerDraftRequest,\n type SendMessageInput,\n type SessionEvent,\n} from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { useEmbeddedSession, type EmbeddedSessionClientOverride } from \"../session-context\";\nimport { useSessionEventTrigger, type SessionEventFeedOptions } from \"./internal\";\n\nexport type ComposerSendExtras = Omit<SendMessageInput, \"text\" | \"clientEventId\">;\n\nexport type UseComposerOptions = EmbeddedSessionClientOverride &\n SessionEventFeedOptions & {\n /** Called with the exact accepted wire input after a successful send. */\n onSent?: ((text: string, input: SendMessageInput) => void) | undefined;\n /**\n * Extra message fields (resources, tools, model, reasoningEffort, latencyMode) merged\n * into every send. A function is evaluated at send time so it can read the\n * surrounding UI state (attachment pickers, model selectors, ...).\n */\n sendExtras?: ComposerSendExtras | (() => ComposerSendExtras) | undefined;\n /**\n * Fail-closed delivery guard evaluated at send time. Attachment hosts use\n * this to preserve unresolved upload cards until the operator waits,\n * retries, or removes them; direct hook callers cannot bypass the UI gate.\n */\n sendBlocked?: (() => boolean) | undefined;\n /** Latest server-derived workstream control; bound into Send/Steer OCC. */\n effectiveControl?: EffectiveSessionControl | null | undefined;\n /** Apply durable model/tool/reasoning settings in the host's controlled UI. */\n onDraftApplied?: ((draft: ComposerDraft) => void) | undefined;\n /** Disable remote composer-draft reads and writes for embedded hosts. */\n draftPersistence?: \"durable\" | \"disabled\" | undefined;\n };\n\ntype ComposerDraftShadow = {\n text: string;\n resources: ResourceRef[];\n};\n\ntype PendingComposerOperation = {\n delivery: \"send\" | \"steer\";\n input: SendMessageInput;\n draftAtSend: string;\n resourcesAtSend: ResourceRef[];\n /** Latest local text/resources that must survive an uncertain delivery. */\n newerShadow: ComposerDraftShadow;\n clearDraftOnAccept: boolean;\n /** False after remount when the original input carried secret credentials. */\n canRetry: boolean;\n};\n\ntype StoredPendingComposerOperation = Omit<PendingComposerOperation, \"input\" | \"canRetry\"> & {\n input: Omit<SendMessageInput, \"mcpCredentialUpdates\">;\n hasMcpCredentialUpdates: boolean;\n};\n\nconst PENDING_COMPOSER_STORAGE_PREFIX = \"opengeni.pending-composer.v1:\";\n\n// A remount must not manufacture a new operation while the previous mutation\n// is still outcome-unknown. Keep only non-credential request fields here; the\n// mounted hook retains the exact input, including any credential updates. The\n// safe shadow is also session-scoped so a refresh cannot lose newer edits.\nconst pendingComposerOperations = new Map<string, StoredPendingComposerOperation>();\n\nfunction pendingComposerOperationKey(\n workspaceId: string,\n sessionId: string | null | undefined,\n): string | null {\n return sessionId ? `${workspaceId}\\u0000${sessionId}` : null;\n}\n\nfunction pendingComposerStorage(): Storage | null {\n try {\n return typeof window === \"undefined\" ? null : window.sessionStorage;\n } catch {\n return null;\n }\n}\n\nfunction pendingComposerStorageKey(key: string): string {\n return `${PENDING_COMPOSER_STORAGE_PREFIX}${encodeURIComponent(key)}`;\n}\n\nfunction resourceList(value: unknown): value is ResourceRef[] {\n return (\n Array.isArray(value) &&\n value.every((candidate) => {\n if (typeof candidate !== \"object\" || candidate === null) return false;\n const resource = candidate as Record<string, unknown>;\n return resource.kind === \"file\"\n ? typeof resource.fileId === \"string\"\n : resource.kind === \"repository\" &&\n typeof resource.uri === \"string\" &&\n typeof resource.ref === \"string\";\n })\n );\n}\n\nfunction readStoredPendingComposerOperation(\n key: string | null,\n): StoredPendingComposerOperation | null {\n const storage = key ? pendingComposerStorage() : null;\n if (!storage || !key) return null;\n try {\n const parsed: unknown = JSON.parse(storage.getItem(pendingComposerStorageKey(key)) ?? \"null\");\n if (typeof parsed !== \"object\" || parsed === null) return null;\n const record = parsed as Record<string, unknown>;\n const input = record.input;\n const shadow = record.newerShadow;\n if (\n typeof input !== \"object\" ||\n input === null ||\n typeof shadow !== \"object\" ||\n shadow === null\n ) {\n return null;\n }\n const inputRecord = input as Record<string, unknown>;\n const shadowRecord = shadow as Record<string, unknown>;\n if (\n (record.delivery !== \"send\" && record.delivery !== \"steer\") ||\n typeof record.draftAtSend !== \"string\" ||\n !resourceList(record.resourcesAtSend) ||\n typeof shadowRecord.text !== \"string\" ||\n !resourceList(shadowRecord.resources) ||\n typeof record.clearDraftOnAccept !== \"boolean\" ||\n typeof record.hasMcpCredentialUpdates !== \"boolean\" ||\n typeof inputRecord.text !== \"string\" ||\n typeof inputRecord.clientEventId !== \"string\" ||\n \"mcpCredentialUpdates\" in inputRecord ||\n (\"resources\" in inputRecord && !resourceList(inputRecord.resources))\n ) {\n return null;\n }\n return record as StoredPendingComposerOperation;\n } catch {\n return null;\n }\n}\n\nfunction writePendingComposerOperation(\n key: string,\n operation: StoredPendingComposerOperation,\n): void {\n const storage = pendingComposerStorage();\n if (!storage) return;\n try {\n storage.setItem(pendingComposerStorageKey(key), JSON.stringify(operation));\n } catch {\n // Storage is best effort; the in-memory record still protects remounts.\n }\n}\n\nfunction restorePendingComposerOperation(key: string | null): PendingComposerOperation | null {\n const stored =\n (key && pendingComposerOperations.get(key)) ?? readStoredPendingComposerOperation(key);\n if (!stored) return null;\n return {\n ...stored,\n input: stored.input,\n newerShadow: stored.newerShadow ?? {\n text: stored.draftAtSend,\n resources: stored.resourcesAtSend,\n },\n canRetry: !stored.hasMcpCredentialUpdates,\n };\n}\n\nfunction rememberPendingComposerOperation(\n key: string | null,\n operation: PendingComposerOperation,\n): void {\n if (!key) return;\n const { canRetry: _retry, ...safeOperation } = operation;\n const { input: originalInput, ...withoutInput } = safeOperation;\n const { mcpCredentialUpdates: _storedMcp, ...safeInput } = originalInput;\n const stored = {\n ...withoutInput,\n input: safeInput,\n hasMcpCredentialUpdates: operation.input.mcpCredentialUpdates !== undefined,\n newerShadow: {\n text: operation.newerShadow.text,\n resources: [...operation.newerShadow.resources],\n },\n } satisfies StoredPendingComposerOperation;\n pendingComposerOperations.set(key, stored);\n writePendingComposerOperation(key, stored);\n}\n\nfunction forgetPendingComposerOperation(key: string | null): void {\n if (!key) return;\n pendingComposerOperations.delete(key);\n const storage = pendingComposerStorage();\n if (!storage) return;\n try {\n storage.removeItem(pendingComposerStorageKey(key));\n } catch {\n // Ignore a blocked storage implementation; delivery has already settled.\n }\n}\n\nfunction updatePendingComposerShadow(\n key: string | null,\n operation: PendingComposerOperation | null,\n shadow: ComposerDraftShadow,\n): PendingComposerOperation | null {\n if (!key || !operation) return operation;\n const next = { ...operation, newerShadow: { ...shadow, resources: [...shadow.resources] } };\n rememberPendingComposerOperation(key, next);\n return next;\n}\n\nexport type ComposerState = {\n value: string;\n setValue: (value: string) => void;\n /** Read the current draft synchronously before a destructive replacement. */\n hasDraftContent: () => boolean;\n /** Append the draft behind prompts already visible in the queue. */\n send: (text?: string) => Promise<boolean>;\n /** Supersede current direction with the draft. */\n steer: (text?: string) => Promise<boolean>;\n /** Optimistic-to-durable projection for a Steer that has not started yet. */\n steering?: ComposerSteeringState | null | undefined;\n sending: boolean;\n canSend: boolean;\n /** Pause the session without deleting its prompt queue. */\n pause: (reason?: string) => Promise<void>;\n pausing: boolean;\n resume: (reason?: string) => Promise<void>;\n resumeScope: (option: EffectiveControlResumeOption) => Promise<void>;\n resuming: boolean;\n draft: ComposerDraft | null;\n draftRevision: number;\n draftLoading: boolean;\n draftSaving: boolean;\n draftConflict: Error | null;\n /** Whether this controller owns a durable server-side draft. */\n draftPersistence?: \"durable\" | \"disabled\" | undefined;\n /** Apply an atomic queue Edit checkout without a second read. */\n applyDraft: (draft: ComposerDraft) => void;\n reloadDraft: () => Promise<void>;\n resolveDraftConflict: (choice: \"keep_mine\" | \"use_remote\") => Promise<void>;\n restoredResources: ResourceRef[];\n removeRestoredResource: (index: number) => void;\n error: Error | null;\n clearError: () => void;\n};\n\nexport type ComposerSteeringState = {\n phase: \"submitting\" | \"accepted\";\n text: string;\n clientEventId: string | null;\n triggerEventId: string | null;\n turnId: string | null;\n};\n\nconst STEERING_SETTLEMENT_EVENT_TYPES = new Set([\n \"turn.started\",\n \"turn.completed\",\n \"turn.failed\",\n \"turn.cancelled\",\n \"turn.superseded\",\n]);\n\nfunction isSteeringSettlementEvent(event: SessionEvent): boolean {\n return STEERING_SETTLEMENT_EVENT_TYPES.has(event.type);\n}\n\nfunction steeringAcceptedEvent(\n steering: ComposerSteeringState,\n events: readonly SessionEvent[],\n): SessionEvent | undefined {\n return events.find(\n (event) =>\n event.type === \"user.message\" &&\n steering.clientEventId !== null &&\n event.clientEventId === steering.clientEventId,\n );\n}\n\nfunction steeringSettledByEvents(\n steering: ComposerSteeringState,\n events: readonly SessionEvent[],\n): boolean {\n const acceptedEventId =\n steering.triggerEventId ?? steeringAcceptedEvent(steering, events)?.id ?? null;\n return events.some((event) => {\n if (steering.turnId && event.turnId === steering.turnId && isSteeringSettlementEvent(event)) {\n return true;\n }\n if (event.type !== \"turn.started\" || !acceptedEventId) return false;\n const payload = event.payload;\n return (\n typeof payload === \"object\" &&\n payload !== null &&\n \"triggerEventId\" in payload &&\n payload.triggerEventId === acceptedEventId\n );\n });\n}\n\n/**\n * Draft + send + Pause/Resume state for the chat composer — the only\n * human-to-agent input surface. The draft survives a failed send (nothing is\n * more hostile than losing a typed message); each send carries a generated\n * `clientEventId` so retries stay idempotent server-side.\n */\nexport function useComposer(\n sessionId: string | null | undefined,\n options: UseComposerOptions = {},\n): ComposerState {\n const { client, workspaceId, registerSessionReconciler } = useEmbeddedSession(options);\n const durableDrafts = options.draftPersistence !== \"disabled\";\n const targetKey = `${workspaceId}\\u0000${sessionId ?? \"\"}\\u0000${durableDrafts ? \"durable\" : \"disabled\"}`;\n const pendingOperationKey = pendingComposerOperationKey(workspaceId, sessionId);\n const initialPendingOperation = restorePendingComposerOperation(pendingOperationKey);\n const initialShadow = initialPendingOperation?.newerShadow;\n const [value, setValue] = useState(() => initialShadow?.text ?? \"\");\n // Keep rendered state behind the committed target identity for one frame:\n // a parent may switch sessionId without remounting this public hook.\n const [stateTargetKey, setStateTargetKey] = useState(targetKey);\n const [sending, setSending] = useState(false);\n const [steering, setSteering] = useState<ComposerSteeringState | null>(() =>\n initialPendingOperation?.delivery === \"steer\"\n ? {\n phase: \"submitting\",\n text: initialPendingOperation.input.text,\n clientEventId: initialPendingOperation.input.clientEventId ?? null,\n triggerEventId: null,\n turnId: null,\n }\n : null,\n );\n const [pausing, setPausing] = useState(false);\n const [resuming, setResuming] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [draft, setDraft] = useState<ComposerDraft | null>(null);\n const [draftLoading, setDraftLoading] = useState(Boolean(sessionId) && durableDrafts);\n const [draftSaving, setDraftSaving] = useState(false);\n const [draftConflict, setDraftConflict] = useState<Error | null>(null);\n const [restoredResources, setRestoredResources] = useState<ResourceRef[]>(\n () => initialShadow?.resources ?? [],\n );\n const pendingOperationRef = useRef<PendingComposerOperation | null>(initialPendingOperation);\n const steeringSettlementEventsRef = useRef<SessionEvent[]>([]);\n const steeringRef = useRef(steering);\n const pendingClientEventId = useRef<string | null>(\n initialPendingOperation?.input.clientEventId ?? null,\n );\n const valueRef = useRef(initialShadow?.text ?? \"\");\n const draftRef = useRef<ComposerDraft | null>(null);\n const restoredResourcesRef = useRef<ResourceRef[]>(initialShadow?.resources ?? []);\n const localEditRevision = useRef(initialShadow ? 1 : 0);\n const targetGeneration = useRef(0);\n const draftReadGeneration = useRef(0);\n const lastSavedSignature = useRef<string | null>(null);\n const saveChain = useRef<Promise<void>>(Promise.resolve());\n const onSent = options.onSent;\n const onDraftApplied = options.onDraftApplied;\n // Read through a ref so live session/policy projections can replace their\n // apply callback without invalidating the draft loader and re-running its\n // initial-load effect. Publish only committed callbacks: a suspended target\n // render must not retarget an in-flight read owned by the committed session.\n const onDraftAppliedRef = useRef(onDraftApplied);\n useLayoutEffect(() => {\n onDraftAppliedRef.current = onDraftApplied;\n }, [onDraftApplied]);\n useLayoutEffect(() => {\n steeringRef.current = steering;\n }, [steering]);\n // Read through a ref so a new extras closure (created every render by\n // callers passing inline functions) does not invalidate `send`.\n const sendExtrasRef = useRef(options.sendExtras);\n sendExtrasRef.current = options.sendExtras;\n const sendBlockedRef = useRef(options.sendBlocked);\n sendBlockedRef.current = options.sendBlocked;\n const liveExtrasVersion = JSON.stringify(resolveSendExtras(options.sendExtras));\n\n // A composer is bound to one session: switching targets must not leak the\n // previous session's draft, error, or retry idempotency key.\n const targetKeyRef = useRef(targetKey);\n useLayoutEffect(() => {\n if (targetKeyRef.current === targetKey) return;\n targetKeyRef.current = targetKey;\n targetGeneration.current += 1;\n draftReadGeneration.current += 1;\n pendingOperationRef.current = restorePendingComposerOperation(pendingOperationKey);\n steeringSettlementEventsRef.current = [];\n pendingClientEventId.current = pendingOperationRef.current?.input.clientEventId ?? null;\n const shadow = pendingOperationRef.current?.newerShadow;\n localEditRevision.current = shadow ? 1 : 0;\n valueRef.current = shadow?.text ?? \"\";\n draftRef.current = null;\n restoredResourcesRef.current = shadow?.resources ?? [];\n lastSavedSignature.current = null;\n // Old saves may still be awaiting the network. Their generation fence\n // prevents settlement, and a fresh chain avoids blocking this target.\n saveChain.current = Promise.resolve();\n setStateTargetKey(targetKey);\n setValue(shadow?.text ?? \"\");\n setSending(false);\n setSteering(\n pendingOperationRef.current?.delivery === \"steer\"\n ? {\n phase: \"submitting\",\n text: pendingOperationRef.current.input.text,\n clientEventId: pendingOperationRef.current.input.clientEventId ?? null,\n triggerEventId: null,\n turnId: null,\n }\n : null,\n );\n setPausing(false);\n setResuming(false);\n setError(null);\n setDraft(null);\n setDraftLoading(Boolean(sessionId) && durableDrafts);\n setDraftSaving(false);\n setDraftConflict(null);\n setRestoredResources(shadow?.resources ?? []);\n }, [durableDrafts, pendingOperationKey, sessionId, targetKey]);\n\n const applyDraft = useCallback(\n (next: ComposerDraft): void => {\n if (targetKeyRef.current !== targetKey) return;\n if (!durableDrafts) {\n localEditRevision.current += 1;\n valueRef.current = next.text;\n restoredResourcesRef.current = next.resources;\n draftRef.current = null;\n lastSavedSignature.current = null;\n setDraft(null);\n setValue(next.text);\n setRestoredResources(next.resources);\n pendingOperationRef.current = updatePendingComposerShadow(\n pendingOperationKey,\n pendingOperationRef.current,\n {\n text: next.text,\n resources: mergeResources(\n next.resources,\n resolveSendExtras(sendExtrasRef.current).resources ?? [],\n ),\n },\n );\n setDraftConflict(null);\n return;\n }\n valueRef.current = next.text;\n draftRef.current = next;\n restoredResourcesRef.current = next.resources;\n lastSavedSignature.current = draftSignature(draftPayload(next));\n localEditRevision.current += 1;\n setDraft(next);\n setValue(next.text);\n setRestoredResources(next.resources);\n pendingOperationRef.current = updatePendingComposerShadow(\n pendingOperationKey,\n pendingOperationRef.current,\n {\n text: next.text,\n resources: mergeResources(\n next.resources,\n resolveSendExtras(sendExtrasRef.current).resources ?? [],\n ),\n },\n );\n setDraftConflict(null);\n onDraftAppliedRef.current?.(next);\n },\n [durableDrafts, pendingOperationKey, targetKey],\n );\n\n const loadDraft = useCallback(\n async (replaceLocal: boolean): Promise<void> => {\n if (targetKeyRef.current !== targetKey) return;\n if (!sessionId || !durableDrafts) {\n setDraftLoading(false);\n return;\n }\n const generation = targetGeneration.current;\n const readTicket = ++draftReadGeneration.current;\n const localAtStart = localEditRevision.current;\n const baseAtStart = draftRef.current;\n const extrasAtStart = resolveSendExtras(sendExtrasRef.current);\n const localSignatureAtStart = baseAtStart\n ? draftSignature(\n composerDraftPayload(\n baseAtStart,\n valueRef.current,\n restoredResourcesRef.current,\n extrasAtStart,\n ),\n )\n : null;\n const localWasDirtyAtStart =\n localSignatureAtStart === null\n ? localAtStart !== 0\n : localSignatureAtStart !== lastSavedSignature.current;\n // Only blank the picker on first hydrate / hard reload. Reconcile and\n // event-triggered soft reloads (loadOlder SSE reconnect) must not flicker\n // draftLoading — stale-while-revalidate keeps the settled UI mounted.\n const showLoading = replaceLocal || draftRef.current === null;\n if (showLoading) {\n setDraftLoading(true);\n }\n try {\n const fetched = await client.getComposerDraft(workspaceId, sessionId);\n if (\n generation !== targetGeneration.current ||\n targetKeyRef.current !== targetKey ||\n readTicket !== draftReadGeneration.current\n ) {\n return;\n }\n const currentRevision = draftRef.current?.revision ?? -1;\n if (fetched.revision >= currentRevision) {\n draftRef.current = fetched;\n setDraft(fetched);\n setDraftConflict(null);\n const shadow = pendingOperationRef.current?.newerShadow;\n if (shadow) {\n // The server can only know the original operation. Never replace\n // newer local edits while that operation is still uncertain.\n valueRef.current = shadow.text;\n restoredResourcesRef.current = shadow.resources;\n localEditRevision.current ||= 1;\n setValue(shadow.text);\n setRestoredResources(shadow.resources);\n } else if (\n replaceLocal ||\n (!localWasDirtyAtStart && localAtStart === localEditRevision.current)\n ) {\n // Model/effort/latency ride in sendExtras (outside\n // localEditRevision). If\n // the picker changed during this fetch, skip onDraftApplied so a\n // stale server policy cannot undo the operator's pick.\n const extrasNow = resolveSendExtras(sendExtrasRef.current);\n const pickerChangedDuringFetch =\n extrasNow.model !== extrasAtStart.model ||\n extrasNow.reasoningEffort !== extrasAtStart.reasoningEffort ||\n extrasNow.latencyMode !== extrasAtStart.latencyMode;\n valueRef.current = fetched.text;\n restoredResourcesRef.current = fetched.resources;\n lastSavedSignature.current = draftSignature(draftPayload(fetched));\n setValue(fetched.text);\n setRestoredResources(fetched.resources);\n if (replaceLocal || !pickerChangedDuringFetch) {\n onDraftAppliedRef.current?.(fetched);\n }\n }\n }\n } catch (cause) {\n if (\n generation === targetGeneration.current &&\n targetKeyRef.current === targetKey &&\n readTicket === draftReadGeneration.current\n ) {\n setError(asError(cause));\n }\n } finally {\n if (\n generation === targetGeneration.current &&\n targetKeyRef.current === targetKey &&\n readTicket === draftReadGeneration.current\n ) {\n setDraftLoading(false);\n }\n }\n },\n [client, durableDrafts, sessionId, targetKey, workspaceId],\n );\n\n useEffect(() => {\n if (!sessionId || !durableDrafts) {\n setDraftLoading(false);\n return;\n }\n void loadDraft(false);\n }, [durableDrafts, loadDraft, sessionId]);\n useEffect(() => {\n if (!sessionId || !durableDrafts) return;\n return registerSessionReconciler(sessionId, \"composer\", async () => await loadDraft(false));\n }, [durableDrafts, loadDraft, registerSessionReconciler, sessionId]);\n const reconcileSteering = useCallback(async (): Promise<void> => {\n if (!sessionId || !steeringRef.current) return;\n const ownedTargetKey = targetKey;\n let events: SessionEvent[];\n try {\n events = await client.listEvents(workspaceId, sessionId, {\n includeTypes: [\n \"user.message\",\n \"turn.started\",\n \"turn.completed\",\n \"turn.failed\",\n \"turn.cancelled\",\n \"turn.superseded\",\n ],\n limit: 250,\n payloadMode: \"full\",\n });\n } catch {\n // Best effort: the live stream still settles steering when its event arrives.\n return;\n }\n if (targetKeyRef.current !== ownedTargetKey) return;\n setSteering((current) => {\n if (!current) return current;\n if (steeringSettledByEvents(current, events)) {\n steeringSettlementEventsRef.current = [];\n return null;\n }\n const accepted = steeringAcceptedEvent(current, events);\n if (!accepted || current.triggerEventId) return current;\n return {\n ...current,\n phase: \"accepted\",\n triggerEventId: accepted.id,\n };\n });\n }, [client, sessionId, targetKey, workspaceId]);\n useSessionEventTrigger(\n client,\n workspaceId,\n sessionId,\n (event) => isComposerDraftEvent(event) || isSteeringSettlementEvent(event),\n (event) => {\n if (isComposerDraftEvent(event)) void loadDraft(false);\n if (!isSteeringSettlementEvent(event)) return;\n steeringSettlementEventsRef.current = [\n ...steeringSettlementEventsRef.current.slice(-15),\n event,\n ];\n setSteering((current) => {\n if (!current || !steeringSettledByEvents(current, [event])) return current;\n steeringSettlementEventsRef.current = [];\n return null;\n });\n },\n {\n enabled: Boolean(sessionId) && (durableDrafts || steering !== null),\n ...(options.events !== undefined ? { events: options.events } : {}),\n },\n reconcileSteering,\n );\n\n useEffect(() => {\n if (!steering) return;\n const observed = [...(options.events ?? []), ...steeringSettlementEventsRef.current];\n if (!steeringSettledByEvents(steering, observed)) return;\n steeringSettlementEventsRef.current = [];\n setSteering(null);\n }, [options.events, steering]);\n\n const currentDraftPayload = useCallback((): SaveComposerDraftRequest | null => {\n if (!durableDrafts || targetKeyRef.current !== targetKey) return null;\n const base = draftRef.current;\n if (!base) return null;\n const extras = resolveSendExtras(sendExtrasRef.current);\n return composerDraftPayload(base, value, restoredResources, extras);\n }, [durableDrafts, restoredResources, targetKey, value]);\n\n const persistPayload = useCallback(\n async (payload: SaveComposerDraftRequest): Promise<boolean> => {\n const ownedTargetKey = targetKey;\n const ownedGeneration = targetGeneration.current;\n if (!sessionId || !durableDrafts || targetKeyRef.current !== ownedTargetKey) {\n return false;\n }\n let success = false;\n const run = async () => {\n if (\n targetKeyRef.current !== ownedTargetKey ||\n targetGeneration.current !== ownedGeneration\n ) {\n return;\n }\n const current = draftRef.current;\n if (!current) return;\n const request = { ...payload, expectedRevision: current.revision };\n const signature = draftSignature(request);\n if (signature === lastSavedSignature.current) {\n success = true;\n return;\n }\n setDraftSaving(true);\n try {\n const saved = await client.saveComposerDraft(workspaceId, sessionId, request);\n if (\n targetKeyRef.current !== ownedTargetKey ||\n targetGeneration.current !== ownedGeneration\n ) {\n return;\n }\n draftRef.current = saved;\n setDraft(saved);\n lastSavedSignature.current = signature;\n setDraftConflict(null);\n success = true;\n } catch (cause) {\n if (\n targetKeyRef.current === ownedTargetKey &&\n targetGeneration.current === ownedGeneration\n ) {\n const problem = asError(cause);\n if (isDraftConflictError(problem)) setDraftConflict(problem);\n setError(problem);\n }\n } finally {\n if (\n targetKeyRef.current === ownedTargetKey &&\n targetGeneration.current === ownedGeneration\n ) {\n setDraftSaving(false);\n }\n }\n };\n saveChain.current = saveChain.current.then(run, run);\n await saveChain.current;\n return success;\n },\n [client, durableDrafts, sessionId, targetKey, workspaceId],\n );\n\n // Private durable autosave. A newer local edit is never replaced by an older\n // response; saves serialize and each reads the latest acknowledged revision.\n useEffect(() => {\n const pending = pendingOperationRef.current;\n if (pending) {\n const shadow = {\n text: valueRef.current,\n resources: mergeResources(\n restoredResourcesRef.current,\n resolveSendExtras(sendExtrasRef.current).resources ?? [],\n ),\n };\n if (\n pending.newerShadow.text !== shadow.text ||\n JSON.stringify(pending.newerShadow.resources) !== JSON.stringify(shadow.resources)\n ) {\n pendingOperationRef.current = updatePendingComposerShadow(\n pendingOperationKey,\n pending,\n shadow,\n );\n }\n return;\n }\n if (\n !durableDrafts ||\n !sessionId ||\n draftLoading ||\n sending ||\n !draftRef.current ||\n draftConflict\n )\n return;\n const payload = currentDraftPayload();\n if (!payload || draftSignature(payload) === lastSavedSignature.current) return;\n const timer = window.setTimeout(() => void persistPayload(payload), 500);\n return () => window.clearTimeout(timer);\n }, [\n currentDraftPayload,\n durableDrafts,\n draftConflict,\n draftLoading,\n liveExtrasVersion,\n pendingOperationKey,\n persistPayload,\n sending,\n sessionId,\n ]);\n\n const dispatch = useCallback(\n async (delivery: \"send\" | \"steer\", explicit?: string): Promise<boolean> => {\n const ownedTargetKey = targetKey;\n const ownedGeneration = targetGeneration.current;\n const operationKey = pendingComposerOperationKey(workspaceId, sessionId);\n const pending = pendingOperationRef.current ?? restorePendingComposerOperation(operationKey);\n if (pending && !pendingOperationRef.current) {\n pendingOperationRef.current = pending;\n pendingClientEventId.current = pending.input.clientEventId ?? null;\n }\n const draftAtSend = value;\n const rawText = explicit ?? draftAtSend;\n const hasText = rawText.trim().length > 0;\n // Resolve the extras once: a file-only message (empty text + ≥1 ready\n // resource) is legitimate, so we must not bail on empty text alone.\n const extras = pending ? {} : resolveSendExtras(sendExtrasRef.current);\n const hasResources = restoredResources.length > 0 || (extras.resources?.length ?? 0) > 0;\n if (\n (!pending && !hasText && !hasResources) ||\n !sessionId ||\n sending ||\n sendBlockedRef.current?.() === true ||\n targetKeyRef.current !== ownedTargetKey\n ) {\n return false;\n }\n\n const clearPending = (): void => {\n pendingOperationRef.current = null;\n pendingClientEventId.current = null;\n forgetPendingComposerOperation(operationKey);\n };\n\n let keepSteering = pending?.delivery === \"steer\";\n\n const settleAccepted = (operation: PendingComposerOperation): void => {\n clearPending();\n const draftWasUnchanged = valueRef.current === operation.draftAtSend;\n const resourcesWereUnchanged =\n JSON.stringify(restoredResourcesRef.current) ===\n JSON.stringify(operation.resourcesAtSend);\n const previousDraft = draftRef.current;\n if (previousDraft) {\n const cleared = {\n ...previousDraft,\n revision: 0,\n text: \"\",\n resources: [],\n sourceTurnId: null,\n sourceTurnVersion: null,\n updatedAt: null,\n };\n draftRef.current = cleared;\n setDraft(cleared);\n lastSavedSignature.current = draftSignature(draftPayload(cleared));\n }\n if (resourcesWereUnchanged) {\n restoredResourcesRef.current = [];\n setRestoredResources([]);\n }\n if (operation.clearDraftOnAccept && draftWasUnchanged) {\n valueRef.current = \"\";\n setValue(\"\");\n }\n onSent?.(operation.input.text, operation.input);\n };\n\n const deliver = async (operation: PendingComposerOperation) => {\n if (operation.delivery === \"steer\") {\n return await client.steerMessage(workspaceId, sessionId, operation.input);\n }\n await client.sendMessage(workspaceId, sessionId, operation.input);\n return null;\n };\n\n if (delivery === \"steer\") {\n setSteering({\n phase: \"submitting\",\n text: rawText,\n clientEventId: pending?.input.clientEventId ?? pendingClientEventId.current,\n triggerEventId: null,\n turnId: null,\n });\n }\n setSending(true);\n setError(null);\n try {\n if (pending) {\n let acceptedEvent: SessionEvent | null = null;\n try {\n const events = await client.listEvents(workspaceId, sessionId, {\n includeTypes: [\"user.message\"],\n limit: 100,\n payloadMode: \"none\",\n });\n acceptedEvent =\n events.find(\n (event) =>\n event.type === \"user.message\" &&\n event.clientEventId === pending.input.clientEventId,\n ) ?? null;\n } catch (cause) {\n if (\n targetKeyRef.current === ownedTargetKey &&\n targetGeneration.current === ownedGeneration\n ) {\n setError(asError(cause));\n }\n return false;\n }\n if (\n targetKeyRef.current !== ownedTargetKey ||\n targetGeneration.current !== ownedGeneration\n ) {\n return false;\n }\n if (acceptedEvent) {\n if (pending.delivery === \"steer\") {\n keepSteering = true;\n setSteering({\n phase: \"accepted\",\n text: pending.input.text,\n clientEventId: pending.input.clientEventId ?? null,\n triggerEventId: acceptedEvent.id,\n turnId: null,\n });\n }\n settleAccepted(pending);\n return true;\n }\n if (!pending.canRetry) {\n setError(\n new Error(\n \"OpenGeni cannot safely retry this uncertain request after remount; reconcile the session before sending again.\",\n ),\n );\n return false;\n }\n try {\n const result = await deliver(pending);\n if (pending.delivery === \"steer\" && result) {\n keepSteering = true;\n setSteering({\n phase: \"accepted\",\n text: pending.input.text,\n clientEventId: pending.input.clientEventId ?? null,\n triggerEventId: result.accepted.id,\n turnId: result.turn.id,\n });\n }\n } catch (cause) {\n if (pending.delivery === \"steer\") keepSteering = true;\n if (\n targetKeyRef.current === ownedTargetKey &&\n targetGeneration.current === ownedGeneration\n ) {\n setError(asError(cause));\n }\n return false;\n }\n if (\n targetKeyRef.current !== ownedTargetKey ||\n targetGeneration.current !== ownedGeneration\n ) {\n return false;\n }\n settleAccepted(pending);\n return true;\n }\n\n // Trimming is only an emptiness check. A non-blank prompt is persisted\n // and submitted byte-for-byte, while file-only sends use the same\n // placeholder for both operations so the server content fence cannot\n // reject its own client.\n const sendText = hasText ? rawText : FILE_ONLY_MESSAGE_TEXT;\n const currentPayload = currentDraftPayload();\n const payload = currentPayload ? { ...currentPayload, text: sendText } : null;\n if (payload && !(await persistPayload(payload))) return false;\n if (\n targetKeyRef.current !== ownedTargetKey ||\n targetGeneration.current !== ownedGeneration\n ) {\n return false;\n }\n // The wire contract requires non-empty text (z.string().min(1)) and the\n // worker rejects whitespace-only text; a file-only message therefore\n // carries a minimal default so the attachments still get delivered.\n pendingClientEventId.current ??= generateClientEventId();\n const input = composeSendInput(sendText, pendingClientEventId.current, extras, {\n ...(options.effectiveControl?.controlEtag\n ? { controlEtag: options.effectiveControl.controlEtag }\n : {}),\n ...(durableDrafts && draftRef.current\n ? { expectedDraftRevision: draftRef.current.revision }\n : {}),\n resources: mergeResources(restoredResources, extras.resources ?? []),\n });\n const operation: PendingComposerOperation = {\n delivery,\n input,\n draftAtSend,\n resourcesAtSend: [...restoredResources],\n newerShadow: {\n text: draftAtSend,\n resources: mergeResources(restoredResources, extras.resources ?? []),\n },\n clearDraftOnAccept: explicit === undefined,\n canRetry: true,\n };\n pendingOperationRef.current = operation;\n rememberPendingComposerOperation(operationKey, operation);\n if (delivery === \"steer\") {\n setSteering({\n phase: \"submitting\",\n text: sendText,\n clientEventId: input.clientEventId ?? null,\n triggerEventId: null,\n turnId: null,\n });\n }\n try {\n const result = await deliver(operation);\n if (delivery === \"steer\" && result) {\n keepSteering = true;\n setSteering({\n phase: \"accepted\",\n text: sendText,\n clientEventId: input.clientEventId ?? null,\n triggerEventId: result.accepted.id,\n turnId: result.turn.id,\n });\n }\n } catch (cause) {\n if (!isOutcomeUnknownError(cause)) {\n clearPending();\n } else if (delivery === \"steer\") {\n keepSteering = true;\n }\n if (\n targetKeyRef.current === ownedTargetKey &&\n targetGeneration.current === ownedGeneration\n ) {\n setError(asError(cause));\n }\n return false;\n }\n if (\n targetKeyRef.current !== ownedTargetKey ||\n targetGeneration.current !== ownedGeneration\n ) {\n return false;\n }\n settleAccepted(operation);\n return true;\n } finally {\n if (\n targetKeyRef.current === ownedTargetKey &&\n targetGeneration.current === ownedGeneration\n ) {\n setSending(false);\n if (delivery === \"steer\" && !keepSteering) setSteering(null);\n }\n }\n },\n [\n client,\n currentDraftPayload,\n durableDrafts,\n onSent,\n options.effectiveControl?.controlEtag,\n persistPayload,\n restoredResources,\n sending,\n sessionId,\n targetKey,\n value,\n workspaceId,\n ],\n );\n\n const send = useCallback(async (text?: string) => await dispatch(\"send\", text), [dispatch]);\n const steer = useCallback(async (text?: string) => await dispatch(\"steer\", text), [dispatch]);\n\n // A send is possible with non-empty text OR with ≥1 attached resource (a\n // file-only message). Resources ride in `sendExtras`, so we resolve them here\n // — keeping useComposer attachment-agnostic while still lighting up the send\n // affordance the moment a file is ready. Attachment hosts bind `sendBlocked`\n // to unresolved uploads so direct send()/steer() calls fail closed too.\n const hasReadyResources =\n restoredResources.length > 0 ||\n (resolveSendExtras(sendExtrasRef.current).resources?.length ?? 0) > 0;\n const hasPendingOperation = pendingOperationRef.current !== null;\n\n const pause = useCallback(\n async (reason?: string): Promise<void> => {\n const ownedTargetKey = targetKey;\n const ownedGeneration = targetGeneration.current;\n if (!sessionId || pausing || targetKeyRef.current !== ownedTargetKey) {\n return;\n }\n setPausing(true);\n setError(null);\n try {\n await client.pauseSession(workspaceId, sessionId, {\n ...(reason !== undefined ? { reason } : {}),\n ...(options.effectiveControl?.controlEtag\n ? { expectedControlEtag: options.effectiveControl.controlEtag }\n : {}),\n });\n } catch (cause) {\n if (\n targetKeyRef.current === ownedTargetKey &&\n targetGeneration.current === ownedGeneration\n ) {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n }\n } finally {\n if (\n targetKeyRef.current === ownedTargetKey &&\n targetGeneration.current === ownedGeneration\n ) {\n setPausing(false);\n }\n }\n },\n [client, workspaceId, sessionId, pausing, options.effectiveControl?.controlEtag, targetKey],\n );\n\n const resume = useCallback(\n async (reason?: string): Promise<void> => {\n const ownedTargetKey = targetKey;\n const ownedGeneration = targetGeneration.current;\n if (!sessionId || resuming || targetKeyRef.current !== ownedTargetKey) return;\n setResuming(true);\n setError(null);\n try {\n await client.resumeSession(workspaceId, sessionId, {\n ...(reason !== undefined ? { reason } : {}),\n ...(options.effectiveControl?.controlEtag\n ? { expectedControlEtag: options.effectiveControl.controlEtag }\n : {}),\n });\n } catch (cause) {\n if (\n targetKeyRef.current === ownedTargetKey &&\n targetGeneration.current === ownedGeneration\n ) {\n setError(cause instanceof Error ? cause : new Error(String(cause)));\n }\n } finally {\n if (\n targetKeyRef.current === ownedTargetKey &&\n targetGeneration.current === ownedGeneration\n ) {\n setResuming(false);\n }\n }\n },\n [client, workspaceId, sessionId, resuming, options.effectiveControl?.controlEtag, targetKey],\n );\n\n const resumeScope = useCallback(\n async (option: EffectiveControlResumeOption): Promise<void> => {\n const ownedTargetKey = targetKey;\n const ownedGeneration = targetGeneration.current;\n if (!sessionId || resuming || targetKeyRef.current !== ownedTargetKey) return;\n setResuming(true);\n setError(null);\n try {\n if (option.scope === \"workspace\") {\n const workspaceBlocker = options.effectiveControl?.blockers.find(\n (blocker) => blocker.kind === \"workspace\",\n );\n if (!client.setWorkspaceInferenceState) {\n throw new Error(\n \"@opengeni/react: workspace-scoped resume requires setWorkspaceInferenceState.\",\n );\n }\n await client.setWorkspaceInferenceState(workspaceId, {\n action: \"resume\",\n clientEventId: generateClientEventId(),\n ...(workspaceBlocker ? { expectedRevision: workspaceBlocker.revision } : {}),\n });\n } else if (option.scope === \"session\" && option.targetId) {\n const target = await client.getQueue(workspaceId, option.targetId);\n if (\n targetKeyRef.current !== ownedTargetKey ||\n targetGeneration.current !== ownedGeneration\n ) {\n return;\n }\n await client.resumeSession(workspaceId, option.targetId, {\n expectedControlEtag: target.effectiveControl.controlEtag,\n });\n } else {\n await client.resumeSession(workspaceId, sessionId, {\n ...(options.effectiveControl?.controlEtag\n ? { expectedControlEtag: options.effectiveControl.controlEtag }\n : {}),\n });\n }\n } catch (cause) {\n if (\n targetKeyRef.current === ownedTargetKey &&\n targetGeneration.current === ownedGeneration\n ) {\n setError(asError(cause));\n }\n } finally {\n if (\n targetKeyRef.current === ownedTargetKey &&\n targetGeneration.current === ownedGeneration\n ) {\n setResuming(false);\n }\n }\n },\n [client, options.effectiveControl, resuming, sessionId, targetKey, workspaceId],\n );\n\n const updateValue = useCallback(\n (next: string) => {\n if (targetKeyRef.current !== targetKey) return;\n localEditRevision.current += 1;\n valueRef.current = next;\n pendingOperationRef.current = updatePendingComposerShadow(\n pendingOperationKey,\n pendingOperationRef.current,\n {\n text: next,\n resources: mergeResources(\n restoredResourcesRef.current,\n resolveSendExtras(sendExtrasRef.current).resources ?? [],\n ),\n },\n );\n setValue(next);\n },\n [pendingOperationKey, targetKey],\n );\n\n const removeRestoredResource = useCallback(\n (index: number) => {\n if (targetKeyRef.current !== targetKey) return;\n localEditRevision.current += 1;\n const next = restoredResourcesRef.current.filter((_, candidate) => candidate !== index);\n restoredResourcesRef.current = next;\n pendingOperationRef.current = updatePendingComposerShadow(\n pendingOperationKey,\n pendingOperationRef.current,\n {\n text: valueRef.current,\n resources: mergeResources(next, resolveSendExtras(sendExtrasRef.current).resources ?? []),\n },\n );\n setRestoredResources(next);\n },\n [pendingOperationKey, targetKey],\n );\n\n const hasDraftContent = useCallback((): boolean => {\n const current = draftRef.current;\n const extras = resolveSendExtras(sendExtrasRef.current);\n return (\n valueRef.current.length > 0 ||\n restoredResourcesRef.current.length > 0 ||\n (extras.resources?.length ?? 0) > 0 ||\n (current?.sourceTurnId !== null && current?.sourceTurnId !== undefined)\n );\n }, []);\n\n const resolveDraftConflict = useCallback(\n async (choice: \"keep_mine\" | \"use_remote\"): Promise<void> => {\n const ownedTargetKey = targetKey;\n const ownedGeneration = targetGeneration.current;\n if (!sessionId || !durableDrafts || targetKeyRef.current !== ownedTargetKey) return;\n const remote = await client.getComposerDraft(workspaceId, sessionId);\n if (targetKeyRef.current !== ownedTargetKey || targetGeneration.current !== ownedGeneration) {\n return;\n }\n if (choice === \"use_remote\") {\n applyDraft(remote);\n return;\n }\n draftRef.current = remote;\n setDraft(remote);\n setDraftConflict(null);\n const payload = currentDraftPayload();\n if (payload) await persistPayload({ ...payload, expectedRevision: remote.revision });\n },\n [\n applyDraft,\n client,\n currentDraftPayload,\n durableDrafts,\n persistPayload,\n sessionId,\n targetKey,\n workspaceId,\n ],\n );\n\n const identityMatches = stateTargetKey === targetKey;\n const reloadDraft = useCallback(async () => await loadDraft(true), [loadDraft]);\n const clearError = useCallback(() => {\n if (targetKeyRef.current !== targetKey) return;\n setError(null);\n setDraftConflict(null);\n }, [targetKey]);\n\n return {\n value: identityMatches ? value : \"\",\n setValue: updateValue,\n hasDraftContent,\n send,\n steer,\n steering: identityMatches ? steering : null,\n sending: identityMatches ? sending : false,\n canSend:\n identityMatches &&\n Boolean(sessionId) &&\n !sending &&\n sendBlockedRef.current?.() !== true &&\n (hasPendingOperation || value.trim().length > 0 || hasReadyResources),\n pause,\n pausing: identityMatches ? pausing : false,\n resume,\n resumeScope,\n resuming: identityMatches ? resuming : false,\n draft: identityMatches ? draft : null,\n draftRevision: identityMatches ? (draft?.revision ?? 0) : 0,\n draftLoading: identityMatches ? draftLoading : Boolean(sessionId) && durableDrafts,\n draftSaving: identityMatches ? draftSaving : false,\n draftConflict: identityMatches ? draftConflict : null,\n draftPersistence: durableDrafts ? \"durable\" : \"disabled\",\n applyDraft,\n reloadDraft,\n resolveDraftConflict,\n restoredResources: identityMatches ? restoredResources : [],\n removeRestoredResource,\n error: identityMatches ? error : null,\n clearError,\n };\n}\n\n/** Events that can atomically replace or clear this subject's durable draft. */\nexport function isComposerDraftEvent(event: Pick<SessionEvent, \"type\">): boolean {\n return event.type === \"user.message\" || event.type === \"session.queue.changed\";\n}\n\n/**\n * Default text for a file-only message (attachment(s) present, no typed draft).\n * Kept non-empty so the wire contract (`text: z.string().min(1)`) and the\n * worker's non-whitespace guard accept it; the attached files still ride in\n * `resources`. Exported for tests.\n */\nexport const FILE_ONLY_MESSAGE_TEXT = \"(see attached files)\";\n\n/** Resolve possibly-deferred extras to a concrete bag (function evaluated now). */\nexport function resolveSendExtras(\n extras: ComposerSendExtras | (() => ComposerSendExtras) | undefined,\n): ComposerSendExtras {\n return (typeof extras === \"function\" ? extras() : extras) ?? {};\n}\n\n/**\n * Merge the draft text + idempotency key with caller-provided extras. The\n * text and clientEventId always win over extras. Exported for tests.\n */\nexport function composeSendInput(\n text: string,\n clientEventId: string,\n extras: ComposerSendExtras | (() => ComposerSendExtras) | undefined,\n bound: Partial<SendMessageInput> = {},\n): SendMessageInput {\n return { ...resolveSendExtras(extras), ...bound, text, clientEventId };\n}\n\n/** Submit on plain Enter; Shift+Enter inserts a newline. Exported for tests. */\nexport function shouldSubmitOnKey(event: {\n key: string;\n shiftKey: boolean;\n metaKey?: boolean;\n ctrlKey?: boolean;\n nativeEvent?: { isComposing?: boolean };\n}): boolean {\n if (event.key !== \"Enter\" || event.shiftKey) {\n return false;\n }\n return event.nativeEvent?.isComposing !== true;\n}\n\n/** Cmd/Ctrl+Enter steers; ordinary Enter appends to the queue. */\nexport function shouldSteerOnKey(event: { metaKey?: boolean; ctrlKey?: boolean }): boolean {\n return event.metaKey === true || event.ctrlKey === true;\n}\n\nfunction generateClientEventId(): string {\n return globalThis.crypto.randomUUID();\n}\n\nfunction isOutcomeUnknownError(cause: unknown): boolean {\n return (\n typeof cause === \"object\" &&\n cause !== null &&\n (cause as { outcomeUnknown?: unknown }).outcomeUnknown === true\n );\n}\n\nfunction asError(cause: unknown): Error {\n return cause instanceof Error ? cause : new Error(String(cause));\n}\n\nfunction isDraftConflictError(error: Error): boolean {\n const apiError = error as Partial<OpenGeniApiError>;\n return (\n apiError.status === 409 &&\n apiError.outcomeUnknown === false &&\n (apiError.code === undefined ||\n apiError.code === \"conflict\" ||\n apiError.code === \"idempotency_conflict\")\n );\n}\n\nfunction draftPayload(draft: ComposerDraft): SaveComposerDraftRequest {\n return {\n expectedRevision: draft.revision,\n text: draft.text,\n resources: draft.resources,\n model: draft.model,\n reasoningEffort: draft.reasoningEffort,\n latencyMode: draft.latencyMode ?? \"standard\",\n };\n}\n\nfunction composerDraftPayload(\n base: ComposerDraft,\n text: string,\n restoredResources: ResourceRef[],\n extras: ComposerSendExtras,\n): SaveComposerDraftRequest {\n return {\n expectedRevision: base.revision,\n text,\n resources: mergeResources(restoredResources, extras.resources ?? []),\n model: extras.model ?? base.model,\n reasoningEffort: extras.reasoningEffort ?? base.reasoningEffort,\n latencyMode: extras.latencyMode ?? base.latencyMode ?? \"standard\",\n };\n}\n\nfunction draftSignature(payload: SaveComposerDraftRequest): string {\n const { expectedRevision: _revision, ...content } = payload;\n return JSON.stringify(content);\n}\n\nfunction mergeResources(base: ResourceRef[], additions: ResourceRef[]): ResourceRef[] {\n const seen = new Set<string>();\n return [...base, ...additions].filter((resource) => {\n // Reconnect reconciliation can restore the canonical server form while\n // the still-mounted upload card supplies the same ready file without its\n // default mount. Treat those two wire shapes as one selected attachment;\n // preserving the first representation keeps custom mounts and ordering\n // intact while preventing the draft and command paths from seeing\n // different duplicate counts after server normalization.\n const key =\n resource.kind === \"file\"\n ? `file:${resource.fileId}\\u0000${resource.mountPath ?? `${DEFAULT_FILE_RESOURCE_MOUNT_ROOT}/${resource.fileId}`}`\n : JSON.stringify(resource);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -53,7 +53,7 @@ function effortOptionsForModel(model) {
|
|
|
53
53
|
if (!efforts || efforts.length === 0) {
|
|
54
54
|
return ["low"];
|
|
55
55
|
}
|
|
56
|
-
const order = ["none", "minimal", "low", "medium", "high", "xhigh"];
|
|
56
|
+
const order = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
57
57
|
return order.filter((effort) => efforts.includes(effort));
|
|
58
58
|
}
|
|
59
59
|
function defaultEffortForModel(model) {
|
|
@@ -84,6 +84,12 @@ function labelLatencyMode(mode) {
|
|
|
84
84
|
}
|
|
85
85
|
return "Standard";
|
|
86
86
|
}
|
|
87
|
+
function labelReasoningEffort(effort) {
|
|
88
|
+
if (effort === "xhigh") {
|
|
89
|
+
return "Extra high";
|
|
90
|
+
}
|
|
91
|
+
return effort.slice(0, 1).toUpperCase() + effort.slice(1);
|
|
92
|
+
}
|
|
87
93
|
function payerSummaryForModel(model) {
|
|
88
94
|
const billing = model.billing;
|
|
89
95
|
if (!billing) {
|
|
@@ -135,6 +141,22 @@ function projectPickerRows(models) {
|
|
|
135
141
|
};
|
|
136
142
|
});
|
|
137
143
|
}
|
|
144
|
+
function projectClientModelRows(models) {
|
|
145
|
+
return models.map((catalog) => {
|
|
146
|
+
const billingClass = billingClassForModel(catalog);
|
|
147
|
+
return {
|
|
148
|
+
id: catalog.id,
|
|
149
|
+
label: catalog.label,
|
|
150
|
+
billingClass,
|
|
151
|
+
billingClassLabel: billingClassLabel(billingClass),
|
|
152
|
+
selectable: true,
|
|
153
|
+
unavailableReason: null,
|
|
154
|
+
provider: catalog.provider,
|
|
155
|
+
providerLabel: catalog.providerLabel,
|
|
156
|
+
catalog
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
}
|
|
138
160
|
function sortPickerRows(rows) {
|
|
139
161
|
return [...rows].sort((left, right) => {
|
|
140
162
|
const classDelta = BILLING_CLASS_ORDER.indexOf(left.billingClass) - BILLING_CLASS_ORDER.indexOf(right.billingClass);
|
|
@@ -177,11 +199,13 @@ export {
|
|
|
177
199
|
coerceReasoningEffortForModel,
|
|
178
200
|
runnableLatencyModesForModel,
|
|
179
201
|
labelLatencyMode,
|
|
202
|
+
labelReasoningEffort,
|
|
180
203
|
payerSummaryForModel,
|
|
181
204
|
advancedSourceSummary,
|
|
182
205
|
projectPickerRows,
|
|
206
|
+
projectClientModelRows,
|
|
183
207
|
sortPickerRows,
|
|
184
208
|
findPickerRow,
|
|
185
209
|
groupPickerRowsByBillingClass
|
|
186
210
|
};
|
|
187
|
-
//# sourceMappingURL=chunk-
|
|
211
|
+
//# sourceMappingURL=chunk-SJKT4TKW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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<TCatalog extends ClientModel = WorkspaceModelCatalogModel> = {\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: TCatalog;\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\", \"max\"];\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 labelReasoningEffort(effort: ReasoningEffort): string {\n if (effort === \"xhigh\") {\n return \"Extra high\";\n }\n return effort.slice(0, 1).toUpperCase() + effort.slice(1);\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\n/** Project the lightweight client-config model list into the same picker contract. */\nexport function projectClientModelRows(models: ClientModel[]): PickerModelRow<ClientModel>[] {\n return models.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: true,\n unavailableReason: null,\n provider: catalog.provider,\n providerLabel: catalog.providerLabel,\n catalog,\n };\n });\n}\n\nexport function sortPickerRows<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n): PickerModelRow<TCatalog>[] {\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<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n modelId: string,\n): PickerModelRow<TCatalog> | 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[] }>;\nexport function groupPickerRowsByBillingClass<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n): Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n}>;\nexport function groupPickerRowsByBillingClass<TCatalog extends ClientModel>(\n rows: PickerModelRow<TCatalog>[],\n): Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\n}> {\n const sorted = sortPickerRows(rows);\n const groups: Array<{\n billingClass: PickerBillingClass;\n label: string;\n rows: PickerModelRow<TCatalog>[];\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":";AAkBA,IAAM,sBAA4C;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,uBAA2D;AAAA,EAC/D,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,MAAM;AACR;AAEA,IAAM,6BAAqD;AAAA,EACzD,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,sBAAsB;AAAA,EACtB,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,aAAa;AACf;AAEO,SAAS,qBAAqB,OAAwC;AAC3E,MAAI,MAAM,WAAW,SAAS;AAC5B,WAAO;AAAA,EACT;AACA,MAAI,MAAM,WAAW,qBAAqB;AACxC,WAAO;AAAA,EACT;AACA,MAAI,MAAM,kBAAkB,SAAS,0BAA0B;AAC7D,WAAO;AAAA,EACT;AACA,MAAI,MAAM,kBAAkB,SAAS,wBAAwB;AAC3D,WAAO;AAAA,EACT;AACA,MAAI,MAAM,SAAS,kBAAkB,0BAA0B;AAC7D,WAAO;AAAA,EACT;AACA,MAAI,MAAM,SAAS,kBAAkB,aAAa;AAChD,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,kBAAkB,cAA0C;AAC1E,SAAO,qBAAqB,YAAY;AAC1C;AAEO,SAAS,wBACd,QACe;AACf,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,SAAO,2BAA2B,MAAM,KAAK;AAC/C;AAEO,SAAS,sBAAsB,OAAuC;AAC3E,QAAM,UAAU,MAAM,cAAc,UAAU;AAC9C,MAAI,CAAC,WAAW,QAAQ,WAAW,GAAG;AACpC,WAAO,CAAC,KAAK;AAAA,EACf;AACA,QAAM,QAA2B,CAAC,QAAQ,WAAW,OAAO,UAAU,QAAQ,SAAS,KAAK;AAC5F,SAAO,MAAM,OAAO,CAAC,WAAW,QAAQ,SAAS,MAAM,CAAC;AAC1D;AAEO,SAAS,sBAAsB,OAAqC;AACzE,QAAM,UAAU,sBAAsB,KAAK;AAC3C,QAAM,aAAa,MAAM,cAAc,UAAU;AACjD,MAAI,cAAc,QAAQ,SAAS,UAAU,GAAG;AAC9C,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,CAAC,KAAK;AACvB;AAEO,SAAS,8BACd,OACA,QACiB;AACjB,QAAM,UAAU,sBAAsB,KAAK;AAC3C,MAAI,QAAQ,SAAS,MAAM,GAAG;AAC5B,WAAO;AAAA,EACT;AACA,SAAO,sBAAsB,KAAK;AACpC;AAEO,SAAS,6BAA6B,OAAqC;AAChF,QAAM,QAAQ,MAAM,cAAc,gBAAgB,CAAC;AACnD,SAAO,MAAM,OAAO,CAAC,SAAS,KAAK,QAAQ,EAAE,IAAI,CAAC,SAAS,KAAK,EAAE;AACpE;AAEO,SAAS,iBAAiB,MAA6B;AAC5D,MAAI,SAAS,QAAQ;AACnB,WAAO;AAAA,EACT;AACA,MAAI,SAAS,YAAY;AACvB,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,qBAAqB,QAAiC;AACpE,MAAI,WAAW,SAAS;AACtB,WAAO;AAAA,EACT;AACA,SAAO,OAAO,MAAM,GAAG,CAAC,EAAE,YAAY,IAAI,OAAO,MAAM,CAAC;AAC1D;AAEO,SAAS,qBAAqB,OAA4B;AAC/D,QAAM,UAAU,MAAM;AACtB,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,aAAa,oBAAoB;AAC3C,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,kBAAkB,0BAA0B;AACtD,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,kBAAkB,aAAa;AACzC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,sBAAsB,OAAmC;AACvE,QAAM,SAAS,MAAM;AACrB,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,MAAI,OAAO,SAAS,0BAA0B;AAC5C,WAAO;AAAA,EACT;AACA,MAAI,OAAO,SAAS,wBAAwB;AAC1C,WAAO;AAAA,EACT;AACA,MAAI,OAAO,SAAS,cAAc;AAChC,WAAO,OAAO,cAAc,oBACxB,8BACA;AAAA,EACN;AACA,SAAO;AACT;AAEO,SAAS,kBAAkB,QAAwD;AACxF,SAAO,OACJ,OAAO,CAAC,YAAY;AACnB,UAAM,eAAe,qBAAqB,OAAO;AACjD,WAAO,iBAAiB,sBAAsB,QAAQ,oBAAoB,WAAW;AAAA,EACvF,CAAC,EACA,IAAI,CAAC,YAAY;AAChB,UAAM,eAAe,qBAAqB,OAAO;AACjD,WAAO;AAAA,MACL,IAAI,QAAQ;AAAA,MACZ,OAAO,QAAQ;AAAA,MACf;AAAA,MACA,mBAAmB,kBAAkB,YAAY;AAAA,MACjD,YAAY,QAAQ,aAAa;AAAA,MACjC,mBAAmB,QAAQ,aAAa,aACpC,OACA,wBAAwB,QAAQ,aAAa,MAAM;AAAA,MACvD,UAAU,QAAQ;AAAA,MAClB,eAAe,QAAQ;AAAA,MACvB;AAAA,IACF;AAAA,EACF,CAAC;AACL;AAGO,SAAS,uBAAuB,QAAsD;AAC3F,SAAO,OAAO,IAAI,CAAC,YAAY;AAC7B,UAAM,eAAe,qBAAqB,OAAO;AACjD,WAAO;AAAA,MACL,IAAI,QAAQ;AAAA,MACZ,OAAO,QAAQ;AAAA,MACf;AAAA,MACA,mBAAmB,kBAAkB,YAAY;AAAA,MACjD,YAAY;AAAA,MACZ,mBAAmB;AAAA,MACnB,UAAU,QAAQ;AAAA,MAClB,eAAe,QAAQ;AAAA,MACvB;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEO,SAAS,eACd,MAC4B;AAC5B,SAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,MAAM,UAAU;AACrC,UAAM,aACJ,oBAAoB,QAAQ,KAAK,YAAY,IAC7C,oBAAoB,QAAQ,MAAM,YAAY;AAChD,QAAI,eAAe,GAAG;AACpB,aAAO;AAAA,IACT;AACA,QAAI,KAAK,eAAe,MAAM,YAAY;AACxC,aAAO,KAAK,aAAa,KAAK;AAAA,IAChC;AACA,WAAO,KAAK,MAAM,cAAc,MAAM,KAAK;AAAA,EAC7C,CAAC;AACH;AAEO,SAAS,cACd,MACA,SACiC;AACjC,SAAO,KAAK,KAAK,CAAC,QAAQ,IAAI,OAAO,OAAO,KAAK;AACnD;AAYO,SAAS,8BACd,MAKC;AACD,QAAM,SAAS,eAAe,IAAI;AAClC,QAAM,SAID,CAAC;AACN,aAAW,OAAO,QAAQ;AACxB,UAAM,WAAW,OAAO,KAAK,CAAC,UAAU,MAAM,iBAAiB,IAAI,YAAY;AAC/E,QAAI,UAAU;AACZ,eAAS,KAAK,KAAK,GAAG;AACtB;AAAA,IACF;AACA,WAAO,KAAK;AAAA,MACV,cAAc,IAAI;AAAA,MAClB,OAAO,IAAI;AAAA,MACX,MAAM,CAAC,GAAG;AAAA,IACZ,CAAC;AAAA,EACH;AACA,SAAO;AACT;","names":[]}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
|
-
OpenGeniContext,
|
|
3
2
|
useMutationRunner,
|
|
4
|
-
useOpenGeni,
|
|
5
3
|
usePolledValue
|
|
6
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EB67J347.js";
|
|
7
5
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
OpenGeniContext,
|
|
7
|
+
useOpenGeni
|
|
8
|
+
} from "./chunk-EKZH6IDG.js";
|
|
10
9
|
import {
|
|
11
10
|
formatBytes,
|
|
12
11
|
formatRelativeTime
|
|
13
12
|
} from "./chunk-LAKLF4PA.js";
|
|
13
|
+
import {
|
|
14
|
+
cn
|
|
15
|
+
} from "./chunk-TK7G6XLT.js";
|
|
14
16
|
|
|
15
17
|
// src/types/machines.ts
|
|
16
18
|
function connectionStatusForState(state) {
|
|
@@ -1955,4 +1957,4 @@ export {
|
|
|
1955
1957
|
OpenGeniProvider,
|
|
1956
1958
|
useMachines
|
|
1957
1959
|
};
|
|
1958
|
-
//# sourceMappingURL=chunk-
|
|
1960
|
+
//# sourceMappingURL=chunk-SXIQK54Z.js.map
|