apex-dev 3.10.3 → 3.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bundle.js ADDED
@@ -0,0 +1,930 @@
1
+ // @bun
2
+ // index.jsx
3
+ var import_store6 = __toESM(require_store(), 1);
4
+ var import_react17 = __toESM(require_react(), 1);
5
+ var import_react11 = __toESM(require_react(), 1);
6
+ var import_store = __toESM(require_store(), 1);
7
+ function useStore() {
8
+ return import_react11.useSyncExternalStore(import_store.subscribe, import_store.getSnapshot);
9
+ }
10
+ var import_store5 = __toESM(require_store(), 1);
11
+ var import_config4 = __toESM(require_config(), 1);
12
+ var import_agent = __toESM(require_agent(), 1);
13
+ var import_commands = __toESM(require_commands(), 1);
14
+ var import_react13 = __toESM(require_react(), 1);
15
+ var import_theme = __toESM(require_theme(), 1);
16
+ var import_config = __toESM(require_config(), 1);
17
+ var NARROW_THRESHOLD = 60;
18
+ function useLayout() {
19
+ const { width } = useTerminalDimensions();
20
+ const w2 = width || 80;
21
+ const isNarrow = w2 < NARROW_THRESHOLD;
22
+ return {
23
+ width: w2,
24
+ isNarrow,
25
+ indent: isNarrow ? 2 : 4,
26
+ smallIndent: isNarrow ? 1 : 2
27
+ };
28
+ }
29
+ var jsx_runtime = __toESM(require_jsx_runtime(), 1);
30
+ var path2 = __require("path");
31
+ var { execSync } = __require("child_process");
32
+ function Header() {
33
+ const [branch, setBranch] = import_react13.useState("");
34
+ const { isNarrow } = useLayout();
35
+ const cwd = path2.basename(import_config.PROJECT_ROOT);
36
+ import_react13.useEffect(() => {
37
+ try {
38
+ const b2 = execSync("git rev-parse --abbrev-ref HEAD 2>/dev/null", {
39
+ encoding: "utf-8",
40
+ cwd: import_config.PROJECT_ROOT
41
+ }).trim();
42
+ setBranch(b2);
43
+ } catch {}
44
+ }, []);
45
+ return /* @__PURE__ */ jsx_runtime.jsx("box", {
46
+ style: { flexDirection: "row", paddingLeft: 1, paddingRight: 1 },
47
+ children: /* @__PURE__ */ jsx_runtime.jsxs("text", {
48
+ children: [
49
+ /* @__PURE__ */ jsx_runtime.jsx("span", {
50
+ fg: import_theme.colors.primary,
51
+ attributes: TextAttributes.BOLD,
52
+ children: "\u26A1 Apex"
53
+ }),
54
+ /* @__PURE__ */ jsx_runtime.jsx("span", {
55
+ fg: import_theme.colors.dim,
56
+ children: " "
57
+ }),
58
+ /* @__PURE__ */ jsx_runtime.jsx("span", {
59
+ fg: import_theme.colors.accent,
60
+ children: "[max]"
61
+ }),
62
+ /* @__PURE__ */ jsx_runtime.jsx("span", {
63
+ fg: import_theme.colors.dim,
64
+ children: " "
65
+ }),
66
+ /* @__PURE__ */ jsx_runtime.jsx("span", {
67
+ fg: import_theme.colors.muted,
68
+ children: isNarrow && cwd.length > 12 ? cwd.slice(0, 12) + "\u2026" : cwd
69
+ }),
70
+ branch && !isNarrow ? /* @__PURE__ */ jsx_runtime.jsxs(jsx_runtime.Fragment, {
71
+ children: [
72
+ /* @__PURE__ */ jsx_runtime.jsx("span", {
73
+ fg: import_theme.colors.dim,
74
+ children: " on "
75
+ }),
76
+ /* @__PURE__ */ jsx_runtime.jsx("span", {
77
+ fg: import_theme.colors.text,
78
+ children: branch
79
+ })
80
+ ]
81
+ }) : null
82
+ ]
83
+ })
84
+ });
85
+ }
86
+ var import_theme2 = __toESM(require_theme(), 1);
87
+ var jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
88
+ function Divider() {
89
+ const { width } = useLayout();
90
+ const cols = Math.min(width, 120);
91
+ return /* @__PURE__ */ jsx_runtime2.jsx("text", {
92
+ fg: import_theme2.colors.dim,
93
+ content: "\u2500".repeat(cols)
94
+ });
95
+ }
96
+ var import_theme11 = __toESM(require_theme(), 1);
97
+ var import_theme3 = __toESM(require_theme(), 1);
98
+ var import_config2 = __toESM(require_config(), 1);
99
+ var jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
100
+ function Welcome() {
101
+ const { isNarrow } = useLayout();
102
+ return /* @__PURE__ */ jsx_runtime3.jsxs("box", {
103
+ style: { flexDirection: "column", paddingLeft: 1, marginTop: 1 },
104
+ children: [
105
+ /* @__PURE__ */ jsx_runtime3.jsx("text", {
106
+ fg: import_theme3.colors.white,
107
+ attributes: TextAttributes.BOLD,
108
+ content: "How can I help?"
109
+ }),
110
+ /* @__PURE__ */ jsx_runtime3.jsx("text", {
111
+ fg: import_theme3.colors.dim,
112
+ content: isNarrow ? `Max ${import_config2.MAX_TOOL_ITERATIONS} iterations` : `Tools available \xB7 Max ${import_config2.MAX_TOOL_ITERATIONS} iterations per turn`
113
+ })
114
+ ]
115
+ });
116
+ }
117
+ var import_theme4 = __toESM(require_theme(), 1);
118
+ var jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
119
+ function UserMessage({ content }) {
120
+ return /* @__PURE__ */ jsx_runtime4.jsxs("box", {
121
+ style: { flexDirection: "column", paddingLeft: 1, marginTop: 1 },
122
+ children: [
123
+ /* @__PURE__ */ jsx_runtime4.jsx("text", {
124
+ fg: import_theme4.colors.blue,
125
+ attributes: TextAttributes.BOLD,
126
+ content: "You"
127
+ }),
128
+ /* @__PURE__ */ jsx_runtime4.jsx("text", {
129
+ fg: import_theme4.colors.text,
130
+ content: content || ""
131
+ })
132
+ ]
133
+ });
134
+ }
135
+ var import_theme5 = __toESM(require_theme(), 1);
136
+ var jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
137
+ function AssistantMessage({ content, isStreaming }) {
138
+ const { indent, isNarrow, width } = useLayout();
139
+ const codeIndent = isNarrow ? 1 : 2;
140
+ const separatorWidth = Math.min(width - indent - codeIndent, isNarrow ? 40 : 60);
141
+ if (!content)
142
+ return null;
143
+ const lines = content.split(`
144
+ `);
145
+ const rendered = [];
146
+ let inCodeBlock = false;
147
+ let codeLines = [];
148
+ let codeLang = "";
149
+ for (let i = 0;i < lines.length; i++) {
150
+ const line = lines[i];
151
+ if (line.startsWith("```") && !inCodeBlock) {
152
+ inCodeBlock = true;
153
+ codeLang = line.slice(3).trim() || "code";
154
+ codeLines = [];
155
+ } else if (line.startsWith("```") && inCodeBlock) {
156
+ inCodeBlock = false;
157
+ rendered.push(/* @__PURE__ */ jsx_runtime5.jsxs("box", {
158
+ style: { flexDirection: "column", paddingLeft: codeIndent, marginTop: 0 },
159
+ children: [
160
+ /* @__PURE__ */ jsx_runtime5.jsx("text", {
161
+ fg: import_theme5.colors.dim,
162
+ content: `\u2500\u2500 ${codeLang} \u2500\u2500`
163
+ }),
164
+ codeLines.map((cl, j2) => /* @__PURE__ */ jsx_runtime5.jsxs("text", {
165
+ children: [
166
+ /* @__PURE__ */ jsx_runtime5.jsx("span", {
167
+ fg: import_theme5.colors.dim,
168
+ children: String(j2 + 1).padStart(isNarrow ? 2 : 3) + " \u2502 "
169
+ }),
170
+ /* @__PURE__ */ jsx_runtime5.jsx("span", {
171
+ fg: import_theme5.colors.text,
172
+ children: cl
173
+ })
174
+ ]
175
+ }, j2)),
176
+ /* @__PURE__ */ jsx_runtime5.jsx("text", {
177
+ fg: import_theme5.colors.dim,
178
+ content: "\u2500".repeat(Math.max(separatorWidth, 10))
179
+ })
180
+ ]
181
+ }, `code-${i}`));
182
+ } else if (inCodeBlock) {
183
+ codeLines.push(line);
184
+ } else {
185
+ const processed = line.replace(/`([^`]+)`/g, "\xAB$1\xBB");
186
+ if (processed.includes("\xAB")) {
187
+ const parts = processed.split(/\u00AB|\u00BB/);
188
+ rendered.push(/* @__PURE__ */ jsx_runtime5.jsx("text", {
189
+ children: parts.map((part, j2) => j2 % 2 === 0 ? /* @__PURE__ */ jsx_runtime5.jsx("span", {
190
+ fg: import_theme5.colors.text,
191
+ children: part
192
+ }, j2) : /* @__PURE__ */ jsx_runtime5.jsx("span", {
193
+ fg: import_theme5.colors.cyan,
194
+ children: part
195
+ }, j2))
196
+ }, `line-${i}`));
197
+ } else {
198
+ rendered.push(/* @__PURE__ */ jsx_runtime5.jsx("text", {
199
+ children: /* @__PURE__ */ jsx_runtime5.jsx("span", {
200
+ fg: import_theme5.colors.text,
201
+ children: line
202
+ })
203
+ }, `line-${i}`));
204
+ }
205
+ }
206
+ }
207
+ if (inCodeBlock && codeLines.length > 0) {
208
+ rendered.push(/* @__PURE__ */ jsx_runtime5.jsxs("box", {
209
+ style: { flexDirection: "column", paddingLeft: codeIndent },
210
+ children: [
211
+ /* @__PURE__ */ jsx_runtime5.jsx("text", {
212
+ fg: import_theme5.colors.dim,
213
+ content: `\u2500\u2500 ${codeLang} \u2500\u2500`
214
+ }),
215
+ codeLines.map((cl, j2) => /* @__PURE__ */ jsx_runtime5.jsxs("text", {
216
+ children: [
217
+ /* @__PURE__ */ jsx_runtime5.jsx("span", {
218
+ fg: import_theme5.colors.dim,
219
+ children: String(j2 + 1).padStart(isNarrow ? 2 : 3) + " \u2502 "
220
+ }),
221
+ /* @__PURE__ */ jsx_runtime5.jsx("span", {
222
+ fg: import_theme5.colors.text,
223
+ children: cl
224
+ })
225
+ ]
226
+ }, j2))
227
+ ]
228
+ }, "code-tail"));
229
+ }
230
+ return /* @__PURE__ */ jsx_runtime5.jsxs("box", {
231
+ style: { flexDirection: "column", paddingLeft: indent },
232
+ children: [
233
+ rendered,
234
+ isStreaming ? /* @__PURE__ */ jsx_runtime5.jsx("text", {
235
+ fg: import_theme5.colors.accent,
236
+ content: "\u258A"
237
+ }) : null
238
+ ]
239
+ });
240
+ }
241
+ var import_theme6 = __toESM(require_theme(), 1);
242
+ var jsx_runtime6 = __toESM(require_jsx_runtime(), 1);
243
+ function ThinkBlock({ content, expanded, onToggle }) {
244
+ const { isNarrow, smallIndent } = useLayout();
245
+ if (!content)
246
+ return null;
247
+ const lines = content.split(`
248
+ `);
249
+ const maxPreview = isNarrow ? 2 : 4;
250
+ const displayLines = expanded ? lines : lines.slice(0, maxPreview);
251
+ const isTruncated = !expanded && lines.length > maxPreview;
252
+ return /* @__PURE__ */ jsx_runtime6.jsxs("box", {
253
+ style: { flexDirection: "column", paddingLeft: smallIndent, marginTop: 0 },
254
+ onMouseDown: onToggle,
255
+ children: [
256
+ /* @__PURE__ */ jsx_runtime6.jsx("text", {
257
+ fg: import_theme6.colors.dim,
258
+ attributes: TextAttributes.ITALIC,
259
+ content: "\u25B8 Thinking"
260
+ }),
261
+ displayLines.map((line, i) => line.trim() ? /* @__PURE__ */ jsx_runtime6.jsx("text", {
262
+ fg: import_theme6.colors.dim,
263
+ attributes: TextAttributes.ITALIC,
264
+ style: { paddingLeft: smallIndent },
265
+ content: line
266
+ }, i) : null),
267
+ isTruncated ? /* @__PURE__ */ jsx_runtime6.jsx("text", {
268
+ fg: import_theme6.colors.dim,
269
+ attributes: TextAttributes.ITALIC,
270
+ style: { paddingLeft: smallIndent },
271
+ content: isNarrow ? `+${lines.length - maxPreview} more (tap)` : `... +${lines.length - maxPreview} more lines (click to expand)`
272
+ }) : null
273
+ ]
274
+ });
275
+ }
276
+ var import_theme8 = __toESM(require_theme(), 1);
277
+ var import_store2 = __toESM(require_store(), 1);
278
+ var import_react14 = __toESM(require_react(), 1);
279
+ var import_theme7 = __toESM(require_theme(), 1);
280
+ var jsx_runtime7 = __toESM(require_jsx_runtime(), 1);
281
+ var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
282
+ function Spinner({ label }) {
283
+ const [frame, setFrame] = import_react14.useState(0);
284
+ const timerRef = import_react14.useRef(null);
285
+ import_react14.useEffect(() => {
286
+ timerRef.current = setInterval(() => {
287
+ setFrame((f) => (f + 1) % FRAMES.length);
288
+ }, 80);
289
+ return () => clearInterval(timerRef.current);
290
+ }, []);
291
+ return /* @__PURE__ */ jsx_runtime7.jsxs("text", {
292
+ children: [
293
+ /* @__PURE__ */ jsx_runtime7.jsx("span", {
294
+ fg: import_theme7.colors.accent,
295
+ children: FRAMES[frame]
296
+ }),
297
+ label ? /* @__PURE__ */ jsx_runtime7.jsx("span", {
298
+ fg: import_theme7.colors.dim,
299
+ children: " " + label
300
+ }) : null
301
+ ]
302
+ });
303
+ }
304
+ var jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
305
+ var SUBAGENT_TOOLS = new Set([
306
+ "FilePickerMax",
307
+ "Thinker",
308
+ "ThinkerBestOfN",
309
+ "EditorMultiPrompt",
310
+ "CodeReview",
311
+ "CodeReviewMulti",
312
+ "Commander",
313
+ "ContextPruner",
314
+ "ResearcherWeb",
315
+ "ResearcherDocs",
316
+ "GeneralAgent"
317
+ ]);
318
+ function formatElapsed(ms) {
319
+ return ms < 1000 ? `${ms}ms` : `${(ms / 1000).toFixed(1)}s`;
320
+ }
321
+ function truncate(str, len) {
322
+ return str.length > len ? str.slice(0, len - 3) + "..." : str;
323
+ }
324
+ function ToolCallItem({ message }) {
325
+ const { indent, isNarrow } = useLayout();
326
+ const truncLen = isNarrow ? 30 : 50;
327
+ const { id, name, detail, status, success, elapsed, output, expanded } = message;
328
+ const isRunning = status === "running" || status === "pending";
329
+ const isSubagent = SUBAGENT_TOOLS.has(name);
330
+ return /* @__PURE__ */ jsx_runtime8.jsxs("box", {
331
+ style: { flexDirection: "column", paddingLeft: indent },
332
+ onMouseDown: () => import_store2.toggleMessageExpanded(id),
333
+ children: [
334
+ /* @__PURE__ */ jsx_runtime8.jsx("box", {
335
+ style: { flexDirection: "row" },
336
+ children: isRunning ? /* @__PURE__ */ jsx_runtime8.jsx(Spinner, {
337
+ label: `[${name}] ${truncate(detail || "...", truncLen)}`
338
+ }) : /* @__PURE__ */ jsx_runtime8.jsxs("text", {
339
+ children: [
340
+ /* @__PURE__ */ jsx_runtime8.jsx("span", {
341
+ fg: success ? import_theme8.colors.green : import_theme8.colors.red,
342
+ children: success ? "\u2713" : "\u2717"
343
+ }),
344
+ isSubagent ? /* @__PURE__ */ jsx_runtime8.jsx("span", {
345
+ fg: import_theme8.colors.dim,
346
+ children: expanded ? " \u25BE" : " \u25B8"
347
+ }) : null,
348
+ /* @__PURE__ */ jsx_runtime8.jsx("span", {
349
+ fg: import_theme8.colors.dim,
350
+ children: " ["
351
+ }),
352
+ /* @__PURE__ */ jsx_runtime8.jsx("span", {
353
+ fg: import_theme8.colors.accent,
354
+ children: name
355
+ }),
356
+ /* @__PURE__ */ jsx_runtime8.jsx("span", {
357
+ fg: import_theme8.colors.dim,
358
+ children: "] "
359
+ }),
360
+ /* @__PURE__ */ jsx_runtime8.jsx("span", {
361
+ fg: import_theme8.colors.dim,
362
+ children: truncate(detail || "", truncLen)
363
+ }),
364
+ elapsed != null ? /* @__PURE__ */ jsx_runtime8.jsx("span", {
365
+ fg: import_theme8.colors.dim,
366
+ children: " " + formatElapsed(elapsed)
367
+ }) : null
368
+ ]
369
+ })
370
+ }),
371
+ expanded && output ? isSubagent ? /* @__PURE__ */ jsx_runtime8.jsxs("box", {
372
+ style: { flexDirection: "column", paddingLeft: indent, marginTop: 0, borderStyle: "single", borderColor: import_theme8.colors.border, paddingRight: 1 },
373
+ children: [
374
+ /* @__PURE__ */ jsx_runtime8.jsx("text", {
375
+ fg: import_theme8.colors.dim,
376
+ attributes: TextAttributes.ITALIC,
377
+ style: { marginBottom: 0 },
378
+ children: `\u2500\u2500 ${name} output \u2500\u2500`
379
+ }),
380
+ /* @__PURE__ */ jsx_runtime8.jsx("text", {
381
+ fg: import_theme8.colors.text,
382
+ content: output,
383
+ wrapMode: "char"
384
+ })
385
+ ]
386
+ }) : /* @__PURE__ */ jsx_runtime8.jsx("box", {
387
+ style: { paddingLeft: indent, marginTop: 0 },
388
+ children: /* @__PURE__ */ jsx_runtime8.jsx("text", {
389
+ fg: import_theme8.colors.dim,
390
+ content: truncate(output, 500),
391
+ wrapMode: "char"
392
+ })
393
+ }) : null
394
+ ]
395
+ });
396
+ }
397
+ var import_theme9 = __toESM(require_theme(), 1);
398
+ var jsx_runtime9 = __toESM(require_jsx_runtime(), 1);
399
+ var path3 = __require("path");
400
+ function DiffView({ filename, content }) {
401
+ const { indent } = useLayout();
402
+ if (!content)
403
+ return null;
404
+ const lines = content.split(`
405
+ `);
406
+ return /* @__PURE__ */ jsx_runtime9.jsxs("box", {
407
+ style: { flexDirection: "column", paddingLeft: indent },
408
+ children: [
409
+ /* @__PURE__ */ jsx_runtime9.jsx("text", {
410
+ fg: import_theme9.colors.text,
411
+ attributes: TextAttributes.BOLD,
412
+ content: path3.basename(filename || "")
413
+ }),
414
+ lines.map((line, i) => {
415
+ if (line.startsWith("+")) {
416
+ return /* @__PURE__ */ jsx_runtime9.jsx("text", {
417
+ fg: import_theme9.colors.green,
418
+ content: line
419
+ }, i);
420
+ }
421
+ if (line.startsWith("-")) {
422
+ return /* @__PURE__ */ jsx_runtime9.jsx("text", {
423
+ fg: import_theme9.colors.red,
424
+ content: line
425
+ }, i);
426
+ }
427
+ return null;
428
+ })
429
+ ]
430
+ });
431
+ }
432
+ var import_theme10 = __toESM(require_theme(), 1);
433
+ var import_store3 = __toESM(require_store(), 1);
434
+ var jsx_runtime10 = __toESM(require_jsx_runtime(), 1);
435
+ function SystemMessage({ message }) {
436
+ const { isNarrow, smallIndent } = useLayout();
437
+ const { id, content = "", label, expanded } = message;
438
+ if (!content)
439
+ return null;
440
+ const lines = content.split(`
441
+ `);
442
+ const maxPreview = isNarrow ? 3 : 6;
443
+ const displayLines = expanded ? lines : lines.slice(0, maxPreview);
444
+ const isTruncated = !expanded && lines.length > maxPreview;
445
+ return /* @__PURE__ */ jsx_runtime10.jsxs("box", {
446
+ style: { flexDirection: "column", paddingLeft: smallIndent, marginTop: 1 },
447
+ onMouseDown: () => import_store3.toggleMessageExpanded(id),
448
+ children: [
449
+ label ? /* @__PURE__ */ jsx_runtime10.jsx("text", {
450
+ fg: import_theme10.colors.accent,
451
+ attributes: TextAttributes.BOLD,
452
+ content: label
453
+ }) : null,
454
+ displayLines.map((line, i) => /* @__PURE__ */ jsx_runtime10.jsx("text", {
455
+ fg: import_theme10.colors.muted,
456
+ content: line
457
+ }, i)),
458
+ isTruncated ? /* @__PURE__ */ jsx_runtime10.jsx("text", {
459
+ fg: import_theme10.colors.dim,
460
+ content: isNarrow ? `+${lines.length - maxPreview} more (tap)` : `... +${lines.length - maxPreview} more lines (click to expand)`
461
+ }) : null
462
+ ]
463
+ });
464
+ }
465
+ var import_store4 = __toESM(require_store(), 1);
466
+ var jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
467
+ function MessageItem({ message }) {
468
+ const { width } = useLayout();
469
+ switch (message.role) {
470
+ case "user":
471
+ return /* @__PURE__ */ jsx_runtime11.jsx(UserMessage, {
472
+ content: message.content
473
+ });
474
+ case "assistant":
475
+ return /* @__PURE__ */ jsx_runtime11.jsxs("box", {
476
+ style: { flexDirection: "column", marginTop: 1 },
477
+ children: [
478
+ /* @__PURE__ */ jsx_runtime11.jsx("text", {
479
+ fg: import_theme11.colors.primary,
480
+ attributes: TextAttributes.BOLD,
481
+ style: { paddingLeft: 1 },
482
+ content: "Apex"
483
+ }),
484
+ /* @__PURE__ */ jsx_runtime11.jsx(AssistantMessage, {
485
+ content: message.content
486
+ })
487
+ ]
488
+ });
489
+ case "thinking":
490
+ return /* @__PURE__ */ jsx_runtime11.jsx(ThinkBlock, {
491
+ content: message.content,
492
+ expanded: message.expanded,
493
+ onToggle: () => import_store4.toggleMessageExpanded(message.id)
494
+ });
495
+ case "tool":
496
+ return /* @__PURE__ */ jsx_runtime11.jsx(ToolCallItem, {
497
+ message
498
+ });
499
+ case "diff":
500
+ return /* @__PURE__ */ jsx_runtime11.jsx(DiffView, {
501
+ filename: message.filename,
502
+ content: message.content
503
+ });
504
+ case "system":
505
+ return /* @__PURE__ */ jsx_runtime11.jsx(SystemMessage, {
506
+ message
507
+ });
508
+ case "divider":
509
+ return /* @__PURE__ */ jsx_runtime11.jsx("text", {
510
+ fg: import_theme11.colors.dim,
511
+ style: { paddingLeft: 1 },
512
+ content: "\u2500".repeat(Math.max(width - 2, 10))
513
+ });
514
+ default:
515
+ return null;
516
+ }
517
+ }
518
+ function ChatArea({ messages, streamingContent, streamingThinking, isProcessing }) {
519
+ const { indent } = useLayout();
520
+ return /* @__PURE__ */ jsx_runtime11.jsx("scrollbox", {
521
+ style: { flexGrow: 1 },
522
+ focused: true,
523
+ stickyScroll: true,
524
+ stickyStart: "bottom",
525
+ scrollY: true,
526
+ children: /* @__PURE__ */ jsx_runtime11.jsxs("box", {
527
+ style: { flexDirection: "column" },
528
+ children: [
529
+ /* @__PURE__ */ jsx_runtime11.jsx(Welcome, {}),
530
+ messages.map((msg) => /* @__PURE__ */ jsx_runtime11.jsx(MessageItem, {
531
+ message: msg
532
+ }, msg.id)),
533
+ streamingThinking ? /* @__PURE__ */ jsx_runtime11.jsx("box", {
534
+ style: { paddingLeft: 2, marginTop: 0 },
535
+ children: /* @__PURE__ */ jsx_runtime11.jsxs("text", {
536
+ fg: import_theme11.colors.dim,
537
+ attributes: TextAttributes.ITALIC,
538
+ children: [
539
+ /* @__PURE__ */ jsx_runtime11.jsx("span", {
540
+ fg: import_theme11.colors.dim,
541
+ children: "\u25B8 Thinking: "
542
+ }),
543
+ /* @__PURE__ */ jsx_runtime11.jsx("span", {
544
+ fg: import_theme11.colors.dim,
545
+ children: streamingThinking.slice(-100)
546
+ })
547
+ ]
548
+ })
549
+ }) : null,
550
+ streamingContent ? /* @__PURE__ */ jsx_runtime11.jsx("box", {
551
+ style: { flexDirection: "column", marginTop: 0 },
552
+ children: /* @__PURE__ */ jsx_runtime11.jsx(AssistantMessage, {
553
+ content: streamingContent,
554
+ isStreaming: true
555
+ })
556
+ }) : null,
557
+ isProcessing && !streamingContent && !streamingThinking ? /* @__PURE__ */ jsx_runtime11.jsx("box", {
558
+ style: { paddingLeft: indent, marginTop: 1 },
559
+ children: /* @__PURE__ */ jsx_runtime11.jsx(Spinner, {
560
+ label: "Reasoning..."
561
+ })
562
+ }) : null,
563
+ /* @__PURE__ */ jsx_runtime11.jsx("box", {
564
+ style: { height: 1 }
565
+ })
566
+ ]
567
+ })
568
+ });
569
+ }
570
+ var import_react15 = __toESM(require_react(), 1);
571
+ var import_theme12 = __toESM(require_theme(), 1);
572
+ var jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
573
+ function InputBar({ disabled, onSubmit }) {
574
+ const inputRef = import_react15.useRef(null);
575
+ const { isNarrow } = useLayout();
576
+ const handleSubmit = (value) => {
577
+ const trimmed = value.trim();
578
+ if (!trimmed)
579
+ return;
580
+ if (inputRef.current)
581
+ inputRef.current.value = "";
582
+ onSubmit(trimmed);
583
+ };
584
+ return /* @__PURE__ */ jsx_runtime12.jsxs("box", {
585
+ style: { flexDirection: "column" },
586
+ children: [
587
+ /* @__PURE__ */ jsx_runtime12.jsx("text", {
588
+ fg: import_theme12.colors.dim,
589
+ style: { paddingLeft: isNarrow ? 1 : 2 },
590
+ content: isNarrow ? "^C exit \xB7 /help" : "Ctrl+C to exit \xB7 /help for commands"
591
+ }),
592
+ /* @__PURE__ */ jsx_runtime12.jsxs("box", {
593
+ style: { flexDirection: "row", paddingLeft: 1 },
594
+ children: [
595
+ /* @__PURE__ */ jsx_runtime12.jsx("text", {
596
+ fg: import_theme12.colors.primary,
597
+ content: "\u276F "
598
+ }),
599
+ /* @__PURE__ */ jsx_runtime12.jsx("input", {
600
+ ref: inputRef,
601
+ focused: !disabled,
602
+ placeholder: disabled ? "Processing..." : "Type a message...",
603
+ onSubmit: handleSubmit,
604
+ fg: import_theme12.colors.text,
605
+ style: { flexGrow: 1 }
606
+ })
607
+ ]
608
+ })
609
+ ]
610
+ });
611
+ }
612
+ var import_theme13 = __toESM(require_theme(), 1);
613
+ var import_config3 = __toESM(require_config(), 1);
614
+ var jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
615
+ function StatusBar({ isProcessing }) {
616
+ const { isNarrow } = useLayout();
617
+ const elapsed = ((Date.now() - import_config3.session.startTime) / 1000 / 60).toFixed(1);
618
+ return /* @__PURE__ */ jsx_runtime13.jsx("box", {
619
+ style: { flexDirection: "row", paddingLeft: isNarrow ? 1 : 2, paddingRight: isNarrow ? 1 : 2 },
620
+ children: /* @__PURE__ */ jsx_runtime13.jsxs("text", {
621
+ children: [
622
+ /* @__PURE__ */ jsx_runtime13.jsxs("span", {
623
+ fg: import_theme13.colors.dim,
624
+ children: [
625
+ elapsed,
626
+ "min"
627
+ ]
628
+ }),
629
+ /* @__PURE__ */ jsx_runtime13.jsx("span", {
630
+ fg: import_theme13.colors.dim,
631
+ children: " \xB7 "
632
+ }),
633
+ /* @__PURE__ */ jsx_runtime13.jsxs("span", {
634
+ fg: import_theme13.colors.dim,
635
+ children: [
636
+ import_config3.session.turnCount,
637
+ " turns"
638
+ ]
639
+ }),
640
+ !isNarrow ? /* @__PURE__ */ jsx_runtime13.jsxs(jsx_runtime13.Fragment, {
641
+ children: [
642
+ /* @__PURE__ */ jsx_runtime13.jsx("span", {
643
+ fg: import_theme13.colors.dim,
644
+ children: " \xB7 "
645
+ }),
646
+ /* @__PURE__ */ jsx_runtime13.jsxs("span", {
647
+ fg: import_theme13.colors.dim,
648
+ children: [
649
+ import_config3.session.toolCallCount,
650
+ " tools"
651
+ ]
652
+ })
653
+ ]
654
+ }) : null,
655
+ !isNarrow ? /* @__PURE__ */ jsx_runtime13.jsxs(jsx_runtime13.Fragment, {
656
+ children: [
657
+ /* @__PURE__ */ jsx_runtime13.jsx("span", {
658
+ fg: import_theme13.colors.dim,
659
+ children: " \xB7 "
660
+ }),
661
+ /* @__PURE__ */ jsx_runtime13.jsxs("span", {
662
+ fg: import_theme13.colors.dim,
663
+ children: [
664
+ import_config3.session.totalTokens.toLocaleString(),
665
+ " tok"
666
+ ]
667
+ })
668
+ ]
669
+ }) : null,
670
+ /* @__PURE__ */ jsx_runtime13.jsx("span", {
671
+ fg: import_theme13.colors.dim,
672
+ children: " \xB7 "
673
+ }),
674
+ /* @__PURE__ */ jsx_runtime13.jsx("span", {
675
+ fg: import_theme13.colors.dim,
676
+ children: "$" + import_config3.session.totalCost.toFixed(4)
677
+ }),
678
+ import_config3.session.filesModified.size > 0 && !isNarrow ? /* @__PURE__ */ jsx_runtime13.jsxs(jsx_runtime13.Fragment, {
679
+ children: [
680
+ /* @__PURE__ */ jsx_runtime13.jsx("span", {
681
+ fg: import_theme13.colors.dim,
682
+ children: " \xB7 "
683
+ }),
684
+ /* @__PURE__ */ jsx_runtime13.jsxs("span", {
685
+ fg: import_theme13.colors.yellow,
686
+ children: [
687
+ import_config3.session.filesModified.size,
688
+ " files modified"
689
+ ]
690
+ })
691
+ ]
692
+ }) : null,
693
+ isProcessing ? /* @__PURE__ */ jsx_runtime13.jsxs(jsx_runtime13.Fragment, {
694
+ children: [
695
+ /* @__PURE__ */ jsx_runtime13.jsx("span", {
696
+ fg: import_theme13.colors.dim,
697
+ children: " \xB7 "
698
+ }),
699
+ /* @__PURE__ */ jsx_runtime13.jsx("span", {
700
+ fg: import_theme13.colors.accent,
701
+ children: isNarrow ? "..." : "processing"
702
+ })
703
+ ]
704
+ }) : null
705
+ ]
706
+ })
707
+ });
708
+ }
709
+ var import_theme14 = __toESM(require_theme(), 1);
710
+ var jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
711
+ var COMMANDS = [
712
+ { cmd: "/help", desc: "Show this menu" },
713
+ { cmd: "/compact", desc: "Compact/summarize conversation context" },
714
+ { cmd: "/files", desc: "Show project file tree" },
715
+ { cmd: "/clear", desc: "Clear conversation" },
716
+ { cmd: "/cost", desc: "Show session stats" },
717
+ { cmd: "/undo", desc: "Undo last edit" },
718
+ { cmd: "/diff", desc: "Show git diff" },
719
+ { cmd: "/git <cmd>", desc: "Run a git command" },
720
+ { cmd: "/quit", desc: "Exit" }
721
+ ];
722
+ var TOOLS = [
723
+ "Read",
724
+ "Write",
725
+ "Edit",
726
+ "Patch",
727
+ "Bash",
728
+ "Grep",
729
+ "Glob",
730
+ "ListDir",
731
+ "UndoEdit",
732
+ "Task",
733
+ "CodeReview"
734
+ ];
735
+ var SUBAGENTS = [
736
+ "FilePickerMax",
737
+ "Thinker",
738
+ "ThinkerBestOfN*",
739
+ "EditorMultiPrompt*",
740
+ "CodeReviewMulti*",
741
+ "Commander",
742
+ "ContextPruner"
743
+ ];
744
+ function HelpModal({ onClose, onCommand }) {
745
+ const { isNarrow } = useLayout();
746
+ useKeyboard((key) => {
747
+ if (key.name === "escape" || key.name === "q") {
748
+ onClose();
749
+ }
750
+ });
751
+ return /* @__PURE__ */ jsx_runtime14.jsxs("box", {
752
+ zIndex: 100,
753
+ border: true,
754
+ borderColor: import_theme14.colors.primary,
755
+ backgroundColor: "#0d0d1a",
756
+ title: " Help ",
757
+ titleAlignment: "center",
758
+ style: {
759
+ position: "absolute",
760
+ top: 2,
761
+ left: isNarrow ? 1 : 4,
762
+ bottom: 2,
763
+ right: isNarrow ? 1 : 4,
764
+ padding: 1,
765
+ flexDirection: "column"
766
+ },
767
+ children: [
768
+ /* @__PURE__ */ jsx_runtime14.jsx("text", {
769
+ fg: import_theme14.colors.white,
770
+ attributes: TextAttributes.BOLD,
771
+ content: "Commands"
772
+ }),
773
+ /* @__PURE__ */ jsx_runtime14.jsx("box", {
774
+ style: { flexDirection: "column", marginTop: 0 },
775
+ children: COMMANDS.map(({ cmd, desc }) => /* @__PURE__ */ jsx_runtime14.jsx("box", {
776
+ style: { flexDirection: "row" },
777
+ onMouseDown: () => {
778
+ const slashCmd = cmd.split(" ")[0];
779
+ if (onCommand && !cmd.includes("<"))
780
+ onCommand(slashCmd);
781
+ onClose();
782
+ },
783
+ children: /* @__PURE__ */ jsx_runtime14.jsxs("text", {
784
+ children: [
785
+ /* @__PURE__ */ jsx_runtime14.jsx("span", {
786
+ fg: import_theme14.colors.accent,
787
+ children: cmd.padEnd(isNarrow ? 10 : 14)
788
+ }),
789
+ /* @__PURE__ */ jsx_runtime14.jsx("span", {
790
+ fg: import_theme14.colors.text,
791
+ children: desc
792
+ })
793
+ ]
794
+ })
795
+ }, cmd))
796
+ }),
797
+ /* @__PURE__ */ jsx_runtime14.jsx("text", {
798
+ fg: import_theme14.colors.white,
799
+ attributes: TextAttributes.BOLD,
800
+ style: { marginTop: 1 },
801
+ content: "Tools"
802
+ }),
803
+ /* @__PURE__ */ jsx_runtime14.jsx("text", {
804
+ fg: import_theme14.colors.dim,
805
+ content: TOOLS.join(", ")
806
+ }),
807
+ /* @__PURE__ */ jsx_runtime14.jsx("text", {
808
+ fg: import_theme14.colors.white,
809
+ attributes: TextAttributes.BOLD,
810
+ style: { marginTop: 1 },
811
+ content: "Sub-Agents"
812
+ }),
813
+ /* @__PURE__ */ jsx_runtime14.jsx("text", {
814
+ fg: import_theme14.colors.dim,
815
+ content: SUBAGENTS.join(", ")
816
+ }),
817
+ /* @__PURE__ */ jsx_runtime14.jsx("text", {
818
+ fg: import_theme14.colors.dim,
819
+ content: " * = MAX mode only"
820
+ }),
821
+ /* @__PURE__ */ jsx_runtime14.jsx("text", {
822
+ fg: import_theme14.colors.dim,
823
+ style: { marginTop: 1 },
824
+ content: "Press ESC or q to close"
825
+ })
826
+ ]
827
+ });
828
+ }
829
+ var jsx_runtime15 = __toESM(require_jsx_runtime(), 1);
830
+ function exitApp() {
831
+ const renderer = import_store5.getRenderer();
832
+ if (renderer)
833
+ renderer.destroy();
834
+ const elapsed = ((Date.now() - import_config4.session.startTime) / 1000 / 60).toFixed(1);
835
+ const parts = [
836
+ `${elapsed} min`,
837
+ `${import_config4.session.turnCount} turns`,
838
+ `${import_config4.session.toolCallCount} tool calls`,
839
+ `${import_config4.session.totalTokens.toLocaleString()} tokens`,
840
+ `$${import_config4.session.totalCost.toFixed(4)}`
841
+ ];
842
+ if (import_config4.session.filesModified.size > 0)
843
+ parts.push(`${import_config4.session.filesModified.size} files modified`);
844
+ if (import_config4.session.commandsRun.length > 0)
845
+ parts.push(`${import_config4.session.commandsRun.length} commands`);
846
+ console.log(`
847
+ Session: ${parts.join(" \xB7 ")}
848
+ `);
849
+ console.log(` Goodbye! \u2726
850
+ `);
851
+ process.exit(0);
852
+ }
853
+ function App() {
854
+ const state = useStore();
855
+ useKeyboard((key) => {
856
+ if (key.ctrl && key.name === "c") {
857
+ exitApp();
858
+ }
859
+ });
860
+ const handleInput = import_react17.useCallback(async (value) => {
861
+ if (value === "exit" || value === "quit") {
862
+ exitApp();
863
+ return;
864
+ }
865
+ if (value.startsWith("/")) {
866
+ const result = await import_commands.handleSlashCommand(value);
867
+ if (result?.action === "quit") {
868
+ exitApp();
869
+ }
870
+ return;
871
+ }
872
+ import_agent.handleUserInput(value).catch((err) => {
873
+ import_store5.addMessage({ role: "system", content: `Error: ${err.message}` });
874
+ import_store5.setState({ isProcessing: false });
875
+ });
876
+ }, []);
877
+ const handleHelpCommand = import_react17.useCallback((cmd) => {
878
+ if (cmd) {
879
+ import_commands.handleSlashCommand(cmd).then((result) => {
880
+ if (result?.action === "quit")
881
+ exitApp();
882
+ });
883
+ }
884
+ }, []);
885
+ return /* @__PURE__ */ jsx_runtime15.jsxs("box", {
886
+ style: { flexDirection: "column", flexGrow: 1 },
887
+ children: [
888
+ /* @__PURE__ */ jsx_runtime15.jsx(Header, {}),
889
+ /* @__PURE__ */ jsx_runtime15.jsx(Divider, {}),
890
+ /* @__PURE__ */ jsx_runtime15.jsx(ChatArea, {
891
+ messages: state.messages,
892
+ streamingContent: state.streamingContent,
893
+ streamingThinking: state.streamingThinking,
894
+ isProcessing: state.isProcessing
895
+ }),
896
+ /* @__PURE__ */ jsx_runtime15.jsx(Divider, {}),
897
+ /* @__PURE__ */ jsx_runtime15.jsx(StatusBar, {
898
+ isProcessing: state.isProcessing
899
+ }),
900
+ /* @__PURE__ */ jsx_runtime15.jsx(InputBar, {
901
+ disabled: state.isProcessing || state.showHelp,
902
+ onSubmit: handleInput
903
+ }),
904
+ state.showHelp ? /* @__PURE__ */ jsx_runtime15.jsx(HelpModal, {
905
+ onClose: () => import_store5.setState({ showHelp: false }),
906
+ onCommand: handleHelpCommand
907
+ }) : null
908
+ ]
909
+ });
910
+ }
911
+ var jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
912
+ async function main2() {
913
+ if (process.env.APEX_LOCAL_SERVER === "1") {
914
+ const { startServer } = await Promise.resolve().then(() => __toESM(require_server(), 1));
915
+ await startServer();
916
+ }
917
+ const renderer = await createCliRenderer({
918
+ useAlternateScreen: true,
919
+ exitOnCtrlC: false,
920
+ useMouse: true
921
+ });
922
+ import_store6.setRenderer(renderer);
923
+ const root = createRoot(renderer);
924
+ root.render(/* @__PURE__ */ jsx_runtime16.jsx(App, {}));
925
+ renderer.start();
926
+ }
927
+ main2().catch((err) => {
928
+ console.error("Failed to start Apex:", err);
929
+ process.exit(1);
930
+ });