@golba98/codexa 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/README.md +17 -18
  2. package/bin/codexa.js +62 -144
  3. package/package.json +4 -3
  4. package/src/app.tsx +642 -303
  5. package/src/commands/handler.ts +7 -18
  6. package/src/config/buildInfo.ts +2 -2
  7. package/src/config/layeredConfig.ts +1 -1
  8. package/src/config/runtimeConfig.ts +1 -1
  9. package/src/config/settings.ts +1 -1
  10. package/src/config/trustStore.ts +1 -1
  11. package/src/core/README.md +52 -0
  12. package/src/core/agent/loop.ts +282 -0
  13. package/src/core/agent/protocol.ts +211 -0
  14. package/src/core/agent/tools.ts +414 -0
  15. package/src/core/{codexExecArgs.ts → codex/codexExecArgs.ts} +2 -2
  16. package/src/core/{codexLaunch.ts → codex/codexLaunch.ts} +3 -3
  17. package/src/core/{codexPrompt.ts → codex/codexPrompt.ts} +3 -3
  18. package/src/core/debug/modelStateDebug.ts +34 -0
  19. package/src/core/executables/antigravityExecutable.ts +48 -0
  20. package/src/core/executables/executableResolver.ts +5 -1
  21. package/src/core/models/codexModelCapabilities.ts +57 -4
  22. package/src/core/models/codexModelsCacheSeed.ts +153 -0
  23. package/src/core/models/providerModelCache.ts +106 -0
  24. package/src/core/perf/renderDebug.ts +10 -6
  25. package/src/core/process/CommandRunner.ts +12 -1
  26. package/src/core/providerLauncher/registry.ts +64 -18
  27. package/src/core/providerLauncher/types.ts +12 -9
  28. package/src/core/providerLauncher/workspaceConfig.ts +41 -26
  29. package/src/core/providerRuntime/anthropic.ts +10 -6
  30. package/src/core/providerRuntime/antigravity.ts +461 -0
  31. package/src/core/providerRuntime/claudeCodeDiscovery.ts +724 -446
  32. package/src/core/providerRuntime/claudeCodeDiscoveryDebug.ts +55 -0
  33. package/src/core/providerRuntime/contextMetadata.ts +12 -24
  34. package/src/core/providerRuntime/local.ts +129 -51
  35. package/src/core/providerRuntime/mistralVibe.ts +663 -0
  36. package/src/core/providerRuntime/models.ts +40 -15
  37. package/src/core/providerRuntime/reasoning.ts +9 -6
  38. package/src/core/providerRuntime/registry.ts +76 -4
  39. package/src/core/providerRuntime/types.ts +20 -14
  40. package/src/core/providers/codexSubprocess.ts +2 -2
  41. package/src/core/providers/types.ts +1 -1
  42. package/src/core/{attachments.ts → shared/attachments.ts} +27 -4
  43. package/src/core/{cleanupFastFail.ts → shared/cleanupFastFail.ts} +1 -1
  44. package/src/core/{hollowResponseFormat.ts → shared/hollowResponseFormat.ts} +1 -1
  45. package/src/core/terminal/clearFrameBoundary.ts +814 -0
  46. package/src/core/terminal/frameLock.ts +109 -0
  47. package/src/core/terminal/inkRenderReset.ts +123 -0
  48. package/src/core/terminal/terminalControl.ts +22 -0
  49. package/src/core/terminal/terminalTitle.ts +16 -102
  50. package/src/core/{channel.ts → version/channel.ts} +1 -1
  51. package/src/core/{updateCheck.ts → version/updateCheck.ts} +10 -5
  52. package/src/core/{launchContext.ts → workspace/launchContext.ts} +9 -16
  53. package/src/core/{planStorage.ts → workspace/planStorage.ts} +2 -2
  54. package/src/core/{workspaceGuard.ts → workspace/workspaceGuard.ts} +97 -13
  55. package/src/headless/execRunner.ts +2 -2
  56. package/src/index.tsx +66 -98
  57. package/src/session/appSession.ts +10 -7
  58. package/src/session/chatLifecycle.ts +1 -1
  59. package/src/session/liveRenderScheduler.ts +1 -1
  60. package/src/session/types.ts +1 -1
  61. package/src/test/runtimeTestUtils.ts +90 -0
  62. package/src/ui/{ActivityBars.tsx → chrome/ActivityBars.tsx} +1 -1
  63. package/src/ui/{ActivityIndicator.tsx → chrome/ActivityIndicator.tsx} +3 -3
  64. package/src/ui/{AnimatedStatusText.tsx → chrome/AnimatedStatusText.tsx} +3 -3
  65. package/src/ui/chrome/AppShell.tsx +672 -0
  66. package/src/ui/{BottomComposer.tsx → chrome/BottomComposer.tsx} +159 -158
  67. package/src/ui/{DashCard.tsx → chrome/DashCard.tsx} +2 -2
  68. package/src/ui/{RunFooter.tsx → chrome/RunFooter.tsx} +3 -3
  69. package/src/ui/chrome/RuntimeStatusBar.tsx +108 -0
  70. package/src/ui/{Spinner.tsx → chrome/Spinner.tsx} +1 -1
  71. package/src/ui/{TopHeader.tsx → chrome/TopHeader.tsx} +54 -38
  72. package/src/ui/{UpdateAvailableCard.tsx → chrome/UpdateAvailableCard.tsx} +5 -5
  73. package/src/ui/{commandNormalize.ts → input/commandNormalize.ts} +1 -1
  74. package/src/ui/{focus.ts → input/focus.ts} +1 -1
  75. package/src/ui/{inputBuffer.ts → input/inputBuffer.ts} +3 -3
  76. package/src/ui/layout.ts +298 -24
  77. package/src/ui/{AttachmentImportPanel.tsx → panels/AttachmentImportPanel.tsx} +3 -3
  78. package/src/ui/{AuthPanel.tsx → panels/AuthPanel.tsx} +5 -5
  79. package/src/ui/{BackendPicker.tsx → panels/BackendPicker.tsx} +2 -2
  80. package/src/ui/{ModePicker.tsx → panels/ModePicker.tsx} +2 -2
  81. package/src/ui/{ModelPicker.tsx → panels/ModelPicker.tsx} +2 -2
  82. package/src/ui/{ModelPickerScreen.tsx → panels/ModelPickerScreen.tsx} +224 -42
  83. package/src/ui/{ModelReasoningPicker.tsx → panels/ModelReasoningPicker.tsx} +5 -5
  84. package/src/ui/{Panel.tsx → panels/Panel.tsx} +1 -1
  85. package/src/ui/{PermissionsPanel.tsx → panels/PermissionsPanel.tsx} +3 -3
  86. package/src/ui/{PlanActionPicker.tsx → panels/PlanActionPicker.tsx} +2 -2
  87. package/src/ui/{PlanReviewPanel.tsx → panels/PlanReviewPanel.tsx} +5 -5
  88. package/src/ui/panels/ProviderPicker.tsx +737 -0
  89. package/src/ui/{ReasoningPicker.tsx → panels/ReasoningPicker.tsx} +3 -3
  90. package/src/ui/{SelectionPanel.tsx → panels/SelectionPanel.tsx} +5 -1
  91. package/src/ui/{SettingsPanel.tsx → panels/SettingsPanel.tsx} +4 -4
  92. package/src/ui/{TextEntryPanel.tsx → panels/TextEntryPanel.tsx} +4 -4
  93. package/src/ui/{ThemePicker.tsx → panels/ThemePicker.tsx} +2 -2
  94. package/src/ui/{UpdatePromptPanel.tsx → panels/UpdatePromptPanel.tsx} +17 -23
  95. package/src/ui/{Markdown.tsx → render/Markdown.tsx} +2 -2
  96. package/src/ui/{diffRenderer.ts → render/diffRenderer.ts} +1 -1
  97. package/src/ui/{logoVariants.ts → render/logoVariants.ts} +4 -8
  98. package/src/ui/{modeDisplay.ts → render/modeDisplay.ts} +2 -2
  99. package/src/ui/{outputPipeline.ts → render/outputPipeline.ts} +2 -2
  100. package/src/ui/{runtimeDisplay.ts → render/runtimeDisplay.ts} +23 -10
  101. package/src/ui/{textLayout.ts → render/textLayout.ts} +15 -4
  102. package/src/ui/{ActionRequiredBlock.tsx → timeline/ActionRequiredBlock.tsx} +3 -3
  103. package/src/ui/{AgentBlock.tsx → timeline/AgentBlock.tsx} +10 -10
  104. package/src/ui/{StaticIntroItem.tsx → timeline/StaticIntroItem.tsx} +2 -2
  105. package/src/ui/{ThinkingBlock.tsx → timeline/ThinkingBlock.tsx} +4 -4
  106. package/src/ui/{Timeline.tsx → timeline/Timeline.tsx} +1620 -1471
  107. package/src/ui/timeline/TranscriptShell.tsx +322 -0
  108. package/src/ui/{TurnGroup.tsx → timeline/TurnGroup.tsx} +15 -15
  109. package/src/ui/timeline/layoutListWindow.ts +145 -0
  110. package/src/ui/{progressEntries.ts → timeline/progressEntries.ts} +3 -3
  111. package/src/ui/{runActivityView.ts → timeline/runActivityView.ts} +1 -1
  112. package/src/ui/{timelineMeasure.ts → timeline/timelineMeasure.ts} +206 -134
  113. package/src/core/codex.ts +0 -124
  114. package/src/ui/AppShell.tsx +0 -706
  115. package/src/ui/ProviderPicker.tsx +0 -321
  116. package/src/ui/StaticTranscriptItem.tsx +0 -56
  117. /package/src/core/{inputDebug.ts → debug/inputDebug.ts} +0 -0
  118. /package/src/core/{clipboard.ts → shared/clipboard.ts} +0 -0
  119. /package/src/core/{githubDiagnostics.ts → shared/githubDiagnostics.ts} +0 -0
  120. /package/src/core/{projectInstructions.ts → workspace/projectInstructions.ts} +0 -0
  121. /package/src/core/{workspaceActivity.ts → workspace/workspaceActivity.ts} +0 -0
  122. /package/src/core/{workspaceRoot.ts → workspace/workspaceRoot.ts} +0 -0
  123. /package/src/ui/{busyStatusAnimation.ts → chrome/busyStatusAnimation.ts} +0 -0
  124. /package/src/ui/{slashCommands.ts → input/slashCommands.ts} +0 -0
  125. /package/src/ui/{terminalAnswerFormat.ts → render/terminalAnswerFormat.ts} +0 -0
@@ -1,321 +0,0 @@
1
- import React, { useMemo, useState } from "react";
2
- import { Box, Text, useFocus, useInput } from "ink";
3
- import type { ProviderConfig, ProviderId, ProviderPickerAction } from "../core/providerLauncher/types.js";
4
- import { traceInputDebug } from "../core/inputDebug.js";
5
- import { FOCUS_IDS } from "./focus.js";
6
- import { clampVisualText, getShellWidth, type Layout } from "./layout.js";
7
- import { useTheme } from "./theme.js";
8
-
9
- // ─── Types & helpers ─────────────────────────────────────────────────────────
10
-
11
- interface ProviderPickerProps {
12
- layout: Layout;
13
- providers: readonly ProviderConfig[];
14
- onAction: (providerId: ProviderId, action: ProviderPickerAction) => void;
15
- onCancel: () => void;
16
- /** When set, the picker mounts directly at this provider's action panel. */
17
- initialProviderId?: ProviderId;
18
- }
19
-
20
- interface ProviderActionItem {
21
- value: ProviderPickerAction;
22
- label: string;
23
- disabledReason?: string | null;
24
- }
25
-
26
- function clampIndex(index: number, length: number): number {
27
- if (length <= 0) return 0;
28
- return Math.max(0, Math.min(length - 1, index));
29
- }
30
-
31
- // ─── Component ────────────────────────────────────────────────────────────────
32
-
33
- export function ProviderPicker({ layout, providers, onAction, onCancel, initialProviderId }: ProviderPickerProps) {
34
- const theme = useTheme();
35
- const { isFocused } = useFocus({ id: FOCUS_IDS.providerPicker, autoFocus: true });
36
- const initialIndex = initialProviderId
37
- ? Math.max(0, providers.findIndex((p) => p.id === initialProviderId))
38
- : 0;
39
- const [providerIndex, setProviderIndex] = useState(initialIndex);
40
- const [mode, setMode] = useState<"providers" | "actions">(
41
- initialProviderId ? "actions" : "providers",
42
- );
43
- const [actionIndex, setActionIndex] = useState(0);
44
-
45
- const selectedProvider = providers[clampIndex(providerIndex, providers.length)];
46
- const shellWidth = getShellWidth(layout.cols);
47
- const panelWidth = Math.max(42, Math.min(shellWidth - 2, layout.mode === "full" ? 86 : 72));
48
- const innerWidth = Math.max(30, panelWidth - 4);
49
- const markerWidth = 2;
50
- const columnGaps = 4;
51
- const columnWidthBudget = Math.max(26, innerWidth - markerWidth - columnGaps);
52
- const statusWidth = Math.min(8, Math.max(6, columnWidthBudget - 20));
53
- const toolsWidth = 4;
54
- const streamWidth = 4;
55
- const contextWidth = Math.min(11, Math.max(7, columnWidthBudget - statusWidth - toolsWidth - streamWidth - 16));
56
- const providerNameWidth = Math.min(layout.mode === "micro" ? 10 : 14, Math.max(8, columnWidthBudget - statusWidth - toolsWidth - streamWidth - contextWidth - 8));
57
- const modelWidth = Math.max(5, columnWidthBudget - providerNameWidth - contextWidth - toolsWidth - streamWidth - statusWidth);
58
-
59
- const helpText = layout.mode === "micro"
60
- ? "Enter select U use S default Esc"
61
- : "Enter = select, U = use, S = set default, Esc = cancel";
62
- const title = mode === "actions" && selectedProvider
63
- ? `Provider action: ${selectedProvider.displayName}`
64
- : "Providers";
65
- const actions = useMemo<ProviderActionItem[]>(() => {
66
- const routeUnavailable = selectedProvider?.routeMode === "in-codexa"
67
- ? null
68
- : selectedProvider?.routeUnavailableReason ?? "In-Codexa routing is not configured yet.";
69
-
70
- return [
71
- { value: "use-in-codexa", label: "Use in Codexa", disabledReason: routeUnavailable },
72
- { value: "select-model", label: "Select model", disabledReason: routeUnavailable },
73
- { value: "refresh-models", label: selectedProvider?.id === "anthropic" ? "Refresh Claude capabilities" : selectedProvider?.id === "local" ? "Refresh LM Studio metadata" : "Refresh models", disabledReason: routeUnavailable },
74
- ...(selectedProvider?.id === "google" || selectedProvider?.id === "local"
75
- ? [{ value: "run-diagnostics" as const, label: selectedProvider.id === "local" ? "Run Local diagnostics" : "Run Gemini diagnostics" }]
76
- : []),
77
- { value: "launch", label: "Launch external CLI" },
78
- { value: "set-default", label: "Set as workspace default" },
79
- { value: "cancel", label: "Cancel" },
80
- ];
81
- }, [selectedProvider]);
82
-
83
- useInput((input, key) => {
84
- traceInputDebug("provider_picker_input", {
85
- handler: "ProviderPicker.useInput",
86
- input,
87
- return: Boolean(key.return),
88
- escape: Boolean(key.escape),
89
- upArrow: Boolean(key.upArrow),
90
- downArrow: Boolean(key.downArrow),
91
- mode,
92
- providerIndex,
93
- actionIndex,
94
- });
95
-
96
- if (key.ctrl && (input === "c" || input === "q")) {
97
- onCancel();
98
- return;
99
- }
100
-
101
- if (key.escape) {
102
- if (mode === "actions") {
103
- setMode("providers");
104
- setActionIndex(0);
105
- return;
106
- }
107
- onCancel();
108
- return;
109
- }
110
-
111
- if (mode === "providers") {
112
- if (key.upArrow || input === "k") {
113
- setProviderIndex((current) => clampIndex(current - 1, providers.length));
114
- return;
115
- }
116
- if (key.downArrow || input === "j") {
117
- setProviderIndex((current) => clampIndex(current + 1, providers.length));
118
- return;
119
- }
120
- if (input.toLowerCase() === "s" && selectedProvider) {
121
- onAction(selectedProvider.id, "set-default");
122
- return;
123
- }
124
- if (input.toLowerCase() === "u" && selectedProvider) {
125
- onAction(selectedProvider.id, "use-in-codexa");
126
- return;
127
- }
128
- if (key.return && selectedProvider) {
129
- setMode("actions");
130
- setActionIndex(0);
131
- }
132
- return;
133
- }
134
-
135
- if (key.upArrow || input === "k") {
136
- setActionIndex((current) => clampIndex(current - 1, actions.length));
137
- return;
138
- }
139
- if (key.downArrow || input === "j") {
140
- setActionIndex((current) => clampIndex(current + 1, actions.length));
141
- return;
142
- }
143
- if (key.return && selectedProvider) {
144
- onAction(selectedProvider.id, actions[actionIndex]?.value ?? "cancel");
145
- }
146
- }, { isActive: isFocused });
147
-
148
- const body = useMemo(() => {
149
- if (mode === "actions" && selectedProvider) {
150
- const inCodexaAvailable = selectedProvider.routeMode === "in-codexa";
151
- const isConfigured = inCodexaAvailable && !selectedProvider.routeUnavailableReason;
152
- const inCodexaStatusText = !inCodexaAvailable ? "Unavailable" : isConfigured ? "Available" : "Needs configuration";
153
- const inCodexaStatusColor = !inCodexaAvailable ? theme.error : isConfigured ? theme.success : theme.warning;
154
-
155
- return (
156
- <Box flexDirection="column">
157
- <Box marginBottom={1} flexDirection="column" paddingX={2}>
158
- <Text color={theme.textDim}>Status: <Text color={theme.text}>{selectedProvider.routeUnavailableReason ?? "Ready"}</Text></Text>
159
- <Text color={theme.textDim}>Backend: <Text color={theme.text}>{selectedProvider.backendType}</Text></Text>
160
- <Text color={theme.textDim}>Use in Codexa: <Text color={inCodexaStatusColor}>{inCodexaStatusText}</Text></Text>
161
- </Box>
162
- {actions.map((action, index) => (
163
- <ActionRow
164
- key={action.value}
165
- label={action.label}
166
- disabledReason={action.disabledReason}
167
- isHighlighted={index === actionIndex}
168
- width={innerWidth}
169
- />
170
- ))}
171
- </Box>
172
- );
173
- }
174
-
175
- return providers.map((provider, index) => (
176
- <ProviderRow
177
- key={provider.id}
178
- provider={provider}
179
- isHighlighted={index === providerIndex}
180
- widths={{ providerNameWidth, modelWidth, contextWidth, toolsWidth, streamWidth, statusWidth }}
181
- />
182
- ));
183
- }, [actionIndex, actions, contextWidth, innerWidth, mode, modelWidth, providerIndex, providerNameWidth, providers, streamWidth, toolsWidth, statusWidth]);
184
-
185
- return (
186
- <Box flexDirection="column" width={panelWidth}>
187
- <Box
188
- borderStyle="round"
189
- borderColor={theme.prompt}
190
- paddingX={1}
191
- paddingY={0}
192
- width={panelWidth}
193
- flexDirection="column"
194
- >
195
- <Box width="100%" overflow="hidden">
196
- <Text color={theme.accent} bold>
197
- {clampVisualText(`${title} ${helpText}`, innerWidth)}
198
- </Text>
199
- </Box>
200
-
201
- {mode === "providers" && (
202
- <Box width="100%" overflow="hidden">
203
- <Text color={theme.textDim}>
204
- {" "}
205
- {clampVisualText("Provider", providerNameWidth)}
206
- {" "}
207
- {clampVisualText("Model", modelWidth)}
208
- {" "}
209
- {clampVisualText("Context", contextWidth)}
210
- {" "}
211
- {clampVisualText("Tool", toolsWidth)}
212
- {" "}
213
- {clampVisualText("Strm", streamWidth)}
214
- {" "}
215
- {clampVisualText("Status", statusWidth)}
216
- </Text>
217
- </Box>
218
- )}
219
-
220
- <Box flexDirection="column" marginTop={0} width="100%">
221
- {body}
222
- </Box>
223
- </Box>
224
- </Box>
225
- );
226
- }
227
-
228
- // ─── Subcomponents ───────────────────────────────────────────────────────────
229
-
230
- function capabilityFlag(value: boolean | null | undefined): string {
231
- if (value === true) return "Y";
232
- if (value === false) return "N";
233
- return "?";
234
- }
235
-
236
- function ProviderRow({
237
- provider,
238
- isHighlighted,
239
- widths,
240
- }: {
241
- provider: ProviderConfig;
242
- isHighlighted: boolean;
243
- widths: {
244
- providerNameWidth: number;
245
- modelWidth: number;
246
- contextWidth: number;
247
- toolsWidth: number;
248
- streamWidth: number;
249
- statusWidth: number;
250
- };
251
- }) {
252
- const theme = useTheme();
253
- const statusColor = provider.isActiveRoute
254
- ? theme.success
255
- : provider.enabled && !provider.routeUnavailableReason
256
- ? theme.success
257
- : theme.warning;
258
- const marker = isHighlighted ? ">" : " ";
259
- const defaultMark = provider.isActiveRoute ? "@" : provider.isDefault ? "*" : " ";
260
- const statusText = provider.isActiveRoute ? "Active" : provider.statusLabel;
261
-
262
- return (
263
- <Box width="100%" overflow="hidden">
264
- <Box width={2} flexShrink={0}>
265
- <Text color={isHighlighted ? theme.accent : theme.textDim}>{marker}{defaultMark}</Text>
266
- </Box>
267
- <Box width={widths.providerNameWidth} flexShrink={0} overflow="hidden">
268
- <Text color={isHighlighted ? theme.text : theme.textMuted} bold={isHighlighted}>
269
- {clampVisualText(provider.displayName, widths.providerNameWidth)}
270
- </Text>
271
- </Box>
272
- <Text> </Text>
273
- <Box width={widths.modelWidth} flexShrink={0} overflow="hidden">
274
- <Text color={theme.textMuted}>{clampVisualText(provider.currentModel, widths.modelWidth)}</Text>
275
- </Box>
276
- <Text> </Text>
277
- <Box width={widths.contextWidth} flexShrink={0} overflow="hidden">
278
- <Text color={theme.textMuted}>{clampVisualText(provider.contextLengthLabel ?? "Unknown", widths.contextWidth)}</Text>
279
- </Box>
280
- <Text> </Text>
281
- <Box width={widths.toolsWidth} flexShrink={0} overflow="hidden">
282
- <Text color={theme.textMuted}>{clampVisualText(capabilityFlag(provider.capabilityProfile?.supportsToolCalls), widths.toolsWidth)}</Text>
283
- </Box>
284
- <Text> </Text>
285
- <Box width={widths.streamWidth} flexShrink={0} overflow="hidden">
286
- <Text color={theme.textMuted}>{clampVisualText(capabilityFlag(provider.capabilityProfile?.supportsStreaming), widths.streamWidth)}</Text>
287
- </Box>
288
- <Text> </Text>
289
- <Box width={widths.statusWidth} flexShrink={0} overflow="hidden">
290
- <Text color={statusColor}>{clampVisualText(statusText, widths.statusWidth)}</Text>
291
- </Box>
292
- </Box>
293
- );
294
- }
295
-
296
- function ActionRow({
297
- label,
298
- disabledReason,
299
- isHighlighted,
300
- width,
301
- }: {
302
- label: string;
303
- disabledReason?: string | null;
304
- isHighlighted: boolean;
305
- width: number;
306
- }) {
307
- const theme = useTheme();
308
- const text = disabledReason ? `${label} unavailable` : label;
309
- return (
310
- <Box width="100%" overflow="hidden">
311
- <Box width={2} flexShrink={0}>
312
- <Text color={isHighlighted ? theme.accent : theme.textDim}>{isHighlighted ? ">" : " "}</Text>
313
- </Box>
314
- <Box width={Math.max(10, width - 2)} flexShrink={0} overflow="hidden">
315
- <Text color={disabledReason ? theme.textDim : isHighlighted ? theme.text : theme.textMuted} bold={isHighlighted && !disabledReason}>
316
- {clampVisualText(text, Math.max(10, width - 2))}
317
- </Text>
318
- </Box>
319
- </Box>
320
- );
321
- }
@@ -1,56 +0,0 @@
1
- import { Box } from "ink";
2
- import type { Layout } from "./layout.js";
3
- import type { TimelineItem } from "./Timeline.js";
4
- import { TimelineRowView } from "./Timeline.js";
5
- import { MemoizedTurnGroup, resolveTurnRunPhase } from "./TurnGroup.js";
6
- import { buildStandaloneEventRows } from "./timelineMeasure.js";
7
- import type { RenderTimelineItem } from "./Timeline.js";
8
-
9
- interface StaticTranscriptItemProps {
10
- item: TimelineItem;
11
- layout: Layout;
12
- verboseMode: boolean;
13
- workspaceRoot: string | null;
14
- }
15
-
16
- export function StaticTranscriptItem({
17
- item,
18
- layout,
19
- verboseMode,
20
- workspaceRoot,
21
- }: StaticTranscriptItemProps) {
22
- if (item.type === "turn") {
23
- if (!item.user) return null;
24
- return (
25
- <MemoizedTurnGroup
26
- cols={layout.cols}
27
- turnIndex={item.turnIndex}
28
- user={item.user}
29
- run={item.run}
30
- assistant={item.assistant}
31
- opacity="active"
32
- question={null}
33
- runPhase={resolveTurnRunPhase(item.run, item.assistant, { kind: "IDLE" }, item.turnId)}
34
- streamPreviewRows={0}
35
- streamMode="assistant-first"
36
- verboseMode={verboseMode}
37
- workspaceRoot={workspaceRoot}
38
- />
39
- );
40
- }
41
-
42
- const renderItem: Extract<RenderTimelineItem, { type: "event" }> = {
43
- key: `static-event-${item.event.id}`,
44
- type: "event",
45
- padded: false,
46
- event: item.event,
47
- };
48
- const rows = buildStandaloneEventRows(renderItem, layout.cols);
49
- return (
50
- <Box flexDirection="column">
51
- {rows.map((row) => (
52
- <TimelineRowView key={row.key} row={row} />
53
- ))}
54
- </Box>
55
- );
56
- }
File without changes
File without changes