@opengeni/react 0.34.2 → 0.34.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-A2WITZTI.js → chunk-4NMH6UJ3.js} +2 -2
- package/dist/{chunk-GZ4KR67U.js → chunk-ALA3UGWB.js} +2 -2
- package/dist/chunk-ATSTR5P3.js +138 -0
- package/dist/chunk-ATSTR5P3.js.map +1 -0
- package/dist/{chunk-KZRUYCL4.js → chunk-FT2TXNGZ.js} +5 -2
- package/dist/chunk-FT2TXNGZ.js.map +1 -0
- package/dist/{chunk-4QOQ2DSR.js → chunk-LAKLF4PA.js} +14 -1
- package/dist/chunk-LAKLF4PA.js.map +1 -0
- package/dist/{chunk-TCCE5ZU5.js → chunk-MEGI4FS6.js} +38 -9
- package/dist/chunk-MEGI4FS6.js.map +1 -0
- package/dist/{chunk-MS3FBZ6A.js → chunk-PVW56EVR.js} +105 -62
- package/dist/chunk-PVW56EVR.js.map +1 -0
- package/dist/{chunk-L7R5RK6A.js → chunk-QRYJCWGD.js} +1199 -897
- package/dist/chunk-QRYJCWGD.js.map +1 -0
- package/dist/components/chat-composer.d.ts +2 -1
- package/dist/components/composer.d.ts +8 -2
- package/dist/components/copy-button.d.ts +4 -2
- package/dist/components/tip-follow.d.ts +3 -0
- package/dist/composer.d.ts +2 -1
- package/dist/composer.js +4 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +105 -101
- package/dist/index.js.map +1 -1
- package/dist/lib/format.d.ts +2 -0
- package/dist/machines.js +2 -2
- package/dist/session-ui.js +4 -3
- package/dist/session.js +4 -4
- package/dist/timeline/index.d.ts +1 -1
- package/dist/timeline/parsers.d.ts +5 -0
- package/dist/timeline/projection.d.ts +1 -12
- package/dist/timeline/tool-display-name.d.ts +17 -6
- package/dist/workstream-control-event.d.ts +6 -0
- package/package.json +1 -1
- package/src/components/chat-composer.tsx +1 -1
- package/src/components/composer-transcription-control.tsx +70 -57
- package/src/components/composer.tsx +197 -126
- package/src/components/copy-button.tsx +27 -8
- package/src/components/message-timeline.tsx +236 -39
- package/src/components/tip-follow.ts +15 -0
- package/src/composer.ts +1 -1
- package/src/hooks/use-composer.ts +7 -1
- package/src/index.ts +2 -1
- package/src/lib/format.ts +14 -0
- package/src/timeline/index.ts +2 -0
- package/src/timeline/parsers.ts +18 -1
- package/src/timeline/projection.ts +50 -20
- package/src/timeline/registry.ts +15 -2
- package/src/timeline/shared.tsx +30 -28
- package/src/timeline/tool-display-name.ts +30 -11
- package/src/timeline/tool-renderers.tsx +347 -16
- package/src/timeline/turn-summary.tsx +5 -2
- package/src/workstream-control-event.ts +6 -0
- package/dist/chunk-4QOQ2DSR.js.map +0 -1
- package/dist/chunk-KZRUYCL4.js.map +0 -1
- package/dist/chunk-L7R5RK6A.js.map +0 -1
- package/dist/chunk-MS3FBZ6A.js.map +0 -1
- package/dist/chunk-TCCE5ZU5.js.map +0 -1
- /package/dist/{chunk-A2WITZTI.js.map → chunk-4NMH6UJ3.js.map} +0 -0
- /package/dist/{chunk-GZ4KR67U.js.map → chunk-ALA3UGWB.js.map} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
buildTimeline,
|
|
3
3
|
groupTimeline,
|
|
4
4
|
sessionStatusFromEvents
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-MEGI4FS6.js";
|
|
6
6
|
import {
|
|
7
7
|
useDebouncedCallback,
|
|
8
8
|
useEmbeddedFileAttachments,
|
|
@@ -2099,4 +2099,4 @@ export {
|
|
|
2099
2099
|
isHumanInputEvent,
|
|
2100
2100
|
useHumanInputRequests
|
|
2101
2101
|
};
|
|
2102
|
-
//# sourceMappingURL=chunk-
|
|
2102
|
+
//# sourceMappingURL=chunk-4NMH6UJ3.js.map
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
formatBytes,
|
|
12
12
|
formatRelativeTime
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-LAKLF4PA.js";
|
|
14
14
|
|
|
15
15
|
// src/types/machines.ts
|
|
16
16
|
function connectionStatusForState(state) {
|
|
@@ -1955,4 +1955,4 @@ export {
|
|
|
1955
1955
|
OpenGeniProvider,
|
|
1956
1956
|
useMachines
|
|
1957
1957
|
};
|
|
1958
|
-
//# sourceMappingURL=chunk-
|
|
1958
|
+
//# sourceMappingURL=chunk-ALA3UGWB.js.map
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-TK7G6XLT.js";
|
|
4
|
+
|
|
5
|
+
// src/components/tooltip.tsx
|
|
6
|
+
import { Tooltip as TooltipPrimitive } from "radix-ui";
|
|
7
|
+
import {
|
|
8
|
+
createContext,
|
|
9
|
+
useContext,
|
|
10
|
+
useRef
|
|
11
|
+
} from "react";
|
|
12
|
+
|
|
13
|
+
// src/lib/use-portal-token-style.ts
|
|
14
|
+
import { useEffect, useState } from "react";
|
|
15
|
+
function usePortalTokenStyle(sourceRef) {
|
|
16
|
+
const [style, setStyle] = useState({});
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const source = sourceRef.current;
|
|
19
|
+
if (!source || typeof MutationObserver === "undefined") return;
|
|
20
|
+
let signature = "";
|
|
21
|
+
const sync = () => {
|
|
22
|
+
const computed = getComputedStyle(source);
|
|
23
|
+
const next = { colorScheme: computed.colorScheme };
|
|
24
|
+
for (let index = 0; index < computed.length; index += 1) {
|
|
25
|
+
const property = computed.item(index);
|
|
26
|
+
if (!property.startsWith("--og-")) continue;
|
|
27
|
+
next[property] = computed.getPropertyValue(property);
|
|
28
|
+
}
|
|
29
|
+
const nextSignature = JSON.stringify(next);
|
|
30
|
+
if (nextSignature !== signature) {
|
|
31
|
+
signature = nextSignature;
|
|
32
|
+
setStyle(next);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const observers = [];
|
|
36
|
+
let ancestor = source;
|
|
37
|
+
while (ancestor) {
|
|
38
|
+
const observer = new MutationObserver(sync);
|
|
39
|
+
observer.observe(ancestor, {
|
|
40
|
+
attributes: true,
|
|
41
|
+
attributeFilter: ["class", "data-og-theme", "style"]
|
|
42
|
+
});
|
|
43
|
+
observers.push(observer);
|
|
44
|
+
ancestor = ancestor.parentElement;
|
|
45
|
+
}
|
|
46
|
+
const colorScheme = window.matchMedia?.("(prefers-color-scheme: dark)");
|
|
47
|
+
colorScheme?.addEventListener?.("change", sync);
|
|
48
|
+
sync();
|
|
49
|
+
return () => {
|
|
50
|
+
for (const observer of observers) observer.disconnect();
|
|
51
|
+
colorScheme?.removeEventListener?.("change", sync);
|
|
52
|
+
};
|
|
53
|
+
}, [sourceRef]);
|
|
54
|
+
return style;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/components/tooltip.tsx
|
|
58
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
59
|
+
var TooltipSourceContext = createContext(null);
|
|
60
|
+
function TooltipProvider({
|
|
61
|
+
delayDuration = 300,
|
|
62
|
+
...props
|
|
63
|
+
}) {
|
|
64
|
+
return /* @__PURE__ */ jsx(TooltipPrimitive.Provider, { delayDuration, ...props });
|
|
65
|
+
}
|
|
66
|
+
function Tooltip({ children, ...props }) {
|
|
67
|
+
const sourceRef = useRef(null);
|
|
68
|
+
return /* @__PURE__ */ jsx(TooltipSourceContext.Provider, { value: sourceRef, children: /* @__PURE__ */ jsx(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props, children }) });
|
|
69
|
+
}
|
|
70
|
+
function TooltipTrigger({
|
|
71
|
+
asChild = true,
|
|
72
|
+
...props
|
|
73
|
+
}) {
|
|
74
|
+
const sourceRef = useContext(TooltipSourceContext);
|
|
75
|
+
return /* @__PURE__ */ jsx(
|
|
76
|
+
TooltipPrimitive.Trigger,
|
|
77
|
+
{
|
|
78
|
+
"data-slot": "tooltip-trigger",
|
|
79
|
+
asChild,
|
|
80
|
+
ref: (node) => {
|
|
81
|
+
if (sourceRef) sourceRef.current = node;
|
|
82
|
+
},
|
|
83
|
+
...props
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
var tooltipSurfaceStyle = {
|
|
88
|
+
backgroundColor: "var(--og-color-fg)",
|
|
89
|
+
color: "var(--og-color-bg)"
|
|
90
|
+
};
|
|
91
|
+
function TooltipContent({
|
|
92
|
+
className,
|
|
93
|
+
sideOffset = 6,
|
|
94
|
+
children,
|
|
95
|
+
style,
|
|
96
|
+
...props
|
|
97
|
+
}) {
|
|
98
|
+
const sourceRef = useContext(TooltipSourceContext);
|
|
99
|
+
const fallbackRef = useRef(null);
|
|
100
|
+
const portalStyle = usePortalTokenStyle(sourceRef ?? fallbackRef);
|
|
101
|
+
return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
102
|
+
TooltipPrimitive.Content,
|
|
103
|
+
{
|
|
104
|
+
"data-slot": "tooltip-content",
|
|
105
|
+
sideOffset,
|
|
106
|
+
className: cn(
|
|
107
|
+
"og-root z-50 w-fit max-w-xs origin-[var(--radix-tooltip-content-transform-origin)]",
|
|
108
|
+
"rounded-og-md px-2.5 py-1.5 text-og-xs leading-4 text-balance shadow-og-md",
|
|
109
|
+
"animate-og-enter data-[state=closed]:opacity-0 data-[state=closed]:transition-opacity",
|
|
110
|
+
className
|
|
111
|
+
),
|
|
112
|
+
style: { ...portalStyle, ...tooltipSurfaceStyle, ...style },
|
|
113
|
+
...props,
|
|
114
|
+
children: [
|
|
115
|
+
children,
|
|
116
|
+
/* @__PURE__ */ jsx(
|
|
117
|
+
TooltipPrimitive.Arrow,
|
|
118
|
+
{
|
|
119
|
+
className: "z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]",
|
|
120
|
+
style: {
|
|
121
|
+
backgroundColor: "var(--og-color-fg)",
|
|
122
|
+
fill: "var(--og-color-fg)"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
) });
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export {
|
|
132
|
+
usePortalTokenStyle,
|
|
133
|
+
TooltipProvider,
|
|
134
|
+
Tooltip,
|
|
135
|
+
TooltipTrigger,
|
|
136
|
+
TooltipContent
|
|
137
|
+
};
|
|
138
|
+
//# sourceMappingURL=chunk-ATSTR5P3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/tooltip.tsx","../src/lib/use-portal-token-style.ts"],"sourcesContent":["/**\n * Token-styled Radix tooltip — SDK counterpart to apps/web `components/ui/tooltip`.\n * Portals copy `--og-*` tokens so embeds keep the host theme outside `.og-root`.\n *\n * Background/foreground are applied as inline styles (not only Tailwind\n * utilities): `.og-root` sets `color: var(--og-color-fg)` after utilities in the\n * consumer CSS cascade, which would otherwise paint light-on-light inverted\n * tips and look like a blank white bubble.\n */\nimport { Tooltip as TooltipPrimitive } from \"radix-ui\";\nimport {\n createContext,\n useContext,\n useRef,\n type ComponentProps,\n type CSSProperties,\n type RefObject,\n} from \"react\";\n\nimport { cn } from \"../lib/cn\";\nimport { usePortalTokenStyle } from \"../lib/use-portal-token-style\";\n\nconst TooltipSourceContext = createContext<RefObject<HTMLElement | null> | null>(null);\n\nfunction TooltipProvider({\n delayDuration = 300,\n ...props\n}: ComponentProps<typeof TooltipPrimitive.Provider>) {\n return <TooltipPrimitive.Provider delayDuration={delayDuration} {...props} />;\n}\n\nfunction Tooltip({ children, ...props }: ComponentProps<typeof TooltipPrimitive.Root>) {\n const sourceRef = useRef<HTMLElement | null>(null);\n return (\n <TooltipSourceContext.Provider value={sourceRef}>\n <TooltipPrimitive.Root data-slot=\"tooltip\" {...props}>\n {children}\n </TooltipPrimitive.Root>\n </TooltipSourceContext.Provider>\n );\n}\n\nfunction TooltipTrigger({\n asChild = true,\n ...props\n}: ComponentProps<typeof TooltipPrimitive.Trigger>) {\n const sourceRef = useContext(TooltipSourceContext);\n return (\n <TooltipPrimitive.Trigger\n data-slot=\"tooltip-trigger\"\n asChild={asChild}\n ref={(node) => {\n if (sourceRef) sourceRef.current = node;\n }}\n {...props}\n />\n );\n}\n\nconst tooltipSurfaceStyle: CSSProperties = {\n backgroundColor: \"var(--og-color-fg)\",\n color: \"var(--og-color-bg)\",\n};\n\nfunction TooltipContent({\n className,\n sideOffset = 6,\n children,\n style,\n ...props\n}: ComponentProps<typeof TooltipPrimitive.Content>) {\n const sourceRef = useContext(TooltipSourceContext);\n const fallbackRef = useRef<HTMLElement | null>(null);\n const portalStyle = usePortalTokenStyle(sourceRef ?? fallbackRef);\n\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(\n \"og-root z-50 w-fit max-w-xs origin-[var(--radix-tooltip-content-transform-origin)]\",\n \"rounded-og-md px-2.5 py-1.5 text-og-xs leading-4 text-balance shadow-og-md\",\n \"animate-og-enter data-[state=closed]:opacity-0 data-[state=closed]:transition-opacity\",\n className,\n )}\n style={{ ...portalStyle, ...tooltipSurfaceStyle, ...style }}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow\n className=\"z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]\"\n style={{\n backgroundColor: \"var(--og-color-fg)\",\n fill: \"var(--og-color-fg)\",\n }}\n />\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n}\n\nexport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };\n","import { type CSSProperties, type RefObject, useEffect, useState } from \"react\";\n\nexport type PortalTokenStyle = CSSProperties & Record<`--${string}`, string>;\n\n/**\n * Copy the effective SDK tokens across a portal boundary. A locally themed or\n * rebranded embed cannot rely on CSS inheritance once a portal mounts under\n * `<body>`. Ancestor theme/class/style mutations and OS color-scheme changes\n * keep the copied values live.\n */\nexport function usePortalTokenStyle(sourceRef: RefObject<HTMLElement | null>): PortalTokenStyle {\n const [style, setStyle] = useState<PortalTokenStyle>({});\n useEffect(() => {\n const source = sourceRef.current;\n if (!source || typeof MutationObserver === \"undefined\") return;\n let signature = \"\";\n const sync = () => {\n const computed = getComputedStyle(source);\n const next: PortalTokenStyle = { colorScheme: computed.colorScheme };\n for (let index = 0; index < computed.length; index += 1) {\n const property = computed.item(index);\n if (!property.startsWith(\"--og-\")) continue;\n next[property as `--${string}`] = computed.getPropertyValue(property);\n }\n const nextSignature = JSON.stringify(next);\n if (nextSignature !== signature) {\n signature = nextSignature;\n setStyle(next);\n }\n };\n const observers: MutationObserver[] = [];\n let ancestor: HTMLElement | null = source;\n while (ancestor) {\n const observer = new MutationObserver(sync);\n observer.observe(ancestor, {\n attributes: true,\n attributeFilter: [\"class\", \"data-og-theme\", \"style\"],\n });\n observers.push(observer);\n ancestor = ancestor.parentElement;\n }\n const colorScheme = window.matchMedia?.(\"(prefers-color-scheme: dark)\");\n colorScheme?.addEventListener?.(\"change\", sync);\n sync();\n return () => {\n for (const observer of observers) observer.disconnect();\n colorScheme?.removeEventListener?.(\"change\", sync);\n };\n }, [sourceRef]);\n return style;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -244,7 +244,10 @@ function useComposer(sessionId, options = {}) {
|
|
|
244
244
|
)
|
|
245
245
|
) : null;
|
|
246
246
|
const localWasDirtyAtStart = localSignatureAtStart === null ? localAtStart !== 0 : localSignatureAtStart !== lastSavedSignature.current;
|
|
247
|
-
|
|
247
|
+
const showLoading = replaceLocal || draftRef.current === null;
|
|
248
|
+
if (showLoading) {
|
|
249
|
+
setDraftLoading(true);
|
|
250
|
+
}
|
|
248
251
|
try {
|
|
249
252
|
const fetched = await client.getComposerDraft(workspaceId, sessionId);
|
|
250
253
|
if (generation !== targetGeneration.current || targetKeyRef.current !== targetKey || readTicket !== draftReadGeneration.current) {
|
|
@@ -855,4 +858,4 @@ export {
|
|
|
855
858
|
shouldSubmitOnKey,
|
|
856
859
|
shouldSteerOnKey
|
|
857
860
|
};
|
|
858
|
-
//# sourceMappingURL=chunk-
|
|
861
|
+
//# sourceMappingURL=chunk-FT2TXNGZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/use-composer.ts"],"sourcesContent":["import type {\n ComposerDraft,\n EffectiveControlResumeOption,\n EffectiveSessionControl,\n OpenGeniApiError,\n ResourceRef,\n SaveComposerDraftRequest,\n SendMessageInput,\n 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 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\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 [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 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 // 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 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 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 ride in sendExtras (outside localEditRevision). If\n // the picker changed during this fetch, skip onDraftApplied so a\n // stale server model/effort 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 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 useSessionEventTrigger(\n client,\n workspaceId,\n sessionId,\n isComposerDraftEvent,\n () => void loadDraft(false),\n {\n enabled: Boolean(sessionId) && durableDrafts,\n ...(options.events !== undefined ? { events: options.events } : {}),\n },\n );\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 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): Promise<void> => {\n if (operation.delivery === \"steer\") {\n await client.steerMessage(workspaceId, sessionId, operation.input);\n } else {\n await client.sendMessage(workspaceId, sessionId, operation.input);\n }\n };\n\n setSending(true);\n setError(null);\n try {\n if (pending) {\n let accepted = false;\n try {\n const events = await client.listEvents(workspaceId, sessionId, {\n includeTypes: [\"user.message\"],\n limit: 100,\n payloadMode: \"none\",\n });\n accepted = events.some(\n (event) =>\n event.type === \"user.message\" &&\n event.clientEventId === pending.input.clientEventId,\n );\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 (accepted) {\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 await deliver(pending);\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 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 try {\n await deliver(operation);\n } catch (cause) {\n if (!isOutcomeUnknownError(cause)) {\n clearPending();\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 }\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 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 ?? `files/${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":[]}
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
// src/lib/format.ts
|
|
2
2
|
import { OpenGeniApiError } from "@opengeni/sdk";
|
|
3
|
+
function formatClockTime(iso) {
|
|
4
|
+
const then = new Date(iso);
|
|
5
|
+
if (Number.isNaN(then.getTime())) {
|
|
6
|
+
return "";
|
|
7
|
+
}
|
|
8
|
+
return then.toLocaleString(void 0, {
|
|
9
|
+
month: "short",
|
|
10
|
+
day: "numeric",
|
|
11
|
+
hour: "numeric",
|
|
12
|
+
minute: "2-digit"
|
|
13
|
+
});
|
|
14
|
+
}
|
|
3
15
|
function formatRelativeTime(iso, now = /* @__PURE__ */ new Date()) {
|
|
4
16
|
const then = new Date(iso).getTime();
|
|
5
17
|
if (Number.isNaN(then)) {
|
|
@@ -114,6 +126,7 @@ function humanizeFailureReason(reason) {
|
|
|
114
126
|
}
|
|
115
127
|
|
|
116
128
|
export {
|
|
129
|
+
formatClockTime,
|
|
117
130
|
formatRelativeTime,
|
|
118
131
|
formatBytes,
|
|
119
132
|
truncate,
|
|
@@ -125,4 +138,4 @@ export {
|
|
|
125
138
|
isCreditExhaustion,
|
|
126
139
|
humanizeFailureReason
|
|
127
140
|
};
|
|
128
|
-
//# sourceMappingURL=chunk-
|
|
141
|
+
//# sourceMappingURL=chunk-LAKLF4PA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/format.ts"],"sourcesContent":["import { OpenGeniApiError } from \"@opengeni/sdk\";\n\n/** Local finished-at stamp for message footers: \"Aug 2, 3:42 PM\" / locale-equivalent. */\nexport function formatClockTime(iso: string): string {\n const then = new Date(iso);\n if (Number.isNaN(then.getTime())) {\n return \"\";\n }\n return then.toLocaleString(undefined, {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n}\n\n/** Compact relative time: \"now\", \"42s\", \"7m\", \"3h\", \"2d\", then a date. */\nexport function formatRelativeTime(iso: string, now: Date = new Date()): string {\n const then = new Date(iso).getTime();\n if (Number.isNaN(then)) {\n return \"\";\n }\n const seconds = Math.max(0, Math.floor((now.getTime() - then) / 1000));\n if (seconds < 10) {\n return \"now\";\n }\n if (seconds < 60) {\n return `${seconds}s`;\n }\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) {\n return `${minutes}m`;\n }\n const hours = Math.floor(minutes / 60);\n if (hours < 24) {\n return `${hours}h`;\n }\n const days = Math.floor(hours / 24);\n if (days < 14) {\n return `${days}d`;\n }\n return new Date(iso).toLocaleDateString();\n}\n\n/** Human-readable byte size: \"512 B\", \"8.0 KB\", \"1.4 MB\", \"3 GB\". */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const units = [\"KB\", \"MB\", \"GB\"] as const;\n let value = bytes / 1024;\n for (const unit of units) {\n if (value < 1024 || unit === \"GB\") {\n return `${value.toFixed(value < 10 ? 1 : 0)} ${unit}`;\n }\n value /= 1024;\n }\n return `${bytes} B`;\n}\n\n/** Single-line preview of arbitrary text, for tiles and collapsed rows. */\nexport function truncate(text: string, maxLength: number): string {\n const collapsed = text.replace(/\\s+/g, \" \").trim();\n if (collapsed.length <= maxLength) {\n return collapsed;\n }\n return `${collapsed.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;\n}\n\n/** Render an unknown payload as readable text (pretty JSON when possible). */\nexport function stringifyPayload(value: unknown): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (typeof value === \"string\") {\n const parsed = tryParseJson(value);\n if (parsed !== undefined && typeof parsed === \"object\") {\n return stringifyPayload(parsed);\n }\n return value;\n }\n try {\n return JSON.stringify(value, null, 2) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n/** JSON.parse that returns `undefined` instead of throwing. */\nexport function tryParseJson(text: string): unknown {\n const trimmed = text.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\") && !trimmed.startsWith('\"')) {\n return undefined;\n }\n try {\n return JSON.parse(trimmed) as unknown;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The canonical credit-death sentence. Credit exhaustion is the one failure a\n * user can fix themselves — the copy must say what happened (empty balance),\n * what to do (add credits), and what is safe (nothing was lost). Crucially it\n * must NOT say \"send a message to revive\": a revive turn burns credits the\n * workspace no longer has.\n */\nexport const CREDIT_EXHAUSTION_MESSAGE =\n \"Out of OpenGeni credits — this workspace's balance is empty. Add credits to continue; the conversation is preserved.\";\n\n/**\n * Actionable composer copy for an edge rejection before a turn is accepted.\n * Unlike an in-flight credit exhaustion, this path has not consumed the\n * actor-private draft or any finalized attachment.\n */\nexport const COMPOSER_PAYMENT_REQUIRED_MESSAGE =\n \"This turn requires OpenGeni managed credits, but the account balance is empty. Add credits or choose a connected Codex subscription model, then retry. Your draft and attachments are preserved.\";\n\nexport function composerSubmissionErrorMessage(error: Error): string {\n return error instanceof OpenGeniApiError &&\n error.status === 402 &&\n error.code === \"payment_required\"\n ? COMPOSER_PAYMENT_REQUIRED_MESSAGE\n : error.message;\n}\n\n/**\n * Does this failure/completion payload (or raw error string) mean the\n * workspace ran out of OpenGeni credits? Matches the engine's\n * \"insufficient OpenGeni credits\" text (case-insensitive, substring — it\n * arrives both bare and wrapped in \"Activity task failed: …\") and the\n * budget-exhausted segment limit the engine stamps on a turn it ended early.\n */\nexport function isCreditExhaustion(\n input: { error?: string | null; detail?: string | null; segmentLimit?: string | null } | string,\n): boolean {\n if (typeof input === \"string\") {\n return input.toLowerCase().includes(\"insufficient opengeni credits\");\n }\n if (input.segmentLimit === \"budget_exhausted\") {\n return true;\n }\n for (const text of [input.error, input.detail]) {\n if (typeof text === \"string\" && text.toLowerCase().includes(\"insufficient opengeni credits\")) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Humanize engine/provider failure text before it reaches the timeline or a\n * failure banner. Raw provider errors leak the wrong audience's instructions —\n * \"Incorrect API key … find your API key at platform.openai.com\" tells a\n * managed-deployment USER to fix credentials only an OPERATOR controls (and is\n * flatly wrong for Azure or subscription-backed engines). Auth, quota, and\n * credit-exhaustion failures collapse to one neutral, honest sentence; every\n * other reason passes through untouched. Raw payloads stay available in the\n * debug surfaces.\n */\nexport function humanizeFailureReason(reason: string | null): string | null {\n if (!reason) {\n return reason;\n }\n if (isCreditExhaustion(reason)) {\n return CREDIT_EXHAUSTION_MESSAGE;\n }\n const normalized = reason.toLowerCase();\n const authFailure =\n normalized.includes(\"incorrect api key\") ||\n normalized.includes(\"invalid api key\") ||\n normalized.includes(\"invalid_api_key\") ||\n normalized.includes(\"platform.openai.com/account/api-keys\") ||\n (normalized.includes(\"401\") &&\n (normalized.includes(\"api key\") || normalized.includes(\"unauthorized\")));\n if (authFailure) {\n return \"The model provider rejected this deployment's engine credentials. Sending messages won't help until the deployment's engine configuration is fixed.\";\n }\n const quotaFailure =\n normalized.includes(\"insufficient_quota\") || normalized.includes(\"exceeded your current quota\");\n if (quotaFailure) {\n return \"The model provider refused the request: this deployment's provider quota is exhausted.\";\n }\n return reason;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,17 +3,29 @@ import {
|
|
|
3
3
|
humanizeFailureReason,
|
|
4
4
|
isCreditExhaustion,
|
|
5
5
|
tryParseJson
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LAKLF4PA.js";
|
|
7
7
|
|
|
8
|
-
// src/timeline/
|
|
9
|
-
|
|
10
|
-
function toolDisplayName(name) {
|
|
8
|
+
// src/timeline/tool-display-name.ts
|
|
9
|
+
function mcpToolLeaf(name) {
|
|
11
10
|
const boundary = name.indexOf("__");
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
return boundary >= 0 ? name.slice(boundary + 2) : name;
|
|
12
|
+
}
|
|
13
|
+
function toolMatchesLeaf(wireName, leaf) {
|
|
14
|
+
return wireName === leaf || wireName.endsWith(`__${leaf}`);
|
|
15
|
+
}
|
|
16
|
+
function toolDisplayName(name) {
|
|
17
|
+
const phrase = mcpToolLeaf(name).replace(/[_-]+/g, " ").trim();
|
|
18
|
+
if (!phrase) {
|
|
19
|
+
return name;
|
|
20
|
+
}
|
|
21
|
+
return phrase.charAt(0).toUpperCase() + phrase.slice(1);
|
|
14
22
|
}
|
|
23
|
+
|
|
24
|
+
// src/timeline/projection.ts
|
|
25
|
+
var { default: fleetDecisionItem } = await import("./fleet-decision-projection-SLNZMS42.js");
|
|
15
26
|
var WORKER_SPAWN_TOOL = "session_create";
|
|
16
27
|
var WORKER_MESSAGE_TOOL = "session_send_message";
|
|
28
|
+
var LANDMARK_ONLY_TOOL_LEAVES = /* @__PURE__ */ new Set(["memory_save", "memory_correct"]);
|
|
17
29
|
function buildTimeline(events) {
|
|
18
30
|
const items = [];
|
|
19
31
|
const prescan = prescanTurnAnchors(events);
|
|
@@ -125,6 +137,7 @@ function buildTimeline(events) {
|
|
|
125
137
|
open.text = text || open.text;
|
|
126
138
|
}
|
|
127
139
|
open.streaming = false;
|
|
140
|
+
open.occurredAt = event.occurredAt;
|
|
128
141
|
if (openIndex < items.length - 1) {
|
|
129
142
|
items.splice(openIndex, 1);
|
|
130
143
|
items.push(open);
|
|
@@ -169,13 +182,13 @@ function buildTimeline(events) {
|
|
|
169
182
|
const callId = typeof payload.id === "string" ? payload.id : null;
|
|
170
183
|
const args = payload.arguments ?? null;
|
|
171
184
|
closeStreamingTail();
|
|
172
|
-
if (name
|
|
185
|
+
if (toolMatchesLeaf(name, WORKER_SPAWN_TOOL) || toolMatchesLeaf(name, WORKER_MESSAGE_TOOL)) {
|
|
173
186
|
items.push({
|
|
174
187
|
kind: "worker",
|
|
175
188
|
id: event.id,
|
|
176
189
|
turnId,
|
|
177
190
|
callId,
|
|
178
|
-
action: name
|
|
191
|
+
action: toolMatchesLeaf(name, WORKER_SPAWN_TOOL) ? "spawn" : "message",
|
|
179
192
|
prompt: workerPrompt(args),
|
|
180
193
|
workerSessionId: extractSessionRef(args),
|
|
181
194
|
status: "running",
|
|
@@ -183,6 +196,9 @@ function buildTimeline(events) {
|
|
|
183
196
|
});
|
|
184
197
|
break;
|
|
185
198
|
}
|
|
199
|
+
if (LANDMARK_ONLY_TOOL_LEAVES.has(mcpToolLeaf(name))) {
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
186
202
|
if (callId) {
|
|
187
203
|
const existing = [...items].reverse().find(
|
|
188
204
|
(item) => item.kind === "tool-call" && item.callId === callId
|
|
@@ -459,6 +475,9 @@ ${message}` : message;
|
|
|
459
475
|
case "goal.resumed":
|
|
460
476
|
case "goal.cleared":
|
|
461
477
|
case "goal.continuation": {
|
|
478
|
+
if (shouldSuppressAgentGoalLandmark(event.type, payload)) {
|
|
479
|
+
break;
|
|
480
|
+
}
|
|
462
481
|
items.push({
|
|
463
482
|
kind: "goal",
|
|
464
483
|
id: event.id,
|
|
@@ -1016,6 +1035,15 @@ function goalText(payload) {
|
|
|
1016
1035
|
}
|
|
1017
1036
|
return null;
|
|
1018
1037
|
}
|
|
1038
|
+
function shouldSuppressAgentGoalLandmark(type, payload) {
|
|
1039
|
+
if (type === "goal.completed") {
|
|
1040
|
+
return true;
|
|
1041
|
+
}
|
|
1042
|
+
if (type === "goal.set" || type === "goal.updated" || type === "goal.paused") {
|
|
1043
|
+
return payload.actor === "agent";
|
|
1044
|
+
}
|
|
1045
|
+
return false;
|
|
1046
|
+
}
|
|
1019
1047
|
function memoryItem(id, type, turnId, payload, occurredAt) {
|
|
1020
1048
|
const memoryId = typeof payload.memoryId === "string" && payload.memoryId ? payload.memoryId : null;
|
|
1021
1049
|
if (!memoryId) {
|
|
@@ -1121,6 +1149,7 @@ function looksLikeId(value) {
|
|
|
1121
1149
|
}
|
|
1122
1150
|
|
|
1123
1151
|
export {
|
|
1152
|
+
mcpToolLeaf,
|
|
1124
1153
|
toolDisplayName,
|
|
1125
1154
|
buildTimeline,
|
|
1126
1155
|
creditExhaustedFromEvents,
|
|
@@ -1128,4 +1157,4 @@ export {
|
|
|
1128
1157
|
groupTimeline,
|
|
1129
1158
|
extractSessionRef
|
|
1130
1159
|
};
|
|
1131
|
-
//# sourceMappingURL=chunk-
|
|
1160
|
+
//# sourceMappingURL=chunk-MEGI4FS6.js.map
|