@opengeni/react 0.28.2 → 0.32.1
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/approvals.d.ts +14 -0
- package/dist/{chunk-M7X4JZOD.js → chunk-4QOQ2DSR.js} +8 -1
- package/dist/chunk-4QOQ2DSR.js.map +1 -0
- package/dist/{chunk-HQFPO7VX.js → chunk-7CJOAW3V.js} +24 -3
- package/dist/{chunk-HQFPO7VX.js.map → chunk-7CJOAW3V.js.map} +1 -1
- package/dist/{chunk-PMSGE233.js → chunk-A2WITZTI.js} +377 -113
- package/dist/chunk-A2WITZTI.js.map +1 -0
- package/dist/{chunk-BC6RKIHS.js → chunk-GZ4KR67U.js} +11 -11
- package/dist/{chunk-4F2YLLHP.js → chunk-KZRUYCL4.js} +14 -17
- package/dist/chunk-KZRUYCL4.js.map +1 -0
- package/dist/{chunk-OCHBZ2X7.js → chunk-TCCE5ZU5.js} +192 -28
- package/dist/chunk-TCCE5ZU5.js.map +1 -0
- package/dist/chunk-U255M5EZ.js +178 -0
- package/dist/chunk-U255M5EZ.js.map +1 -0
- package/dist/{chunk-XVVQP7A4.js → chunk-WY2QN2CX.js} +2539 -2174
- package/dist/chunk-WY2QN2CX.js.map +1 -0
- package/dist/chunk-ZNNE2VES.js +6413 -0
- package/dist/chunk-ZNNE2VES.js.map +1 -0
- package/dist/client.d.ts +33 -0
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/registry.d.ts +41 -0
- package/dist/commands/types.d.ts +85 -0
- package/dist/components/approval-surface.d.ts +28 -0
- package/dist/components/chat-composer.d.ts +51 -0
- package/dist/components/code-editor.d.ts +43 -0
- package/dist/components/command-palette.d.ts +25 -0
- package/dist/components/composer-transcription-control.d.ts +36 -0
- package/dist/components/composer.d.ts +277 -0
- package/dist/components/copy-button.d.ts +26 -0
- package/dist/components/desktop-viewer.d.ts +85 -0
- package/dist/components/diff-view.d.ts +38 -0
- package/dist/components/enrollment-consent.d.ts +33 -0
- package/dist/components/enrollment-device-flow.d.ts +27 -0
- package/dist/components/file-browser.d.ts +47 -0
- package/dist/components/fleet-tile.d.ts +18 -0
- package/dist/components/human-input-form.d.ts +47 -0
- package/dist/components/machine-card.d.ts +21 -0
- package/dist/components/machine-dock-bar.d.ts +31 -0
- package/dist/components/machine-health-pill.d.ts +9 -0
- package/dist/components/machine-metrics.d.ts +15 -0
- package/dist/components/machine-status-pill.d.ts +54 -0
- package/dist/components/machines/health.d.ts +25 -0
- package/dist/components/machines/machine-detail.d.ts +14 -0
- package/dist/components/machines/metric-history-chart.d.ts +24 -0
- package/dist/components/machines/metric-sparkline.d.ts +9 -0
- package/dist/components/machines/series.d.ts +24 -0
- package/dist/components/machines-dashboard.d.ts +30 -0
- package/dist/components/markdown.d.ts +31 -0
- package/dist/components/message-timeline.d.ts +98 -0
- package/dist/components/model-picker.d.ts +19 -0
- package/dist/components/pierre-diff.d.ts +34 -0
- package/dist/components/pierre-file.d.ts +27 -0
- package/dist/components/queue-draft-policy.d.ts +7 -0
- package/dist/components/queue-surface-implementation.d.ts +20 -0
- package/dist/components/queue-surface-state.d.ts +12 -0
- package/dist/components/queue-surface.d.ts +12 -0
- package/dist/components/sandbox-files.d.ts +49 -0
- package/dist/components/sandbox-terminal.d.ts +123 -0
- package/dist/components/sandbox-workspace.d.ts +128 -0
- package/dist/components/session-chrome.d.ts +70 -0
- package/dist/components/session-status.d.ts +25 -0
- package/dist/components/soften-streaming-markdown.d.ts +13 -0
- package/dist/components/stream-reveal.d.ts +37 -0
- package/dist/components/tip-follow.d.ts +139 -0
- package/dist/components/tooltip.d.ts +16 -0
- package/dist/components/workbench-changes.d.ts +34 -0
- package/dist/components/workspace-dock.d.ts +35 -0
- package/dist/composer.d.ts +11 -7
- package/dist/composer.js +9 -6
- package/dist/hooks/internal.d.ts +46 -0
- package/dist/hooks/use-available-models.d.ts +37 -0
- package/dist/hooks/use-billing-usage.d.ts +26 -0
- package/dist/hooks/use-codex-accounts.d.ts +69 -0
- package/dist/{use-composer-ClHy1rkL.d.ts → hooks/use-composer.d.ts} +16 -24
- package/dist/hooks/use-desktop-stream.d.ts +43 -0
- package/dist/hooks/use-environments.d.ts +35 -0
- package/dist/{use-file-attachments-BmT8WtqO.d.ts → hooks/use-file-attachments.d.ts} +6 -9
- package/dist/hooks/use-goal.d.ts +46 -0
- package/dist/hooks/use-human-input.d.ts +26 -0
- package/dist/hooks/use-last-started-turn-policy.d.ts +27 -0
- package/dist/hooks/use-machine-chip.d.ts +54 -0
- package/dist/hooks/use-machines.d.ts +81 -0
- package/dist/hooks/use-packs.d.ts +27 -0
- package/dist/hooks/use-relay-frame-stream.d.ts +53 -0
- package/dist/hooks/use-rigs.d.ts +87 -0
- package/dist/hooks/use-sandbox-files.d.ts +108 -0
- package/dist/hooks/use-sandbox-git.d.ts +58 -0
- package/dist/hooks/use-sandbox-terminal.d.ts +62 -0
- package/dist/hooks/use-scheduled-tasks.d.ts +15 -0
- package/dist/hooks/use-session-capabilities.d.ts +83 -0
- package/dist/hooks/use-session-control.d.ts +22 -0
- package/dist/hooks/use-session-events.d.ts +92 -0
- package/dist/hooks/use-session-lineage.d.ts +17 -0
- package/dist/hooks/use-session-mcp-approval-policy.d.ts +23 -0
- package/dist/hooks/use-session.d.ts +23 -0
- package/dist/hooks/use-slash-commands.d.ts +66 -0
- package/dist/hooks/use-terminal-stream.d.ts +46 -0
- package/dist/hooks/use-transcription.d.ts +73 -0
- package/dist/hooks/use-turn-queue.d.ts +44 -0
- package/dist/hooks/use-voice-input.d.ts +25 -0
- package/dist/hooks/use-windowed-sections.d.ts +42 -0
- package/dist/hooks/use-workspace-capture.d.ts +49 -0
- package/dist/hooks/use-workspace-edit.d.ts +73 -0
- package/dist/hooks/use-workspace-sessions.d.ts +30 -0
- package/dist/hooks/use-workspaces.d.ts +22 -0
- package/dist/human-input.d.ts +18 -0
- package/dist/index.d.ts +144 -2119
- package/dist/index.js +421 -324
- package/dist/index.js.map +1 -1
- package/dist/lib/clipboard.d.ts +7 -0
- package/dist/lib/cn.d.ts +3 -0
- package/dist/lib/format.d.ts +48 -0
- package/dist/lib/git-patch.d.ts +8 -0
- package/dist/lib/motion-inspect.d.ts +5 -0
- package/dist/lib/motion.d.ts +14 -0
- package/dist/lib/noto-sans-arabic-loader.d.ts +1 -0
- package/dist/lib/noto-sans-jp-loader.generated.d.ts +1 -0
- package/dist/lib/relay-wire.d.ts +30 -0
- package/dist/lib/use-portal-token-style.d.ts +9 -0
- package/dist/lib/use-theme-type.d.ts +5 -0
- package/dist/lib/use-unicode-fonts.d.ts +12 -0
- package/dist/lib/xterm-renderer.d.ts +19 -0
- package/dist/lib/xterm-theme.d.ts +75 -0
- package/dist/machines.d.ts +30 -413
- package/dist/machines.js +3 -3
- package/dist/model-policy.d.ts +32 -0
- package/dist/model-policy.js +33 -0
- package/dist/model-policy.js.map +1 -0
- package/dist/provider.d.ts +16 -0
- package/dist/{queue-surface-implementation-UQ535OKQ.js → queue-surface-implementation-THPAKGMD.js} +2 -2
- package/dist/{queue-surface-implementation-UQ535OKQ.js.map → queue-surface-implementation-THPAKGMD.js.map} +1 -1
- package/dist/session-context.d.ts +82 -0
- package/dist/session-ui.d.ts +10 -7
- package/dist/session-ui.js +9 -5
- package/dist/session.d.ts +28 -6
- package/dist/session.js +11 -11
- package/dist/timeline/activity-rail.d.ts +19 -0
- package/dist/timeline/disclosure-context.d.ts +14 -0
- package/dist/timeline/entrance.d.ts +14 -0
- package/dist/timeline/fleet-decision-projection.d.ts +9 -0
- package/dist/timeline/fleet-decision-row.d.ts +11 -0
- package/dist/timeline/fold-memory.d.ts +15 -0
- package/dist/timeline/index.d.ts +18 -0
- package/dist/timeline/parsers.d.ts +96 -0
- package/dist/timeline/projection.d.ts +38 -0
- package/dist/timeline/registry.d.ts +40 -0
- package/dist/timeline/screenshot-lightbox.d.ts +26 -0
- package/dist/timeline/seen-activity-ids.d.ts +2 -0
- package/dist/timeline/shared.d.ts +125 -0
- package/dist/timeline/tool-diff.d.ts +8 -0
- package/dist/timeline/tool-display-name.d.ts +10 -0
- package/dist/timeline/tool-renderers.d.ts +5 -0
- package/dist/timeline/turn-summary.d.ts +116 -0
- package/dist/{use-turn-queue-Drm_ypue.d.ts → timeline/types.d.ts} +57 -67
- package/dist/types/machines.d.ts +11 -0
- package/package.json +8 -4
- package/src/client.ts +1 -0
- package/src/components/composer-transcription-control.tsx +278 -130
- package/src/components/composer.tsx +20 -15
- package/src/components/copy-button.tsx +127 -0
- package/src/components/markdown.tsx +231 -32
- package/src/components/message-timeline.tsx +1382 -378
- package/src/components/model-picker.tsx +83 -43
- package/src/components/queue-surface-implementation.tsx +1 -1
- package/src/components/session-chrome.tsx +942 -0
- package/src/components/soften-streaming-markdown.ts +205 -0
- package/src/components/stream-reveal.ts +195 -0
- package/src/components/tip-follow.ts +459 -0
- package/src/components/tooltip.tsx +103 -0
- package/src/composer.ts +6 -0
- package/src/hooks/internal.ts +30 -4
- package/src/hooks/use-available-models.ts +51 -4
- package/src/hooks/use-composer.ts +24 -18
- package/src/hooks/use-last-started-turn-policy.ts +95 -0
- package/src/hooks/use-session-events.ts +359 -5
- package/src/hooks/use-voice-input.ts +232 -0
- package/src/index.ts +49 -1
- package/src/lib/clipboard.ts +58 -0
- package/src/lib/format.ts +18 -0
- package/src/lib/motion-inspect.ts +5 -0
- package/src/lib/motion.ts +80 -0
- package/src/model-policy.ts +210 -0
- package/src/session-ui.ts +7 -0
- package/src/session.ts +2 -0
- package/src/timeline/activity-rail.tsx +46 -7
- package/src/timeline/entrance.tsx +10 -0
- package/src/timeline/fold-memory.ts +52 -0
- package/src/timeline/index.ts +11 -1
- package/src/timeline/projection.ts +252 -47
- package/src/timeline/seen-activity-ids.ts +19 -0
- package/src/timeline/shared.tsx +1 -1
- package/src/timeline/tool-renderers.tsx +75 -6
- package/src/timeline/turn-summary.tsx +387 -97
- package/src/timeline/types.ts +47 -0
- package/styles/index.css +99 -7
- package/styles/tokens.css +44 -3
- package/dist/chunk-4F2YLLHP.js.map +0 -1
- package/dist/chunk-M7X4JZOD.js.map +0 -1
- package/dist/chunk-OCHBZ2X7.js.map +0 -1
- package/dist/chunk-PMSGE233.js.map +0 -1
- package/dist/chunk-WAA247AB.js +0 -3858
- package/dist/chunk-WAA247AB.js.map +0 -1
- package/dist/chunk-XVVQP7A4.js.map +0 -1
- package/dist/composer-BMzimGTO.d.ts +0 -528
- package/dist/session-C3tIXLim.d.ts +0 -264
- package/dist/session-context-CAjlaeZb.d.ts +0 -84
- package/dist/session-ui-B_7cfN5u.d.ts +0 -259
- /package/dist/{chunk-BC6RKIHS.js.map → chunk-GZ4KR67U.js.map} +0 -0
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ChevronRightIcon, CircleSlashIcon, TriangleAlertIcon } from "lucide-react";
|
|
2
|
+
import {
|
|
3
|
+
Component,
|
|
4
|
+
createContext,
|
|
5
|
+
useContext,
|
|
6
|
+
useEffect,
|
|
7
|
+
useMemo,
|
|
8
|
+
useRef,
|
|
9
|
+
useState,
|
|
10
|
+
type ReactNode,
|
|
11
|
+
} from "react";
|
|
3
12
|
import { Collapsible } from "radix-ui";
|
|
13
|
+
import { CopyButton } from "../components/copy-button";
|
|
4
14
|
import { cn } from "../lib/cn";
|
|
15
|
+
import { MOTION_INSPECT_SCALE } from "../lib/motion-inspect";
|
|
5
16
|
import { useForcedDefaultOpen } from "./disclosure-context";
|
|
6
17
|
import { useEntranceAnimation } from "./entrance";
|
|
18
|
+
import { useFoldMemory, type FoldRestingState } from "./fold-memory";
|
|
7
19
|
import { applyPatchOps, isApplyPatch, mediaPreviewFact, screenshotDataUrl } from "./parsers";
|
|
8
20
|
import { rawTypeOf } from "./registry";
|
|
9
21
|
import type { ActivityItem, ToolCallItem, TurnOutcome } from "./types";
|
|
@@ -14,19 +26,33 @@ export type { TurnOutcome } from "./types";
|
|
|
14
26
|
|
|
15
27
|
A completed (or failed/cancelled) turn folds behind one quiet summary chip:
|
|
16
28
|
"N steps · M files · K commands · 1 screenshot · 4m". The chip is the default
|
|
17
|
-
surface; expanding it reveals the full settled turn body.
|
|
18
|
-
|
|
29
|
+
surface; expanding it reveals the full settled turn body. Top-level live
|
|
30
|
+
activity keeps the same open shell so settling never remounts the rail into
|
|
31
|
+
a brand-new wrapper (that remount was the hard yank).
|
|
19
32
|
|
|
20
33
|
This keeps the timeline calm: a finished turn is a single line until the
|
|
21
34
|
reader chooses to look inside it.
|
|
22
35
|
-------------------------------------------------------------------------- */
|
|
23
36
|
|
|
37
|
+
const TurnSettleChromeContext = createContext(false);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* True while settle chrome is active (open beat, slow collapse, or the short
|
|
41
|
+
* cancel-close latch). Nested cluster chips stay mounted and forced OPEN for
|
|
42
|
+
* this window so the body keeps a stable height — never flat-map to bare
|
|
43
|
+
* rails, and never remount closed nested chips mid-collapse (that yanked).
|
|
44
|
+
*/
|
|
45
|
+
export function useTurnSettleOpen(): boolean {
|
|
46
|
+
return useContext(TurnSettleChromeContext);
|
|
47
|
+
}
|
|
48
|
+
|
|
24
49
|
export const BUILT_IN_TURN_SUMMARY_FACET_IDS = [
|
|
25
50
|
"steps",
|
|
26
51
|
"files",
|
|
27
52
|
"commands",
|
|
28
53
|
"screenshots",
|
|
29
54
|
"memories",
|
|
55
|
+
"compacted",
|
|
30
56
|
"duration",
|
|
31
57
|
] as const;
|
|
32
58
|
|
|
@@ -45,6 +71,11 @@ export type TurnSummaryContext = Readonly<{
|
|
|
45
71
|
durationMs: number | undefined;
|
|
46
72
|
/** False when any projected activity is still running or streaming. */
|
|
47
73
|
settled: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Adjacent compaction landmarks next to this fold. Landmark remains the
|
|
76
|
+
* primary UI; this is a secondary chip signal only.
|
|
77
|
+
*/
|
|
78
|
+
contextCompactionCount: number;
|
|
48
79
|
}>;
|
|
49
80
|
|
|
50
81
|
export type TurnSummaryFacetResult = Readonly<{
|
|
@@ -106,10 +137,45 @@ export type TurnSummaryProps = {
|
|
|
106
137
|
bare?: boolean | undefined;
|
|
107
138
|
/** Per-instance facet customization. Omit to preserve the built-in summary exactly. */
|
|
108
139
|
facets?: TurnSummaryFacetConfiguration | undefined;
|
|
140
|
+
/**
|
|
141
|
+
* Settle choreography: this fold replaced rows the reader was just watching
|
|
142
|
+
* live. Instead of yanking them behind a chip in one frame, the fold mounts
|
|
143
|
+
* OPEN with the summary chip easing in above the still-visible rows, holds a
|
|
144
|
+
* short beat so the reader registers the settle, then glides closed. Any
|
|
145
|
+
* user interaction during the beat cancels the auto-collapse. Captured at
|
|
146
|
+
* mount; ignored when the fold starts expanded (e.g. a failed turn).
|
|
147
|
+
*/
|
|
148
|
+
settleFold?: boolean | undefined;
|
|
149
|
+
/**
|
|
150
|
+
* Durable identity (timeline group id) for cross-remount fold memory. When
|
|
151
|
+
* an ancestor provides a {@link FoldMemoryProvider} map, reaching a resting
|
|
152
|
+
* state is recorded under this key: "closed" when the settle choreography
|
|
153
|
+
* completes its collapse or the reader closes the chip, "open" when the
|
|
154
|
+
* reader expands it. A later remount under the same key restores that
|
|
155
|
+
* resting state and never replays the open settle beat — the activity→turn
|
|
156
|
+
* wrap and the nested force-open during settle chrome must not re-expand a
|
|
157
|
+
* fold that already settled closed.
|
|
158
|
+
*/
|
|
159
|
+
foldKey?: string | undefined;
|
|
160
|
+
/**
|
|
161
|
+
* When set, a hover/focus copy control sits on the chip row (outside the
|
|
162
|
+
* disclosure trigger) so the reader can copy the turn's assistant prose
|
|
163
|
+
* without toggling the fold.
|
|
164
|
+
*/
|
|
165
|
+
copyText?: string | undefined;
|
|
166
|
+
/** Adjacent compaction landmark count for the secondary chip facet. */
|
|
167
|
+
contextCompactionCount?: number | undefined;
|
|
109
168
|
/** The rendered activity rail revealed on expand. */
|
|
110
169
|
children: ReactNode;
|
|
111
170
|
};
|
|
112
171
|
|
|
172
|
+
/** How long a settling fold stays open before gliding closed. */
|
|
173
|
+
const SETTLE_FOLD_BEAT_MS = 1100 * MOTION_INSPECT_SCALE;
|
|
174
|
+
/** Keep in sync with `--og-duration-disclose-settle`. */
|
|
175
|
+
const SETTLE_COLLAPSE_MS = 820 * MOTION_INSPECT_SCALE;
|
|
176
|
+
/** Keep in sync with `--og-duration-disclose` (manual / cancel-close). */
|
|
177
|
+
const DISCLOSE_MS = 120 * MOTION_INSPECT_SCALE;
|
|
178
|
+
|
|
113
179
|
export function TurnSummary({
|
|
114
180
|
items,
|
|
115
181
|
outcome,
|
|
@@ -118,16 +184,176 @@ export function TurnSummary({
|
|
|
118
184
|
defaultOpen,
|
|
119
185
|
bare,
|
|
120
186
|
facets: facetConfiguration,
|
|
187
|
+
settleFold,
|
|
188
|
+
foldKey,
|
|
189
|
+
copyText,
|
|
190
|
+
contextCompactionCount,
|
|
121
191
|
children,
|
|
122
192
|
}: TurnSummaryProps) {
|
|
123
193
|
// An explicit `defaultOpen` always wins; otherwise an ancestor may seed it
|
|
124
194
|
// (screenshot instrumentation); otherwise the turn starts folded.
|
|
125
195
|
const forcedDefaultOpen = useForcedDefaultOpen();
|
|
126
|
-
const
|
|
196
|
+
const foldMemory = useFoldMemory();
|
|
197
|
+
// A remembered resting state outranks author defaults: a fold that already
|
|
198
|
+
// finished its settle collapse (or that the reader closed) mounts closed
|
|
199
|
+
// even when a remount asks for the settle beat or a forced defaultOpen —
|
|
200
|
+
// and one the reader expanded mounts open instead of snapping shut.
|
|
201
|
+
const remembered = foldKey !== undefined ? foldMemory?.get(foldKey) : undefined;
|
|
202
|
+
const restingOpen =
|
|
203
|
+
remembered === "closed"
|
|
204
|
+
? false
|
|
205
|
+
: remembered === "open"
|
|
206
|
+
? true
|
|
207
|
+
: (defaultOpen ?? forcedDefaultOpen ?? false);
|
|
208
|
+
const initialSettle = Boolean(settleFold) && !restingOpen && remembered === undefined;
|
|
209
|
+
const [settling, setSettling] = useState(initialSettle);
|
|
210
|
+
const [open, setOpen] = useState(initialSettle ? true : restingOpen);
|
|
211
|
+
// While true, a close uses the slow settle collapse. Cleared after that
|
|
212
|
+
// auto-collapse finishes (or on first user interaction) so later manual
|
|
213
|
+
// closes are the fast disclose pair.
|
|
214
|
+
const [settlePhase, setSettlePhase] = useState(initialSettle);
|
|
215
|
+
// Separate from settlePhase CSS: keep nested chips force-open through
|
|
216
|
+
// cancel-close (fast collapse) without forcing the slow settle-collapse.
|
|
217
|
+
const [nestSuppressLatch, setNestSuppressLatch] = useState(initialSettle);
|
|
218
|
+
// Expand animation must NOT run on the settle mount (rows were already
|
|
219
|
+
// visible — a height sweep would flash them). Armed once we leave that
|
|
220
|
+
// initial open, so a later manual reopen animates instead of snapping.
|
|
221
|
+
const [expandReady, setExpandReady] = useState(!initialSettle);
|
|
222
|
+
const settleTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
223
|
+
const settleCloseDoneRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
224
|
+
const nestLatchClearRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
225
|
+
const settleFoldSeenRef = useRef(Boolean(settleFold));
|
|
226
|
+
const settleArmedRef = useRef(false);
|
|
227
|
+
const clearNestLatchTimer = () => {
|
|
228
|
+
if (nestLatchClearRef.current !== null) {
|
|
229
|
+
clearTimeout(nestLatchClearRef.current);
|
|
230
|
+
nestLatchClearRef.current = null;
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
const clearSettleTimers = () => {
|
|
234
|
+
if (settleTimerRef.current !== null) {
|
|
235
|
+
clearTimeout(settleTimerRef.current);
|
|
236
|
+
settleTimerRef.current = null;
|
|
237
|
+
}
|
|
238
|
+
if (settleCloseDoneRef.current !== null) {
|
|
239
|
+
clearTimeout(settleCloseDoneRef.current);
|
|
240
|
+
settleCloseDoneRef.current = null;
|
|
241
|
+
}
|
|
242
|
+
clearNestLatchTimer();
|
|
243
|
+
};
|
|
244
|
+
const rememberResting = (state: FoldRestingState) => {
|
|
245
|
+
if (foldKey !== undefined && foldMemory) {
|
|
246
|
+
foldMemory.set(foldKey, state);
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
const armSettleCollapse = () => {
|
|
250
|
+
if (settleArmedRef.current) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
settleArmedRef.current = true;
|
|
254
|
+
setSettling(true);
|
|
255
|
+
setSettlePhase(true);
|
|
256
|
+
setNestSuppressLatch(true);
|
|
257
|
+
setExpandReady(false);
|
|
258
|
+
setOpen(true);
|
|
259
|
+
clearSettleTimers();
|
|
260
|
+
settleTimerRef.current = setTimeout(() => {
|
|
261
|
+
settleTimerRef.current = null;
|
|
262
|
+
setExpandReady(true);
|
|
263
|
+
setOpen(false);
|
|
264
|
+
// The glide toward closed IS the choreography completing — record it
|
|
265
|
+
// now, so a wrap that lands mid-collapse still remounts this fold shut.
|
|
266
|
+
rememberResting("closed");
|
|
267
|
+
settleCloseDoneRef.current = setTimeout(() => {
|
|
268
|
+
settleCloseDoneRef.current = null;
|
|
269
|
+
settleArmedRef.current = false;
|
|
270
|
+
setSettlePhase(false);
|
|
271
|
+
setSettling(false);
|
|
272
|
+
setNestSuppressLatch(false);
|
|
273
|
+
}, SETTLE_COLLAPSE_MS);
|
|
274
|
+
}, SETTLE_FOLD_BEAT_MS);
|
|
275
|
+
};
|
|
276
|
+
const mountSettleRef = useRef(initialSettle);
|
|
277
|
+
// Mount-time settle (new turn wrap).
|
|
278
|
+
// Mount-once settle arm + unmount timer cleanup — re-running on foldMemory
|
|
279
|
+
// identity churn would restart the beat mid-choreography.
|
|
280
|
+
useEffect(() => {
|
|
281
|
+
if (mountSettleRef.current) {
|
|
282
|
+
armSettleCollapse();
|
|
283
|
+
}
|
|
284
|
+
return () => {
|
|
285
|
+
clearSettleTimers();
|
|
286
|
+
settleArmedRef.current = false;
|
|
287
|
+
};
|
|
288
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
|
289
|
+
}, []);
|
|
290
|
+
// Live shell already open: settleFold rises later without remounting.
|
|
291
|
+
// Do not require !restingOpen — live shells mount with defaultOpen and
|
|
292
|
+
// only later receive settleFold. Failed turns mount with both at once
|
|
293
|
+
// (seen=true), so they never take this edge.
|
|
294
|
+
// Edge-trigger on settleFold only; foldMemory/foldKey are reopen guards.
|
|
295
|
+
useEffect(() => {
|
|
296
|
+
const was = settleFoldSeenRef.current;
|
|
297
|
+
settleFoldSeenRef.current = Boolean(settleFold);
|
|
298
|
+
if (!was && settleFold) {
|
|
299
|
+
// A remembered resting state means this fold's story already resolved
|
|
300
|
+
// once (choreography closed it, or the reader chose a state). Replaying
|
|
301
|
+
// the open beat would re-expand it — the exact reopen this guards.
|
|
302
|
+
if (foldKey !== undefined && foldMemory?.get(foldKey) !== undefined) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
armSettleCollapse();
|
|
306
|
+
}
|
|
307
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
|
308
|
+
}, [settleFold]);
|
|
309
|
+
const onOpenChange = (next: boolean) => {
|
|
310
|
+
// The reader took over — cancel the pending auto-collapse for good.
|
|
311
|
+
// Clear settle CSS phase immediately (fast collapse) but keep nest latch
|
|
312
|
+
// through the disclose window so nested chips stay force-open mid-close
|
|
313
|
+
// (remounting them closed here yanks height).
|
|
314
|
+
const wasNestFlat = settling || settlePhase || nestSuppressLatch;
|
|
315
|
+
clearSettleTimers();
|
|
316
|
+
settleArmedRef.current = false;
|
|
317
|
+
rememberResting(next ? "open" : "closed");
|
|
318
|
+
setExpandReady(true);
|
|
319
|
+
setSettlePhase(false);
|
|
320
|
+
setSettling(false);
|
|
321
|
+
if (next) {
|
|
322
|
+
setNestSuppressLatch(false);
|
|
323
|
+
setOpen(true);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
setOpen(false);
|
|
327
|
+
if (wasNestFlat) {
|
|
328
|
+
setNestSuppressLatch(true);
|
|
329
|
+
nestLatchClearRef.current = setTimeout(() => {
|
|
330
|
+
nestLatchClearRef.current = null;
|
|
331
|
+
setNestSuppressLatch(false);
|
|
332
|
+
}, DISCLOSE_MS);
|
|
333
|
+
} else {
|
|
334
|
+
setNestSuppressLatch(false);
|
|
335
|
+
}
|
|
336
|
+
};
|
|
127
337
|
const enter = useEntranceAnimation();
|
|
338
|
+
// Capture once: after a settle choreography the chip is already on screen.
|
|
339
|
+
// Re-applying `animate-og-enter` when `settling` clears was the post-collapse
|
|
340
|
+
// flash (opacity replay on the summary row).
|
|
341
|
+
const [allowEnterAnimation] = useState(() =>
|
|
342
|
+
Boolean(enter && !bare && !initialSettle && !restingOpen),
|
|
343
|
+
);
|
|
344
|
+
// Hold duration (and its "· 8s" insertion) until settle choreography finishes.
|
|
345
|
+
// Surfacing it mid-beat or on the activity→turn remount made the chip text
|
|
346
|
+
// reflow twice and read as another flash after the fold.
|
|
128
347
|
const context = useMemo(
|
|
129
|
-
() =>
|
|
130
|
-
|
|
348
|
+
() =>
|
|
349
|
+
createTurnSummaryContext(
|
|
350
|
+
items,
|
|
351
|
+
outcome,
|
|
352
|
+
failureText,
|
|
353
|
+
settling || settlePhase ? undefined : durationMs,
|
|
354
|
+
contextCompactionCount ?? 0,
|
|
355
|
+
),
|
|
356
|
+
[items, outcome, failureText, durationMs, settling, settlePhase, contextCompactionCount],
|
|
131
357
|
);
|
|
132
358
|
const facetDefinitions = useMemo(
|
|
133
359
|
() => resolveTurnSummaryFacets(facetConfiguration),
|
|
@@ -148,104 +374,152 @@ export function TurnSummary({
|
|
|
148
374
|
[context, facetDefinitions],
|
|
149
375
|
);
|
|
150
376
|
|
|
377
|
+
// Live open shell: keep the chip in-flow (so settle never inserts layout)
|
|
378
|
+
// but quiet it until there is an outcome or a settle beat.
|
|
379
|
+
const liveShell = outcome === undefined && open && !settlePhase && !bare;
|
|
380
|
+
// Settle CSS phase OR cancel-close latch — see useTurnSettleOpen.
|
|
381
|
+
// Nested chips stay force-open for this window (stable height).
|
|
382
|
+
const settleChrome = settling || settlePhase || nestSuppressLatch;
|
|
383
|
+
|
|
384
|
+
// Copy only on the collapsed chip — when open, per-message copy is enough
|
|
385
|
+
// and a second control on the summary row felt crowded / off.
|
|
386
|
+
const copyable = Boolean(
|
|
387
|
+
copyText && copyText.trim().length > 0 && !bare && !liveShell && !open && !settlePhase,
|
|
388
|
+
);
|
|
389
|
+
|
|
151
390
|
return (
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
// FLAT rail row — chevron + glyph + facets on the page background, no
|
|
161
|
-
// border, no fill. Only a hover tint hints the row is expandable, so a
|
|
162
|
-
// collapsed turn never reads as a boxed card. The top-level row is a
|
|
163
|
-
// touch larger (base text, size-5 glyph, wider gap) so it still reads
|
|
164
|
-
// as a turn landmark above the nested cluster rows it groups.
|
|
165
|
-
"group flex w-full items-center rounded-og-sm text-left transition-colors",
|
|
166
|
-
// A folded turn is a touch target on coarse pointers: grow the row so it
|
|
167
|
-
// clears the 40px minimum without disturbing the calm desktop rhythm.
|
|
168
|
-
"pointer-coarse:py-2.5",
|
|
169
|
-
bare
|
|
170
|
-
? "gap-2 px-1.5 py-1.5 text-og-sm text-og-fg-muted"
|
|
171
|
-
: "-mx-2 gap-2.5 px-2 py-1.5 text-og-base text-og-fg-muted",
|
|
172
|
-
// A failed fold keeps its red accent (glyph + inline reason below) and a
|
|
173
|
-
// faint red hover wash so attention still lands there; every other
|
|
174
|
-
// outcome gets the neutral surface hover.
|
|
175
|
-
outcome === "failed"
|
|
176
|
-
? "hover:bg-og-status-failed/[0.06] hover:text-og-fg"
|
|
177
|
-
: "hover:bg-og-surface-1 hover:text-og-fg",
|
|
178
|
-
)}
|
|
179
|
-
>
|
|
180
|
-
{/* Disclosure grammar matches the rows: chevron leads (far left), then the
|
|
181
|
-
outcome glyph, then the facets — one expand affordance side everywhere. */}
|
|
182
|
-
<ChevronRightIcon className="size-3.5 shrink-0 text-og-fg-subtle transition-transform duration-150 group-data-[state=open]:rotate-90" />
|
|
183
|
-
{/* The outcome glyph carries the state by hue alone — no filled circle, no
|
|
184
|
-
card. A clean (complete) run draws a bare muted check; a failed one a
|
|
185
|
-
red triangle; a cancelled one a muted slash; a still-running cluster a
|
|
186
|
-
quiet pulse dot in the glyph's place so alignment holds. */}
|
|
187
|
-
<span
|
|
188
|
-
className={cn(
|
|
189
|
-
"inline-flex shrink-0 items-center justify-center",
|
|
190
|
-
bare ? "size-3.5" : "size-5",
|
|
191
|
-
outcome === "failed" ? "text-og-status-failed" : "text-og-fg-subtle",
|
|
192
|
-
)}
|
|
391
|
+
<TurnSettleChromeContext.Provider value={settleChrome}>
|
|
392
|
+
<div className={cn(copyable && "group/copy relative")}>
|
|
393
|
+
<Collapsible.Root
|
|
394
|
+
open={open}
|
|
395
|
+
onOpenChange={onOpenChange}
|
|
396
|
+
// History-only entrance. Never toggle this on after mount — see
|
|
397
|
+
// allowEnterAnimation. Settle uses animate-og-settle-chip on the trigger.
|
|
398
|
+
className={allowEnterAnimation && !liveShell ? "animate-og-enter" : undefined}
|
|
193
399
|
>
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
400
|
+
<Collapsible.Trigger
|
|
401
|
+
className={cn(
|
|
402
|
+
settling && "animate-og-settle-chip",
|
|
403
|
+
// Top-level turn fold and (when used) nested cluster folds render as
|
|
404
|
+
// FLAT rail rows — chevron + glyph + facets on the page background, no
|
|
405
|
+
// border, no fill. Only a hover tint hints the row is expandable, so a
|
|
406
|
+
// collapsed turn never reads as a boxed card. The top-level row is a
|
|
407
|
+
// touch larger (base text, size-5 glyph, wider gap) so it still reads
|
|
408
|
+
// as a turn landmark above any nested cluster rows it groups.
|
|
409
|
+
"group flex w-full items-center rounded-og-sm text-left transition-colors",
|
|
410
|
+
// A folded turn is a touch target on coarse pointers: grow the row so it
|
|
411
|
+
// clears the 40px minimum without disturbing the calm desktop rhythm.
|
|
412
|
+
"pointer-coarse:py-2.5",
|
|
413
|
+
bare
|
|
414
|
+
? "gap-2 px-1.5 py-1.5 text-og-sm text-og-fg-muted"
|
|
415
|
+
: "-mx-2 gap-2.5 px-2 py-1.5 text-og-base text-og-fg-muted",
|
|
416
|
+
// A failed fold keeps its red accent (glyph + inline reason below) and a
|
|
417
|
+
// faint red hover wash so attention still lands there; every other
|
|
418
|
+
// outcome gets the neutral surface hover.
|
|
419
|
+
outcome === "failed"
|
|
420
|
+
? "hover:bg-og-status-failed/[0.06] hover:text-og-fg"
|
|
421
|
+
: "hover:bg-og-surface-1 hover:text-og-fg",
|
|
422
|
+
liveShell && "pointer-events-none text-og-fg-subtle",
|
|
423
|
+
)}
|
|
424
|
+
>
|
|
425
|
+
{/* Disclosure grammar matches the rows: chevron leads (far left), then any
|
|
426
|
+
exceptional or active state, then the facets — one expand affordance
|
|
427
|
+
side everywhere. */}
|
|
428
|
+
<ChevronRightIcon
|
|
429
|
+
className={cn(
|
|
430
|
+
"size-3.5 shrink-0 text-og-fg-subtle transition-transform ease-og-in-out group-data-[state=open]:rotate-90",
|
|
431
|
+
settlePhase
|
|
432
|
+
? "duration-[var(--og-duration-disclose-settle)]"
|
|
433
|
+
: "duration-[var(--og-duration-disclose)]",
|
|
434
|
+
)}
|
|
435
|
+
/>
|
|
436
|
+
{/* Completion is the quiet default and needs no repeated glyph. Failed,
|
|
437
|
+
cancelled, and still-running folds retain a visible state marker. */}
|
|
438
|
+
{outcome === "complete" ? null : (
|
|
439
|
+
<span
|
|
440
|
+
className={cn(
|
|
441
|
+
"inline-flex shrink-0 items-center justify-center",
|
|
442
|
+
bare ? "size-3.5" : "size-5",
|
|
443
|
+
outcome === "failed" ? "text-og-status-failed" : "text-og-fg-subtle",
|
|
444
|
+
)}
|
|
445
|
+
>
|
|
446
|
+
{outcome === "failed" ? (
|
|
447
|
+
<TriangleAlertIcon className="size-3" />
|
|
448
|
+
) : outcome === "cancelled" ? (
|
|
449
|
+
<CircleSlashIcon className="size-3" />
|
|
450
|
+
) : (
|
|
451
|
+
<span className="size-1.5 animate-og-pulse rounded-full bg-og-fg-subtle" />
|
|
452
|
+
)}
|
|
453
|
+
</span>
|
|
454
|
+
)}
|
|
455
|
+
<span
|
|
456
|
+
className={cn("min-w-0 flex-1 truncate", bare ? "text-og-sm" : "text-og-fg-muted")}
|
|
457
|
+
>
|
|
458
|
+
{facets.map(({ facet, result }, index) => (
|
|
459
|
+
<FacetRenderBoundary key={facet.id}>
|
|
460
|
+
<>
|
|
461
|
+
{index > 0 ? " · " : null}
|
|
462
|
+
<span aria-label={result.ariaLabel} title={result.title}>
|
|
463
|
+
{result.icon ? (
|
|
464
|
+
<span aria-hidden className="mr-1 inline-flex align-[-0.125em]">
|
|
465
|
+
{result.icon}
|
|
466
|
+
</span>
|
|
467
|
+
) : null}
|
|
468
|
+
{result.content}
|
|
213
469
|
</span>
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
) : null}
|
|
226
|
-
</span>
|
|
227
|
-
{/* The disclosure hint. Calm at rest on fine pointers (revealed on hover
|
|
470
|
+
</>
|
|
471
|
+
</FacetRenderBoundary>
|
|
472
|
+
))}
|
|
473
|
+
{outcome === "failed" && failureText ? (
|
|
474
|
+
<span className="text-og-status-failed"> · {failureText}</span>
|
|
475
|
+
) : null}
|
|
476
|
+
{outcome === "cancelled" ? (
|
|
477
|
+
<span className="text-og-fg-subtle"> · interrupted</span>
|
|
478
|
+
) : null}
|
|
479
|
+
</span>
|
|
480
|
+
{/* The disclosure hint. Calm at rest on fine pointers (revealed on hover
|
|
228
481
|
and keyboard focus), but always present on coarse pointers where there
|
|
229
482
|
is no hover to lean on — so the fold never reads as a static status
|
|
230
483
|
line. Purely visual: the trigger's aria-expanded already conveys state
|
|
231
484
|
to assistive tech, so the hint is hidden from the accessible name. */}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
485
|
+
<span
|
|
486
|
+
aria-hidden
|
|
487
|
+
className={cn(
|
|
488
|
+
"ml-auto shrink-0 pl-2 text-og-xs text-og-fg-subtle transition-opacity duration-150",
|
|
489
|
+
// Leave a sliver so a collapsed-chip copy icon can sit outside.
|
|
490
|
+
copyable ? "pr-8" : null,
|
|
491
|
+
"opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100",
|
|
492
|
+
"pointer-coarse:opacity-100",
|
|
493
|
+
)}
|
|
494
|
+
>
|
|
495
|
+
{open ? "hide steps" : "show steps"}
|
|
496
|
+
</span>
|
|
497
|
+
</Collapsible.Trigger>
|
|
498
|
+
<Collapsible.Content
|
|
499
|
+
data-og-fold-content=""
|
|
500
|
+
className={cn(
|
|
501
|
+
"overflow-hidden",
|
|
502
|
+
expandReady && "data-[state=open]:animate-og-expand",
|
|
503
|
+
// Auto-close: slow settle. Manual close (settlePhase cleared): fast.
|
|
504
|
+
settlePhase
|
|
505
|
+
? "data-[state=closed]:animate-og-settle-collapse"
|
|
506
|
+
: "data-[state=closed]:animate-og-collapse",
|
|
507
|
+
)}
|
|
508
|
+
>
|
|
509
|
+
{/* A nested node indents its revealed rows under the glyph (thread nesting
|
|
245
510
|
off the parent rail); the top-level turn body owns its own rail. */}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
511
|
+
<div className={bare ? "pt-1 pl-5" : "pt-2"}>{children}</div>
|
|
512
|
+
</Collapsible.Content>
|
|
513
|
+
</Collapsible.Root>
|
|
514
|
+
{copyable ? (
|
|
515
|
+
<div className="pointer-events-none absolute top-1.5 right-0 z-10">
|
|
516
|
+
<div className="pointer-events-auto">
|
|
517
|
+
<CopyButton text={copyText!} label="Copy turn" reveal="group-hover" />
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
520
|
+
) : null}
|
|
521
|
+
</div>
|
|
522
|
+
</TurnSettleChromeContext.Provider>
|
|
249
523
|
);
|
|
250
524
|
}
|
|
251
525
|
|
|
@@ -254,6 +528,7 @@ function createTurnSummaryContext(
|
|
|
254
528
|
outcome: TurnOutcome | undefined,
|
|
255
529
|
failureText: string | undefined,
|
|
256
530
|
durationMs: number | undefined,
|
|
531
|
+
contextCompactionCount: number,
|
|
257
532
|
): TurnSummaryContext {
|
|
258
533
|
const itemSnapshot = Object.freeze([...items]);
|
|
259
534
|
const toolCalls = Object.freeze(
|
|
@@ -275,6 +550,7 @@ function createTurnSummaryContext(
|
|
|
275
550
|
failureText,
|
|
276
551
|
durationMs,
|
|
277
552
|
settled,
|
|
553
|
+
contextCompactionCount: Math.max(0, Math.floor(contextCompactionCount)),
|
|
278
554
|
});
|
|
279
555
|
}
|
|
280
556
|
|
|
@@ -352,6 +628,20 @@ const BUILT_IN_TURN_SUMMARY_FACETS: readonly TurnSummaryFacet[] = Object.freeze(
|
|
|
352
628
|
return parts.length > 0 ? { content: parts.join(" · ") } : null;
|
|
353
629
|
},
|
|
354
630
|
},
|
|
631
|
+
{
|
|
632
|
+
id: "compacted",
|
|
633
|
+
summarize: ({ contextCompactionCount }) =>
|
|
634
|
+
contextCompactionCount > 0
|
|
635
|
+
? {
|
|
636
|
+
content:
|
|
637
|
+
contextCompactionCount === 1 ? "compacted" : `${contextCompactionCount} compacts`,
|
|
638
|
+
ariaLabel:
|
|
639
|
+
contextCompactionCount === 1
|
|
640
|
+
? "Conversation memory compacted"
|
|
641
|
+
: `${contextCompactionCount} conversation memory compactions`,
|
|
642
|
+
}
|
|
643
|
+
: null,
|
|
644
|
+
},
|
|
355
645
|
{
|
|
356
646
|
id: "duration",
|
|
357
647
|
summarize: ({ durationMs }) => {
|
package/src/timeline/types.ts
CHANGED
|
@@ -226,6 +226,49 @@ export type NoticeItem = {
|
|
|
226
226
|
occurredAt: string;
|
|
227
227
|
};
|
|
228
228
|
|
|
229
|
+
/**
|
|
230
|
+
* First-class conversation-memory checkpoint. Stays outside collapsed turns so
|
|
231
|
+
* auto-compaction cannot vanish behind a chevron. Chat bubbles are unchanged.
|
|
232
|
+
*/
|
|
233
|
+
export type ContextCompactionItem = {
|
|
234
|
+
kind: "context-compaction";
|
|
235
|
+
id: string;
|
|
236
|
+
turnId: string | null;
|
|
237
|
+
phase: "started" | "compacted" | "skipped";
|
|
238
|
+
trigger: "auto" | "operator" | "proactive" | "overflow" | null;
|
|
239
|
+
estimatedTokensBefore: number | null;
|
|
240
|
+
estimatedTokensAfter: number | null;
|
|
241
|
+
skipReason: string | null;
|
|
242
|
+
/** Provider implementation id for debug disclosure only. */
|
|
243
|
+
implementation: string | null;
|
|
244
|
+
occurredAt: string;
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
export type MachineInputMember = {
|
|
248
|
+
id: string;
|
|
249
|
+
kind:
|
|
250
|
+
| "scheduled_occurrence"
|
|
251
|
+
| "goal_continuation"
|
|
252
|
+
| "agent_message"
|
|
253
|
+
| "agent_steer_instruction"
|
|
254
|
+
| "child_terminal_result";
|
|
255
|
+
classification: "success" | "failure" | "action_required" | "info";
|
|
256
|
+
sourceId: string;
|
|
257
|
+
summary: string;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* One or more durable non-human inputs that joined the following agent turn.
|
|
262
|
+
* This is communication, not a warning or a protocol-debug payload.
|
|
263
|
+
*/
|
|
264
|
+
export type MachineInputBatchItem = {
|
|
265
|
+
kind: "machine-input-batch";
|
|
266
|
+
id: string;
|
|
267
|
+
turnId: string | null;
|
|
268
|
+
members: MachineInputMember[];
|
|
269
|
+
occurredAt: string;
|
|
270
|
+
};
|
|
271
|
+
|
|
229
272
|
/**
|
|
230
273
|
* A tool call hit a missing or lapsed connection. The broker reports that
|
|
231
274
|
* condition as a tool error and the turn continues; reconnecting never resumes
|
|
@@ -278,6 +321,8 @@ export type TimelineItem =
|
|
|
278
321
|
| SessionStatusItem
|
|
279
322
|
| GoalItem
|
|
280
323
|
| NoticeItem
|
|
324
|
+
| ContextCompactionItem
|
|
325
|
+
| MachineInputBatchItem
|
|
281
326
|
| AuthNeededItem
|
|
282
327
|
| MemoryItem
|
|
283
328
|
| FleetDecisionItem
|
|
@@ -309,4 +354,6 @@ export type TimelineGroup =
|
|
|
309
354
|
startedAt: string;
|
|
310
355
|
endedAt: string;
|
|
311
356
|
groups: TimelineGroup[];
|
|
357
|
+
/** Adjacent compaction landmark just before this fold (secondary chip facet). */
|
|
358
|
+
contextCompactionCount?: number;
|
|
312
359
|
};
|