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