@ganakailabs/cloudeval-cli 0.20.3 → 0.21.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/README.md +27 -9
- package/dist/{App-7N7BOWNP.js → App-77Q76GI5.js} +1717 -407
- package/dist/{Banner-FTZBMWDO.js → Banner-43UE3WHI.js} +5 -3
- package/dist/Onboarding-4N4WIORR.js +8 -0
- package/dist/{ReportDashboard-T63UGA7M.js → ReportDashboard-DOAUB727.js} +1 -1
- package/dist/{chunk-7B3KVSVK.js → chunk-6AHSCVTF.js} +7 -5
- package/dist/{chunk-TCNIIMWL.js → chunk-74TONCUI.js} +1 -1
- package/dist/{chunk-2D4BE3OS.js → chunk-LDDHLUZH.js} +64 -12
- package/dist/{chunk-2GTSKMHA.js → chunk-Q5D5HYWW.js} +2 -2
- package/dist/chunk-ZDKRIOMB.js +68 -0
- package/dist/cli.js +60 -60
- package/dist/{dist-TBAQ5KOK.js → dist-AGQQPJUD.js} +1 -1
- package/package.json +2 -2
- package/sbom.spdx.json +1 -1
- package/dist/Onboarding-3NZCPBCO.js +0 -8
- package/dist/chunk-QKZCKI55.js +0 -45
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-RCRNSEQS.js";
|
|
9
9
|
import {
|
|
10
10
|
Onboarding
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-Q5D5HYWW.js";
|
|
12
12
|
import {
|
|
13
13
|
checkUserStatus,
|
|
14
14
|
completeActiveAssistantMessage,
|
|
@@ -35,17 +35,17 @@ import {
|
|
|
35
35
|
reduceChunk,
|
|
36
36
|
runReports,
|
|
37
37
|
streamChat
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-LDDHLUZH.js";
|
|
39
39
|
import {
|
|
40
40
|
Banner
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-6AHSCVTF.js";
|
|
42
42
|
import {
|
|
43
43
|
CLI_VERSION
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-74TONCUI.js";
|
|
45
45
|
import {
|
|
46
46
|
raisedButtonStyle,
|
|
47
47
|
terminalTheme
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-ZDKRIOMB.js";
|
|
49
49
|
|
|
50
50
|
// src/ui/App.tsx
|
|
51
51
|
import React8, { useEffect as useEffect4, useMemo, useState as useState4, startTransition } from "react";
|
|
@@ -53,14 +53,49 @@ import { Box as Box9, Text as Text10, useApp, useInput as useInput4 } from "ink"
|
|
|
53
53
|
import { ScrollView } from "ink-scroll-view";
|
|
54
54
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
55
55
|
import { spawn } from "child_process";
|
|
56
|
-
import { mkdirSync, writeFileSync } from "fs";
|
|
57
|
-
import { join, resolve } from "path";
|
|
56
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
57
|
+
import { join as join2, resolve as resolve2 } from "path";
|
|
58
58
|
|
|
59
59
|
// src/ui/components/Loader.tsx
|
|
60
60
|
import { useEffect, useState } from "react";
|
|
61
|
-
import { Box, Text } from "ink";
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
import { Box, Text as Text2 } from "ink";
|
|
62
|
+
|
|
63
|
+
// src/ui/components/Spinner.tsx
|
|
64
|
+
import React from "react";
|
|
65
|
+
import { Text } from "ink";
|
|
66
|
+
import { jsx } from "react/jsx-runtime";
|
|
67
|
+
var spinnerFrames = ["\u25DC", "\u25E0", "\u25DD", "\u25DE", "\u25E1", "\u25DF"];
|
|
68
|
+
var SPINNER_FRAME_INTERVAL_MS = 1e3;
|
|
69
|
+
var shouldAnimateSpinner = (animate = true) => animate;
|
|
70
|
+
var getSpinnerFrames = (_type = "line") => spinnerFrames;
|
|
71
|
+
var getLoaderStepMarker = (state, frameIndex = 0) => {
|
|
72
|
+
if (state === "complete") {
|
|
73
|
+
return "\u2713";
|
|
74
|
+
}
|
|
75
|
+
if (state === "pending") {
|
|
76
|
+
return "\xB7";
|
|
77
|
+
}
|
|
78
|
+
const frames = getSpinnerFrames("line");
|
|
79
|
+
return frames[Math.abs(frameIndex) % frames.length] ?? frames[0];
|
|
80
|
+
};
|
|
81
|
+
var Spinner = ({ type = "dots", animate = true }) => {
|
|
82
|
+
const [frame, setFrame] = React.useState(0);
|
|
83
|
+
const frames = getSpinnerFrames(type);
|
|
84
|
+
React.useEffect(() => {
|
|
85
|
+
if (!shouldAnimateSpinner(animate)) {
|
|
86
|
+
setFrame(0);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const id = setInterval(() => {
|
|
90
|
+
setFrame((f) => (f + 1) % frames.length);
|
|
91
|
+
}, SPINNER_FRAME_INTERVAL_MS);
|
|
92
|
+
return () => clearInterval(id);
|
|
93
|
+
}, [animate, frames.length]);
|
|
94
|
+
return /* @__PURE__ */ jsx(Text, { color: terminalTheme.brand, children: frames[frame] });
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// src/ui/components/Loader.tsx
|
|
98
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
64
99
|
var LOADER_FRAME_INTERVAL_MS = 1e3;
|
|
65
100
|
var Loader = ({
|
|
66
101
|
step,
|
|
@@ -68,7 +103,7 @@ var Loader = ({
|
|
|
68
103
|
animate = true
|
|
69
104
|
}) => {
|
|
70
105
|
const [frame, setFrame] = useState(0);
|
|
71
|
-
const frames =
|
|
106
|
+
const frames = getSpinnerFrames("line");
|
|
72
107
|
useEffect(() => {
|
|
73
108
|
if (!animate) return;
|
|
74
109
|
const id = setInterval(() => {
|
|
@@ -76,13 +111,16 @@ var Loader = ({
|
|
|
76
111
|
}, LOADER_FRAME_INTERVAL_MS);
|
|
77
112
|
return () => clearInterval(id);
|
|
78
113
|
}, [animate, frames.length]);
|
|
79
|
-
const
|
|
80
|
-
return /* @__PURE__ */
|
|
114
|
+
const activeFrame = animate ? frame : 0;
|
|
115
|
+
return /* @__PURE__ */ jsx2(Box, { flexDirection: "column", gap: 1, children: steps.map((label, idx) => {
|
|
81
116
|
const isActive = idx === step;
|
|
82
117
|
const isComplete = idx < step;
|
|
83
|
-
const prefix =
|
|
118
|
+
const prefix = getLoaderStepMarker(
|
|
119
|
+
isComplete ? "complete" : isActive ? "active" : "pending",
|
|
120
|
+
activeFrame
|
|
121
|
+
);
|
|
84
122
|
const color = isComplete ? terminalTheme.success : isActive ? terminalTheme.brand : void 0;
|
|
85
|
-
return /* @__PURE__ */ jsxs(
|
|
123
|
+
return /* @__PURE__ */ jsxs(Text2, { color, children: [
|
|
86
124
|
prefix,
|
|
87
125
|
" ",
|
|
88
126
|
label
|
|
@@ -96,6 +134,162 @@ import { Box as Box3, Text as Text4 } from "ink";
|
|
|
96
134
|
import { supportsLanguage } from "cli-highlight";
|
|
97
135
|
import SyntaxHighlight from "ink-syntax-highlight";
|
|
98
136
|
|
|
137
|
+
// src/ui/citationContent.ts
|
|
138
|
+
var CITATION_TAG_RE = /\[S([A-Za-z0-9_.:-]+)\]/g;
|
|
139
|
+
var CITATION_TAG_ALT_RE = /\[(tool_[A-Za-z0-9_.:-]+)\]/g;
|
|
140
|
+
var DEFAULT_MAX_INLINE_CITATIONS_PER_SOURCE = 3;
|
|
141
|
+
var normalizeCitationSourceId = (sourceId) => sourceId.startsWith("_tool_") ? sourceId.slice(1) : sourceId;
|
|
142
|
+
var findCitationMatches = (value) => {
|
|
143
|
+
const matches = [];
|
|
144
|
+
let match;
|
|
145
|
+
CITATION_TAG_RE.lastIndex = 0;
|
|
146
|
+
while ((match = CITATION_TAG_RE.exec(value)) !== null) {
|
|
147
|
+
matches.push({
|
|
148
|
+
index: match.index,
|
|
149
|
+
end: match.index + match[0].length,
|
|
150
|
+
sourceId: normalizeCitationSourceId(match[1] ?? "")
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
CITATION_TAG_ALT_RE.lastIndex = 0;
|
|
154
|
+
while ((match = CITATION_TAG_ALT_RE.exec(value)) !== null) {
|
|
155
|
+
matches.push({
|
|
156
|
+
index: match.index,
|
|
157
|
+
end: match.index + match[0].length,
|
|
158
|
+
sourceId: normalizeCitationSourceId(match[1] ?? "")
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
matches.sort((a, b) => a.index - b.index);
|
|
162
|
+
const seenIndexes = /* @__PURE__ */ new Set();
|
|
163
|
+
return matches.filter((candidate) => {
|
|
164
|
+
if (seenIndexes.has(candidate.index)) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
seenIndexes.add(candidate.index);
|
|
168
|
+
return true;
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
var getCitationSourceOrder = (content) => {
|
|
172
|
+
const seen = /* @__PURE__ */ new Set();
|
|
173
|
+
const order = [];
|
|
174
|
+
for (const { sourceId } of findCitationMatches(content)) {
|
|
175
|
+
if (!sourceId || seen.has(sourceId)) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
seen.add(sourceId);
|
|
179
|
+
order.push(sourceId);
|
|
180
|
+
}
|
|
181
|
+
return order;
|
|
182
|
+
};
|
|
183
|
+
var citationNumberMap = (content) => {
|
|
184
|
+
const map = /* @__PURE__ */ new Map();
|
|
185
|
+
getCitationSourceOrder(content).forEach((sourceId, index) => {
|
|
186
|
+
map.set(sourceId, index + 1);
|
|
187
|
+
});
|
|
188
|
+
return map;
|
|
189
|
+
};
|
|
190
|
+
var toDisplayCitationContent = (content, options = {}) => {
|
|
191
|
+
if (!content) {
|
|
192
|
+
return content;
|
|
193
|
+
}
|
|
194
|
+
const matches = findCitationMatches(content);
|
|
195
|
+
if (!matches.length) {
|
|
196
|
+
return content;
|
|
197
|
+
}
|
|
198
|
+
const sourceIdToNumber = citationNumberMap(content);
|
|
199
|
+
const perSourceCount = /* @__PURE__ */ new Map();
|
|
200
|
+
const maxInlinePerSource = options.maxInlinePerSource ?? DEFAULT_MAX_INLINE_CITATIONS_PER_SOURCE;
|
|
201
|
+
let cursor = 0;
|
|
202
|
+
let result = "";
|
|
203
|
+
for (const match of matches) {
|
|
204
|
+
result += content.slice(cursor, match.index);
|
|
205
|
+
const count = (perSourceCount.get(match.sourceId) ?? 0) + 1;
|
|
206
|
+
perSourceCount.set(match.sourceId, count);
|
|
207
|
+
const number = sourceIdToNumber.get(match.sourceId);
|
|
208
|
+
if (number !== void 0 && count <= maxInlinePerSource) {
|
|
209
|
+
result += `[${number}]`;
|
|
210
|
+
}
|
|
211
|
+
cursor = match.end;
|
|
212
|
+
}
|
|
213
|
+
return result + content.slice(cursor);
|
|
214
|
+
};
|
|
215
|
+
var firstString = (...values) => {
|
|
216
|
+
for (const value of values) {
|
|
217
|
+
if (typeof value !== "string") {
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
const trimmed = value.trim();
|
|
221
|
+
if (trimmed) {
|
|
222
|
+
return trimmed;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return void 0;
|
|
226
|
+
};
|
|
227
|
+
var fallbackSourceLabel = (sourceId) => sourceId.replace(/^tool_/, "").replace(/[_:-]+/g, " ").trim() || sourceId;
|
|
228
|
+
var buildCitationReferences = ({
|
|
229
|
+
content,
|
|
230
|
+
toolsUsed,
|
|
231
|
+
citations
|
|
232
|
+
}) => {
|
|
233
|
+
const order = getCitationSourceOrder(content);
|
|
234
|
+
if (!order.length) {
|
|
235
|
+
return [];
|
|
236
|
+
}
|
|
237
|
+
const toolBySourceId = /* @__PURE__ */ new Map();
|
|
238
|
+
for (const tool of toolsUsed ?? []) {
|
|
239
|
+
const sourceId = typeof tool.source_id === "string" ? normalizeCitationSourceId(tool.source_id.trim()) : "";
|
|
240
|
+
if (sourceId && !toolBySourceId.has(sourceId)) {
|
|
241
|
+
toolBySourceId.set(sourceId, tool);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const citationBySourceId = /* @__PURE__ */ new Map();
|
|
245
|
+
for (const citation of citations ?? []) {
|
|
246
|
+
const sourceId = typeof citation.source_id === "string" ? normalizeCitationSourceId(citation.source_id.trim()) : "";
|
|
247
|
+
if (sourceId && !citationBySourceId.has(sourceId)) {
|
|
248
|
+
citationBySourceId.set(sourceId, citation);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return order.map((sourceId, index) => {
|
|
252
|
+
const tool = toolBySourceId.get(sourceId);
|
|
253
|
+
const citation = citationBySourceId.get(sourceId);
|
|
254
|
+
return {
|
|
255
|
+
number: index + 1,
|
|
256
|
+
sourceId,
|
|
257
|
+
label: firstString(
|
|
258
|
+
citation?.title,
|
|
259
|
+
tool?.title,
|
|
260
|
+
tool?.tool_friendly_name,
|
|
261
|
+
tool?.tool_name
|
|
262
|
+
) ?? fallbackSourceLabel(sourceId),
|
|
263
|
+
url: firstString(citation?.url, tool?.source_url)
|
|
264
|
+
};
|
|
265
|
+
});
|
|
266
|
+
};
|
|
267
|
+
var buildReferencesSection = (references) => {
|
|
268
|
+
if (!references.length) {
|
|
269
|
+
return "";
|
|
270
|
+
}
|
|
271
|
+
return [
|
|
272
|
+
"---",
|
|
273
|
+
"## References",
|
|
274
|
+
...references.map(
|
|
275
|
+
(reference) => `- [${reference.number}] ${reference.label}${reference.url ? ` - ${reference.url}` : ""}`
|
|
276
|
+
)
|
|
277
|
+
].join("\n");
|
|
278
|
+
};
|
|
279
|
+
var toCitationExportContent = ({
|
|
280
|
+
content,
|
|
281
|
+
toolsUsed,
|
|
282
|
+
citations
|
|
283
|
+
}) => {
|
|
284
|
+
const displayContent = toDisplayCitationContent(content);
|
|
285
|
+
const references = buildReferencesSection(
|
|
286
|
+
buildCitationReferences({ content, toolsUsed, citations })
|
|
287
|
+
);
|
|
288
|
+
return references ? `${displayContent.trim()}
|
|
289
|
+
|
|
290
|
+
${references}` : displayContent;
|
|
291
|
+
};
|
|
292
|
+
|
|
99
293
|
// src/ui/transcriptModel.ts
|
|
100
294
|
var hasRenderableTranscriptMessage = (message) => {
|
|
101
295
|
const content = (message.content ?? "").trim();
|
|
@@ -105,31 +299,6 @@ var hasRenderableTranscriptMessages = (messages, excludeStreaming = false) => me
|
|
|
105
299
|
(message) => excludeStreaming && message.role === "assistant" && message.pending ? false : hasRenderableTranscriptMessage(message)
|
|
106
300
|
);
|
|
107
301
|
|
|
108
|
-
// src/ui/components/Spinner.tsx
|
|
109
|
-
import React2 from "react";
|
|
110
|
-
import { Text as Text2 } from "ink";
|
|
111
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
112
|
-
var dotFrames = ["\xB7 ", "\xB7\xB7 ", "\xB7\xB7\xB7"];
|
|
113
|
-
var lineFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
114
|
-
var pulseFrames = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
|
|
115
|
-
var SPINNER_FRAME_INTERVAL_MS = 1e3;
|
|
116
|
-
var shouldAnimateSpinner = (animate = true) => animate;
|
|
117
|
-
var Spinner = ({ type = "dots", animate = true }) => {
|
|
118
|
-
const [frame, setFrame] = React2.useState(0);
|
|
119
|
-
const frames = type === "dots" ? dotFrames : type === "pulse" ? pulseFrames : lineFrames;
|
|
120
|
-
React2.useEffect(() => {
|
|
121
|
-
if (!shouldAnimateSpinner(animate)) {
|
|
122
|
-
setFrame(0);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
const id = setInterval(() => {
|
|
126
|
-
setFrame((f) => (f + 1) % frames.length);
|
|
127
|
-
}, SPINNER_FRAME_INTERVAL_MS);
|
|
128
|
-
return () => clearInterval(id);
|
|
129
|
-
}, [animate, frames.length]);
|
|
130
|
-
return /* @__PURE__ */ jsx2(Text2, { children: frames[frame] });
|
|
131
|
-
};
|
|
132
|
-
|
|
133
302
|
// src/ui/components/TitledBox.tsx
|
|
134
303
|
import { Box as Box2, Text as Text3 } from "ink";
|
|
135
304
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
@@ -197,6 +366,7 @@ var TitledBox = ({
|
|
|
197
366
|
// src/ui/components/Transcript.tsx
|
|
198
367
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
199
368
|
var AI_NAME = "Cloudeval AI";
|
|
369
|
+
var getTranscriptRoleColor = (role) => role === "user" ? terminalTheme.userName : terminalTheme.aiName;
|
|
200
370
|
var normalizeFenceLanguage = (language) => {
|
|
201
371
|
const normalized = (language ?? "").replace(/^```/, "").trim().split(/\s+/)[0]?.toLowerCase();
|
|
202
372
|
return normalized || "text";
|
|
@@ -227,17 +397,35 @@ var parseMarkdown = (text) => {
|
|
|
227
397
|
}
|
|
228
398
|
return blocks;
|
|
229
399
|
};
|
|
400
|
+
var tokenizeInlineMarkdown = (text) => {
|
|
401
|
+
const segments = text.split(/(`[^`\n]+`|\*\*[^*\n]+\*\*|\[[1-9][0-9]*\])/g).filter(Boolean);
|
|
402
|
+
return segments.map((segment) => {
|
|
403
|
+
if (segment.startsWith("`") && segment.endsWith("`")) {
|
|
404
|
+
return { type: "code", text: segment.slice(1, -1) };
|
|
405
|
+
}
|
|
406
|
+
if (segment.startsWith("**") && segment.endsWith("**")) {
|
|
407
|
+
return { type: "bold", text: segment.slice(2, -2) };
|
|
408
|
+
}
|
|
409
|
+
if (/^\[[1-9][0-9]*\]$/.test(segment)) {
|
|
410
|
+
return { type: "citation", text: segment };
|
|
411
|
+
}
|
|
412
|
+
return { type: "text", text: segment };
|
|
413
|
+
});
|
|
414
|
+
};
|
|
230
415
|
var renderInlineMarkdown = (text, keyPrefix) => {
|
|
231
|
-
const segments = text
|
|
416
|
+
const segments = tokenizeInlineMarkdown(text);
|
|
232
417
|
return segments.map((segment, index) => {
|
|
233
418
|
const key = `${keyPrefix}-${index}`;
|
|
234
|
-
if (segment.
|
|
235
|
-
return /* @__PURE__ */ jsx4(Text4, { color: terminalTheme.accent, children: segment.
|
|
419
|
+
if (segment.type === "code") {
|
|
420
|
+
return /* @__PURE__ */ jsx4(Text4, { color: terminalTheme.accent, children: segment.text }, key);
|
|
236
421
|
}
|
|
237
|
-
if (segment.
|
|
238
|
-
return /* @__PURE__ */ jsx4(Text4, { bold: true, children: segment.
|
|
422
|
+
if (segment.type === "bold") {
|
|
423
|
+
return /* @__PURE__ */ jsx4(Text4, { bold: true, children: segment.text }, key);
|
|
239
424
|
}
|
|
240
|
-
|
|
425
|
+
if (segment.type === "citation") {
|
|
426
|
+
return /* @__PURE__ */ jsx4(Text4, { color: terminalTheme.citation, bold: true, children: segment.text }, key);
|
|
427
|
+
}
|
|
428
|
+
return /* @__PURE__ */ jsx4(Text4, { children: segment.text }, key);
|
|
241
429
|
});
|
|
242
430
|
};
|
|
243
431
|
var MarkdownText = ({
|
|
@@ -266,31 +454,66 @@ var MarkdownText = ({
|
|
|
266
454
|
return /* @__PURE__ */ jsx4(Text4, { dimColor: dim, wrap: "wrap", children: renderInlineMarkdown(line, key) }, key);
|
|
267
455
|
}) });
|
|
268
456
|
};
|
|
269
|
-
var
|
|
457
|
+
var CitationReferences = ({
|
|
458
|
+
references
|
|
459
|
+
}) => {
|
|
460
|
+
if (!references.length) {
|
|
461
|
+
return null;
|
|
462
|
+
}
|
|
463
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, children: [
|
|
464
|
+
/* @__PURE__ */ jsx4(Text4, { color: terminalTheme.brand, children: "Sources" }),
|
|
465
|
+
references.map((reference) => /* @__PURE__ */ jsxs3(Text4, { dimColor: true, wrap: "wrap", children: [
|
|
466
|
+
/* @__PURE__ */ jsxs3(Text4, { color: terminalTheme.brand, children: [
|
|
467
|
+
"[",
|
|
468
|
+
reference.number,
|
|
469
|
+
"]"
|
|
470
|
+
] }),
|
|
471
|
+
" ",
|
|
472
|
+
reference.label,
|
|
473
|
+
reference.url ? ` - ${reference.url}` : ""
|
|
474
|
+
] }, reference.sourceId))
|
|
475
|
+
] });
|
|
476
|
+
};
|
|
477
|
+
var FormattedContent = ({ message, role }) => {
|
|
478
|
+
const content = message.content;
|
|
270
479
|
if (role === "user") {
|
|
271
480
|
return /* @__PURE__ */ jsx4(MarkdownText, { content });
|
|
272
481
|
}
|
|
273
482
|
const blocks = parseMarkdown(content);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
483
|
+
const references = buildCitationReferences({
|
|
484
|
+
content,
|
|
485
|
+
toolsUsed: message.toolsUsed,
|
|
486
|
+
citations: message.citations
|
|
487
|
+
});
|
|
488
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
489
|
+
blocks.map((block, idx) => {
|
|
490
|
+
if (block.type === "code") {
|
|
491
|
+
const syntaxLanguage = getSyntaxHighlightLanguage(block.language);
|
|
492
|
+
const blockTitle = block.language ? normalizeFenceLanguage(block.language) : "Code";
|
|
493
|
+
return /* @__PURE__ */ jsx4(
|
|
494
|
+
TitledBox,
|
|
495
|
+
{
|
|
496
|
+
title: blockTitle,
|
|
497
|
+
borderStyle: "single",
|
|
498
|
+
borderColor: terminalTheme.muted,
|
|
499
|
+
padding: 0,
|
|
500
|
+
paddingX: 1,
|
|
501
|
+
marginY: 1,
|
|
502
|
+
children: /* @__PURE__ */ jsx4(SyntaxHighlight, { code: block.content, language: syntaxLanguage })
|
|
503
|
+
},
|
|
504
|
+
idx
|
|
505
|
+
);
|
|
506
|
+
}
|
|
278
507
|
return /* @__PURE__ */ jsx4(
|
|
279
|
-
|
|
508
|
+
MarkdownText,
|
|
280
509
|
{
|
|
281
|
-
|
|
282
|
-
borderStyle: "single",
|
|
283
|
-
borderColor: terminalTheme.muted,
|
|
284
|
-
padding: 0,
|
|
285
|
-
paddingX: 1,
|
|
286
|
-
marginY: 1,
|
|
287
|
-
children: /* @__PURE__ */ jsx4(SyntaxHighlight, { code: block.content, language: syntaxLanguage })
|
|
510
|
+
content: toDisplayCitationContent(block.content)
|
|
288
511
|
},
|
|
289
512
|
idx
|
|
290
513
|
);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
514
|
+
}),
|
|
515
|
+
/* @__PURE__ */ jsx4(CitationReferences, { references })
|
|
516
|
+
] });
|
|
294
517
|
};
|
|
295
518
|
var formatDuration = (durationMs) => {
|
|
296
519
|
if (durationMs < 1e3) {
|
|
@@ -329,6 +552,24 @@ var getStepStatusMeta = (status) => {
|
|
|
329
552
|
}
|
|
330
553
|
return { marker: "\u2022", label: status || "pending", color: terminalTheme.muted };
|
|
331
554
|
};
|
|
555
|
+
var summarizeThinkingLedger = (steps) => {
|
|
556
|
+
const completed = steps.filter((step) => step.status === "completed").length;
|
|
557
|
+
const failed = steps.filter(
|
|
558
|
+
(step) => step.status === "error" || step.status === "aborted" || step.status === "cancelled"
|
|
559
|
+
).length;
|
|
560
|
+
const running = steps.filter((step) => step.status === "streaming").length;
|
|
561
|
+
return {
|
|
562
|
+
title: "Task Ledger",
|
|
563
|
+
completed,
|
|
564
|
+
failed,
|
|
565
|
+
running,
|
|
566
|
+
parts: [
|
|
567
|
+
`${completed}/${steps.length} done`,
|
|
568
|
+
failed ? `${failed} failed` : "",
|
|
569
|
+
running ? `${running} running` : ""
|
|
570
|
+
].filter(Boolean)
|
|
571
|
+
};
|
|
572
|
+
};
|
|
332
573
|
var ProgressBar = ({
|
|
333
574
|
completed,
|
|
334
575
|
total,
|
|
@@ -347,7 +588,7 @@ var ProgressBar = ({
|
|
|
347
588
|
(_, index) => active && index === pulsePosition ? "\u2501" : "\u2500"
|
|
348
589
|
);
|
|
349
590
|
return /* @__PURE__ */ jsxs3(Text4, { children: [
|
|
350
|
-
/* @__PURE__ */ jsx4(Text4, { color: terminalTheme.
|
|
591
|
+
/* @__PURE__ */ jsx4(Text4, { color: terminalTheme.brand, children: "\u2501".repeat(filled) }),
|
|
351
592
|
/* @__PURE__ */ jsx4(Text4, { color: terminalTheme.danger, children: "\u2501".repeat(failedWidth) }),
|
|
352
593
|
openRail.map((character, index) => /* @__PURE__ */ jsx4(
|
|
353
594
|
Text4,
|
|
@@ -374,37 +615,29 @@ var ThinkingSteps = ({ message, expanded, forceExpanded = false, animate = true
|
|
|
374
615
|
if (!steps.length) {
|
|
375
616
|
return null;
|
|
376
617
|
}
|
|
377
|
-
const
|
|
378
|
-
const failedCount = steps.filter(
|
|
379
|
-
(step) => step.status === "error" || step.status === "aborted" || step.status === "cancelled"
|
|
380
|
-
).length;
|
|
381
|
-
const runningCount = steps.filter((step) => step.status === "streaming").length;
|
|
382
|
-
const summaryParts = [
|
|
383
|
-
`${completedCount}/${steps.length} completed`,
|
|
384
|
-
failedCount ? `${failedCount} failed` : "",
|
|
385
|
-
runningCount ? `${runningCount} running` : ""
|
|
386
|
-
].filter(Boolean);
|
|
618
|
+
const ledger = summarizeThinkingLedger(steps);
|
|
387
619
|
const runningStep = [...steps].reverse().find((step) => step.status === "streaming");
|
|
388
620
|
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, children: [
|
|
389
621
|
/* @__PURE__ */ jsxs3(Box3, { flexDirection: "row", gap: 1, children: [
|
|
390
|
-
/* @__PURE__ */ jsxs3(Text4, { color:
|
|
622
|
+
/* @__PURE__ */ jsxs3(Text4, { color: terminalTheme.brand, children: [
|
|
391
623
|
isExpanded ? "\u25BE" : "\u25B8",
|
|
392
|
-
"
|
|
624
|
+
" ",
|
|
625
|
+
ledger.title
|
|
393
626
|
] }),
|
|
394
627
|
message.pending ? /* @__PURE__ */ jsx4(Spinner, { type: "pulse", animate }) : null,
|
|
395
628
|
/* @__PURE__ */ jsx4(
|
|
396
629
|
ProgressBar,
|
|
397
630
|
{
|
|
398
|
-
completed:
|
|
399
|
-
failed:
|
|
631
|
+
completed: ledger.completed,
|
|
632
|
+
failed: ledger.failed,
|
|
400
633
|
total: steps.length,
|
|
401
|
-
active: message.pending ||
|
|
634
|
+
active: message.pending || ledger.running > 0,
|
|
402
635
|
pulseIndex: animate ? Math.floor(now / 1e3) : 0
|
|
403
636
|
}
|
|
404
637
|
),
|
|
405
638
|
/* @__PURE__ */ jsxs3(Text4, { dimColor: true, children: [
|
|
406
639
|
"(",
|
|
407
|
-
|
|
640
|
+
ledger.parts.join(", "),
|
|
408
641
|
")"
|
|
409
642
|
] })
|
|
410
643
|
] }),
|
|
@@ -456,7 +689,7 @@ var Transcript = ({
|
|
|
456
689
|
const hasThinkingSteps = Boolean(message.thinkingSteps?.length);
|
|
457
690
|
if (!content && !hasThinkingSteps) return null;
|
|
458
691
|
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingY: 0, marginBottom: 1, children: [
|
|
459
|
-
/* @__PURE__ */ jsxs3(Text4, { bold: true, color: isUser ?
|
|
692
|
+
/* @__PURE__ */ jsxs3(Text4, { bold: true, color: getTranscriptRoleColor(isUser ? "user" : "assistant"), children: [
|
|
460
693
|
isUser ? userName : AI_NAME,
|
|
461
694
|
":",
|
|
462
695
|
isUser && message.queued ? " (queued)" : ""
|
|
@@ -469,7 +702,7 @@ var Transcript = ({
|
|
|
469
702
|
animate
|
|
470
703
|
}
|
|
471
704
|
) : null,
|
|
472
|
-
/* @__PURE__ */ jsx4(Box3, { paddingLeft: 0, children: content ? /* @__PURE__ */ jsx4(FormattedContent, {
|
|
705
|
+
/* @__PURE__ */ jsx4(Box3, { paddingLeft: 0, children: content ? /* @__PURE__ */ jsx4(FormattedContent, { message, role: message.role }) : !hasThinkingSteps && !message.error ? /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "No final response content." }) : null }),
|
|
473
706
|
!isUser && message.followUpQuestions?.length ? /* @__PURE__ */ jsx4(Box3, { flexDirection: "column", paddingLeft: 2, marginTop: 1, children: /* @__PURE__ */ jsx4(Text4, { dimColor: true, italic: true, children: "Follow-ups are available above the input." }) }) : null,
|
|
474
707
|
!isUser && message.hitlQuestionsAnswered?.answers.length ? /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingLeft: 2, marginTop: 1, children: [
|
|
475
708
|
/* @__PURE__ */ jsx4(Text4, { dimColor: true, italic: true, children: "Human input:" }),
|
|
@@ -492,7 +725,7 @@ var Transcript = ({
|
|
|
492
725
|
const hasThinkingSteps = Boolean(streamingMessage.thinkingSteps?.length);
|
|
493
726
|
if (!hasContent && hasThinkingSteps) {
|
|
494
727
|
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingY: 0, children: [
|
|
495
|
-
/* @__PURE__ */ jsxs3(Text4, { bold: true, color:
|
|
728
|
+
/* @__PURE__ */ jsxs3(Text4, { bold: true, color: getTranscriptRoleColor("assistant"), children: [
|
|
496
729
|
AI_NAME,
|
|
497
730
|
":"
|
|
498
731
|
] }),
|
|
@@ -509,7 +742,7 @@ var Transcript = ({
|
|
|
509
742
|
}
|
|
510
743
|
if (hasContent) {
|
|
511
744
|
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingY: 0, children: [
|
|
512
|
-
/* @__PURE__ */ jsxs3(Text4, { bold: true, color:
|
|
745
|
+
/* @__PURE__ */ jsxs3(Text4, { bold: true, color: getTranscriptRoleColor("assistant"), children: [
|
|
513
746
|
AI_NAME,
|
|
514
747
|
":"
|
|
515
748
|
] }),
|
|
@@ -523,7 +756,7 @@ var Transcript = ({
|
|
|
523
756
|
}
|
|
524
757
|
),
|
|
525
758
|
/* @__PURE__ */ jsxs3(Box3, { paddingLeft: 0, children: [
|
|
526
|
-
/* @__PURE__ */ jsx4(FormattedContent, {
|
|
759
|
+
/* @__PURE__ */ jsx4(FormattedContent, { message: streamingMessage, role: "assistant" }),
|
|
527
760
|
/* @__PURE__ */ jsx4(Text4, { color: terminalTheme.cursor, children: "|" })
|
|
528
761
|
] })
|
|
529
762
|
] }, streamingMessage.id);
|
|
@@ -602,7 +835,7 @@ var getTuiKeyBindings = (platform = process.platform) => ({
|
|
|
602
835
|
quit: "Ctrl+C quit",
|
|
603
836
|
tabFocus: "Tab focus",
|
|
604
837
|
tabSwitch: "Arrow keys move focus",
|
|
605
|
-
commandComplete: "Tab
|
|
838
|
+
commandComplete: "Tab/\u2191\u2193 slash command menu",
|
|
606
839
|
historySearch: "Ctrl+R history search",
|
|
607
840
|
cancel: "Esc cancel response",
|
|
608
841
|
scroll: "Ctrl+Up/Down scroll",
|
|
@@ -622,9 +855,9 @@ var getChatInputHelpText = ({
|
|
|
622
855
|
return "Type to edit | Tab/Arrows controls | 1-8 tabs | /help";
|
|
623
856
|
}
|
|
624
857
|
if (promptCount <= 0) {
|
|
625
|
-
return "Enter send | Esc controls |
|
|
858
|
+
return "Enter send | Esc controls | /copy | /download | /help";
|
|
626
859
|
}
|
|
627
|
-
return "Enter send/choose | Esc controls |
|
|
860
|
+
return "Enter send/choose | Esc controls | /copy | Tab focus | /help";
|
|
628
861
|
};
|
|
629
862
|
|
|
630
863
|
// src/ui/workspaceTabs.ts
|
|
@@ -666,6 +899,16 @@ var workspaceTabFromPromptChange = (previousValue, nextValue) => {
|
|
|
666
899
|
return nextValue.length === 1 ? workspaceTabFromShortcut(nextValue) : void 0;
|
|
667
900
|
};
|
|
668
901
|
var workspaceTabButtonLabel = (tab) => `${workspaceTabs.indexOf(tab) + 1} ${workspaceTabLabels[tab]}`;
|
|
902
|
+
var workspaceTabButtonContent = (tab, active = false) => `${active ? raisedButtonStyle.activeMarker : raisedButtonStyle.inactiveMarker} ${workspaceTabButtonLabel(tab)}`;
|
|
903
|
+
var workspaceTabButtonInterior = (tab, active = false) => ` ${workspaceTabButtonContent(tab, active)} `;
|
|
904
|
+
var workspaceTabButtonStyle = (active = false) => ({
|
|
905
|
+
backgroundColor: active ? terminalTheme.selectedBackground : void 0,
|
|
906
|
+
borderColor: active ? terminalTheme.focus : terminalTheme.muted,
|
|
907
|
+
borderStyle: active ? "bold" : raisedButtonStyle.border,
|
|
908
|
+
color: active ? "black" : terminalTheme.muted,
|
|
909
|
+
bold: active,
|
|
910
|
+
underline: active
|
|
911
|
+
});
|
|
669
912
|
var getWorkspaceTabHitAreas = ({
|
|
670
913
|
startColumn = 1,
|
|
671
914
|
startRow = 1,
|
|
@@ -712,7 +955,7 @@ var shouldBlinkPromptCursor = ({
|
|
|
712
955
|
busy = false,
|
|
713
956
|
selectorOpen = false,
|
|
714
957
|
searching = false
|
|
715
|
-
}) => Boolean(animationsEnabled && inputActive &&
|
|
958
|
+
}) => Boolean(animationsEnabled && inputActive && !selectorOpen && !searching);
|
|
716
959
|
var getInputCursorColor = ({
|
|
717
960
|
disabled,
|
|
718
961
|
inputActive = true,
|
|
@@ -732,6 +975,20 @@ var getInputCursorGlyph = ({
|
|
|
732
975
|
}
|
|
733
976
|
return cursorVisible ? "\u258C" : "\u258F";
|
|
734
977
|
};
|
|
978
|
+
var getPromptDisplayRows = ({
|
|
979
|
+
visibleRows,
|
|
980
|
+
startRow,
|
|
981
|
+
inputRowCount
|
|
982
|
+
}) => visibleRows.map((line, index) => {
|
|
983
|
+
const rowIndex = startRow + index;
|
|
984
|
+
const isFiller = rowIndex >= inputRowCount;
|
|
985
|
+
return {
|
|
986
|
+
line,
|
|
987
|
+
isFiller,
|
|
988
|
+
showPromptPrefix: !isFiller,
|
|
989
|
+
showCursor: !isFiller && rowIndex === inputRowCount - 1
|
|
990
|
+
};
|
|
991
|
+
});
|
|
735
992
|
var Scrollbar = ({
|
|
736
993
|
totalRows,
|
|
737
994
|
visibleRows,
|
|
@@ -833,8 +1090,49 @@ var getFollowUpRowViewport = ({
|
|
|
833
1090
|
rowCount: 1
|
|
834
1091
|
};
|
|
835
1092
|
};
|
|
1093
|
+
var getCommandCompletionViewport = ({
|
|
1094
|
+
commands,
|
|
1095
|
+
focusedIndex = 0,
|
|
1096
|
+
terminalColumns
|
|
1097
|
+
}) => {
|
|
1098
|
+
const availableWidth = Math.max(24, terminalColumns - 28);
|
|
1099
|
+
const activeIndex = commands.length ? Math.min(Math.max(0, focusedIndex), commands.length - 1) : 0;
|
|
1100
|
+
const items = commands.map((command, index) => {
|
|
1101
|
+
const label = `${index === activeIndex ? raisedButtonStyle.activeMarker : raisedButtonStyle.inactiveMarker} ${command.name}`;
|
|
1102
|
+
return { command, index, label, width: label.length };
|
|
1103
|
+
});
|
|
1104
|
+
if (!items.length) {
|
|
1105
|
+
return { items: [], clippedStart: false, clippedEnd: false, rowCount: 0 };
|
|
1106
|
+
}
|
|
1107
|
+
let start = activeIndex;
|
|
1108
|
+
let usedWidth = items[start]?.width ?? 0;
|
|
1109
|
+
while (start > 0) {
|
|
1110
|
+
const nextWidth = items[start - 1].width + 1;
|
|
1111
|
+
if (usedWidth + nextWidth > availableWidth) {
|
|
1112
|
+
break;
|
|
1113
|
+
}
|
|
1114
|
+
usedWidth += nextWidth;
|
|
1115
|
+
start--;
|
|
1116
|
+
}
|
|
1117
|
+
let end = activeIndex + 1;
|
|
1118
|
+
while (end < items.length) {
|
|
1119
|
+
const nextWidth = items[end].width + (end > start ? 1 : 0);
|
|
1120
|
+
if (usedWidth + nextWidth > availableWidth) {
|
|
1121
|
+
break;
|
|
1122
|
+
}
|
|
1123
|
+
usedWidth += nextWidth;
|
|
1124
|
+
end++;
|
|
1125
|
+
}
|
|
1126
|
+
return {
|
|
1127
|
+
items: items.slice(start, end),
|
|
1128
|
+
clippedStart: start > 0,
|
|
1129
|
+
clippedEnd: end < items.length,
|
|
1130
|
+
rowCount: 1
|
|
1131
|
+
};
|
|
1132
|
+
};
|
|
836
1133
|
var InputBox = ({
|
|
837
1134
|
title = "Prompt",
|
|
1135
|
+
variant = "panel",
|
|
838
1136
|
value,
|
|
839
1137
|
onChange,
|
|
840
1138
|
onSubmit,
|
|
@@ -857,7 +1155,11 @@ var InputBox = ({
|
|
|
857
1155
|
scrollOffset,
|
|
858
1156
|
onTabShortcut,
|
|
859
1157
|
blinkCursor = false,
|
|
860
|
-
ghostText
|
|
1158
|
+
ghostText,
|
|
1159
|
+
commandCompletions = [],
|
|
1160
|
+
focusedCommandCompletionIndex,
|
|
1161
|
+
commandCompletionsActive = false,
|
|
1162
|
+
onCommandCompletionSubmit
|
|
861
1163
|
}) => {
|
|
862
1164
|
const [cursorVisible, setCursorVisible] = useState2(true);
|
|
863
1165
|
const keyBindings = getTuiKeyBindings();
|
|
@@ -869,7 +1171,22 @@ var InputBox = ({
|
|
|
869
1171
|
focusedFollowUpIndex,
|
|
870
1172
|
terminalColumns
|
|
871
1173
|
});
|
|
872
|
-
const
|
|
1174
|
+
const commandCompletionViewport = getCommandCompletionViewport({
|
|
1175
|
+
commands: commandCompletions,
|
|
1176
|
+
focusedIndex: focusedCommandCompletionIndex,
|
|
1177
|
+
terminalColumns
|
|
1178
|
+
});
|
|
1179
|
+
const commandCompletionLine = [
|
|
1180
|
+
commandCompletionViewport.clippedStart ? "<--" : void 0,
|
|
1181
|
+
...commandCompletionViewport.items.map((item) => item.label),
|
|
1182
|
+
commandCompletionViewport.clippedEnd ? "-->" : void 0
|
|
1183
|
+
].filter(Boolean).join(" ");
|
|
1184
|
+
const activeCommand = focusedCommandCompletionIndex === void 0 ? void 0 : commandCompletions[Math.min(
|
|
1185
|
+
Math.max(0, focusedCommandCompletionIndex),
|
|
1186
|
+
Math.max(0, commandCompletions.length - 1)
|
|
1187
|
+
)];
|
|
1188
|
+
const promptPrefix = ">";
|
|
1189
|
+
const inputWidth = Math.max(20, terminalColumns - 10);
|
|
873
1190
|
const inputViewport = getInputViewport({
|
|
874
1191
|
value,
|
|
875
1192
|
width: inputWidth,
|
|
@@ -881,6 +1198,11 @@ var InputBox = ({
|
|
|
881
1198
|
const visibleRowCount = inputViewport.visibleRowCount;
|
|
882
1199
|
const startRow = inputViewport.startRow;
|
|
883
1200
|
const visibleRows = inputViewport.visibleRows;
|
|
1201
|
+
const promptRows = getPromptDisplayRows({
|
|
1202
|
+
visibleRows,
|
|
1203
|
+
startRow,
|
|
1204
|
+
inputRowCount: inputRows.length
|
|
1205
|
+
});
|
|
884
1206
|
useEffect2(() => {
|
|
885
1207
|
if (!shouldAnimateInputCursor({ disabled, inputActive, blinkCursor })) {
|
|
886
1208
|
setCursorVisible(true);
|
|
@@ -920,6 +1242,10 @@ var InputBox = ({
|
|
|
920
1242
|
insertNewline();
|
|
921
1243
|
return;
|
|
922
1244
|
}
|
|
1245
|
+
if (commandCompletionsActive && activeCommand && onCommandCompletionSubmit) {
|
|
1246
|
+
onCommandCompletionSubmit(activeCommand);
|
|
1247
|
+
return;
|
|
1248
|
+
}
|
|
923
1249
|
if (!shouldSubmitInputOnReturn(value)) {
|
|
924
1250
|
return;
|
|
925
1251
|
}
|
|
@@ -952,7 +1278,98 @@ var InputBox = ({
|
|
|
952
1278
|
const cursorGlyph = getInputCursorGlyph({ inputActive, cursorVisible });
|
|
953
1279
|
const cursorColor = getInputCursorColor({ disabled, inputActive, cursorVisible });
|
|
954
1280
|
const inputBorderColor = disabled ? terminalTheme.muted : followUpsActive || inputActive ? terminalTheme.focus : terminalTheme.muted;
|
|
955
|
-
|
|
1281
|
+
const content = /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
1282
|
+
followUps.length ? /* @__PURE__ */ jsxs4(Text5, { wrap: "truncate", children: [
|
|
1283
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: `${followUpsLabel}: ` }),
|
|
1284
|
+
followUpViewport.clippedStart ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "<-- " }) : null,
|
|
1285
|
+
followUpViewport.items.map(({ question, index, label }) => {
|
|
1286
|
+
const focused = followUpsActive && focusedFollowUpIndex === index;
|
|
1287
|
+
return /* @__PURE__ */ jsxs4(
|
|
1288
|
+
Text5,
|
|
1289
|
+
{
|
|
1290
|
+
color: focused ? terminalTheme.focus : void 0,
|
|
1291
|
+
bold: focused,
|
|
1292
|
+
children: [
|
|
1293
|
+
focused ? raisedButtonStyle.activeMarker : raisedButtonStyle.inactiveMarker,
|
|
1294
|
+
" ",
|
|
1295
|
+
label,
|
|
1296
|
+
" "
|
|
1297
|
+
]
|
|
1298
|
+
},
|
|
1299
|
+
`${index}-${question}`
|
|
1300
|
+
);
|
|
1301
|
+
}),
|
|
1302
|
+
followUpViewport.clippedEnd ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "-->" }) : null
|
|
1303
|
+
] }) : null,
|
|
1304
|
+
/* @__PURE__ */ jsxs4(
|
|
1305
|
+
Box4,
|
|
1306
|
+
{
|
|
1307
|
+
flexDirection: compact ? "column" : "row",
|
|
1308
|
+
children: [
|
|
1309
|
+
/* @__PURE__ */ jsx5(Box4, { flexDirection: "column", flexGrow: 1, children: !value ? /* @__PURE__ */ jsxs4(Text5, { wrap: "truncate", children: [
|
|
1310
|
+
/* @__PURE__ */ jsxs4(Text5, { color: inputActive ? terminalTheme.brand : terminalTheme.muted, children: [
|
|
1311
|
+
promptPrefix,
|
|
1312
|
+
" "
|
|
1313
|
+
] }),
|
|
1314
|
+
/* @__PURE__ */ jsx5(Text5, { color: cursorColor, children: cursorGlyph }),
|
|
1315
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: ` ${placeholder}` })
|
|
1316
|
+
] }) : promptRows.map((row, index) => {
|
|
1317
|
+
return /* @__PURE__ */ jsxs4(Text5, { wrap: "truncate", children: [
|
|
1318
|
+
row.showPromptPrefix ? /* @__PURE__ */ jsxs4(Text5, { color: inputActive ? terminalTheme.brand : terminalTheme.muted, children: [
|
|
1319
|
+
promptPrefix,
|
|
1320
|
+
" "
|
|
1321
|
+
] }) : /* @__PURE__ */ jsx5(Text5, { children: " " }),
|
|
1322
|
+
row.line,
|
|
1323
|
+
row.showCursor ? /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
1324
|
+
/* @__PURE__ */ jsx5(
|
|
1325
|
+
Text5,
|
|
1326
|
+
{
|
|
1327
|
+
dimColor: true,
|
|
1328
|
+
italic: true,
|
|
1329
|
+
color: terminalTheme.inputGhost,
|
|
1330
|
+
children: ghostText ?? ""
|
|
1331
|
+
}
|
|
1332
|
+
),
|
|
1333
|
+
/* @__PURE__ */ jsx5(Text5, { color: cursorColor, children: cursorGlyph })
|
|
1334
|
+
] }) : null
|
|
1335
|
+
] }, `${startRow}-${index}`);
|
|
1336
|
+
}) }),
|
|
1337
|
+
/* @__PURE__ */ jsx5(
|
|
1338
|
+
Scrollbar,
|
|
1339
|
+
{
|
|
1340
|
+
totalRows: inputRows.length,
|
|
1341
|
+
visibleRows: visibleRowCount,
|
|
1342
|
+
startRow
|
|
1343
|
+
}
|
|
1344
|
+
)
|
|
1345
|
+
]
|
|
1346
|
+
}
|
|
1347
|
+
),
|
|
1348
|
+
actionHint ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, wrap: "truncate", children: actionHint }) : resolvedHelpText ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, wrap: "truncate", children: resolvedHelpText }) : null,
|
|
1349
|
+
commandCompletionViewport.items.length ? /* @__PURE__ */ jsx5(
|
|
1350
|
+
Text5,
|
|
1351
|
+
{
|
|
1352
|
+
color: commandCompletionsActive ? terminalTheme.focus : terminalTheme.muted,
|
|
1353
|
+
bold: commandCompletionsActive,
|
|
1354
|
+
wrap: "truncate",
|
|
1355
|
+
children: `/commands: ${commandCompletionLine} | Tab/\u2191\u2193 move | Enter choose`
|
|
1356
|
+
}
|
|
1357
|
+
) : null,
|
|
1358
|
+
footerControls ? /* @__PURE__ */ jsx5(Box4, { flexDirection: "column", marginTop: 1, children: footerControls }) : null
|
|
1359
|
+
] });
|
|
1360
|
+
if (variant === "dock") {
|
|
1361
|
+
return /* @__PURE__ */ jsx5(
|
|
1362
|
+
Box4,
|
|
1363
|
+
{
|
|
1364
|
+
flexDirection: "column",
|
|
1365
|
+
borderStyle: "single",
|
|
1366
|
+
borderColor: inputBorderColor,
|
|
1367
|
+
paddingX: 1,
|
|
1368
|
+
children: content
|
|
1369
|
+
}
|
|
1370
|
+
);
|
|
1371
|
+
}
|
|
1372
|
+
return /* @__PURE__ */ jsx5(
|
|
956
1373
|
TitledBox,
|
|
957
1374
|
{
|
|
958
1375
|
title,
|
|
@@ -960,69 +1377,7 @@ var InputBox = ({
|
|
|
960
1377
|
borderColor: inputBorderColor,
|
|
961
1378
|
padding: 0,
|
|
962
1379
|
paddingX: 1,
|
|
963
|
-
children:
|
|
964
|
-
followUps.length ? /* @__PURE__ */ jsxs4(Text5, { wrap: "truncate", children: [
|
|
965
|
-
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: `${followUpsLabel}: ` }),
|
|
966
|
-
followUpViewport.clippedStart ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "<-- " }) : null,
|
|
967
|
-
followUpViewport.items.map(({ question, index, label }) => {
|
|
968
|
-
const focused = followUpsActive && focusedFollowUpIndex === index;
|
|
969
|
-
return /* @__PURE__ */ jsxs4(
|
|
970
|
-
Text5,
|
|
971
|
-
{
|
|
972
|
-
color: focused ? terminalTheme.focus : void 0,
|
|
973
|
-
bold: focused,
|
|
974
|
-
children: [
|
|
975
|
-
focused ? raisedButtonStyle.activeMarker : raisedButtonStyle.inactiveMarker,
|
|
976
|
-
" ",
|
|
977
|
-
label,
|
|
978
|
-
" "
|
|
979
|
-
]
|
|
980
|
-
},
|
|
981
|
-
`${index}-${question}`
|
|
982
|
-
);
|
|
983
|
-
}),
|
|
984
|
-
followUpViewport.clippedEnd ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "-->" }) : null
|
|
985
|
-
] }) : null,
|
|
986
|
-
/* @__PURE__ */ jsxs4(
|
|
987
|
-
Box4,
|
|
988
|
-
{
|
|
989
|
-
flexDirection: compact ? "column" : "row",
|
|
990
|
-
children: [
|
|
991
|
-
/* @__PURE__ */ jsx5(Box4, { flexDirection: "column", flexGrow: 1, children: !value ? /* @__PURE__ */ jsxs4(Text5, { wrap: "truncate", children: [
|
|
992
|
-
/* @__PURE__ */ jsx5(Text5, { color: cursorColor, children: cursorGlyph }),
|
|
993
|
-
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: ` ${placeholder}` })
|
|
994
|
-
] }) : visibleRows.map((line, index) => {
|
|
995
|
-
const isLastValueRow = startRow + index === inputRows.length - 1;
|
|
996
|
-
return /* @__PURE__ */ jsxs4(Text5, { wrap: "truncate", children: [
|
|
997
|
-
line,
|
|
998
|
-
isLastValueRow ? /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
999
|
-
/* @__PURE__ */ jsx5(
|
|
1000
|
-
Text5,
|
|
1001
|
-
{
|
|
1002
|
-
dimColor: true,
|
|
1003
|
-
italic: true,
|
|
1004
|
-
color: terminalTheme.inputGhost,
|
|
1005
|
-
children: ghostText ?? ""
|
|
1006
|
-
}
|
|
1007
|
-
),
|
|
1008
|
-
/* @__PURE__ */ jsx5(Text5, { color: cursorColor, children: cursorGlyph })
|
|
1009
|
-
] }) : null
|
|
1010
|
-
] }, `${startRow}-${index}`);
|
|
1011
|
-
}) }),
|
|
1012
|
-
/* @__PURE__ */ jsx5(
|
|
1013
|
-
Scrollbar,
|
|
1014
|
-
{
|
|
1015
|
-
totalRows: inputRows.length,
|
|
1016
|
-
visibleRows: visibleRowCount,
|
|
1017
|
-
startRow
|
|
1018
|
-
}
|
|
1019
|
-
)
|
|
1020
|
-
]
|
|
1021
|
-
}
|
|
1022
|
-
),
|
|
1023
|
-
actionHint ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, wrap: "truncate", children: actionHint }) : resolvedHelpText ? /* @__PURE__ */ jsx5(Text5, { dimColor: true, wrap: "truncate", children: resolvedHelpText }) : null,
|
|
1024
|
-
footerControls ? /* @__PURE__ */ jsx5(Box4, { flexDirection: "column", marginTop: 1, children: footerControls }) : null
|
|
1025
|
-
]
|
|
1380
|
+
children: content
|
|
1026
1381
|
}
|
|
1027
1382
|
);
|
|
1028
1383
|
};
|
|
@@ -1242,7 +1597,7 @@ var slashCommands = [
|
|
|
1242
1597
|
{
|
|
1243
1598
|
name: "/thread",
|
|
1244
1599
|
aliases: ["/threads"],
|
|
1245
|
-
description: "Open thread selector or use /thread <title-or-id>."
|
|
1600
|
+
description: "Open session/thread selector or use /thread <title-or-id>."
|
|
1246
1601
|
},
|
|
1247
1602
|
{
|
|
1248
1603
|
name: "/project",
|
|
@@ -1284,6 +1639,16 @@ var slashCommands = [
|
|
|
1284
1639
|
aliases: ["/frontend"],
|
|
1285
1640
|
description: "Open the current thread in the frontend."
|
|
1286
1641
|
},
|
|
1642
|
+
{
|
|
1643
|
+
name: "/copy",
|
|
1644
|
+
aliases: ["/copy-response"],
|
|
1645
|
+
description: "Copy the latest assistant response with numbered citations."
|
|
1646
|
+
},
|
|
1647
|
+
{
|
|
1648
|
+
name: "/download",
|
|
1649
|
+
aliases: ["/export"],
|
|
1650
|
+
description: "Download the current chat transcript as Markdown."
|
|
1651
|
+
},
|
|
1287
1652
|
{
|
|
1288
1653
|
name: "/help",
|
|
1289
1654
|
aliases: ["/?"],
|
|
@@ -1300,6 +1665,28 @@ var firstTokenAndRest = (input) => {
|
|
|
1300
1665
|
};
|
|
1301
1666
|
};
|
|
1302
1667
|
var allCommandNames = () => slashCommands.flatMap((command) => [command.name, ...command.aliases]);
|
|
1668
|
+
var buildSlashCommandCompletionItems = (input) => {
|
|
1669
|
+
const trimmed = input.trimStart();
|
|
1670
|
+
if (!trimmed.startsWith("/") || /\s/.test(trimmed)) {
|
|
1671
|
+
return [];
|
|
1672
|
+
}
|
|
1673
|
+
const query = normalize(trimmed);
|
|
1674
|
+
return slashCommands.filter((command) => {
|
|
1675
|
+
if (query === "/") {
|
|
1676
|
+
return true;
|
|
1677
|
+
}
|
|
1678
|
+
return [command.name, ...command.aliases].some(
|
|
1679
|
+
(name) => name.startsWith(query)
|
|
1680
|
+
);
|
|
1681
|
+
});
|
|
1682
|
+
};
|
|
1683
|
+
var slashCommandGhostSuffix = (input, command) => {
|
|
1684
|
+
const trimmed = input.trimStart();
|
|
1685
|
+
if (!command || !trimmed.startsWith("/") || /\s/.test(trimmed)) {
|
|
1686
|
+
return void 0;
|
|
1687
|
+
}
|
|
1688
|
+
return toGhostSuffix(trimmed, command.name);
|
|
1689
|
+
};
|
|
1303
1690
|
var completeFromCandidates = (input, values, previous) => {
|
|
1304
1691
|
const candidates = [...new Set(values)].filter(Boolean);
|
|
1305
1692
|
if (!candidates.length) {
|
|
@@ -1314,12 +1701,12 @@ var completeFromCandidates = (input, values, previous) => {
|
|
|
1314
1701
|
index
|
|
1315
1702
|
};
|
|
1316
1703
|
};
|
|
1317
|
-
|
|
1704
|
+
function toGhostSuffix(input, suggestion) {
|
|
1318
1705
|
if (!suggestion.startsWith(input) || suggestion === input) {
|
|
1319
1706
|
return void 0;
|
|
1320
1707
|
}
|
|
1321
1708
|
return suggestion.slice(input.length);
|
|
1322
|
-
}
|
|
1709
|
+
}
|
|
1323
1710
|
var modelValue = (item) => item.value || "auto";
|
|
1324
1711
|
var projectName = (project) => project.name || project.id;
|
|
1325
1712
|
var completePromptInput = (input, context, previous) => {
|
|
@@ -1484,6 +1871,12 @@ var resolvePromptCommand = (input, context) => {
|
|
|
1484
1871
|
if (command === "/open" || command === "/frontend") {
|
|
1485
1872
|
return { type: "openFrontend" };
|
|
1486
1873
|
}
|
|
1874
|
+
if (command === "/copy" || command === "/copy-response") {
|
|
1875
|
+
return { type: "copyLatestResponse" };
|
|
1876
|
+
}
|
|
1877
|
+
if (command === "/download" || command === "/export") {
|
|
1878
|
+
return { type: "downloadTranscript" };
|
|
1879
|
+
}
|
|
1487
1880
|
if (command === "/help" || command === "/?") {
|
|
1488
1881
|
return { type: "showHelp" };
|
|
1489
1882
|
}
|
|
@@ -1503,11 +1896,18 @@ var creditProgressText = ({
|
|
|
1503
1896
|
const filled = Math.round(ratio * safeWidth);
|
|
1504
1897
|
return `[${"\u2588".repeat(filled)}${"\u2591".repeat(safeWidth - filled)}] ${Math.round(ratio * 100)}%`;
|
|
1505
1898
|
};
|
|
1506
|
-
var billingSummaryText = (billing, progressWidth = 10) =>
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1899
|
+
var billingSummaryText = (billing, progressWidth = 10) => {
|
|
1900
|
+
if (!billing) {
|
|
1901
|
+
return "Plan: loading | Credits: loading";
|
|
1902
|
+
}
|
|
1903
|
+
const used = Math.max(Number(billing.reportedUsed ?? billing.used ?? 0), 0);
|
|
1904
|
+
const creditLabel = used > 0 ? `${formatCredits(billing.remaining)} left | Used: ${formatCredits(used)}` : `${formatCredits(billing.remaining)}/${formatCredits(billing.total)}`;
|
|
1905
|
+
return `Plan: ${billing.plan} | Credits: ${creditLabel} ${creditProgressText({
|
|
1906
|
+
remaining: billing.remaining,
|
|
1907
|
+
total: billing.total,
|
|
1908
|
+
width: progressWidth
|
|
1909
|
+
})}`;
|
|
1910
|
+
};
|
|
1511
1911
|
|
|
1512
1912
|
// src/ui/interactionModel.ts
|
|
1513
1913
|
var selectorControls = ["thread", "project", "model", "mode", "profile"];
|
|
@@ -1692,10 +2092,40 @@ var getPromptInputRowBudget = (size) => {
|
|
|
1692
2092
|
const rows = normalizeDimension(size.rows, 32);
|
|
1693
2093
|
return clamp2(Math.floor(rows * 0.13), 4, 8);
|
|
1694
2094
|
};
|
|
1695
|
-
var
|
|
2095
|
+
var getChatResponsiveMode = (size) => {
|
|
1696
2096
|
const columns = normalizeDimension(size.columns, 100);
|
|
1697
2097
|
const rows = normalizeDimension(size.rows, 32);
|
|
1698
|
-
|
|
2098
|
+
if (columns >= 132 && rows >= 40) {
|
|
2099
|
+
return "wide";
|
|
2100
|
+
}
|
|
2101
|
+
if (columns >= 112 && rows >= 34) {
|
|
2102
|
+
return "medium";
|
|
2103
|
+
}
|
|
2104
|
+
return "narrow";
|
|
2105
|
+
};
|
|
2106
|
+
var shouldUseSplitChatLayout = (size) => getChatResponsiveMode(size) !== "narrow";
|
|
2107
|
+
var getContextRailWidth = (size) => {
|
|
2108
|
+
const mode = getChatResponsiveMode(size);
|
|
2109
|
+
const columns = normalizeDimension(size.columns, 100);
|
|
2110
|
+
if (mode === "wide") {
|
|
2111
|
+
return Math.min(40, Math.max(34, Math.ceil(columns * 0.25)));
|
|
2112
|
+
}
|
|
2113
|
+
if (mode === "medium") {
|
|
2114
|
+
return Math.min(30, Math.max(28, Math.ceil(columns * 0.25)));
|
|
2115
|
+
}
|
|
2116
|
+
return 0;
|
|
2117
|
+
};
|
|
2118
|
+
var estimateComposerRows = ({
|
|
2119
|
+
inputRows,
|
|
2120
|
+
suggestionRows,
|
|
2121
|
+
includeControls = true,
|
|
2122
|
+
controlRows = 0,
|
|
2123
|
+
variant = "panel"
|
|
2124
|
+
}) => {
|
|
2125
|
+
const chromeRows = variant === "dock" ? 1 : 2;
|
|
2126
|
+
const inputRowsWithHint = inputRows + 1;
|
|
2127
|
+
const footerRows = includeControls ? controlRows : 0;
|
|
2128
|
+
return chromeRows + Math.max(0, suggestionRows) + inputRowsWithHint + footerRows;
|
|
1699
2129
|
};
|
|
1700
2130
|
var truncateForTerminal = (value, maxLength) => {
|
|
1701
2131
|
if (maxLength <= 0) {
|
|
@@ -1710,6 +2140,130 @@ var truncateForTerminal = (value, maxLength) => {
|
|
|
1710
2140
|
return `${value.slice(0, maxLength - 3)}...`;
|
|
1711
2141
|
};
|
|
1712
2142
|
|
|
2143
|
+
// src/ui/artifactChips.ts
|
|
2144
|
+
var buildChatArtifactChips = ({
|
|
2145
|
+
projectName: projectName2,
|
|
2146
|
+
reportsStatus = "idle",
|
|
2147
|
+
coverageLabel,
|
|
2148
|
+
topActionCount = 0,
|
|
2149
|
+
frontendThreadUrl
|
|
2150
|
+
}) => {
|
|
2151
|
+
const chips = [];
|
|
2152
|
+
if (projectName2) {
|
|
2153
|
+
chips.push({ label: "Project", value: projectName2, tone: "brand" });
|
|
2154
|
+
}
|
|
2155
|
+
if (coverageLabel) {
|
|
2156
|
+
chips.push({ label: "Reports", value: coverageLabel, tone: "success" });
|
|
2157
|
+
} else if (reportsStatus === "loading" || reportsStatus === "ready" || reportsStatus === "error") {
|
|
2158
|
+
chips.push({
|
|
2159
|
+
label: "Reports",
|
|
2160
|
+
value: reportsStatus,
|
|
2161
|
+
tone: reportsStatus === "error" ? "danger" : "normal"
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
2164
|
+
if (topActionCount > 0) {
|
|
2165
|
+
chips.push({
|
|
2166
|
+
label: "Actions",
|
|
2167
|
+
value: `${topActionCount} next`,
|
|
2168
|
+
tone: "warning"
|
|
2169
|
+
});
|
|
2170
|
+
}
|
|
2171
|
+
if (frontendThreadUrl) {
|
|
2172
|
+
chips.push({ label: "Web", value: "open thread", tone: "normal" });
|
|
2173
|
+
}
|
|
2174
|
+
return chips;
|
|
2175
|
+
};
|
|
2176
|
+
|
|
2177
|
+
// src/ui/chatResponseActions.ts
|
|
2178
|
+
import { spawnSync } from "child_process";
|
|
2179
|
+
import { mkdirSync, writeFileSync } from "fs";
|
|
2180
|
+
import { join, resolve } from "path";
|
|
2181
|
+
var getLatestAssistantMessage = (messages) => [...messages].reverse().find((message) => message.role === "assistant" && message.content.trim());
|
|
2182
|
+
var getClipboardCommand = (platform = process.platform) => {
|
|
2183
|
+
if (platform === "darwin") {
|
|
2184
|
+
return { command: "pbcopy", args: [] };
|
|
2185
|
+
}
|
|
2186
|
+
if (platform === "win32") {
|
|
2187
|
+
return { command: "cmd", args: ["/c", "clip"] };
|
|
2188
|
+
}
|
|
2189
|
+
return {
|
|
2190
|
+
command: "sh",
|
|
2191
|
+
args: [
|
|
2192
|
+
"-lc",
|
|
2193
|
+
"if command -v wl-copy >/dev/null 2>&1; then wl-copy; elif command -v xclip >/dev/null 2>&1; then xclip -selection clipboard; elif command -v xsel >/dev/null 2>&1; then xsel --clipboard --input; else exit 127; fi"
|
|
2194
|
+
]
|
|
2195
|
+
};
|
|
2196
|
+
};
|
|
2197
|
+
var copyTextToClipboard = (text, options = {}) => {
|
|
2198
|
+
const clipboardCommand = getClipboardCommand(options.platform);
|
|
2199
|
+
const result = (options.spawnSyncImpl ?? spawnSync)(
|
|
2200
|
+
clipboardCommand.command,
|
|
2201
|
+
clipboardCommand.args,
|
|
2202
|
+
{ input: text, encoding: "utf8" }
|
|
2203
|
+
);
|
|
2204
|
+
if (result.error) {
|
|
2205
|
+
throw result.error;
|
|
2206
|
+
}
|
|
2207
|
+
if (result.status !== 0) {
|
|
2208
|
+
throw new Error("No clipboard command is available for this terminal.");
|
|
2209
|
+
}
|
|
2210
|
+
};
|
|
2211
|
+
var buildLatestAssistantResponseText = (messages) => {
|
|
2212
|
+
const message = getLatestAssistantMessage(messages);
|
|
2213
|
+
if (!message) {
|
|
2214
|
+
return void 0;
|
|
2215
|
+
}
|
|
2216
|
+
return toCitationExportContent({
|
|
2217
|
+
content: message.content,
|
|
2218
|
+
toolsUsed: message.toolsUsed,
|
|
2219
|
+
citations: message.citations
|
|
2220
|
+
}).trim();
|
|
2221
|
+
};
|
|
2222
|
+
var roleLabel = (message, userName) => message.role === "user" ? userName : "Cloudeval AI";
|
|
2223
|
+
var buildChatTranscriptMarkdown = ({
|
|
2224
|
+
messages,
|
|
2225
|
+
userName,
|
|
2226
|
+
threadId,
|
|
2227
|
+
exportedAt = /* @__PURE__ */ new Date()
|
|
2228
|
+
}) => {
|
|
2229
|
+
const renderedMessages = messages.filter((message) => message.content.trim()).map((message) => {
|
|
2230
|
+
const content = message.role === "assistant" ? toCitationExportContent({
|
|
2231
|
+
content: message.content,
|
|
2232
|
+
toolsUsed: message.toolsUsed,
|
|
2233
|
+
citations: message.citations
|
|
2234
|
+
}) : message.content;
|
|
2235
|
+
return `## ${roleLabel(message, userName)}
|
|
2236
|
+
|
|
2237
|
+
${content.trim()}`;
|
|
2238
|
+
});
|
|
2239
|
+
return [
|
|
2240
|
+
"# CloudEval chat transcript",
|
|
2241
|
+
"",
|
|
2242
|
+
`Exported: ${exportedAt.toISOString()}`,
|
|
2243
|
+
threadId ? `Thread: ${threadId}` : void 0,
|
|
2244
|
+
"",
|
|
2245
|
+
...renderedMessages,
|
|
2246
|
+
""
|
|
2247
|
+
].filter((line) => line !== void 0).join("\n");
|
|
2248
|
+
};
|
|
2249
|
+
var writeChatTranscriptDownload = ({
|
|
2250
|
+
messages,
|
|
2251
|
+
userName,
|
|
2252
|
+
threadId,
|
|
2253
|
+
cwd = process.cwd()
|
|
2254
|
+
}) => {
|
|
2255
|
+
const dir = resolve(cwd, ".cloudeval-downloads");
|
|
2256
|
+
mkdirSync(dir, { recursive: true });
|
|
2257
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
2258
|
+
const file = join(dir, `chat-transcript-${timestamp}.md`);
|
|
2259
|
+
writeFileSync(
|
|
2260
|
+
file,
|
|
2261
|
+
buildChatTranscriptMarkdown({ messages, userName, threadId }),
|
|
2262
|
+
"utf8"
|
|
2263
|
+
);
|
|
2264
|
+
return file;
|
|
2265
|
+
};
|
|
2266
|
+
|
|
1713
2267
|
// src/ui/scrollBehavior.ts
|
|
1714
2268
|
var shouldAutoScrollToBottom = ({
|
|
1715
2269
|
currentOffset,
|
|
@@ -2042,6 +2596,11 @@ var sessionDescription = (session, age) => {
|
|
|
2042
2596
|
const messages = `${session.messageCount} message${session.messageCount === 1 ? "" : "s"}`;
|
|
2043
2597
|
return [createdAgeDescription(age), project, messages].filter(Boolean).join(" \xB7 ");
|
|
2044
2598
|
};
|
|
2599
|
+
var draftDescription = (draft, age) => {
|
|
2600
|
+
const messages = `${draft.messageCount} message${draft.messageCount === 1 ? "" : "s"}`;
|
|
2601
|
+
const status = draft.status && draft.status !== "idle" && draft.status !== "complete" ? draft.status.replace(/_/g, " ") : "active locally";
|
|
2602
|
+
return ["Open session", status, createdAgeDescription(age), draft.projectName, messages].filter(Boolean).join(" \xB7 ");
|
|
2603
|
+
};
|
|
2045
2604
|
var remoteTitle = (thread) => {
|
|
2046
2605
|
const title = String(thread.title || "").trim();
|
|
2047
2606
|
const preview = String(thread.last_message_preview || "").trim();
|
|
@@ -2133,12 +2692,48 @@ var localSessionMessagesToChatMessages = (session) => session.messages.map((mess
|
|
|
2133
2692
|
content: message.content,
|
|
2134
2693
|
createdAt: timestampFromIso(message.createdAt, index)
|
|
2135
2694
|
}));
|
|
2695
|
+
var buildDraftThreadSummary = ({
|
|
2696
|
+
key,
|
|
2697
|
+
state,
|
|
2698
|
+
projectName: projectName2,
|
|
2699
|
+
updatedAt
|
|
2700
|
+
}) => {
|
|
2701
|
+
const messages = state.messages.filter((message) => message.content.trim());
|
|
2702
|
+
if (!messages.length && !state.threadId) {
|
|
2703
|
+
return null;
|
|
2704
|
+
}
|
|
2705
|
+
const firstUserMessage = messages.find((message) => message.role === "user");
|
|
2706
|
+
const fallbackTitle = state.threadId ?? "New local session";
|
|
2707
|
+
const title = truncateForTerminal(
|
|
2708
|
+
firstUserMessage?.content.trim() || messages[0]?.content.trim() || fallbackTitle,
|
|
2709
|
+
72
|
|
2710
|
+
);
|
|
2711
|
+
const messageTimestamps = messages.map((message) => message.updatedAt ?? message.createdAt).filter((value) => Number.isFinite(value));
|
|
2712
|
+
const lastUpdated = updatedAt ?? (messageTimestamps.length ? Math.max(...messageTimestamps) : Date.now());
|
|
2713
|
+
return {
|
|
2714
|
+
key,
|
|
2715
|
+
title,
|
|
2716
|
+
threadId: state.threadId,
|
|
2717
|
+
updatedAt: lastUpdated,
|
|
2718
|
+
projectName: projectName2,
|
|
2719
|
+
messageCount: messages.length,
|
|
2720
|
+
status: state.status
|
|
2721
|
+
};
|
|
2722
|
+
};
|
|
2136
2723
|
var buildThreadSelectItems = (sessions, activeThreadId, remoteThreads = [], options = {}) => [
|
|
2137
2724
|
{
|
|
2138
2725
|
label: "New thread",
|
|
2139
2726
|
value: { kind: "new" },
|
|
2140
2727
|
description: activeThreadId ? "Start a fresh CloudEval chat thread." : "Current selection."
|
|
2141
2728
|
},
|
|
2729
|
+
...(options.drafts ?? []).map((draft) => {
|
|
2730
|
+
const age = draft.updatedAt ? relativeThreadAge(new Date(draft.updatedAt).toISOString(), options.now) : void 0;
|
|
2731
|
+
return {
|
|
2732
|
+
label: titleWithAge(draft.title, age),
|
|
2733
|
+
value: { kind: "draft", draft },
|
|
2734
|
+
description: draftDescription(draft, age)
|
|
2735
|
+
};
|
|
2736
|
+
}),
|
|
2142
2737
|
...remoteThreads.map((thread) => {
|
|
2143
2738
|
const age = relativeThreadAge(thread.created_at ?? thread.updated_at, options.now);
|
|
2144
2739
|
return {
|
|
@@ -2440,7 +3035,7 @@ var firstNumber2 = (value, keys) => {
|
|
|
2440
3035
|
}
|
|
2441
3036
|
return void 0;
|
|
2442
3037
|
};
|
|
2443
|
-
var
|
|
3038
|
+
var firstString2 = (value, keys) => {
|
|
2444
3039
|
const record = toRecord2(value);
|
|
2445
3040
|
if (!record) {
|
|
2446
3041
|
return void 0;
|
|
@@ -2519,7 +3114,7 @@ var extractPillarScores = (report) => {
|
|
|
2519
3114
|
const rows = pillarArray.map((item) => {
|
|
2520
3115
|
const record = toRecord2(item);
|
|
2521
3116
|
if (!record) return void 0;
|
|
2522
|
-
const label =
|
|
3117
|
+
const label = firstString2(record, ["label", "id", "pillar"]);
|
|
2523
3118
|
const value = firstNumber2(record, ["score", "value"]);
|
|
2524
3119
|
return label && value !== void 0 ? { [label]: value } : void 0;
|
|
2525
3120
|
}).filter(Boolean).reduce((acc, row) => ({ ...acc, ...row }), {});
|
|
@@ -2558,7 +3153,7 @@ var extractMonthlySavings = (report) => firstNumber2(firstRecord2(report, ["pars
|
|
|
2558
3153
|
]) ?? firstNumber2(report, ["total_monthly_savings", "monthly_savings"]);
|
|
2559
3154
|
var extractCurrency = (...values) => {
|
|
2560
3155
|
for (const value of values) {
|
|
2561
|
-
const currency =
|
|
3156
|
+
const currency = firstString2(value, ["currency"]) ?? firstString2(firstRecord2(value, ["parsed", "totalSpend"]), ["currency"]) ?? firstString2(firstRecord2(value, ["dashboard"]), ["currency"]) ?? firstString2(firstRecord2(value, ["processed"]), ["currency"]);
|
|
2562
3157
|
if (currency) {
|
|
2563
3158
|
return currency;
|
|
2564
3159
|
}
|
|
@@ -2617,7 +3212,7 @@ var projectHealthRows = (reportsSummary, selectedProjectId) => firstArray(report
|
|
|
2617
3212
|
architectureStatus: String(record.architecture_status ?? "not_started"),
|
|
2618
3213
|
unitTestsStatus: String(record.unit_tests_status ?? "not_started"),
|
|
2619
3214
|
freshness: String(record.freshness ?? "missing"),
|
|
2620
|
-
lastReportAt:
|
|
3215
|
+
lastReportAt: firstString2(record, ["last_report_at"]),
|
|
2621
3216
|
criticalIssues: firstNumber2(record, ["critical_issues"]) ?? 0,
|
|
2622
3217
|
coveragePercent: firstNumber2(record, ["coverage_percent"]) ?? 0,
|
|
2623
3218
|
isSelected: Boolean(selectedProjectId && projectId === selectedProjectId)
|
|
@@ -2797,8 +3392,8 @@ var buildReportsDashboardModel = ({
|
|
|
2797
3392
|
return {
|
|
2798
3393
|
label: String(record.label ?? "Action"),
|
|
2799
3394
|
issueCount: firstNumber2(record, ["issue_count"]),
|
|
2800
|
-
priority:
|
|
2801
|
-
pillar:
|
|
3395
|
+
priority: firstString2(record, ["priority"]),
|
|
3396
|
+
pillar: firstString2(record, ["pillar"])
|
|
2802
3397
|
};
|
|
2803
3398
|
}).filter((action) => action.label.trim()).slice(0, 20),
|
|
2804
3399
|
topInsights: firstArray(reportsSummary, ["top_insights"]).map((insight) => String(insight)).filter(Boolean).slice(0, 20)
|
|
@@ -2906,7 +3501,7 @@ var directArray = (value) => {
|
|
|
2906
3501
|
}
|
|
2907
3502
|
return [];
|
|
2908
3503
|
};
|
|
2909
|
-
var
|
|
3504
|
+
var firstString3 = (value, keys, fallback = "") => {
|
|
2910
3505
|
const record = toRecord3(value);
|
|
2911
3506
|
if (!record) {
|
|
2912
3507
|
return fallback;
|
|
@@ -2972,11 +3567,11 @@ var buildReportsSummaryFromHistory = ({
|
|
|
2972
3567
|
const statusBreakdown = {};
|
|
2973
3568
|
const rowsByProject = /* @__PURE__ */ new Map();
|
|
2974
3569
|
for (const item of rows) {
|
|
2975
|
-
const reportType = normalizeReportType(
|
|
2976
|
-
const status =
|
|
2977
|
-
const projectId =
|
|
2978
|
-
const projectName2 =
|
|
2979
|
-
const generatedAt =
|
|
3570
|
+
const reportType = normalizeReportType(firstString3(item, ["report_type", "kind"], "cost"));
|
|
3571
|
+
const status = firstString3(item, ["status"], "completed").toLowerCase();
|
|
3572
|
+
const projectId = firstString3(item, ["project_id", "projectId"], "unknown-project");
|
|
3573
|
+
const projectName2 = firstString3(item, ["project_name", "projectName"]) || projects.find((project) => project.id === projectId)?.name || projectId;
|
|
3574
|
+
const generatedAt = firstString3(item, ["generated_at", "generatedAt"]);
|
|
2980
3575
|
const metrics = toRecord3((toRecord3(item) ?? {}).metrics) ?? {};
|
|
2981
3576
|
const existing = rowsByProject.get(projectId) ?? {
|
|
2982
3577
|
project_id: projectId,
|
|
@@ -3077,7 +3672,7 @@ var loadWorkspacePanelData = async ({
|
|
|
3077
3672
|
return void 0;
|
|
3078
3673
|
}
|
|
3079
3674
|
};
|
|
3080
|
-
if (tab === "overview" || tab === "connections") {
|
|
3675
|
+
if (tab === "overview" || tab === "connections" || tab === "projects") {
|
|
3081
3676
|
if (currentUserId) {
|
|
3082
3677
|
await capture(
|
|
3083
3678
|
"connections",
|
|
@@ -3211,7 +3806,8 @@ var loadWorkspacePanelData = async ({
|
|
|
3211
3806
|
import React7 from "react";
|
|
3212
3807
|
import { Box as Box8, Text as Text9 } from "ink";
|
|
3213
3808
|
import { plot as plotAsciiChart } from "asciichart";
|
|
3214
|
-
|
|
3809
|
+
|
|
3810
|
+
// src/ui/workspaceEntityDetails.ts
|
|
3215
3811
|
var toRecord4 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
3216
3812
|
var directArray2 = (value) => {
|
|
3217
3813
|
if (Array.isArray(value)) {
|
|
@@ -3221,6 +3817,199 @@ var directArray2 = (value) => {
|
|
|
3221
3817
|
if (!record) {
|
|
3222
3818
|
return [];
|
|
3223
3819
|
}
|
|
3820
|
+
for (const key of ["items", "data", "rows", "results", "connections", "projects"]) {
|
|
3821
|
+
const candidate = record[key];
|
|
3822
|
+
if (Array.isArray(candidate)) {
|
|
3823
|
+
return candidate;
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
return [];
|
|
3827
|
+
};
|
|
3828
|
+
var firstString4 = (value, keys, fallback = "") => {
|
|
3829
|
+
const record = toRecord4(value);
|
|
3830
|
+
if (!record) {
|
|
3831
|
+
return fallback;
|
|
3832
|
+
}
|
|
3833
|
+
for (const key of keys) {
|
|
3834
|
+
const current = record[key];
|
|
3835
|
+
if (typeof current === "string" && current.trim()) {
|
|
3836
|
+
return current.trim();
|
|
3837
|
+
}
|
|
3838
|
+
if (typeof current === "number" && Number.isFinite(current)) {
|
|
3839
|
+
return String(current);
|
|
3840
|
+
}
|
|
3841
|
+
if (typeof current === "boolean") {
|
|
3842
|
+
return current ? "on" : "off";
|
|
3843
|
+
}
|
|
3844
|
+
}
|
|
3845
|
+
return fallback;
|
|
3846
|
+
};
|
|
3847
|
+
var firstNumber4 = (value, keys) => {
|
|
3848
|
+
const record = toRecord4(value);
|
|
3849
|
+
if (!record) {
|
|
3850
|
+
return void 0;
|
|
3851
|
+
}
|
|
3852
|
+
for (const key of keys) {
|
|
3853
|
+
const current = record[key];
|
|
3854
|
+
const numberValue = typeof current === "number" ? current : Number(current);
|
|
3855
|
+
if (Number.isFinite(numberValue)) {
|
|
3856
|
+
return numberValue;
|
|
3857
|
+
}
|
|
3858
|
+
}
|
|
3859
|
+
return void 0;
|
|
3860
|
+
};
|
|
3861
|
+
var statusTone = (value) => {
|
|
3862
|
+
const normalized = value.toLowerCase();
|
|
3863
|
+
if (["completed", "ready", "fresh", "synced", "success", "active"].includes(normalized)) {
|
|
3864
|
+
return "success";
|
|
3865
|
+
}
|
|
3866
|
+
if (["running", "partial", "pending", "stale"].includes(normalized)) {
|
|
3867
|
+
return "warning";
|
|
3868
|
+
}
|
|
3869
|
+
if (["failed", "error", "missing", "outdated", "disabled"].includes(normalized)) {
|
|
3870
|
+
return "danger";
|
|
3871
|
+
}
|
|
3872
|
+
return "muted";
|
|
3873
|
+
};
|
|
3874
|
+
var truncateDetail = (value, limit = 96) => value.length <= limit ? value : `${value.slice(0, limit - 3)}...`;
|
|
3875
|
+
var projectIdsForConnection = (connection) => {
|
|
3876
|
+
const record = toRecord4(connection);
|
|
3877
|
+
if (!record) {
|
|
3878
|
+
return [];
|
|
3879
|
+
}
|
|
3880
|
+
const values = [
|
|
3881
|
+
record.project_id,
|
|
3882
|
+
record.projectId,
|
|
3883
|
+
record.project,
|
|
3884
|
+
record.project_name
|
|
3885
|
+
];
|
|
3886
|
+
const arrayValues = [
|
|
3887
|
+
record.project_ids,
|
|
3888
|
+
record.projectIds,
|
|
3889
|
+
record.projects,
|
|
3890
|
+
record.linked_project_ids
|
|
3891
|
+
].flatMap((value) => directArray2(value));
|
|
3892
|
+
return [...values, ...arrayValues].map((value) => firstString4({ value }, ["value"])).filter(Boolean);
|
|
3893
|
+
};
|
|
3894
|
+
var connectionMatchesProject = (connection, project) => {
|
|
3895
|
+
const haystack = projectIdsForConnection(connection).map((value) => value.toLowerCase());
|
|
3896
|
+
const id = String(project.id ?? "").toLowerCase();
|
|
3897
|
+
const name = String(project.name ?? "").toLowerCase();
|
|
3898
|
+
return Boolean(id && haystack.includes(id) || name && haystack.includes(name));
|
|
3899
|
+
};
|
|
3900
|
+
var projectHealthFor = (reportsSummary, project) => {
|
|
3901
|
+
const rows = directArray2(toRecord4(reportsSummary)?.project_health);
|
|
3902
|
+
return rows.map(toRecord4).find((row) => {
|
|
3903
|
+
if (!row) {
|
|
3904
|
+
return false;
|
|
3905
|
+
}
|
|
3906
|
+
return String(row.project_id ?? row.projectId ?? "").toLowerCase() === String(project.id ?? "").toLowerCase() || String(row.project_name ?? row.projectName ?? "").toLowerCase() === String(project.name ?? "").toLowerCase();
|
|
3907
|
+
});
|
|
3908
|
+
};
|
|
3909
|
+
var buildProjectDetailModel = ({
|
|
3910
|
+
project,
|
|
3911
|
+
connections,
|
|
3912
|
+
reportsSummary
|
|
3913
|
+
}) => {
|
|
3914
|
+
if (!project) {
|
|
3915
|
+
return null;
|
|
3916
|
+
}
|
|
3917
|
+
const linkedConnections = connections.filter(
|
|
3918
|
+
(connection) => connectionMatchesProject(connection, project)
|
|
3919
|
+
);
|
|
3920
|
+
const status = firstString4(project, ["status", "sync_status", "last_sync_status"], "unknown");
|
|
3921
|
+
const health = projectHealthFor(reportsSummary, project);
|
|
3922
|
+
const coverage = firstNumber4(health, ["coverage_percent", "coveragePercent"]);
|
|
3923
|
+
const critical = firstNumber4(health, ["critical_issues", "criticalIssues", "critical_count"]);
|
|
3924
|
+
const lastReport = firstString4(health, ["last_report_at", "lastReportAt", "generated_at"]);
|
|
3925
|
+
return {
|
|
3926
|
+
title: firstString4(project, ["name"], "Project"),
|
|
3927
|
+
subtitle: firstString4(project, ["id"]),
|
|
3928
|
+
metrics: [
|
|
3929
|
+
{
|
|
3930
|
+
label: "Provider",
|
|
3931
|
+
value: firstString4(project, ["cloud_provider", "provider"], "cloud"),
|
|
3932
|
+
tone: "brand"
|
|
3933
|
+
},
|
|
3934
|
+
{ label: "Type", value: firstString4(project, ["type", "source_type"], "project") },
|
|
3935
|
+
{ label: "Status", value: status, tone: statusTone(status) },
|
|
3936
|
+
{ label: "Connections", value: String(linkedConnections.length), tone: "brand" }
|
|
3937
|
+
],
|
|
3938
|
+
detailRows: [
|
|
3939
|
+
{ label: "Created", value: firstString4(project, ["created_at", "createdAt"], "-") },
|
|
3940
|
+
{ label: "Updated", value: firstString4(project, ["updated_at", "updatedAt"], "-") },
|
|
3941
|
+
...coverage !== void 0 ? [{ label: "Report coverage", value: `${Math.round(coverage)}%`, tone: "brand" }] : [],
|
|
3942
|
+
...critical !== void 0 ? [{ label: "Critical issues", value: String(critical), tone: critical > 0 ? "danger" : "success" }] : [],
|
|
3943
|
+
...lastReport ? [{ label: "Last report", value: lastReport }] : []
|
|
3944
|
+
],
|
|
3945
|
+
relatedItems: linkedConnections.map((connection) => ({
|
|
3946
|
+
label: firstString4(connection, ["name"], "Connection"),
|
|
3947
|
+
detail: firstString4(connection, ["last_sync_status", "status", "type"], ""),
|
|
3948
|
+
tone: statusTone(firstString4(connection, ["last_sync_status", "status"], ""))
|
|
3949
|
+
}))
|
|
3950
|
+
};
|
|
3951
|
+
};
|
|
3952
|
+
var linkedProjectForConnection = (connection, projects) => {
|
|
3953
|
+
const ids = projectIdsForConnection(connection).map((value) => value.toLowerCase());
|
|
3954
|
+
return projects.find((project) => {
|
|
3955
|
+
const id = String(project.id ?? "").toLowerCase();
|
|
3956
|
+
const name = String(project.name ?? "").toLowerCase();
|
|
3957
|
+
return id && ids.includes(id) || name && ids.includes(name);
|
|
3958
|
+
});
|
|
3959
|
+
};
|
|
3960
|
+
var buildConnectionDetailModel = ({
|
|
3961
|
+
connection,
|
|
3962
|
+
projects
|
|
3963
|
+
}) => {
|
|
3964
|
+
const record = toRecord4(connection);
|
|
3965
|
+
if (!record) {
|
|
3966
|
+
return null;
|
|
3967
|
+
}
|
|
3968
|
+
const linkedProject = linkedProjectForConnection(connection, projects);
|
|
3969
|
+
const sync = firstString4(connection, ["last_sync_status", "sync_status", "status"], "unknown");
|
|
3970
|
+
const autoSync = firstString4(connection, ["auto_sync", "autoSync"], "off");
|
|
3971
|
+
const source = firstString4(connection, [
|
|
3972
|
+
"template_url",
|
|
3973
|
+
"source_url",
|
|
3974
|
+
"repo_url",
|
|
3975
|
+
"repository_url",
|
|
3976
|
+
"visualization_source_path",
|
|
3977
|
+
"workspace_file_paths"
|
|
3978
|
+
]);
|
|
3979
|
+
return {
|
|
3980
|
+
title: firstString4(connection, ["name"], "Connection"),
|
|
3981
|
+
subtitle: firstString4(connection, ["id"]),
|
|
3982
|
+
metrics: [
|
|
3983
|
+
{
|
|
3984
|
+
label: "Provider",
|
|
3985
|
+
value: firstString4(connection, ["cloud_provider", "provider"], "cloud"),
|
|
3986
|
+
tone: "brand"
|
|
3987
|
+
},
|
|
3988
|
+
{ label: "Type", value: firstString4(connection, ["type", "connection_type"], "connection") },
|
|
3989
|
+
{ label: "Sync", value: sync, tone: statusTone(sync) },
|
|
3990
|
+
{ label: "Auto", value: autoSync, tone: autoSync === "on" ? "success" : "muted" }
|
|
3991
|
+
],
|
|
3992
|
+
detailRows: [
|
|
3993
|
+
{ label: "Project", value: linkedProject?.name ?? firstString4(connection, ["project_name", "project_id"], "-") },
|
|
3994
|
+
{ label: "Last synced", value: firstString4(connection, ["last_synced", "lastSynced", "updated_at"], "-") },
|
|
3995
|
+
...source ? [{ label: "Source", value: truncateDetail(source), tone: "brand" }] : [],
|
|
3996
|
+
{ label: "Created", value: firstString4(connection, ["created_at", "createdAt"], "-") }
|
|
3997
|
+
],
|
|
3998
|
+
relatedItems: linkedProject ? [{ label: linkedProject.name, detail: linkedProject.cloud_provider ?? "project", tone: "brand" }] : []
|
|
3999
|
+
};
|
|
4000
|
+
};
|
|
4001
|
+
|
|
4002
|
+
// src/ui/workspacePanel.tsx
|
|
4003
|
+
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
4004
|
+
var toRecord5 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
4005
|
+
var directArray3 = (value) => {
|
|
4006
|
+
if (Array.isArray(value)) {
|
|
4007
|
+
return value;
|
|
4008
|
+
}
|
|
4009
|
+
const record = toRecord5(value);
|
|
4010
|
+
if (!record) {
|
|
4011
|
+
return [];
|
|
4012
|
+
}
|
|
3224
4013
|
for (const key of [
|
|
3225
4014
|
"data",
|
|
3226
4015
|
"items",
|
|
@@ -3240,9 +4029,9 @@ var directArray2 = (value) => {
|
|
|
3240
4029
|
if (Array.isArray(candidate)) {
|
|
3241
4030
|
return candidate;
|
|
3242
4031
|
}
|
|
3243
|
-
const nested =
|
|
4032
|
+
const nested = toRecord5(candidate);
|
|
3244
4033
|
if (nested) {
|
|
3245
|
-
const nestedArray =
|
|
4034
|
+
const nestedArray = directArray3(nested);
|
|
3246
4035
|
if (nestedArray.length) {
|
|
3247
4036
|
return nestedArray;
|
|
3248
4037
|
}
|
|
@@ -3266,7 +4055,7 @@ var allNumbers = (value, limit = 36) => {
|
|
|
3266
4055
|
}
|
|
3267
4056
|
return;
|
|
3268
4057
|
}
|
|
3269
|
-
const record =
|
|
4058
|
+
const record = toRecord5(current);
|
|
3270
4059
|
if (!record) {
|
|
3271
4060
|
return;
|
|
3272
4061
|
}
|
|
@@ -3281,8 +4070,8 @@ var allNumbers = (value, limit = 36) => {
|
|
|
3281
4070
|
visit(value);
|
|
3282
4071
|
return output;
|
|
3283
4072
|
};
|
|
3284
|
-
var
|
|
3285
|
-
const record =
|
|
4073
|
+
var firstString5 = (value, keys, fallback = "unknown") => {
|
|
4074
|
+
const record = toRecord5(value);
|
|
3286
4075
|
if (!record) {
|
|
3287
4076
|
return fallback;
|
|
3288
4077
|
}
|
|
@@ -3297,8 +4086,8 @@ var firstString3 = (value, keys, fallback = "unknown") => {
|
|
|
3297
4086
|
}
|
|
3298
4087
|
return fallback;
|
|
3299
4088
|
};
|
|
3300
|
-
var
|
|
3301
|
-
const record =
|
|
4089
|
+
var firstNumber5 = (value, keys) => {
|
|
4090
|
+
const record = toRecord5(value);
|
|
3302
4091
|
if (!record) {
|
|
3303
4092
|
return void 0;
|
|
3304
4093
|
}
|
|
@@ -3312,14 +4101,14 @@ var firstNumber4 = (value, keys) => {
|
|
|
3312
4101
|
return void 0;
|
|
3313
4102
|
};
|
|
3314
4103
|
var billingUsageTrendValues = (usageSummary) => {
|
|
3315
|
-
const record =
|
|
3316
|
-
const buckets =
|
|
3317
|
-
const bucketValues = buckets.map((bucket) =>
|
|
4104
|
+
const record = toRecord5(usageSummary);
|
|
4105
|
+
const buckets = directArray3(record?.buckets);
|
|
4106
|
+
const bucketValues = buckets.map((bucket) => firstNumber5(bucket, ["credits_used", "total_credits", "credits"])).filter((value) => value !== void 0);
|
|
3318
4107
|
if (bucketValues.length) {
|
|
3319
4108
|
return bucketValues;
|
|
3320
4109
|
}
|
|
3321
|
-
const totals =
|
|
3322
|
-
const total =
|
|
4110
|
+
const totals = toRecord5(record?.totals);
|
|
4111
|
+
const total = firstNumber5(totals ?? usageSummary, ["credits_used", "total_credits", "credits"]);
|
|
3323
4112
|
return total !== void 0 ? [total] : allNumbers(usageSummary);
|
|
3324
4113
|
};
|
|
3325
4114
|
var formatNumber3 = (value) => value === void 0 ? "-" : new Intl.NumberFormat("en-US", { maximumFractionDigits: 2 }).format(
|
|
@@ -3327,6 +4116,8 @@ var formatNumber3 = (value) => value === void 0 ? "-" : new Intl.NumberFormat("e
|
|
|
3327
4116
|
);
|
|
3328
4117
|
var formatPercent = (value) => value === void 0 ? "-" : `${Math.round(value * 100)}%`;
|
|
3329
4118
|
var metricColor = (tone) => {
|
|
4119
|
+
if (tone === "brand") return terminalTheme.brand;
|
|
4120
|
+
if (tone === "muted") return terminalTheme.muted;
|
|
3330
4121
|
if (tone === "success") return terminalTheme.success;
|
|
3331
4122
|
if (tone === "warning") return terminalTheme.warning;
|
|
3332
4123
|
if (tone === "danger") return terminalTheme.danger;
|
|
@@ -3407,7 +4198,7 @@ var AsciiLineChart = ({ values, width, height = 4, tone }) => {
|
|
|
3407
4198
|
)) });
|
|
3408
4199
|
};
|
|
3409
4200
|
var keySummary = (value) => {
|
|
3410
|
-
const record =
|
|
4201
|
+
const record = toRecord5(value);
|
|
3411
4202
|
if (!record) {
|
|
3412
4203
|
return "no object payload";
|
|
3413
4204
|
}
|
|
@@ -3415,11 +4206,11 @@ var keySummary = (value) => {
|
|
|
3415
4206
|
return keys.length ? keys.join(", ") : "empty object";
|
|
3416
4207
|
};
|
|
3417
4208
|
var rowLabel = (value, fallback) => {
|
|
3418
|
-
const record =
|
|
4209
|
+
const record = toRecord5(value);
|
|
3419
4210
|
if (!record) {
|
|
3420
4211
|
return typeof value === "string" ? value : fallback;
|
|
3421
4212
|
}
|
|
3422
|
-
return
|
|
4213
|
+
return firstString5(
|
|
3423
4214
|
record,
|
|
3424
4215
|
[
|
|
3425
4216
|
"name",
|
|
@@ -3435,21 +4226,21 @@ var rowLabel = (value, fallback) => {
|
|
|
3435
4226
|
);
|
|
3436
4227
|
};
|
|
3437
4228
|
var rowDetail = (value) => {
|
|
3438
|
-
const record =
|
|
4229
|
+
const record = toRecord5(value);
|
|
3439
4230
|
if (!record) {
|
|
3440
4231
|
return "";
|
|
3441
4232
|
}
|
|
3442
4233
|
const parts = [
|
|
3443
|
-
|
|
4234
|
+
firstString5(record, ["cloud_provider", "provider"], ""),
|
|
3444
4235
|
(() => {
|
|
3445
|
-
const status =
|
|
4236
|
+
const status = firstString5(
|
|
3446
4237
|
record,
|
|
3447
4238
|
["effective_status", "status", "outcome"],
|
|
3448
4239
|
""
|
|
3449
4240
|
);
|
|
3450
4241
|
return status.toLowerCase().replace(/[\s-]+/g, "_") === "trial_active" ? "" : status;
|
|
3451
4242
|
})(),
|
|
3452
|
-
|
|
4243
|
+
firstString5(
|
|
3453
4244
|
record,
|
|
3454
4245
|
["created_at", "updated_at", "timestamp", "period"],
|
|
3455
4246
|
""
|
|
@@ -3543,11 +4334,9 @@ var BillingSummaryLine = ({
|
|
|
3543
4334
|
/* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
|
|
3544
4335
|
"Credits:",
|
|
3545
4336
|
" ",
|
|
3546
|
-
/* @__PURE__ */
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
formatCredits(billing.total)
|
|
3550
|
-
] })
|
|
4337
|
+
/* @__PURE__ */ jsx9(Text9, { color: billingToneColor(billing.tone), children: Math.max(Number(billing.reportedUsed ?? billing.used ?? 0), 0) > 0 ? `${formatCredits(billing.remaining)} left | Used ${formatCredits(
|
|
4338
|
+
Math.max(Number(billing.reportedUsed ?? billing.used ?? 0), 0)
|
|
4339
|
+
)}` : `${formatCredits(billing.remaining)}/${formatCredits(billing.total)}` })
|
|
3551
4340
|
] }),
|
|
3552
4341
|
/* @__PURE__ */ jsx9(
|
|
3553
4342
|
CreditProgress,
|
|
@@ -3712,7 +4501,7 @@ var HelpLegend = ({
|
|
|
3712
4501
|
] }, segment.key)) });
|
|
3713
4502
|
};
|
|
3714
4503
|
var ResourceSummary = ({ label, value, terminalColumns }) => {
|
|
3715
|
-
const rows =
|
|
4504
|
+
const rows = directArray3(value);
|
|
3716
4505
|
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", children: [
|
|
3717
4506
|
/* @__PURE__ */ jsx9(Text9, { bold: true, children: label }),
|
|
3718
4507
|
/* @__PURE__ */ jsx9(Text9, { dimColor: true, wrap: "wrap", children: rows.length ? `${rows.length} row(s) returned` : `keys: ${truncateForTerminal(keySummary(value), Math.max(32, terminalColumns - 14))}` }),
|
|
@@ -3723,86 +4512,185 @@ var ResourceSummary = ({ label, value, terminalColumns }) => {
|
|
|
3723
4512
|
truncateForTerminal(rowLabel(row, `row ${index + 1}`), 36),
|
|
3724
4513
|
rowDetail(row) ? ` - ${truncateForTerminal(rowDetail(row), 64)}` : ""
|
|
3725
4514
|
] }, `${label}-${index}`)),
|
|
3726
|
-
!rows.length && !
|
|
4515
|
+
!rows.length && !toRecord5(value) ? /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "No data returned." }) : null
|
|
4516
|
+
] });
|
|
4517
|
+
};
|
|
4518
|
+
var cleanBackendWarning = (warning, terminalColumns) => {
|
|
4519
|
+
const compact = warning.replace(
|
|
4520
|
+
/:\s*\{"detail":"Device token not authorized for this endpoint"\}/g,
|
|
4521
|
+
" (backend denied CLI device-token access)"
|
|
4522
|
+
).replace(/\s+/g, " ").trim();
|
|
4523
|
+
return truncateForTerminal(
|
|
4524
|
+
compact,
|
|
4525
|
+
Math.max(72, Math.min(180, terminalColumns - 8))
|
|
4526
|
+
);
|
|
4527
|
+
};
|
|
4528
|
+
var entityToneColor = (tone) => {
|
|
4529
|
+
if (tone === "brand") return terminalTheme.brand;
|
|
4530
|
+
if (tone === "success") return terminalTheme.success;
|
|
4531
|
+
if (tone === "warning") return terminalTheme.warning;
|
|
4532
|
+
if (tone === "danger") return terminalTheme.danger;
|
|
4533
|
+
return terminalTheme.muted;
|
|
4534
|
+
};
|
|
4535
|
+
var EntityDetailPanel = ({ model, emptyLabel, compact, terminalColumns }) => {
|
|
4536
|
+
if (!model) {
|
|
4537
|
+
return /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: emptyLabel });
|
|
4538
|
+
}
|
|
4539
|
+
return /* @__PURE__ */ jsx9(SectionCard, { title: "Selected detail", borderColor: terminalTheme.focus, children: /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 1, children: [
|
|
4540
|
+
/* @__PURE__ */ jsxs7(Box8, { flexDirection: compact ? "column" : "row", justifyContent: "space-between", gap: 1, children: [
|
|
4541
|
+
/* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", flexShrink: 1, children: [
|
|
4542
|
+
/* @__PURE__ */ jsx9(Text9, { color: terminalTheme.focus, bold: true, wrap: "truncate", children: truncateForTerminal(model.title, Math.max(24, terminalColumns - 32)) }),
|
|
4543
|
+
model.subtitle ? /* @__PURE__ */ jsx9(Text9, { dimColor: true, wrap: "truncate", children: model.subtitle }) : null
|
|
4544
|
+
] }),
|
|
4545
|
+
/* @__PURE__ */ jsx9(MetricStrip, { metrics: model.metrics, compact })
|
|
4546
|
+
] }),
|
|
4547
|
+
/* @__PURE__ */ jsx9(Box8, { flexDirection: "column", children: model.detailRows.map((row) => /* @__PURE__ */ jsxs7(Text9, { wrap: "truncate", children: [
|
|
4548
|
+
/* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
|
|
4549
|
+
row.label.padEnd(16),
|
|
4550
|
+
" "
|
|
4551
|
+
] }),
|
|
4552
|
+
/* @__PURE__ */ jsx9(Text9, { color: entityToneColor(row.tone), children: truncateForTerminal(row.value || "-", Math.max(20, terminalColumns - 24)) })
|
|
4553
|
+
] }, `${row.label}-${row.value}`)) }),
|
|
4554
|
+
model.relatedItems.length ? /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", children: [
|
|
4555
|
+
/* @__PURE__ */ jsx9(Text9, { color: terminalTheme.brand, children: "Linked" }),
|
|
4556
|
+
model.relatedItems.slice(0, 5).map((item, index) => /* @__PURE__ */ jsxs7(Text9, { wrap: "truncate", children: [
|
|
4557
|
+
/* @__PURE__ */ jsx9(Text9, { color: entityToneColor(item.tone), children: "\u25CF " }),
|
|
4558
|
+
truncateForTerminal(item.label, 36),
|
|
4559
|
+
item.detail ? /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
|
|
4560
|
+
" - ",
|
|
4561
|
+
truncateForTerminal(item.detail, 36)
|
|
4562
|
+
] }) : null
|
|
4563
|
+
] }, `${item.label}-${index}`))
|
|
4564
|
+
] }) : null
|
|
4565
|
+
] }) });
|
|
4566
|
+
};
|
|
4567
|
+
var ProjectsView = ({ projects, selectedProject, connections, reportsSummary, compact, terminalColumns }) => {
|
|
4568
|
+
const selectedModel = buildProjectDetailModel({
|
|
4569
|
+
project: selectedProject ?? projects[0],
|
|
4570
|
+
connections,
|
|
4571
|
+
reportsSummary
|
|
4572
|
+
});
|
|
4573
|
+
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 1, children: [
|
|
4574
|
+
/* @__PURE__ */ jsx9(
|
|
4575
|
+
MetricStrip,
|
|
4576
|
+
{
|
|
4577
|
+
compact,
|
|
4578
|
+
metrics: [
|
|
4579
|
+
{ label: "Projects", value: String(projects.length) },
|
|
4580
|
+
{ label: "Selected", value: selectedProject?.name ?? "none" }
|
|
4581
|
+
]
|
|
4582
|
+
}
|
|
4583
|
+
),
|
|
4584
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "J/K or Up/Down selects project | Enter confirms | O opens frontend" }),
|
|
4585
|
+
/* @__PURE__ */ jsxs7(Box8, { flexDirection: compact ? "column" : "row", gap: 2, children: [
|
|
4586
|
+
/* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", flexBasis: compact ? void 0 : 52, flexShrink: 0, children: [
|
|
4587
|
+
/* @__PURE__ */ jsx9(Text9, { color: terminalTheme.brand, children: "Project list" }),
|
|
4588
|
+
projects.length ? projects.slice(0, 12).map((project, index) => {
|
|
4589
|
+
const active = project.id === (selectedProject ?? projects[0])?.id;
|
|
4590
|
+
return /* @__PURE__ */ jsxs7(
|
|
4591
|
+
Text9,
|
|
4592
|
+
{
|
|
4593
|
+
color: active ? terminalTheme.focus : void 0,
|
|
4594
|
+
backgroundColor: active ? terminalTheme.selectedBackground : void 0,
|
|
4595
|
+
bold: active,
|
|
4596
|
+
wrap: "truncate",
|
|
4597
|
+
children: [
|
|
4598
|
+
active ? ">" : " ",
|
|
4599
|
+
" ",
|
|
4600
|
+
truncateForTerminal(project.name, 30),
|
|
4601
|
+
" ",
|
|
4602
|
+
/* @__PURE__ */ jsx9(Text9, { color: terminalTheme.brand, children: project.cloud_provider ?? "cloud" }),
|
|
4603
|
+
" ",
|
|
4604
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: project.id })
|
|
4605
|
+
]
|
|
4606
|
+
},
|
|
4607
|
+
project.id ?? index
|
|
4608
|
+
);
|
|
4609
|
+
}) : /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "No projects returned by the backend." })
|
|
4610
|
+
] }),
|
|
4611
|
+
/* @__PURE__ */ jsx9(Box8, { flexGrow: 1, children: /* @__PURE__ */ jsx9(
|
|
4612
|
+
EntityDetailPanel,
|
|
4613
|
+
{
|
|
4614
|
+
model: selectedModel,
|
|
4615
|
+
emptyLabel: "Select a project to inspect backend details.",
|
|
4616
|
+
compact,
|
|
4617
|
+
terminalColumns: Math.max(32, terminalColumns - 56)
|
|
4618
|
+
}
|
|
4619
|
+
) })
|
|
4620
|
+
] })
|
|
4621
|
+
] });
|
|
4622
|
+
};
|
|
4623
|
+
var ConnectionsView = ({ connections, projects, selectedIndex, compact, terminalColumns }) => {
|
|
4624
|
+
const safeIndex = connections.length ? Math.min(Math.max(0, selectedIndex), connections.length - 1) : -1;
|
|
4625
|
+
const selectedConnection = safeIndex >= 0 ? connections[safeIndex] : void 0;
|
|
4626
|
+
const selectedModel = buildConnectionDetailModel({
|
|
4627
|
+
connection: selectedConnection,
|
|
4628
|
+
projects
|
|
4629
|
+
});
|
|
4630
|
+
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 1, children: [
|
|
4631
|
+
/* @__PURE__ */ jsx9(
|
|
4632
|
+
MetricStrip,
|
|
4633
|
+
{
|
|
4634
|
+
compact,
|
|
4635
|
+
metrics: [{ label: "Connections", value: String(connections.length) }]
|
|
4636
|
+
}
|
|
4637
|
+
),
|
|
4638
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "J/K or Up/Down selects connection | Enter confirms | O opens frontend | D downloads table data" }),
|
|
4639
|
+
/* @__PURE__ */ jsxs7(Box8, { flexDirection: compact ? "column" : "row", gap: 2, children: [
|
|
4640
|
+
/* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", flexBasis: compact ? void 0 : 58, flexShrink: 0, children: [
|
|
4641
|
+
/* @__PURE__ */ jsx9(Text9, { color: terminalTheme.brand, children: "Connection list" }),
|
|
4642
|
+
connections.length ? connections.slice(0, 12).map((connection, index) => {
|
|
4643
|
+
const active = index === safeIndex;
|
|
4644
|
+
return /* @__PURE__ */ jsxs7(
|
|
4645
|
+
Text9,
|
|
4646
|
+
{
|
|
4647
|
+
color: active ? terminalTheme.focus : void 0,
|
|
4648
|
+
backgroundColor: active ? terminalTheme.selectedBackground : void 0,
|
|
4649
|
+
bold: active,
|
|
4650
|
+
wrap: "truncate",
|
|
4651
|
+
children: [
|
|
4652
|
+
active ? ">" : " ",
|
|
4653
|
+
" ",
|
|
4654
|
+
String(index + 1).padStart(2),
|
|
4655
|
+
" ",
|
|
4656
|
+
truncateForTerminal(rowLabel(connection, "connection"), 34),
|
|
4657
|
+
rowDetail(connection) ? /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
|
|
4658
|
+
" - ",
|
|
4659
|
+
truncateForTerminal(rowDetail(connection), 28)
|
|
4660
|
+
] }) : ""
|
|
4661
|
+
]
|
|
4662
|
+
},
|
|
4663
|
+
String(firstString5(connection, ["id"], String(index)))
|
|
4664
|
+
);
|
|
4665
|
+
}) : /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "No connections returned by the backend." })
|
|
4666
|
+
] }),
|
|
4667
|
+
/* @__PURE__ */ jsx9(Box8, { flexGrow: 1, children: /* @__PURE__ */ jsx9(
|
|
4668
|
+
EntityDetailPanel,
|
|
4669
|
+
{
|
|
4670
|
+
model: selectedModel,
|
|
4671
|
+
emptyLabel: "Select a connection to inspect backend details.",
|
|
4672
|
+
compact,
|
|
4673
|
+
terminalColumns: Math.max(32, terminalColumns - 62)
|
|
4674
|
+
}
|
|
4675
|
+
) })
|
|
4676
|
+
] })
|
|
3727
4677
|
] });
|
|
3728
4678
|
};
|
|
3729
|
-
var cleanBackendWarning = (warning, terminalColumns) => {
|
|
3730
|
-
const compact = warning.replace(
|
|
3731
|
-
/:\s*\{"detail":"Device token not authorized for this endpoint"\}/g,
|
|
3732
|
-
" (backend denied CLI device-token access)"
|
|
3733
|
-
).replace(/\s+/g, " ").trim();
|
|
3734
|
-
return truncateForTerminal(
|
|
3735
|
-
compact,
|
|
3736
|
-
Math.max(72, Math.min(180, terminalColumns - 8))
|
|
3737
|
-
);
|
|
3738
|
-
};
|
|
3739
|
-
var ProjectsView = ({ projects, selectedProject }) => /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 1, children: [
|
|
3740
|
-
/* @__PURE__ */ jsx9(
|
|
3741
|
-
MetricStrip,
|
|
3742
|
-
{
|
|
3743
|
-
compact: false,
|
|
3744
|
-
metrics: [
|
|
3745
|
-
{ label: "Projects", value: String(projects.length) },
|
|
3746
|
-
{ label: "Selected", value: selectedProject?.name ?? "none" }
|
|
3747
|
-
]
|
|
3748
|
-
}
|
|
3749
|
-
),
|
|
3750
|
-
projects.length ? projects.slice(0, 12).map((project, index) => /* @__PURE__ */ jsxs7(
|
|
3751
|
-
Text9,
|
|
3752
|
-
{
|
|
3753
|
-
color: project.id === selectedProject?.id ? terminalTheme.brand : void 0,
|
|
3754
|
-
wrap: "truncate",
|
|
3755
|
-
children: [
|
|
3756
|
-
project.id === selectedProject?.id ? ">" : " ",
|
|
3757
|
-
" ",
|
|
3758
|
-
project.name,
|
|
3759
|
-
" |",
|
|
3760
|
-
" ",
|
|
3761
|
-
project.cloud_provider ?? "cloud",
|
|
3762
|
-
" | ",
|
|
3763
|
-
project.id
|
|
3764
|
-
]
|
|
3765
|
-
},
|
|
3766
|
-
project.id ?? index
|
|
3767
|
-
)) : /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "No projects returned by the backend." })
|
|
3768
|
-
] });
|
|
3769
|
-
var ConnectionsView = ({ connections }) => /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 1, children: [
|
|
3770
|
-
/* @__PURE__ */ jsx9(
|
|
3771
|
-
MetricStrip,
|
|
3772
|
-
{
|
|
3773
|
-
compact: false,
|
|
3774
|
-
metrics: [{ label: "Connections", value: String(connections.length) }]
|
|
3775
|
-
}
|
|
3776
|
-
),
|
|
3777
|
-
connections.length ? connections.slice(0, 12).map((connection, index) => /* @__PURE__ */ jsxs7(
|
|
3778
|
-
Text9,
|
|
3779
|
-
{
|
|
3780
|
-
wrap: "truncate",
|
|
3781
|
-
children: [
|
|
3782
|
-
index + 1,
|
|
3783
|
-
".",
|
|
3784
|
-
" ",
|
|
3785
|
-
truncateForTerminal(rowLabel(connection, "connection"), 36),
|
|
3786
|
-
rowDetail(connection) ? ` - ${truncateForTerminal(rowDetail(connection), 72)}` : ""
|
|
3787
|
-
]
|
|
3788
|
-
},
|
|
3789
|
-
String(firstString3(connection, ["id"], String(index)))
|
|
3790
|
-
)) : /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "No connections returned by the backend." })
|
|
3791
|
-
] });
|
|
3792
4679
|
var BillingView = ({ state, compact, terminalColumns, frontendUrl }) => {
|
|
3793
|
-
const creditStatus =
|
|
3794
|
-
const entitlement =
|
|
3795
|
-
const plan =
|
|
4680
|
+
const creditStatus = toRecord5(state.data.creditStatus);
|
|
4681
|
+
const entitlement = toRecord5(state.data.entitlement);
|
|
4682
|
+
const plan = toRecord5(entitlement?.plan);
|
|
3796
4683
|
const usageValues = billingUsageTrendValues(state.data.usageSummary);
|
|
3797
|
-
const ledger =
|
|
3798
|
-
const invoices =
|
|
3799
|
-
const topups =
|
|
3800
|
-
const notifications =
|
|
3801
|
-
const remainingRatio =
|
|
3802
|
-
const creditTone =
|
|
4684
|
+
const ledger = directArray3(state.data.ledger);
|
|
4685
|
+
const invoices = directArray3(state.data.billingInfo);
|
|
4686
|
+
const topups = directArray3(state.data.topups);
|
|
4687
|
+
const notifications = directArray3(state.data.notifications);
|
|
4688
|
+
const remainingRatio = firstNumber5(creditStatus, ["remainingRatio"]);
|
|
4689
|
+
const creditTone = firstString5(creditStatus, ["tone"], "normal");
|
|
3803
4690
|
const tone = metricToneFromBillingTone(creditTone);
|
|
3804
|
-
const remaining =
|
|
3805
|
-
const total =
|
|
4691
|
+
const remaining = firstNumber5(creditStatus, ["remaining"]);
|
|
4692
|
+
const total = firstNumber5(creditStatus, ["total"]);
|
|
4693
|
+
const reportedUsed = firstNumber5(creditStatus, ["reportedUsed"]) ?? firstNumber5(creditStatus, ["used"]);
|
|
3806
4694
|
const plansUrl = buildFrontendUrl({
|
|
3807
4695
|
baseUrl: frontendUrl,
|
|
3808
4696
|
target: "billing",
|
|
@@ -3816,17 +4704,18 @@ var BillingView = ({ state, compact, terminalColumns, frontendUrl }) => {
|
|
|
3816
4704
|
const metrics = [
|
|
3817
4705
|
{
|
|
3818
4706
|
label: "Plan",
|
|
3819
|
-
value:
|
|
4707
|
+
value: firstString5(
|
|
3820
4708
|
creditStatus,
|
|
3821
4709
|
["planName"],
|
|
3822
|
-
|
|
4710
|
+
firstString5(plan, ["name"], "-")
|
|
3823
4711
|
)
|
|
3824
4712
|
},
|
|
3825
4713
|
{ label: "Remaining", value: formatNumber3(remaining) },
|
|
3826
|
-
{ label: "
|
|
4714
|
+
{ label: "Included", value: formatNumber3(total) },
|
|
4715
|
+
{ label: "Used", value: formatNumber3(reportedUsed) },
|
|
3827
4716
|
{
|
|
3828
4717
|
label: "Top-up",
|
|
3829
|
-
value: formatNumber3(
|
|
4718
|
+
value: formatNumber3(firstNumber5(creditStatus, ["topUpBalance"]))
|
|
3830
4719
|
}
|
|
3831
4720
|
];
|
|
3832
4721
|
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 1, children: [
|
|
@@ -4058,7 +4947,7 @@ var ReportsView = ({
|
|
|
4058
4947
|
const chartWidth = compact ? Math.max(24, terminalColumns - 28) : 42;
|
|
4059
4948
|
const selectedSummary = model.selectedProjectSummary;
|
|
4060
4949
|
const selectedStatuses = selectedSummary.reportStatuses;
|
|
4061
|
-
const hasReportData = Boolean(
|
|
4950
|
+
const hasReportData = Boolean(toRecord5(state.data.reportsSummary));
|
|
4062
4951
|
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", gap: 1, children: [
|
|
4063
4952
|
/* @__PURE__ */ jsxs7(
|
|
4064
4953
|
Box8,
|
|
@@ -4279,7 +5168,7 @@ var OverviewView = ({
|
|
|
4279
5168
|
terminalColumns,
|
|
4280
5169
|
tablePage
|
|
4281
5170
|
}) => {
|
|
4282
|
-
const connections =
|
|
5171
|
+
const connections = directArray3(state.data.connections);
|
|
4283
5172
|
const model = buildOverviewDashboardModel({
|
|
4284
5173
|
dashboard: state.data.dashboard,
|
|
4285
5174
|
reportsSummary: state.data.reportsSummary,
|
|
@@ -4518,23 +5407,21 @@ var WorkspaceTabBar = ({ activeTab, showBrand = false, billingSummary }) => {
|
|
|
4518
5407
|
) : null,
|
|
4519
5408
|
/* @__PURE__ */ jsx9(Box8, { flexDirection: "row", gap: 0, flexWrap: "wrap", children: workspaceTabs.map((tab) => {
|
|
4520
5409
|
const active = tab === activeTab;
|
|
5410
|
+
const style = workspaceTabButtonStyle(active);
|
|
4521
5411
|
return /* @__PURE__ */ jsx9(
|
|
4522
5412
|
Box8,
|
|
4523
5413
|
{
|
|
4524
|
-
borderStyle:
|
|
4525
|
-
borderColor:
|
|
4526
|
-
paddingX: 1,
|
|
5414
|
+
borderStyle: style.borderStyle,
|
|
5415
|
+
borderColor: style.borderColor,
|
|
4527
5416
|
marginRight: 1,
|
|
4528
|
-
children: /* @__PURE__ */
|
|
5417
|
+
children: /* @__PURE__ */ jsx9(
|
|
4529
5418
|
Text9,
|
|
4530
5419
|
{
|
|
4531
|
-
bold:
|
|
4532
|
-
color:
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
workspaceTabButtonLabel(tab)
|
|
4537
|
-
]
|
|
5420
|
+
bold: style.bold,
|
|
5421
|
+
color: style.color,
|
|
5422
|
+
backgroundColor: style.backgroundColor,
|
|
5423
|
+
underline: style.underline,
|
|
5424
|
+
children: workspaceTabButtonInterior(tab, active)
|
|
4538
5425
|
}
|
|
4539
5426
|
)
|
|
4540
5427
|
},
|
|
@@ -4550,7 +5437,7 @@ var WorkspacePanel = (props) => {
|
|
|
4550
5437
|
const state = props.state;
|
|
4551
5438
|
const animate = props.animate ?? true;
|
|
4552
5439
|
const framed = props.framed ?? true;
|
|
4553
|
-
const connections =
|
|
5440
|
+
const connections = directArray3(state.data.connections);
|
|
4554
5441
|
const isInitialLoading = state.status === "loading";
|
|
4555
5442
|
const isBackgroundRefreshing = Boolean(
|
|
4556
5443
|
state.isRefreshing && !isInitialLoading
|
|
@@ -4562,7 +5449,7 @@ var WorkspacePanel = (props) => {
|
|
|
4562
5449
|
] }) }) : null,
|
|
4563
5450
|
isInitialLoading ? /* @__PURE__ */ jsxs7(Box8, { flexDirection: "row", gap: 1, children: [
|
|
4564
5451
|
/* @__PURE__ */ jsx9(Spinner, { type: "dots", animate }),
|
|
4565
|
-
/* @__PURE__ */ jsx9(Text9, { color: terminalTheme.brand, children: "Loading
|
|
5452
|
+
/* @__PURE__ */ jsx9(Text9, { color: terminalTheme.brand, children: "Loading workspace data..." })
|
|
4566
5453
|
] }) : null,
|
|
4567
5454
|
isBackgroundRefreshing ? /* @__PURE__ */ jsxs7(Box8, { flexDirection: "row", gap: 1, children: [
|
|
4568
5455
|
/* @__PURE__ */ jsx9(Spinner, { type: "dots", animate }),
|
|
@@ -4626,10 +5513,23 @@ var WorkspacePanel = (props) => {
|
|
|
4626
5513
|
ProjectsView,
|
|
4627
5514
|
{
|
|
4628
5515
|
projects: props.projects,
|
|
4629
|
-
selectedProject: props.selectedProject
|
|
5516
|
+
selectedProject: props.selectedProject,
|
|
5517
|
+
connections,
|
|
5518
|
+
reportsSummary: state.data.reportsSummary,
|
|
5519
|
+
compact,
|
|
5520
|
+
terminalColumns: props.terminalColumns
|
|
5521
|
+
}
|
|
5522
|
+
) : null,
|
|
5523
|
+
props.tab === "connections" ? /* @__PURE__ */ jsx9(
|
|
5524
|
+
ConnectionsView,
|
|
5525
|
+
{
|
|
5526
|
+
connections,
|
|
5527
|
+
projects: props.projects,
|
|
5528
|
+
selectedIndex: props.selectedConnectionIndex ?? 0,
|
|
5529
|
+
compact,
|
|
5530
|
+
terminalColumns: props.terminalColumns
|
|
4630
5531
|
}
|
|
4631
5532
|
) : null,
|
|
4632
|
-
props.tab === "connections" ? /* @__PURE__ */ jsx9(ConnectionsView, { connections }) : null,
|
|
4633
5533
|
props.tab === "billing" ? /* @__PURE__ */ jsx9(
|
|
4634
5534
|
BillingView,
|
|
4635
5535
|
{
|
|
@@ -4658,6 +5558,20 @@ var WorkspacePanel = (props) => {
|
|
|
4658
5558
|
);
|
|
4659
5559
|
};
|
|
4660
5560
|
|
|
5561
|
+
// src/ui/workspaceSelection.ts
|
|
5562
|
+
var selectableWorkspaceTab = (tab) => tab === "projects" || tab === "connections";
|
|
5563
|
+
var nextWorkspaceSelectionIndex = ({
|
|
5564
|
+
currentIndex,
|
|
5565
|
+
itemCount,
|
|
5566
|
+
direction
|
|
5567
|
+
}) => {
|
|
5568
|
+
if (itemCount <= 0) {
|
|
5569
|
+
return 0;
|
|
5570
|
+
}
|
|
5571
|
+
const normalizedCurrent = Math.min(Math.max(0, currentIndex), itemCount - 1);
|
|
5572
|
+
return Math.min(Math.max(0, normalizedCurrent + direction), itemCount - 1);
|
|
5573
|
+
};
|
|
5574
|
+
|
|
4661
5575
|
// src/ui/animationPolicy.ts
|
|
4662
5576
|
var truthyEnv = (value) => value !== void 0 && /^(1|true|yes|on)$/i.test(value);
|
|
4663
5577
|
var shouldEnableTuiAnimations = ({
|
|
@@ -4671,7 +5585,7 @@ var shouldEnableTuiAnimations = ({
|
|
|
4671
5585
|
};
|
|
4672
5586
|
|
|
4673
5587
|
// src/ui/App.tsx
|
|
4674
|
-
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
5588
|
+
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4675
5589
|
var bootSteps = [
|
|
4676
5590
|
"Loading config",
|
|
4677
5591
|
"Validating auth",
|
|
@@ -4679,10 +5593,11 @@ var bootSteps = [
|
|
|
4679
5593
|
"Ready"
|
|
4680
5594
|
];
|
|
4681
5595
|
var defaultUser = { id: "cli-user", name: "CLI User" };
|
|
5596
|
+
var newDraftChatSessionKey = () => `draft-${randomUUID2()}`;
|
|
4682
5597
|
var getUserNameFromToken = async (token) => {
|
|
4683
5598
|
if (!token) return "You";
|
|
4684
5599
|
try {
|
|
4685
|
-
const { extractEmailFromToken } = await import("./dist-
|
|
5600
|
+
const { extractEmailFromToken } = await import("./dist-AGQQPJUD.js");
|
|
4686
5601
|
const email = extractEmailFromToken(token);
|
|
4687
5602
|
return getFirstNameForDisplay({ email: email ?? void 0 });
|
|
4688
5603
|
} catch {
|
|
@@ -4700,9 +5615,9 @@ var dropdownIndicator = "\u25BE";
|
|
|
4700
5615
|
var bundledAgentProfiles = getBundledAgentProfiles();
|
|
4701
5616
|
var agentProfileItems = [
|
|
4702
5617
|
{
|
|
4703
|
-
label: "
|
|
5618
|
+
label: "General",
|
|
4704
5619
|
value: "",
|
|
4705
|
-
description: "
|
|
5620
|
+
description: "Built-in CloudEval chat flow without a named Agent Profile."
|
|
4706
5621
|
},
|
|
4707
5622
|
...bundledAgentProfiles.map((profile) => ({
|
|
4708
5623
|
label: profile.display_name,
|
|
@@ -4790,11 +5705,27 @@ var billingHeaderFromEntitlement = (entitlement, usageSummary) => {
|
|
|
4790
5705
|
plan: creditStatus.planName,
|
|
4791
5706
|
remaining: creditStatus.remaining,
|
|
4792
5707
|
total: creditStatus.total,
|
|
5708
|
+
used: creditStatus.used,
|
|
5709
|
+
reportedUsed: creditStatus.reportedUsed,
|
|
4793
5710
|
tone: creditStatus.tone,
|
|
4794
5711
|
status: entitlement?.effective_status
|
|
4795
5712
|
};
|
|
4796
5713
|
};
|
|
4797
5714
|
var isBusyStatus = (status) => status === "connecting" || status === "thinking" || status === "streaming" || status === "tool_running" || status === "hitl_waiting";
|
|
5715
|
+
var buildTuiHeaderDetails = ({
|
|
5716
|
+
apiBase,
|
|
5717
|
+
frontendBaseUrl,
|
|
5718
|
+
billingSummary,
|
|
5719
|
+
userName
|
|
5720
|
+
}) => {
|
|
5721
|
+
const displayName = truncateForTerminal(userName.trim() || "You", 64);
|
|
5722
|
+
return [
|
|
5723
|
+
`User: ${displayName}`,
|
|
5724
|
+
`API: ${apiBase}`,
|
|
5725
|
+
`Frontend: ${frontendBaseUrl}`,
|
|
5726
|
+
billingSummary
|
|
5727
|
+
];
|
|
5728
|
+
};
|
|
4798
5729
|
var isTerminalThinkingStatus = (status) => status === "completed" || status === "error" || status === "aborted" || status === "cancelled";
|
|
4799
5730
|
var hasCancellableAssistantWork = (messages) => messages.some(
|
|
4800
5731
|
(message) => message.role === "assistant" && (message.pending || message.thinkingSteps?.some((step) => !isTerminalThinkingStatus(step.status ?? "streaming")))
|
|
@@ -4890,6 +5821,35 @@ var openExternalUrl = (url) => {
|
|
|
4890
5821
|
});
|
|
4891
5822
|
child.unref();
|
|
4892
5823
|
};
|
|
5824
|
+
var directArray4 = (value) => {
|
|
5825
|
+
if (Array.isArray(value)) {
|
|
5826
|
+
return value;
|
|
5827
|
+
}
|
|
5828
|
+
if (!value || typeof value !== "object") {
|
|
5829
|
+
return [];
|
|
5830
|
+
}
|
|
5831
|
+
const record = value;
|
|
5832
|
+
for (const key of ["data", "items", "rows", "results", "connections", "ledger", "invoices", "notifications", "topups"]) {
|
|
5833
|
+
const candidate = record[key];
|
|
5834
|
+
if (Array.isArray(candidate)) {
|
|
5835
|
+
return candidate;
|
|
5836
|
+
}
|
|
5837
|
+
}
|
|
5838
|
+
return [];
|
|
5839
|
+
};
|
|
5840
|
+
var recordLabel = (value, fallback) => {
|
|
5841
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5842
|
+
return fallback;
|
|
5843
|
+
}
|
|
5844
|
+
const record = value;
|
|
5845
|
+
for (const key of ["name", "title", "id"]) {
|
|
5846
|
+
const current = record[key];
|
|
5847
|
+
if (typeof current === "string" && current.trim()) {
|
|
5848
|
+
return current.trim();
|
|
5849
|
+
}
|
|
5850
|
+
}
|
|
5851
|
+
return fallback;
|
|
5852
|
+
};
|
|
4893
5853
|
var writeTableDownload = ({
|
|
4894
5854
|
tab,
|
|
4895
5855
|
data,
|
|
@@ -4897,27 +5857,11 @@ var writeTableDownload = ({
|
|
|
4897
5857
|
selectedProject,
|
|
4898
5858
|
tablePage
|
|
4899
5859
|
}) => {
|
|
4900
|
-
const directArray3 = (value) => {
|
|
4901
|
-
if (Array.isArray(value)) {
|
|
4902
|
-
return value;
|
|
4903
|
-
}
|
|
4904
|
-
if (!value || typeof value !== "object") {
|
|
4905
|
-
return [];
|
|
4906
|
-
}
|
|
4907
|
-
const record = value;
|
|
4908
|
-
for (const key of ["data", "items", "rows", "results", "connections", "ledger", "invoices", "notifications", "topups"]) {
|
|
4909
|
-
const candidate = record[key];
|
|
4910
|
-
if (Array.isArray(candidate)) {
|
|
4911
|
-
return candidate;
|
|
4912
|
-
}
|
|
4913
|
-
}
|
|
4914
|
-
return [];
|
|
4915
|
-
};
|
|
4916
5860
|
const derived = tab === "overview" ? buildOverviewDashboardModel({
|
|
4917
5861
|
dashboard: data.dashboard,
|
|
4918
5862
|
reportsSummary: data.reportsSummary,
|
|
4919
5863
|
fallbackProjectCount: projects.length,
|
|
4920
|
-
fallbackConnectionCount:
|
|
5864
|
+
fallbackConnectionCount: directArray4(data.connections).length
|
|
4921
5865
|
}) : tab === "reports" ? buildReportsDashboardModel({
|
|
4922
5866
|
dashboard: data.dashboard,
|
|
4923
5867
|
reportsSummary: data.reportsSummary,
|
|
@@ -4926,18 +5870,18 @@ var writeTableDownload = ({
|
|
|
4926
5870
|
wafReport: data.wafReport
|
|
4927
5871
|
}) : {
|
|
4928
5872
|
rows: {
|
|
4929
|
-
connections:
|
|
4930
|
-
ledger:
|
|
4931
|
-
invoices:
|
|
4932
|
-
topups:
|
|
4933
|
-
notifications:
|
|
5873
|
+
connections: directArray4(data.connections),
|
|
5874
|
+
ledger: directArray4(data.ledger),
|
|
5875
|
+
invoices: directArray4(data.billingInfo),
|
|
5876
|
+
topups: directArray4(data.topups),
|
|
5877
|
+
notifications: directArray4(data.notifications)
|
|
4934
5878
|
}
|
|
4935
5879
|
};
|
|
4936
|
-
const dir =
|
|
4937
|
-
|
|
5880
|
+
const dir = resolve2(process.cwd(), ".cloudeval-downloads");
|
|
5881
|
+
mkdirSync2(dir, { recursive: true });
|
|
4938
5882
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
4939
|
-
const file =
|
|
4940
|
-
|
|
5883
|
+
const file = join2(dir, `${tab}-tables-${timestamp}.json`);
|
|
5884
|
+
writeFileSync2(
|
|
4941
5885
|
file,
|
|
4942
5886
|
`${JSON.stringify(
|
|
4943
5887
|
{
|
|
@@ -4980,12 +5924,17 @@ var estimatePromptPanelRows = ({
|
|
|
4980
5924
|
suggestionRows,
|
|
4981
5925
|
compact,
|
|
4982
5926
|
hasThinkingSteps,
|
|
4983
|
-
includeControls = true
|
|
5927
|
+
includeControls = true,
|
|
5928
|
+
variant = "panel"
|
|
4984
5929
|
}) => {
|
|
4985
|
-
const
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
5930
|
+
const controlRows = includeControls ? 1 + estimatePromptControlRows({ compact, hasThinkingSteps }) : 0;
|
|
5931
|
+
return estimateComposerRows({
|
|
5932
|
+
inputRows,
|
|
5933
|
+
suggestionRows,
|
|
5934
|
+
includeControls,
|
|
5935
|
+
controlRows,
|
|
5936
|
+
variant
|
|
5937
|
+
});
|
|
4989
5938
|
};
|
|
4990
5939
|
var useTerminalSize = () => {
|
|
4991
5940
|
const [size, setSize] = useState4(() => readTerminalSize());
|
|
@@ -5129,6 +6078,24 @@ var QueuePanel = ({ messages, compact, terminalColumns }) => {
|
|
|
5129
6078
|
}
|
|
5130
6079
|
);
|
|
5131
6080
|
};
|
|
6081
|
+
var artifactToneColor = (tone) => {
|
|
6082
|
+
if (tone === "brand") return terminalTheme.brand;
|
|
6083
|
+
if (tone === "success") return terminalTheme.success;
|
|
6084
|
+
if (tone === "warning") return terminalTheme.warning;
|
|
6085
|
+
if (tone === "danger") return terminalTheme.danger;
|
|
6086
|
+
return void 0;
|
|
6087
|
+
};
|
|
6088
|
+
var ArtifactStrip = ({ chips, compact = false, terminalColumns }) => {
|
|
6089
|
+
if (!chips.length) {
|
|
6090
|
+
return null;
|
|
6091
|
+
}
|
|
6092
|
+
const valueLimit = compact ? Math.max(10, terminalColumns - 15) : 24;
|
|
6093
|
+
return /* @__PURE__ */ jsx10(Box9, { flexDirection: compact ? "column" : "row", gap: compact ? 0 : 1, flexWrap: "wrap", children: chips.map((chip) => /* @__PURE__ */ jsxs8(Text10, { children: [
|
|
6094
|
+
/* @__PURE__ */ jsx10(Text10, { color: artifactToneColor(chip.tone), bold: true, children: chip.label }),
|
|
6095
|
+
/* @__PURE__ */ jsx10(Text10, { dimColor: true, children: " " }),
|
|
6096
|
+
/* @__PURE__ */ jsx10(Text10, { color: artifactToneColor(chip.tone), children: truncateForTerminal(chip.value, valueLimit) })
|
|
6097
|
+
] }, `${chip.label}-${chip.value}`)) });
|
|
6098
|
+
};
|
|
5132
6099
|
var PromptControlBar = ({
|
|
5133
6100
|
focused,
|
|
5134
6101
|
selectedThreadTitle,
|
|
@@ -5178,7 +6145,8 @@ var PromptControlBar = ({
|
|
|
5178
6145
|
return /* @__PURE__ */ jsxs8(
|
|
5179
6146
|
Text10,
|
|
5180
6147
|
{
|
|
5181
|
-
color: isFocused ?
|
|
6148
|
+
color: isFocused ? "white" : void 0,
|
|
6149
|
+
backgroundColor: isFocused ? terminalTheme.selectedBackground : void 0,
|
|
5182
6150
|
bold: isFocused,
|
|
5183
6151
|
wrap: "truncate",
|
|
5184
6152
|
children: [
|
|
@@ -5203,7 +6171,8 @@ var PromptControlBar = ({
|
|
|
5203
6171
|
hasThinkingSteps ? /* @__PURE__ */ jsxs8(
|
|
5204
6172
|
Text10,
|
|
5205
6173
|
{
|
|
5206
|
-
color: focused === "thinking" ?
|
|
6174
|
+
color: focused === "thinking" ? "white" : void 0,
|
|
6175
|
+
backgroundColor: focused === "thinking" ? terminalTheme.selectedBackground : void 0,
|
|
5207
6176
|
bold: focused === "thinking",
|
|
5208
6177
|
wrap: "truncate",
|
|
5209
6178
|
children: [
|
|
@@ -5222,7 +6191,7 @@ var PromptControlBar = ({
|
|
|
5222
6191
|
] });
|
|
5223
6192
|
}
|
|
5224
6193
|
return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", gap: 0, children: [
|
|
5225
|
-
/* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "
|
|
6194
|
+
/* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "Command context" }),
|
|
5226
6195
|
/* @__PURE__ */ jsxs8(Box9, { flexDirection: compact ? "column" : "row", gap: controlGap, flexWrap: "wrap", children: [
|
|
5227
6196
|
selectorOrder.map((kind) => {
|
|
5228
6197
|
const isFocused = focused === kind;
|
|
@@ -5243,15 +6212,23 @@ var PromptControlBar = ({
|
|
|
5243
6212
|
borderStyle: raisedButtonStyle.border,
|
|
5244
6213
|
borderColor: isFocused ? terminalTheme.focus : terminalTheme.muted,
|
|
5245
6214
|
paddingX: 1,
|
|
5246
|
-
children: /* @__PURE__ */ jsxs8(
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
6215
|
+
children: /* @__PURE__ */ jsxs8(
|
|
6216
|
+
Text10,
|
|
6217
|
+
{
|
|
6218
|
+
color: isFocused ? "white" : void 0,
|
|
6219
|
+
backgroundColor: isFocused ? terminalTheme.selectedBackground : void 0,
|
|
6220
|
+
bold: isFocused,
|
|
6221
|
+
children: [
|
|
6222
|
+
isFocused ? raisedButtonStyle.activeMarker : raisedButtonStyle.inactiveMarker,
|
|
6223
|
+
" ",
|
|
6224
|
+
label,
|
|
6225
|
+
" [",
|
|
6226
|
+
value,
|
|
6227
|
+
"] ",
|
|
6228
|
+
dropdownIndicator
|
|
6229
|
+
]
|
|
6230
|
+
}
|
|
6231
|
+
)
|
|
5255
6232
|
},
|
|
5256
6233
|
kind
|
|
5257
6234
|
);
|
|
@@ -5265,7 +6242,8 @@ var PromptControlBar = ({
|
|
|
5265
6242
|
children: /* @__PURE__ */ jsxs8(
|
|
5266
6243
|
Text10,
|
|
5267
6244
|
{
|
|
5268
|
-
color: focused === "thinking" ?
|
|
6245
|
+
color: focused === "thinking" ? "white" : void 0,
|
|
6246
|
+
backgroundColor: focused === "thinking" ? terminalTheme.selectedBackground : void 0,
|
|
5269
6247
|
bold: focused === "thinking",
|
|
5270
6248
|
children: [
|
|
5271
6249
|
focused === "thinking" ? raisedButtonStyle.activeMarker : raisedButtonStyle.inactiveMarker,
|
|
@@ -5287,8 +6265,10 @@ var PromptControlBar = ({
|
|
|
5287
6265
|
var ChatContextPanel = ({
|
|
5288
6266
|
width,
|
|
5289
6267
|
height,
|
|
6268
|
+
mode,
|
|
5290
6269
|
active,
|
|
5291
6270
|
focused,
|
|
6271
|
+
artifactChips,
|
|
5292
6272
|
selectedProject,
|
|
5293
6273
|
selectedThreadTitle,
|
|
5294
6274
|
selectedModel,
|
|
@@ -5302,50 +6282,82 @@ var ChatContextPanel = ({
|
|
|
5302
6282
|
busy,
|
|
5303
6283
|
animate
|
|
5304
6284
|
}) => {
|
|
5305
|
-
return /* @__PURE__ */
|
|
6285
|
+
return /* @__PURE__ */ jsxs8(
|
|
5306
6286
|
TitledBox,
|
|
5307
6287
|
{
|
|
5308
|
-
title: "
|
|
6288
|
+
title: "Context",
|
|
5309
6289
|
borderStyle: "round",
|
|
5310
6290
|
borderColor: active ? terminalTheme.focus : terminalTheme.muted,
|
|
5311
|
-
padding: 1,
|
|
6291
|
+
padding: mode === "medium" ? 0 : 1,
|
|
6292
|
+
paddingX: 1,
|
|
5312
6293
|
width,
|
|
5313
6294
|
height,
|
|
5314
|
-
children:
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
6295
|
+
children: [
|
|
6296
|
+
artifactChips.length ? /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", marginBottom: 1, children: [
|
|
6297
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.brand, children: "Artifacts" }),
|
|
6298
|
+
/* @__PURE__ */ jsx10(
|
|
6299
|
+
ArtifactStrip,
|
|
6300
|
+
{
|
|
6301
|
+
chips: artifactChips,
|
|
6302
|
+
compact: true,
|
|
6303
|
+
terminalColumns: Math.max(24, width - 4)
|
|
6304
|
+
}
|
|
6305
|
+
)
|
|
6306
|
+
] }) : null,
|
|
6307
|
+
/* @__PURE__ */ jsx10(
|
|
6308
|
+
PromptControlBar,
|
|
6309
|
+
{
|
|
6310
|
+
focused,
|
|
6311
|
+
selectedThreadTitle,
|
|
6312
|
+
selectedProject,
|
|
6313
|
+
selectedModel,
|
|
6314
|
+
selectedMode,
|
|
6315
|
+
selectedAgentProfileLabel,
|
|
6316
|
+
hasThinkingSteps,
|
|
6317
|
+
thinkingExpanded,
|
|
6318
|
+
thinkingSummary,
|
|
6319
|
+
compact: true,
|
|
6320
|
+
terminalColumns: Math.max(24, width - 4),
|
|
6321
|
+
statusText,
|
|
6322
|
+
statusColor,
|
|
6323
|
+
busy,
|
|
6324
|
+
animate
|
|
6325
|
+
}
|
|
6326
|
+
)
|
|
6327
|
+
]
|
|
5334
6328
|
}
|
|
5335
6329
|
);
|
|
5336
6330
|
};
|
|
5337
6331
|
var BottomControls = ({ tab }) => /* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", justifyContent: "space-between", children: [
|
|
5338
6332
|
/* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
|
|
5339
|
-
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.
|
|
5340
|
-
/* @__PURE__ */ jsx10(Text10, { children: "
|
|
5341
|
-
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.
|
|
5342
|
-
/* @__PURE__ */ jsx10(Text10, { children: "
|
|
5343
|
-
/* @__PURE__ */
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
6333
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.accent, bold: true, children: "\u2303Q" }),
|
|
6334
|
+
/* @__PURE__ */ jsx10(Text10, { children: " Quit " }),
|
|
6335
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.accent, bold: true, children: "\u2303T" }),
|
|
6336
|
+
/* @__PURE__ */ jsx10(Text10, { children: " Tabs " }),
|
|
6337
|
+
tab === "chat" ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
6338
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.accent, bold: true, children: "Y" }),
|
|
6339
|
+
/* @__PURE__ */ jsx10(Text10, { children: " Copy " }),
|
|
6340
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.accent, bold: true, children: "D" }),
|
|
6341
|
+
/* @__PURE__ */ jsx10(Text10, { children: " Download " }),
|
|
6342
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.accent, bold: true, children: "O" }),
|
|
6343
|
+
/* @__PURE__ */ jsx10(Text10, { children: " Open " }),
|
|
6344
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.brand, children: "/ Commands" })
|
|
6345
|
+
] }) : /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
6346
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.accent, bold: true, children: "R" }),
|
|
6347
|
+
/* @__PURE__ */ jsx10(Text10, { children: " Refresh " }),
|
|
6348
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.accent, bold: true, children: "O" }),
|
|
6349
|
+
/* @__PURE__ */ jsx10(Text10, { children: " Open " }),
|
|
6350
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.accent, bold: true, children: "D" }),
|
|
6351
|
+
/* @__PURE__ */ jsx10(Text10, { children: " Download " }),
|
|
6352
|
+
tab === "projects" || tab === "connections" ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
6353
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.accent, bold: true, children: "\u2191\u2193/J/K" }),
|
|
6354
|
+
/* @__PURE__ */ jsx10(Text10, { children: " Select " }),
|
|
6355
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.accent, bold: true, children: "Enter" }),
|
|
6356
|
+
/* @__PURE__ */ jsx10(Text10, { children: " Confirm " })
|
|
6357
|
+
] }) : null,
|
|
6358
|
+
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.accent, bold: true, children: "[/]" }),
|
|
6359
|
+
/* @__PURE__ */ jsx10(Text10, { children: " Page" })
|
|
6360
|
+
] })
|
|
5349
6361
|
] }),
|
|
5350
6362
|
tab === "reports" ? /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
|
|
5351
6363
|
/* @__PURE__ */ jsx10(Text10, { color: terminalTheme.brand, bold: true, children: "Reports" }),
|
|
@@ -5443,6 +6455,10 @@ var App = ({
|
|
|
5443
6455
|
threadId: conversationId,
|
|
5444
6456
|
debug
|
|
5445
6457
|
});
|
|
6458
|
+
const [activeDraftSessionKey, setActiveDraftSessionKey] = useState4(
|
|
6459
|
+
() => conversationId ? void 0 : newDraftChatSessionKey()
|
|
6460
|
+
);
|
|
6461
|
+
const [draftChatSessions, setDraftChatSessions] = useState4({});
|
|
5446
6462
|
const [projects, setProjects] = useState4([]);
|
|
5447
6463
|
const [selectedProject, setSelectedProject] = useState4(null);
|
|
5448
6464
|
const [selectedModel, setSelectedModel] = useState4(model ?? "");
|
|
@@ -5455,6 +6471,7 @@ var App = ({
|
|
|
5455
6471
|
createWorkspacePanelStateMap
|
|
5456
6472
|
);
|
|
5457
6473
|
const [tablePageByTab, setTablePageByTab] = useState4({});
|
|
6474
|
+
const [selectedConnectionIndex, setSelectedConnectionIndex] = useState4(0);
|
|
5458
6475
|
const [workspaceRefreshKeys, setWorkspaceRefreshKeys] = useState4({});
|
|
5459
6476
|
const [workspaceStaleTick, setWorkspaceStaleTick] = useState4(0);
|
|
5460
6477
|
const [modelItems, setModelItems] = useState4(() => {
|
|
@@ -5485,6 +6502,7 @@ var App = ({
|
|
|
5485
6502
|
const [scrollOffset, setScrollOffset] = useState4(0);
|
|
5486
6503
|
const [contentHeight, setContentHeight] = useState4(0);
|
|
5487
6504
|
const [viewportHeight, setViewportHeight] = useState4(20);
|
|
6505
|
+
const [slashCommandCompletionIndex, setSlashCommandCompletionIndex] = useState4(0);
|
|
5488
6506
|
const [workspaceScrollOffset, setWorkspaceScrollOffset] = useState4(0);
|
|
5489
6507
|
const [workspaceContentHeight, setWorkspaceContentHeight] = useState4(0);
|
|
5490
6508
|
const [workspaceViewportHeight, setWorkspaceViewportHeight] = useState4(14);
|
|
@@ -5500,7 +6518,7 @@ var App = ({
|
|
|
5500
6518
|
() => bundledAgentProfiles.find((profile) => profile.id === selectedAgentProfileId),
|
|
5501
6519
|
[selectedAgentProfileId]
|
|
5502
6520
|
);
|
|
5503
|
-
const selectedAgentProfileLabel = selectedAgentProfile?.display_name ?? "
|
|
6521
|
+
const selectedAgentProfileLabel = selectedAgentProfile?.display_name ?? "General";
|
|
5504
6522
|
const frontendThreadUrl = useMemo(
|
|
5505
6523
|
() => buildFrontendThreadUrl(frontendBaseUrl, chatState.threadId),
|
|
5506
6524
|
[frontendBaseUrl, chatState.threadId]
|
|
@@ -5555,6 +6573,17 @@ var App = ({
|
|
|
5555
6573
|
() => remoteThreads.find((thread) => thread.thread_id === chatState.threadId),
|
|
5556
6574
|
[chatState.threadId, remoteThreads]
|
|
5557
6575
|
);
|
|
6576
|
+
const draftThreadSummaries = useMemo(
|
|
6577
|
+
() => Object.values(draftChatSessions).map(
|
|
6578
|
+
(draft) => buildDraftThreadSummary({
|
|
6579
|
+
key: draft.key,
|
|
6580
|
+
state: draft.state,
|
|
6581
|
+
projectName: draft.projectName,
|
|
6582
|
+
updatedAt: draft.updatedAt
|
|
6583
|
+
})
|
|
6584
|
+
).filter((draft) => Boolean(draft)),
|
|
6585
|
+
[draftChatSessions]
|
|
6586
|
+
);
|
|
5558
6587
|
const selectedThreadTitle = useMemo(
|
|
5559
6588
|
() => threadPanelTitle({
|
|
5560
6589
|
session: selectedLocalSession,
|
|
@@ -5565,8 +6594,10 @@ var App = ({
|
|
|
5565
6594
|
[chatState.messages.length, chatState.threadId, selectedLocalSession, selectedRemoteThread]
|
|
5566
6595
|
);
|
|
5567
6596
|
const threadSelectItems = useMemo(
|
|
5568
|
-
() => buildThreadSelectItems(localSessions, chatState.threadId, remoteThreads
|
|
5569
|
-
|
|
6597
|
+
() => buildThreadSelectItems(localSessions, chatState.threadId, remoteThreads, {
|
|
6598
|
+
drafts: draftThreadSummaries
|
|
6599
|
+
}),
|
|
6600
|
+
[chatState.threadId, draftThreadSummaries, localSessions, remoteThreads]
|
|
5570
6601
|
);
|
|
5571
6602
|
const checkHealth = useMemo(() => {
|
|
5572
6603
|
return async (token) => {
|
|
@@ -5602,7 +6633,7 @@ var App = ({
|
|
|
5602
6633
|
modes: modeItems,
|
|
5603
6634
|
threads: threadSelectItems.map((item) => ({
|
|
5604
6635
|
label: item.label,
|
|
5605
|
-
value: item.value.kind === "remote" ? item.value.thread.thread_id : item.value.kind === "session" ? item.value.session.threadId : "new",
|
|
6636
|
+
value: item.value.kind === "remote" ? item.value.thread.thread_id : item.value.kind === "session" ? item.value.session.threadId : item.value.kind === "draft" ? item.value.draft.key : "new",
|
|
5606
6637
|
description: item.description
|
|
5607
6638
|
})),
|
|
5608
6639
|
profiles: agentProfileItems
|
|
@@ -5691,6 +6722,7 @@ var App = ({
|
|
|
5691
6722
|
threadId: session.threadId,
|
|
5692
6723
|
messages
|
|
5693
6724
|
}));
|
|
6725
|
+
setActiveDraftSessionKey(void 0);
|
|
5694
6726
|
if (session.model) {
|
|
5695
6727
|
setSelectedModel(session.model);
|
|
5696
6728
|
}
|
|
@@ -5738,6 +6770,7 @@ var App = ({
|
|
|
5738
6770
|
threadId,
|
|
5739
6771
|
messages
|
|
5740
6772
|
}));
|
|
6773
|
+
setActiveDraftSessionKey(void 0);
|
|
5741
6774
|
const nextModel = history.model || history.thread_head?.model || thread.model;
|
|
5742
6775
|
if (nextModel) {
|
|
5743
6776
|
setSelectedModel(nextModel);
|
|
@@ -5764,11 +6797,33 @@ var App = ({
|
|
|
5764
6797
|
},
|
|
5765
6798
|
[loadRemoteThreadHistory, projects]
|
|
5766
6799
|
);
|
|
6800
|
+
const restoreDraftThread = React8.useCallback((key) => {
|
|
6801
|
+
const draft = draftChatSessions[key];
|
|
6802
|
+
if (!draft) {
|
|
6803
|
+
setNotice("Open session was not found.");
|
|
6804
|
+
return;
|
|
6805
|
+
}
|
|
6806
|
+
if (isBusyStatus(chatState.status) || controllerRef.current) {
|
|
6807
|
+
setNotice("Stop the running response before switching sessions.");
|
|
6808
|
+
return;
|
|
6809
|
+
}
|
|
6810
|
+
setActiveDraftSessionKey(key);
|
|
6811
|
+
setChatState((prev) => ({
|
|
6812
|
+
...draft.state,
|
|
6813
|
+
debug: prev.debug
|
|
6814
|
+
}));
|
|
6815
|
+
setActiveSelector(null);
|
|
6816
|
+
autoExpandedThinkingMessageIdsRef.current.clear();
|
|
6817
|
+
setExpandedThinkingMessageIds(/* @__PURE__ */ new Set());
|
|
6818
|
+
setNotice(`Loaded open session: ${truncateForTerminal(draft.state.threadId ?? key, 90)}`);
|
|
6819
|
+
setTimeout(() => scrollViewRef.current?.scrollToBottom(), 0);
|
|
6820
|
+
}, [chatState.status, draftChatSessions]);
|
|
5767
6821
|
const startNewThread = React8.useCallback(() => {
|
|
5768
6822
|
if (isBusyStatus(chatState.status) || controllerRef.current) {
|
|
5769
|
-
setNotice("Stop the running response before
|
|
6823
|
+
setNotice("Stop the running response before starting another session.");
|
|
5770
6824
|
return;
|
|
5771
6825
|
}
|
|
6826
|
+
setActiveDraftSessionKey(newDraftChatSessionKey());
|
|
5772
6827
|
queueRef.current = [];
|
|
5773
6828
|
setQueuedMessages([]);
|
|
5774
6829
|
setChatState((prev) => ({
|
|
@@ -5792,7 +6847,11 @@ var App = ({
|
|
|
5792
6847
|
return;
|
|
5793
6848
|
}
|
|
5794
6849
|
if (isBusyStatus(chatState.status) || controllerRef.current) {
|
|
5795
|
-
setNotice("Stop the running response before switching
|
|
6850
|
+
setNotice("Stop the running response before switching sessions.");
|
|
6851
|
+
return;
|
|
6852
|
+
}
|
|
6853
|
+
if (choice.kind === "draft") {
|
|
6854
|
+
restoreDraftThread(choice.draft.key);
|
|
5796
6855
|
return;
|
|
5797
6856
|
}
|
|
5798
6857
|
if (choice.kind === "remote") {
|
|
@@ -5803,7 +6862,7 @@ var App = ({
|
|
|
5803
6862
|
}
|
|
5804
6863
|
restoreLocalSession(choice.session);
|
|
5805
6864
|
},
|
|
5806
|
-
[chatState.status, restoreLocalSession, restoreRemoteThread, startNewThread]
|
|
6865
|
+
[chatState.status, restoreDraftThread, restoreLocalSession, restoreRemoteThread, startNewThread]
|
|
5807
6866
|
);
|
|
5808
6867
|
const selectProjectForUser = async (token, user) => {
|
|
5809
6868
|
setLoadingProjects(true);
|
|
@@ -5844,6 +6903,24 @@ var App = ({
|
|
|
5844
6903
|
controllerRef.current?.abort("App unmounted");
|
|
5845
6904
|
};
|
|
5846
6905
|
}, []);
|
|
6906
|
+
useEffect4(() => {
|
|
6907
|
+
if (!activeDraftSessionKey) {
|
|
6908
|
+
return;
|
|
6909
|
+
}
|
|
6910
|
+
const hasLocalContent = Boolean(chatState.threadId) || chatState.messages.some((message) => message.content.trim());
|
|
6911
|
+
if (!hasLocalContent) {
|
|
6912
|
+
return;
|
|
6913
|
+
}
|
|
6914
|
+
setDraftChatSessions((current) => ({
|
|
6915
|
+
...current,
|
|
6916
|
+
[activeDraftSessionKey]: {
|
|
6917
|
+
key: activeDraftSessionKey,
|
|
6918
|
+
state: chatState,
|
|
6919
|
+
projectName: selectedProject?.name,
|
|
6920
|
+
updatedAt: Date.now()
|
|
6921
|
+
}
|
|
6922
|
+
}));
|
|
6923
|
+
}, [activeDraftSessionKey, chatState, selectedProject?.name]);
|
|
5847
6924
|
useEffect4(() => {
|
|
5848
6925
|
if (phase !== "ready") {
|
|
5849
6926
|
return;
|
|
@@ -5964,7 +7041,7 @@ var App = ({
|
|
|
5964
7041
|
setIsLoggingIn(true);
|
|
5965
7042
|
setLoaderStep(1);
|
|
5966
7043
|
try {
|
|
5967
|
-
const { login } = await import("./dist-
|
|
7044
|
+
const { login } = await import("./dist-AGQQPJUD.js");
|
|
5968
7045
|
const newToken = await login(baseUrl, {
|
|
5969
7046
|
headless: Boolean(process.env.SSH_TTY || process.env.CI)
|
|
5970
7047
|
});
|
|
@@ -6095,7 +7172,7 @@ var App = ({
|
|
|
6095
7172
|
if (!loadReason) {
|
|
6096
7173
|
return;
|
|
6097
7174
|
}
|
|
6098
|
-
if (tab === "chat" || tab === "
|
|
7175
|
+
if (tab === "chat" || tab === "options" || tab === "help") {
|
|
6099
7176
|
const now = Date.now();
|
|
6100
7177
|
setWorkspacePanelTabState(tab, (previous) => ({
|
|
6101
7178
|
...previous,
|
|
@@ -6470,7 +7547,36 @@ var App = ({
|
|
|
6470
7547
|
setNotice(`Profile selected: ${label}. Mode set to Agent.`);
|
|
6471
7548
|
return;
|
|
6472
7549
|
}
|
|
6473
|
-
setNotice("Agent Profile cleared.
|
|
7550
|
+
setNotice("Agent Profile cleared. General chat flow active.");
|
|
7551
|
+
};
|
|
7552
|
+
const copyLatestAssistantResponse = () => {
|
|
7553
|
+
const text = buildLatestAssistantResponseText(chatState.messages);
|
|
7554
|
+
if (!text) {
|
|
7555
|
+
setNotice("No assistant response to copy yet.");
|
|
7556
|
+
return;
|
|
7557
|
+
}
|
|
7558
|
+
try {
|
|
7559
|
+
copyTextToClipboard(text);
|
|
7560
|
+
setNotice("Copied latest response with numbered citations.");
|
|
7561
|
+
} catch (error) {
|
|
7562
|
+
setNotice(`Copy failed: ${error?.message ?? "clipboard unavailable"}`);
|
|
7563
|
+
}
|
|
7564
|
+
};
|
|
7565
|
+
const downloadChatTranscript = () => {
|
|
7566
|
+
if (!chatState.messages.some((message) => message.content.trim())) {
|
|
7567
|
+
setNotice("No chat transcript to download yet.");
|
|
7568
|
+
return;
|
|
7569
|
+
}
|
|
7570
|
+
try {
|
|
7571
|
+
const file = writeChatTranscriptDownload({
|
|
7572
|
+
messages: chatState.messages,
|
|
7573
|
+
userName,
|
|
7574
|
+
threadId: chatState.threadId
|
|
7575
|
+
});
|
|
7576
|
+
setNotice(`Downloaded chat transcript: ${file}`);
|
|
7577
|
+
} catch (error) {
|
|
7578
|
+
setNotice(`Failed to download chat transcript: ${error?.message ?? "Unknown error"}`);
|
|
7579
|
+
}
|
|
6474
7580
|
};
|
|
6475
7581
|
const handlePromptSubmit = (value) => {
|
|
6476
7582
|
const cleanedValue = sanitizeTerminalMultilineInput(value);
|
|
@@ -6498,6 +7604,13 @@ var App = ({
|
|
|
6498
7604
|
selectThread({ kind: "remote", thread: remoteThread });
|
|
6499
7605
|
return;
|
|
6500
7606
|
}
|
|
7607
|
+
const draftThread = draftThreadSummaries.find(
|
|
7608
|
+
(candidate) => candidate.key === promptCommand.threadId
|
|
7609
|
+
);
|
|
7610
|
+
if (draftThread) {
|
|
7611
|
+
selectThread({ kind: "draft", draft: draftThread });
|
|
7612
|
+
return;
|
|
7613
|
+
}
|
|
6501
7614
|
const session = localSessions.find(
|
|
6502
7615
|
(candidate) => candidate.threadId === promptCommand.threadId
|
|
6503
7616
|
);
|
|
@@ -6533,6 +7646,12 @@ var App = ({
|
|
|
6533
7646
|
case "openFrontend":
|
|
6534
7647
|
handleOpenFrontend();
|
|
6535
7648
|
return;
|
|
7649
|
+
case "copyLatestResponse":
|
|
7650
|
+
copyLatestAssistantResponse();
|
|
7651
|
+
return;
|
|
7652
|
+
case "downloadTranscript":
|
|
7653
|
+
downloadChatTranscript();
|
|
7654
|
+
return;
|
|
6536
7655
|
case "showHelp":
|
|
6537
7656
|
setActiveWorkspaceTab("help");
|
|
6538
7657
|
setNotice(void 0);
|
|
@@ -6608,6 +7727,7 @@ var App = ({
|
|
|
6608
7727
|
return;
|
|
6609
7728
|
}
|
|
6610
7729
|
}
|
|
7730
|
+
const draftKeyAtStart = activeDraftSessionKey;
|
|
6611
7731
|
const threadId = chatState.threadId ?? randomUUID2();
|
|
6612
7732
|
const now = Date.now();
|
|
6613
7733
|
const userMessage = options.hitlResume || options.queuedMessageId ? void 0 : {
|
|
@@ -6765,6 +7885,16 @@ var App = ({
|
|
|
6765
7885
|
model: selectedModel,
|
|
6766
7886
|
profile: configProfile
|
|
6767
7887
|
});
|
|
7888
|
+
if (draftKeyAtStart) {
|
|
7889
|
+
setDraftChatSessions((current) => {
|
|
7890
|
+
const next = { ...current };
|
|
7891
|
+
delete next[draftKeyAtStart];
|
|
7892
|
+
return next;
|
|
7893
|
+
});
|
|
7894
|
+
setActiveDraftSessionKey(
|
|
7895
|
+
(current) => current === draftKeyAtStart ? void 0 : current
|
|
7896
|
+
);
|
|
7897
|
+
}
|
|
6768
7898
|
void refreshLocalSessions().catch(() => void 0);
|
|
6769
7899
|
void refreshRemoteThreads().catch(() => void 0);
|
|
6770
7900
|
} catch (error) {
|
|
@@ -6830,9 +7960,20 @@ var App = ({
|
|
|
6830
7960
|
0,
|
|
6831
7961
|
terminalSize.columns < 110 ? 3 : 4
|
|
6832
7962
|
);
|
|
7963
|
+
const slashCommandCompletions = useMemo(
|
|
7964
|
+
() => buildSlashCommandCompletionItems(input),
|
|
7965
|
+
[input]
|
|
7966
|
+
);
|
|
7967
|
+
const activeSlashCommandCompletionIndex = slashCommandCompletions.length ? Math.min(slashCommandCompletionIndex, slashCommandCompletions.length - 1) : void 0;
|
|
7968
|
+
const activeSlashCommandCompletion = activeSlashCommandCompletionIndex === void 0 ? void 0 : slashCommandCompletions[activeSlashCommandCompletionIndex];
|
|
7969
|
+
const slashCommandCompletionsActive = promptInputActive && activeWorkspaceTab === "chat" && !activeSelector && !isSearching && slashCommandCompletions.length > 0;
|
|
6833
7970
|
const promptGhostSuffix = useMemo(() => {
|
|
6834
7971
|
const trimmedStart = input.trimStart();
|
|
6835
7972
|
if (trimmedStart.startsWith("/")) {
|
|
7973
|
+
const commandGhost = slashCommandGhostSuffix(input, activeSlashCommandCompletion);
|
|
7974
|
+
if (commandGhost) {
|
|
7975
|
+
return commandGhost;
|
|
7976
|
+
}
|
|
6836
7977
|
return completePromptInput(input, promptCompletionContext)?.ghostSuffix;
|
|
6837
7978
|
}
|
|
6838
7979
|
for (const suggestion of visiblePromptSuggestions) {
|
|
@@ -6844,7 +7985,7 @@ var App = ({
|
|
|
6844
7985
|
return visiblePromptSuggestions[0];
|
|
6845
7986
|
}
|
|
6846
7987
|
return void 0;
|
|
6847
|
-
}, [input, promptCompletionContext, visiblePromptSuggestions]);
|
|
7988
|
+
}, [activeSlashCommandCompletion, input, promptCompletionContext, visiblePromptSuggestions]);
|
|
6848
7989
|
const promptInputWidth = Math.max(20, terminalSize.columns - 14);
|
|
6849
7990
|
const promptInputRowBudget = getPromptInputRowBudget(terminalSize);
|
|
6850
7991
|
const promptInputViewport = getInputViewport({
|
|
@@ -6855,11 +7996,12 @@ var App = ({
|
|
|
6855
7996
|
scrollOffset: promptInputScrollOffset
|
|
6856
7997
|
});
|
|
6857
7998
|
const promptInputRows = promptInputViewport.visibleRowCount;
|
|
6858
|
-
const
|
|
6859
|
-
|
|
6860
|
-
);
|
|
7999
|
+
const promptCommandCompletionRows = slashCommandCompletions.length ? 1 : 0;
|
|
8000
|
+
const promptSuggestionRows = estimatePromptSuggestionRows(visiblePromptSuggestions.length) + promptCommandCompletionRows;
|
|
8001
|
+
const chatResponsiveMode = getChatResponsiveMode(terminalSize);
|
|
6861
8002
|
const splitChatLayout = shouldUseSplitChatLayout(terminalSize);
|
|
6862
8003
|
const promptControlsCompact = terminalSize.columns < 96;
|
|
8004
|
+
const promptFooterControlsVisible = !slashCommandCompletionsActive;
|
|
6863
8005
|
const focusedFollowUpIndex = focusFollowUpIndex(focusedControl);
|
|
6864
8006
|
const activeChatPanel = chatPanelFocusForControl(focusedControl);
|
|
6865
8007
|
const controlFocusOrder = buildControlFocusOrder({
|
|
@@ -6883,18 +8025,19 @@ var App = ({
|
|
|
6883
8025
|
const bannerDisabled = bannerDisabledByConfig || !tuiLayout.showBanner;
|
|
6884
8026
|
const bannerContentColumns = Math.max(1, terminalSize.columns - tuiLayout.paddingX * 2);
|
|
6885
8027
|
const billingSummary = billingHeaderError ? `Plan: unavailable | Credits: unavailable` : billingSummaryText(billingHeader);
|
|
6886
|
-
const headerDetails =
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
billingSummary
|
|
6890
|
-
|
|
8028
|
+
const headerDetails = buildTuiHeaderDetails({
|
|
8029
|
+
apiBase,
|
|
8030
|
+
frontendBaseUrl,
|
|
8031
|
+
billingSummary,
|
|
8032
|
+
userName
|
|
8033
|
+
});
|
|
6891
8034
|
const keyBindings = getTuiKeyBindings();
|
|
6892
8035
|
const scrollHelp = mouseTrackingEnabled ? `${keyBindings.mouse} | wheel scroll` : keyBindings.scroll;
|
|
6893
8036
|
const chatAvailableWidth = Math.max(
|
|
6894
8037
|
24,
|
|
6895
8038
|
terminalSize.columns - tuiLayout.paddingX * 2
|
|
6896
8039
|
);
|
|
6897
|
-
const chatContextPanelWidth = splitChatLayout ?
|
|
8040
|
+
const chatContextPanelWidth = splitChatLayout ? getContextRailWidth(terminalSize) : 0;
|
|
6898
8041
|
const chatSplitGap = splitChatLayout ? 1 : 0;
|
|
6899
8042
|
const chatThreadPanelWidth = splitChatLayout ? Math.max(60, chatAvailableWidth - chatContextPanelWidth - chatSplitGap) : void 0;
|
|
6900
8043
|
const threadContentWidth = Math.max(
|
|
@@ -6902,6 +8045,92 @@ var App = ({
|
|
|
6902
8045
|
splitChatLayout ? (chatThreadPanelWidth ?? chatAvailableWidth) - 8 : chatAvailableWidth - 8
|
|
6903
8046
|
);
|
|
6904
8047
|
const activeWorkspacePanelState = workspacePanelStore[activeWorkspaceTab] ?? createWorkspacePanelState(activeWorkspaceTab, "loading");
|
|
8048
|
+
const activeConnections = directArray4(activeWorkspacePanelState.data.connections);
|
|
8049
|
+
const activeProjectList = projects.length ? projects : [selectedProject ?? defaultProject];
|
|
8050
|
+
const selectedProjectIndex = Math.max(
|
|
8051
|
+
0,
|
|
8052
|
+
activeProjectList.findIndex(
|
|
8053
|
+
(project) => project.id === (selectedProject ?? activeProjectList[0])?.id
|
|
8054
|
+
)
|
|
8055
|
+
);
|
|
8056
|
+
const moveSelectedProject = React8.useCallback(
|
|
8057
|
+
(direction) => {
|
|
8058
|
+
const nextIndex = nextWorkspaceSelectionIndex({
|
|
8059
|
+
currentIndex: selectedProjectIndex,
|
|
8060
|
+
itemCount: activeProjectList.length,
|
|
8061
|
+
direction
|
|
8062
|
+
});
|
|
8063
|
+
const project = activeProjectList[nextIndex];
|
|
8064
|
+
if (!project) {
|
|
8065
|
+
setNotice("No project rows are available to select.");
|
|
8066
|
+
return;
|
|
8067
|
+
}
|
|
8068
|
+
setSelectedProject(project);
|
|
8069
|
+
setNotice(`Project selected: ${truncateForTerminal(project.name, 80)}`);
|
|
8070
|
+
},
|
|
8071
|
+
[activeProjectList, selectedProjectIndex]
|
|
8072
|
+
);
|
|
8073
|
+
const moveSelectedConnection = React8.useCallback(
|
|
8074
|
+
(direction) => {
|
|
8075
|
+
setSelectedConnectionIndex((current) => {
|
|
8076
|
+
const next = nextWorkspaceSelectionIndex({
|
|
8077
|
+
currentIndex: current,
|
|
8078
|
+
itemCount: activeConnections.length,
|
|
8079
|
+
direction
|
|
8080
|
+
});
|
|
8081
|
+
const selected = activeConnections[next];
|
|
8082
|
+
if (selected) {
|
|
8083
|
+
setNotice(
|
|
8084
|
+
`Connection selected: ${truncateForTerminal(recordLabel(selected, "connection"), 80)}`
|
|
8085
|
+
);
|
|
8086
|
+
} else {
|
|
8087
|
+
setNotice("No connection rows are available to select.");
|
|
8088
|
+
}
|
|
8089
|
+
return next;
|
|
8090
|
+
});
|
|
8091
|
+
},
|
|
8092
|
+
[activeConnections]
|
|
8093
|
+
);
|
|
8094
|
+
useEffect4(() => {
|
|
8095
|
+
setSelectedConnectionIndex(
|
|
8096
|
+
(current) => activeConnections.length ? Math.min(Math.max(0, current), activeConnections.length - 1) : 0
|
|
8097
|
+
);
|
|
8098
|
+
}, [activeConnections.length]);
|
|
8099
|
+
useEffect4(() => {
|
|
8100
|
+
setSlashCommandCompletionIndex(0);
|
|
8101
|
+
}, [input]);
|
|
8102
|
+
useEffect4(() => {
|
|
8103
|
+
setSlashCommandCompletionIndex(
|
|
8104
|
+
(current) => slashCommandCompletions.length ? Math.min(current, slashCommandCompletions.length - 1) : 0
|
|
8105
|
+
);
|
|
8106
|
+
}, [slashCommandCompletions.length]);
|
|
8107
|
+
const reportsPanelState = workspacePanelStore.reports ?? createWorkspacePanelState("reports", "idle");
|
|
8108
|
+
const reportsDashboardModel = useMemo(
|
|
8109
|
+
() => reportsPanelState.status === "ready" ? buildReportsDashboardModel({
|
|
8110
|
+
dashboard: reportsPanelState.data.dashboard,
|
|
8111
|
+
reportsSummary: reportsPanelState.data.reportsSummary,
|
|
8112
|
+
selectedProject,
|
|
8113
|
+
costReport: reportsPanelState.data.costReport,
|
|
8114
|
+
wafReport: reportsPanelState.data.wafReport
|
|
8115
|
+
}) : void 0,
|
|
8116
|
+
[reportsPanelState.data, reportsPanelState.status, selectedProject]
|
|
8117
|
+
);
|
|
8118
|
+
const chatArtifactChips = useMemo(
|
|
8119
|
+
() => buildChatArtifactChips({
|
|
8120
|
+
projectName: selectedProject?.name ?? defaultProject.name,
|
|
8121
|
+
reportsStatus: reportsPanelState.status,
|
|
8122
|
+
coverageLabel: reportsDashboardModel?.coverageLabel,
|
|
8123
|
+
topActionCount: reportsDashboardModel?.topActions.length ?? 0,
|
|
8124
|
+
frontendThreadUrl
|
|
8125
|
+
}),
|
|
8126
|
+
[
|
|
8127
|
+
frontendThreadUrl,
|
|
8128
|
+
reportsDashboardModel?.coverageLabel,
|
|
8129
|
+
reportsDashboardModel?.topActions.length,
|
|
8130
|
+
reportsPanelState.status,
|
|
8131
|
+
selectedProject?.name
|
|
8132
|
+
]
|
|
8133
|
+
);
|
|
6905
8134
|
const activeTablePage = tablePageByTab[activeWorkspaceTab] ?? 0;
|
|
6906
8135
|
const bannerRenderedRows = bannerDisabled ? 0 : estimateBannerRows({ detailsCount: headerDetails.length, columns: bannerContentColumns });
|
|
6907
8136
|
const workspaceContentWidth = Math.max(24, terminalSize.columns - tuiLayout.paddingX * 2 - 3);
|
|
@@ -6943,7 +8172,8 @@ var App = ({
|
|
|
6943
8172
|
suggestionRows: promptSuggestionRows,
|
|
6944
8173
|
compact: promptControlsCompact,
|
|
6945
8174
|
hasThinkingSteps,
|
|
6946
|
-
includeControls: !splitChatLayout
|
|
8175
|
+
includeControls: !splitChatLayout && promptFooterControlsVisible,
|
|
8176
|
+
variant: "dock"
|
|
6947
8177
|
});
|
|
6948
8178
|
const searchPromptPanelRows = estimatePromptPanelRows({
|
|
6949
8179
|
inputRows: promptInputRows,
|
|
@@ -6971,6 +8201,7 @@ var App = ({
|
|
|
6971
8201
|
footerRows: chatFooterRows
|
|
6972
8202
|
});
|
|
6973
8203
|
const chatMiddleAuxiliaryRows = (isSearching ? 3 : 0) + (queuedMessages.length > 0 ? 4 : 0) + (notice ? 1 : 0) + (errorText ? 5 : 0) + (chatState.status === "hitl_waiting" && chatState.hitl?.waiting ? 7 : 0) + (activeSelector ? tuiLayout.selectorLimit + 4 : 0);
|
|
8204
|
+
const contextRailArtifactRows = splitChatLayout && chatArtifactChips.length ? chatArtifactChips.length + 2 : 0;
|
|
6974
8205
|
const chatMainPanelRows = Math.max(4, chatMiddleViewportRows - chatMiddleAuxiliaryRows);
|
|
6975
8206
|
const chatThreadHeight = getFramedBodyRows(chatMainPanelRows);
|
|
6976
8207
|
const chatMiddleOverflowing = chatMiddleContentHeight > chatMiddleViewportHeight;
|
|
@@ -6980,9 +8211,10 @@ var App = ({
|
|
|
6980
8211
|
return Math.max(1, terminalSize.rows - (promptControlsCompact ? 7 : 5));
|
|
6981
8212
|
}
|
|
6982
8213
|
const auxiliaryRows = (isSearching ? 3 : 0) + (queuedMessages.length > 0 ? 4 : 0) + (notice ? 1 : 0) + (errorText ? 5 : 0);
|
|
6983
|
-
return workspaceTabStartRow + 9 + auxiliaryRows;
|
|
8214
|
+
return workspaceTabStartRow + 9 + auxiliaryRows + contextRailArtifactRows;
|
|
6984
8215
|
},
|
|
6985
8216
|
[
|
|
8217
|
+
contextRailArtifactRows,
|
|
6986
8218
|
errorText,
|
|
6987
8219
|
isSearching,
|
|
6988
8220
|
notice,
|
|
@@ -7019,7 +8251,8 @@ var App = ({
|
|
|
7019
8251
|
suggestionRows: promptSuggestionRows,
|
|
7020
8252
|
compact: promptControlsCompact,
|
|
7021
8253
|
hasThinkingSteps,
|
|
7022
|
-
includeControls: !splitChatLayout
|
|
8254
|
+
includeControls: !splitChatLayout && promptFooterControlsVisible,
|
|
8255
|
+
variant: "dock"
|
|
7023
8256
|
}) + 1
|
|
7024
8257
|
),
|
|
7025
8258
|
[
|
|
@@ -7028,6 +8261,7 @@ var App = ({
|
|
|
7028
8261
|
promptSuggestionRows,
|
|
7029
8262
|
terminalSize.rows,
|
|
7030
8263
|
promptControlsCompact,
|
|
8264
|
+
promptFooterControlsVisible,
|
|
7031
8265
|
splitChatLayout
|
|
7032
8266
|
]
|
|
7033
8267
|
);
|
|
@@ -7069,6 +8303,20 @@ var App = ({
|
|
|
7069
8303
|
}
|
|
7070
8304
|
void sendMessage(question);
|
|
7071
8305
|
};
|
|
8306
|
+
const chooseSlashCommandCompletion = (command) => {
|
|
8307
|
+
completionCycleRef.current = void 0;
|
|
8308
|
+
setSlashCommandCompletionIndex(0);
|
|
8309
|
+
handlePromptSubmit(command.name);
|
|
8310
|
+
};
|
|
8311
|
+
const moveSlashCommandCompletion = (direction) => {
|
|
8312
|
+
if (!slashCommandCompletions.length) {
|
|
8313
|
+
return;
|
|
8314
|
+
}
|
|
8315
|
+
completionCycleRef.current = void 0;
|
|
8316
|
+
setSlashCommandCompletionIndex(
|
|
8317
|
+
(current) => (current + direction + slashCommandCompletions.length) % slashCommandCompletions.length
|
|
8318
|
+
);
|
|
8319
|
+
};
|
|
7072
8320
|
const handleFocusedControlEnter = () => {
|
|
7073
8321
|
if (isSelectorControlFocus(focusedControl)) {
|
|
7074
8322
|
setActiveSelector(focusedControl);
|
|
@@ -7216,6 +8464,29 @@ var App = ({
|
|
|
7216
8464
|
exit();
|
|
7217
8465
|
return;
|
|
7218
8466
|
}
|
|
8467
|
+
const selectionDirection = key.downArrow || lowerInput === "j" ? 1 : key.upArrow || lowerInput === "k" ? -1 : void 0;
|
|
8468
|
+
if (selectionDirection && selectableWorkspaceTab(activeWorkspaceTab) && !key.ctrl && !key.meta) {
|
|
8469
|
+
if (activeWorkspaceTab === "projects") {
|
|
8470
|
+
moveSelectedProject(selectionDirection);
|
|
8471
|
+
} else {
|
|
8472
|
+
moveSelectedConnection(selectionDirection);
|
|
8473
|
+
}
|
|
8474
|
+
return;
|
|
8475
|
+
}
|
|
8476
|
+
if (key.return && selectableWorkspaceTab(activeWorkspaceTab)) {
|
|
8477
|
+
if (activeWorkspaceTab === "projects") {
|
|
8478
|
+
const project = activeProjectList[selectedProjectIndex];
|
|
8479
|
+
setNotice(
|
|
8480
|
+
project ? `Project selected for chat context: ${truncateForTerminal(project.name, 80)}` : "No project rows are available to select."
|
|
8481
|
+
);
|
|
8482
|
+
} else {
|
|
8483
|
+
const connection = activeConnections[selectedConnectionIndex];
|
|
8484
|
+
setNotice(
|
|
8485
|
+
connection ? `Connection selected: ${truncateForTerminal(recordLabel(connection, "connection"), 80)}` : "No connection rows are available to select."
|
|
8486
|
+
);
|
|
8487
|
+
}
|
|
8488
|
+
return;
|
|
8489
|
+
}
|
|
7219
8490
|
if (key.upArrow && !key.ctrl && !key.meta) {
|
|
7220
8491
|
workspaceScrollViewRef.current?.scrollBy(-1);
|
|
7221
8492
|
return;
|
|
@@ -7325,7 +8596,15 @@ var App = ({
|
|
|
7325
8596
|
}
|
|
7326
8597
|
return;
|
|
7327
8598
|
}
|
|
7328
|
-
if (
|
|
8599
|
+
if (slashCommandCompletionsActive && (key.tab || inputKey === " " || key.downArrow) && !key.ctrl && !key.meta) {
|
|
8600
|
+
moveSlashCommandCompletion(1);
|
|
8601
|
+
return;
|
|
8602
|
+
}
|
|
8603
|
+
if (slashCommandCompletionsActive && key.upArrow && !key.ctrl && !key.meta) {
|
|
8604
|
+
moveSlashCommandCompletion(-1);
|
|
8605
|
+
return;
|
|
8606
|
+
}
|
|
8607
|
+
if (promptInputActive && (key.tab || inputKey === " ") && input.trimStart().startsWith("/") && !slashCommandCompletionsActive) {
|
|
7329
8608
|
const completion = completePromptInput(
|
|
7330
8609
|
input,
|
|
7331
8610
|
promptCompletionContext,
|
|
@@ -7399,6 +8678,20 @@ var App = ({
|
|
|
7399
8678
|
return;
|
|
7400
8679
|
}
|
|
7401
8680
|
}
|
|
8681
|
+
if (phase === "ready" && activeWorkspaceTab === "chat" && !promptInputActive && !activeSelector && !isSearching) {
|
|
8682
|
+
if (lowerInput === "y") {
|
|
8683
|
+
copyLatestAssistantResponse();
|
|
8684
|
+
return;
|
|
8685
|
+
}
|
|
8686
|
+
if (lowerInput === "d") {
|
|
8687
|
+
downloadChatTranscript();
|
|
8688
|
+
return;
|
|
8689
|
+
}
|
|
8690
|
+
if (lowerInput === "o") {
|
|
8691
|
+
handleOpenFrontend();
|
|
8692
|
+
return;
|
|
8693
|
+
}
|
|
8694
|
+
}
|
|
7402
8695
|
if (phase === "ready" && (!input.trim() || !promptInputActive)) {
|
|
7403
8696
|
if (key.tab || inputKey === " ") {
|
|
7404
8697
|
setFocusedControl((current) => nextControlFocus(current, controlFocusOrder));
|
|
@@ -7527,6 +8820,7 @@ var App = ({
|
|
|
7527
8820
|
stopActiveChat();
|
|
7528
8821
|
}
|
|
7529
8822
|
if (key.ctrl && inputKey.toLowerCase() === "l") {
|
|
8823
|
+
setActiveDraftSessionKey(newDraftChatSessionKey());
|
|
7530
8824
|
setChatState((prev) => ({
|
|
7531
8825
|
...initialChatState,
|
|
7532
8826
|
status: "idle",
|
|
@@ -7740,6 +9034,7 @@ var App = ({
|
|
|
7740
9034
|
state: activeWorkspacePanelState,
|
|
7741
9035
|
projects,
|
|
7742
9036
|
selectedProject,
|
|
9037
|
+
selectedConnectionIndex,
|
|
7743
9038
|
currentUserId,
|
|
7744
9039
|
selectedModel,
|
|
7745
9040
|
selectedMode,
|
|
@@ -7856,14 +9151,23 @@ var App = ({
|
|
|
7856
9151
|
]
|
|
7857
9152
|
}
|
|
7858
9153
|
) : null,
|
|
9154
|
+
!splitChatLayout && chatArtifactChips.length ? /* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx10(
|
|
9155
|
+
ArtifactStrip,
|
|
9156
|
+
{
|
|
9157
|
+
chips: chatArtifactChips,
|
|
9158
|
+
terminalColumns: chatAvailableWidth
|
|
9159
|
+
}
|
|
9160
|
+
) }) : null,
|
|
7859
9161
|
splitChatLayout ? /* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", columnGap: chatSplitGap, children: [
|
|
7860
9162
|
/* @__PURE__ */ jsx10(
|
|
7861
9163
|
ChatContextPanel,
|
|
7862
9164
|
{
|
|
7863
9165
|
width: chatContextPanelWidth,
|
|
7864
9166
|
height: chatMainPanelRows,
|
|
9167
|
+
mode: chatResponsiveMode,
|
|
7865
9168
|
active: activeChatPanel === "settings",
|
|
7866
9169
|
focused: focusedControl,
|
|
9170
|
+
artifactChips: chatArtifactChips,
|
|
7867
9171
|
selectedThreadTitle,
|
|
7868
9172
|
selectedProject,
|
|
7869
9173
|
selectedModel,
|
|
@@ -7904,7 +9208,7 @@ var App = ({
|
|
|
7904
9208
|
selectedIndex: Math.max(
|
|
7905
9209
|
0,
|
|
7906
9210
|
threadSelectItems.findIndex(
|
|
7907
|
-
(item) => item.value.kind === "remote" && item.value.thread.thread_id === chatState.threadId || item.value.kind === "session" && item.value.session.threadId === chatState.threadId
|
|
9211
|
+
(item) => item.value.kind === "remote" && item.value.thread.thread_id === chatState.threadId || item.value.kind === "session" && item.value.session.threadId === chatState.threadId || item.value.kind === "draft" && item.value.draft.key === activeDraftSessionKey
|
|
7908
9212
|
)
|
|
7909
9213
|
),
|
|
7910
9214
|
onSubmit: (item) => selectThread(item.value),
|
|
@@ -8023,6 +9327,7 @@ var App = ({
|
|
|
8023
9327
|
) : activeSelector ? null : /* @__PURE__ */ jsx10(
|
|
8024
9328
|
InputBox,
|
|
8025
9329
|
{
|
|
9330
|
+
variant: "dock",
|
|
8026
9331
|
value: input,
|
|
8027
9332
|
onChange: handlePromptChange,
|
|
8028
9333
|
onSubmit: handlePromptSubmit,
|
|
@@ -8044,6 +9349,10 @@ var App = ({
|
|
|
8044
9349
|
followUpsLabel: promptSuggestions.label,
|
|
8045
9350
|
focusedFollowUpIndex,
|
|
8046
9351
|
followUpsActive: focusedFollowUpIndex !== void 0,
|
|
9352
|
+
commandCompletions: slashCommandCompletions,
|
|
9353
|
+
focusedCommandCompletionIndex: activeSlashCommandCompletionIndex,
|
|
9354
|
+
commandCompletionsActive: slashCommandCompletionsActive,
|
|
9355
|
+
onCommandCompletionSubmit: chooseSlashCommandCompletion,
|
|
8047
9356
|
terminalColumns: terminalSize.columns,
|
|
8048
9357
|
scrollOffset: promptInputViewport.startRow,
|
|
8049
9358
|
minInputRows: promptInputRowBudget,
|
|
@@ -8055,7 +9364,7 @@ var App = ({
|
|
|
8055
9364
|
selectorOpen: Boolean(activeSelector),
|
|
8056
9365
|
searching: isSearching
|
|
8057
9366
|
}),
|
|
8058
|
-
footerControls: promptFooterControls,
|
|
9367
|
+
footerControls: slashCommandCompletionsActive ? void 0 : promptFooterControls,
|
|
8059
9368
|
helpText: "",
|
|
8060
9369
|
actionLabel: promptActionIsCancel ? "ESC to cancel" : void 0,
|
|
8061
9370
|
actionHint: getChatInputHelpText({
|
|
@@ -8077,5 +9386,6 @@ var App = ({
|
|
|
8077
9386
|
] });
|
|
8078
9387
|
};
|
|
8079
9388
|
export {
|
|
8080
|
-
App
|
|
9389
|
+
App,
|
|
9390
|
+
buildTuiHeaderDetails
|
|
8081
9391
|
};
|