codebase-cli 2.0.0-pre.4 → 2.0.0-pre.40
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/agent/agent.js +43 -15
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/config.js +61 -20
- package/dist/agent/config.js.map +1 -1
- package/dist/agent/events.bench.js +84 -0
- package/dist/agent/events.bench.js.map +1 -0
- package/dist/agent/prompt-suggestion.js +141 -0
- package/dist/agent/prompt-suggestion.js.map +1 -0
- package/dist/agent/system-prompt.js +15 -0
- package/dist/agent/system-prompt.js.map +1 -1
- package/dist/app-server/protocol.js +7 -0
- package/dist/app-server/protocol.js.map +1 -0
- package/dist/app-server/server.js +241 -0
- package/dist/app-server/server.js.map +1 -0
- package/dist/auth/cli.js +1 -1
- package/dist/auth/cli.js.map +1 -1
- package/dist/auth/credentials.js +33 -2
- package/dist/auth/credentials.js.map +1 -1
- package/dist/auth/flow.js +145 -24
- package/dist/auth/flow.js.map +1 -1
- package/dist/auth/token-manager.js +73 -0
- package/dist/auth/token-manager.js.map +1 -0
- package/dist/cli.js +56 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/builtins.js +160 -14
- package/dist/commands/builtins.js.map +1 -1
- package/dist/commands/registry.js +46 -1
- package/dist/commands/registry.js.map +1 -1
- package/dist/compaction/monitor.js +38 -0
- package/dist/compaction/monitor.js.map +1 -0
- package/dist/config/types.js.map +1 -1
- package/dist/glue/client.js +12 -2
- package/dist/glue/client.js.map +1 -1
- package/dist/hooks/manager.js +8 -2
- package/dist/hooks/manager.js.map +1 -1
- package/dist/memory/store.js +2 -3
- package/dist/memory/store.js.map +1 -1
- package/dist/plan/run-flow.js +89 -0
- package/dist/plan/run-flow.js.map +1 -0
- package/dist/projects/cli.js +92 -0
- package/dist/projects/cli.js.map +1 -0
- package/dist/projects/client.js +120 -0
- package/dist/projects/client.js.map +1 -0
- package/dist/projects/types.js +2 -0
- package/dist/projects/types.js.map +1 -0
- package/dist/skills/platform-loader.js +133 -38
- package/dist/skills/platform-loader.js.map +1 -1
- package/dist/tools/__test__/mock-tool-context.js +31 -0
- package/dist/tools/__test__/mock-tool-context.js.map +1 -0
- package/dist/tools/file-state-cache.js.map +1 -1
- package/dist/tools/read-file.js +7 -2
- package/dist/tools/read-file.js.map +1 -1
- package/dist/ui/App.js +109 -110
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/CompactionBanner.js +23 -0
- package/dist/ui/CompactionBanner.js.map +1 -0
- package/dist/ui/FirstRunSetup.js +66 -14
- package/dist/ui/FirstRunSetup.js.map +1 -1
- package/dist/ui/Input.js +370 -20
- package/dist/ui/Input.js.map +1 -1
- package/dist/ui/Markdown.js +286 -0
- package/dist/ui/Markdown.js.map +1 -0
- package/dist/ui/Message.js +110 -48
- package/dist/ui/Message.js.map +1 -1
- package/dist/ui/MessageList.js +100 -3
- package/dist/ui/MessageList.js.map +1 -1
- package/dist/ui/Permission.js +43 -20
- package/dist/ui/Permission.js.map +1 -1
- package/dist/ui/PixelC.js +25 -0
- package/dist/ui/PixelC.js.map +1 -0
- package/dist/ui/Status.js +267 -7
- package/dist/ui/Status.js.map +1 -1
- package/dist/ui/Throbber.js +11 -7
- package/dist/ui/Throbber.js.map +1 -1
- package/dist/ui/Welcome.js +59 -0
- package/dist/ui/Welcome.js.map +1 -0
- package/dist/ui/attachments.js +68 -0
- package/dist/ui/attachments.js.map +1 -0
- package/dist/ui/debug-input.js +44 -0
- package/dist/ui/debug-input.js.map +1 -0
- package/dist/ui/diff-summary.js +171 -0
- package/dist/ui/diff-summary.js.map +1 -0
- package/dist/ui/highlight.js +324 -0
- package/dist/ui/highlight.js.map +1 -0
- package/dist/ui/history-store.js +60 -0
- package/dist/ui/history-store.js.map +1 -0
- package/dist/ui/input-state.js +125 -1
- package/dist/ui/input-state.js.map +1 -1
- package/dist/ui/path-complete.js +102 -0
- package/dist/ui/path-complete.js.map +1 -0
- package/dist/ui/paths.js +41 -0
- package/dist/ui/paths.js.map +1 -0
- package/dist/ui/shell-escape.js +42 -0
- package/dist/ui/shell-escape.js.map +1 -0
- package/dist/ui/terminal-restore.js +83 -0
- package/dist/ui/terminal-restore.js.map +1 -0
- package/dist/ui/terminal-title.js +21 -0
- package/dist/ui/terminal-title.js.map +1 -0
- package/dist/ui/tool-call-line.js +83 -0
- package/dist/ui/tool-call-line.js.map +1 -0
- package/dist/ui/tool-labels.js +194 -0
- package/dist/ui/tool-labels.js.map +1 -0
- package/dist/ui/truncated-output.js +42 -0
- package/dist/ui/truncated-output.js.map +1 -0
- package/dist/ui/use-coalesced-agent-events.js +70 -0
- package/dist/ui/use-coalesced-agent-events.js.map +1 -0
- package/dist/ui/use-prompt-suggestion.js +52 -0
- package/dist/ui/use-prompt-suggestion.js.map +1 -0
- package/dist/ui/wrapped-lines.js +18 -0
- package/dist/ui/wrapped-lines.js.map +1 -0
- package/package.json +4 -1
package/dist/ui/MessageList.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Static, useStdout } from "ink";
|
|
3
|
-
import { useEffect, useState } from "react";
|
|
3
|
+
import { useEffect, useMemo, useState } from "react";
|
|
4
4
|
import { Message } from "./Message.js";
|
|
5
5
|
/**
|
|
6
6
|
* Static finalized history + a live streaming pane. Ink's <Static> renders
|
|
@@ -9,10 +9,93 @@ import { Message } from "./Message.js";
|
|
|
9
9
|
*
|
|
10
10
|
* Threads the live terminal width down to Message so its body pre-wraps
|
|
11
11
|
* at word boundaries — see ui/wrap.ts for why we want manual wrap.
|
|
12
|
+
*
|
|
13
|
+
* Note: the static-rendered finalized messages don't see live `tools`
|
|
14
|
+
* updates after they're committed — that's fine because by the time a
|
|
15
|
+
* message is finalized its tool calls have completed. The streaming
|
|
16
|
+
* pane (which DOES update) is where the live spinner lives.
|
|
12
17
|
*/
|
|
13
|
-
export function MessageList({ messages, streaming }) {
|
|
18
|
+
export function MessageList({ messages, streaming, tools }) {
|
|
14
19
|
const width = useTerminalWidth();
|
|
15
|
-
|
|
20
|
+
const rows = useTerminalRows();
|
|
21
|
+
// Cap how many lines the streaming pane renders. The big jank class
|
|
22
|
+
// users hit is: streaming message grows past the visible viewport,
|
|
23
|
+
// every token update writes more lines than before, and the terminal
|
|
24
|
+
// scrolls them down — yanking the user's manual scroll position to
|
|
25
|
+
// the bottom on every keystroke from the model. By trimming the
|
|
26
|
+
// streamed body to a bounded *tail* (the most recent N text lines),
|
|
27
|
+
// the rendered region is constant-height after it fills, log-update
|
|
28
|
+
// clears and rewrites the same number of rows every time, and the
|
|
29
|
+
// terminal stops fighting the scrollbar. The full message goes into
|
|
30
|
+
// <Static> once finalized so terminal scrollback still has the rest.
|
|
31
|
+
//
|
|
32
|
+
// Reserve a chunk for chrome (input bar, status, welcome banner).
|
|
33
|
+
// 12 rows is conservative — leaves enough room that the user can
|
|
34
|
+
// still see "the agent is doing something" without the tree ever
|
|
35
|
+
// trying to exceed the viewport.
|
|
36
|
+
const streamingTailRows = Math.max(8, rows - 12);
|
|
37
|
+
const visibleStreaming = useMemo(() => (streaming ? clipToTail(streaming, streamingTailRows) : undefined), [streaming, streamingTailRows]);
|
|
38
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: messages.map((message, index) => ({ message, key: indexKey(message, index) })), children: ({ message, key }) => (_jsx(Box, { marginBottom: 1, children: _jsx(Message, { message: message, width: width, tools: tools }) }, key)) }), visibleStreaming ? (_jsx(Box, { marginBottom: 1, children: _jsx(Message, { message: visibleStreaming, streaming: true, width: width, tools: tools }) })) : null] }));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Trim an in-flight assistant message down to ~`maxLines` of trailing
|
|
42
|
+
* content for live rendering. Content blocks are processed back-to-front
|
|
43
|
+
* until we've accumulated enough lines; earlier blocks are dropped or
|
|
44
|
+
* truncated. The original message object is unchanged — this returns a
|
|
45
|
+
* shallow copy with a new `content` array.
|
|
46
|
+
*
|
|
47
|
+
* Tool calls/results stay intact (each counts as ~1 row, replacing a
|
|
48
|
+
* dropped tool call would change the message's meaning to the user).
|
|
49
|
+
* Text blocks at the head of the kept region get a leading-line trim
|
|
50
|
+
* with a one-line "(earlier output trimmed)" marker so it's obvious
|
|
51
|
+
* we're showing a tail.
|
|
52
|
+
*/
|
|
53
|
+
function clipToTail(message, maxLines) {
|
|
54
|
+
if (message.role !== "assistant" || !Array.isArray(message.content))
|
|
55
|
+
return message;
|
|
56
|
+
const blocks = message.content;
|
|
57
|
+
const kept = [];
|
|
58
|
+
let remaining = maxLines;
|
|
59
|
+
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
60
|
+
const block = blocks[i];
|
|
61
|
+
if (remaining <= 0)
|
|
62
|
+
break;
|
|
63
|
+
if (block.type === "text" && typeof block.text === "string") {
|
|
64
|
+
const lines = block.text.split("\n");
|
|
65
|
+
if (lines.length <= remaining) {
|
|
66
|
+
kept.unshift(block);
|
|
67
|
+
remaining -= lines.length;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const tail = lines.slice(lines.length - remaining).join("\n");
|
|
71
|
+
kept.unshift({
|
|
72
|
+
...block,
|
|
73
|
+
text: `(earlier output trimmed — full message in scrollback once finished)\n${tail}`,
|
|
74
|
+
});
|
|
75
|
+
remaining = 0;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else if (block.type === "thinking" && typeof block.thinking === "string") {
|
|
79
|
+
const lines = block.thinking.split("\n");
|
|
80
|
+
if (lines.length <= remaining) {
|
|
81
|
+
kept.unshift(block);
|
|
82
|
+
remaining -= lines.length;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const tail = lines.slice(lines.length - remaining).join("\n");
|
|
86
|
+
kept.unshift({ ...block, thinking: tail });
|
|
87
|
+
remaining = 0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Tool calls / results: keep verbatim, count as 1 row each.
|
|
92
|
+
kept.unshift(block);
|
|
93
|
+
remaining -= 1;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (kept.length === blocks.length)
|
|
97
|
+
return message;
|
|
98
|
+
return { ...message, content: kept };
|
|
16
99
|
}
|
|
17
100
|
function useTerminalWidth(fallback = 80) {
|
|
18
101
|
const { stdout } = useStdout();
|
|
@@ -28,6 +111,20 @@ function useTerminalWidth(fallback = 80) {
|
|
|
28
111
|
}, [stdout, fallback]);
|
|
29
112
|
return width;
|
|
30
113
|
}
|
|
114
|
+
function useTerminalRows(fallback = 24) {
|
|
115
|
+
const { stdout } = useStdout();
|
|
116
|
+
const [rows, setRows] = useState(stdout?.rows ?? fallback);
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (!stdout)
|
|
119
|
+
return;
|
|
120
|
+
const onResize = () => setRows(stdout.rows ?? fallback);
|
|
121
|
+
stdout.on("resize", onResize);
|
|
122
|
+
return () => {
|
|
123
|
+
stdout.off("resize", onResize);
|
|
124
|
+
};
|
|
125
|
+
}, [stdout, fallback]);
|
|
126
|
+
return rows;
|
|
127
|
+
}
|
|
31
128
|
function indexKey(message, index) {
|
|
32
129
|
const ts = "timestamp" in message && typeof message.timestamp === "number" ? message.timestamp : 0;
|
|
33
130
|
return `${index}:${message.role}:${ts}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageList.js","sourceRoot":"","sources":["../../src/ui/MessageList.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"MessageList.js","sourceRoot":"","sources":["../../src/ui/MessageList.tsx"],"names":[],"mappings":"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"}
|
package/dist/ui/Permission.js
CHANGED
|
@@ -1,39 +1,62 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text, useInput } from "ink";
|
|
3
|
+
import { useState } from "react";
|
|
3
4
|
const RISK_COLOR = {
|
|
4
5
|
low: "yellow",
|
|
5
6
|
medium: "yellow",
|
|
6
7
|
high: "red",
|
|
7
8
|
};
|
|
8
|
-
const
|
|
9
|
-
low: "
|
|
10
|
-
medium: "
|
|
11
|
-
high: "
|
|
9
|
+
const RISK_LABEL = {
|
|
10
|
+
low: "LOW RISK",
|
|
11
|
+
medium: "REVIEW",
|
|
12
|
+
high: "HIGH RISK",
|
|
12
13
|
};
|
|
14
|
+
const CHOICES = [
|
|
15
|
+
{ label: "Allow", key: "allow-once", hint: "this one time", color: "green", shortcut: "y" },
|
|
16
|
+
{ label: "Trust tool", key: "trust-tool", hint: "for the rest of this session", color: "cyan", shortcut: "t" },
|
|
17
|
+
{ label: "Trust all", key: "trust-all", hint: "any tool, this session", color: "cyan", shortcut: "a" },
|
|
18
|
+
{ label: "Deny", key: "deny", hint: "block this call", color: "red", shortcut: "n" },
|
|
19
|
+
];
|
|
13
20
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
21
|
+
* Permission prompt — bordered box with risk badge, tool summary,
|
|
22
|
+
* collapsed detail, and four arrow-navigable choices. Single-key
|
|
23
|
+
* shortcuts still work (y/t/a/n) for muscle memory; Enter on the
|
|
24
|
+
* highlighted choice for newcomers; Esc maps to Deny.
|
|
18
25
|
*/
|
|
19
26
|
export function Permission({ request, onRespond }) {
|
|
27
|
+
const [cursor, setCursor] = useState(0);
|
|
20
28
|
useInput((input, key) => {
|
|
21
29
|
if (key.escape) {
|
|
22
30
|
onRespond("deny");
|
|
23
31
|
return;
|
|
24
32
|
}
|
|
33
|
+
if (key.return) {
|
|
34
|
+
onRespond(CHOICES[cursor].key);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (key.leftArrow || (key.shift && key.tab)) {
|
|
38
|
+
setCursor((c) => (c - 1 + CHOICES.length) % CHOICES.length);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (key.rightArrow || key.tab || key.downArrow || key.upArrow) {
|
|
42
|
+
setCursor((c) => (c + 1) % CHOICES.length);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
25
45
|
const ch = input.toLowerCase();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
onRespond("deny");
|
|
30
|
-
else if (ch === "t")
|
|
31
|
-
onRespond("trust-tool");
|
|
32
|
-
else if (ch === "a")
|
|
33
|
-
onRespond("trust-all");
|
|
46
|
+
const direct = CHOICES.find((c) => c.shortcut === ch);
|
|
47
|
+
if (direct)
|
|
48
|
+
onRespond(direct.key);
|
|
34
49
|
});
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginY: 0, children: [_jsxs(Box, { children: [
|
|
50
|
+
const riskColor = RISK_COLOR[request.risk];
|
|
51
|
+
const riskLabel = RISK_LABEL[request.risk];
|
|
52
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: riskColor, paddingX: 1, marginY: 0, children: [_jsxs(Box, { children: [_jsx(Text, { color: riskColor, bold: true, children: riskLabel }), _jsx(Text, { children: " " }), _jsx(Text, { dimColor: true, children: "\u00B7 permission needed" })] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { bold: true, children: request.tool }), _jsx(Text, { dimColor: true, children: " " }), _jsx(Text, { children: request.summary })] }), request.detail ? (_jsx(Box, { marginTop: 1, flexDirection: "column", children: _jsx(Text, { dimColor: true, children: truncate(request.detail, 600) }) })) : null, _jsx(Box, { marginTop: 1, flexDirection: "row", children: CHOICES.map((c, i) => {
|
|
53
|
+
const selected = i === cursor;
|
|
54
|
+
return (_jsxs(Box, { marginRight: 2, children: [_jsxs(Text, { color: selected ? c.color : "gray", bold: selected, children: [selected ? "▸ " : " ", c.label] }), _jsxs(Text, { dimColor: true, children: [" (", c.shortcut, ")"] })] }, c.key));
|
|
55
|
+
}) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: [CHOICES[cursor].hint, " \u00B7 \u2190\u2192 Enter \u00B7 y/t/a/n shortcuts \u00B7 Esc to deny"] }) })] }));
|
|
56
|
+
}
|
|
57
|
+
function truncate(s, n) {
|
|
58
|
+
if (s.length <= n)
|
|
59
|
+
return s;
|
|
60
|
+
return `${s.slice(0, n - 1)}…`;
|
|
38
61
|
}
|
|
39
62
|
//# sourceMappingURL=Permission.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Permission.js","sourceRoot":"","sources":["../../src/ui/Permission.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"Permission.js","sourceRoot":"","sources":["../../src/ui/Permission.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
/**
|
|
4
|
+
* Static pixel-C brand mark. Mirrors `web/public/favicon.svg`:
|
|
5
|
+
* 5-row × 4-col grid, 9 filled pixels (3 top + 3 left + 3 bottom).
|
|
6
|
+
* Each SVG pixel renders as two block chars wide so the C reads
|
|
7
|
+
* proportionally in a 1:2 cell-ratio terminal.
|
|
8
|
+
*/
|
|
9
|
+
const FILL = "██";
|
|
10
|
+
const GAP = " ";
|
|
11
|
+
// Row id doubles as the React key. Names describe the C shape so the
|
|
12
|
+
// keys are stable regardless of order (biome's array-index-as-key rule
|
|
13
|
+
// is right in general — but here the rows aren't unique by content
|
|
14
|
+
// (the three FILL rows repeat), so we lean on positional ids).
|
|
15
|
+
const ROWS = [
|
|
16
|
+
{ id: "top", text: `${GAP}${FILL}${FILL}${FILL}` },
|
|
17
|
+
{ id: "mid-1", text: FILL },
|
|
18
|
+
{ id: "mid-2", text: FILL },
|
|
19
|
+
{ id: "mid-3", text: FILL },
|
|
20
|
+
{ id: "bot", text: `${GAP}${FILL}${FILL}${FILL}` },
|
|
21
|
+
];
|
|
22
|
+
export function PixelC({ color = "cyan" }) {
|
|
23
|
+
return (_jsx(Box, { flexDirection: "column", children: ROWS.map((row) => (_jsx(Text, { bold: true, color: color, children: row.text }, row.id))) }));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=PixelC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PixelC.js","sourceRoot":"","sources":["../../src/ui/PixelC.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC;;;;;GAKG;AAEH,MAAM,IAAI,GAAG,IAAI,CAAC;AAClB,MAAM,GAAG,GAAG,IAAI,CAAC;AAMjB,qEAAqE;AACrE,uEAAuE;AACvE,mEAAmE;AACnE,+DAA+D;AAC/D,MAAM,IAAI,GAA4C;IACrD,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE;IAClD,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE;IAC3B,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE;IAC3B,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE;IAC3B,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE;CAClD,CAAC;AAEF,MAAM,UAAU,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,EAAe;IACrD,OAAO,CACN,KAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,YACzB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAClB,KAAC,IAAI,IAAc,IAAI,QAAC,KAAK,EAAE,KAAK,YAClC,GAAG,CAAC,IAAI,IADC,GAAG,CAAC,EAAE,CAEV,CACP,CAAC,GACG,CACN,CAAC;AACH,CAAC"}
|
package/dist/ui/Status.js
CHANGED
|
@@ -1,11 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { basename } from "node:path";
|
|
2
3
|
import { Box, Text } from "ink";
|
|
4
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
5
|
import { Throbber } from "./Throbber.js";
|
|
6
|
+
/** Average chars-per-token across the major model families. Used only as a
|
|
7
|
+
* fallback when the provider doesn't return usage info on message_end. */
|
|
8
|
+
const CHARS_PER_TOKEN = 4;
|
|
9
|
+
/**
|
|
10
|
+
* Playful verbs we cycle through while the agent is thinking. They all
|
|
11
|
+
* read as "the model is working." Kept ASCII-clean so they line up in
|
|
12
|
+
* any terminal font.
|
|
13
|
+
*/
|
|
14
|
+
const THINKING_VERBS = [
|
|
15
|
+
"Thinking",
|
|
16
|
+
"Pondering",
|
|
17
|
+
"Synthesizing",
|
|
18
|
+
"Cogitating",
|
|
19
|
+
"Ruminating",
|
|
20
|
+
"Deliberating",
|
|
21
|
+
"Mulling",
|
|
22
|
+
"Marinating",
|
|
23
|
+
"Brewing",
|
|
24
|
+
"Contemplating",
|
|
25
|
+
"Reasoning",
|
|
26
|
+
"Considering",
|
|
27
|
+
];
|
|
4
28
|
const STATUS_LABEL = {
|
|
5
29
|
idle: "ready",
|
|
6
|
-
thinking: "
|
|
7
|
-
streaming: "
|
|
8
|
-
tool: "
|
|
30
|
+
thinking: "Thinking",
|
|
31
|
+
streaming: "Writing",
|
|
32
|
+
tool: "Working",
|
|
9
33
|
aborted: "aborted",
|
|
10
34
|
error: "error",
|
|
11
35
|
};
|
|
@@ -17,12 +41,248 @@ const STATUS_COLOR = {
|
|
|
17
41
|
aborted: "red",
|
|
18
42
|
error: "red",
|
|
19
43
|
};
|
|
20
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Bottom status line — spinner + state on the left, model + cwd +
|
|
46
|
+
* context % + cost on the right. Stays on one row in normal terminal
|
|
47
|
+
* widths; the cwd basename is the only dynamic-length piece so we
|
|
48
|
+
* always show what matters.
|
|
49
|
+
*/
|
|
50
|
+
export function Status({ state, cwd, contextWindow = 200_000 }) {
|
|
21
51
|
const busy = state.status === "thinking" || state.status === "streaming" || state.status === "tool";
|
|
22
|
-
const
|
|
52
|
+
const verb = useThinkingVerb(state.status === "thinking");
|
|
53
|
+
let label = state.status === "thinking" ? verb : STATUS_LABEL[state.status];
|
|
54
|
+
if (state.status === "tool") {
|
|
55
|
+
const running = findRunningTool(state);
|
|
56
|
+
if (running)
|
|
57
|
+
label = `${STATUS_LABEL.tool} · ${running}`;
|
|
58
|
+
}
|
|
23
59
|
const color = STATUS_COLOR[state.status];
|
|
60
|
+
const tokRate = useTokenRate(state);
|
|
61
|
+
const elapsedSec = useBusyElapsed(busy);
|
|
24
62
|
const u = state.usage;
|
|
25
|
-
|
|
63
|
+
const usedTokens = estimateContextTokens(state);
|
|
64
|
+
const ctxPct = contextWindow > 0 ? Math.min(100, Math.round((usedTokens / contextWindow) * 100)) : 0;
|
|
65
|
+
const cwdLabel = cwd ? basename(cwd) || "/" : "";
|
|
66
|
+
const modelLabel = state.model.name || state.model.id;
|
|
67
|
+
return (_jsxs(Box, { flexDirection: "column", children: [state.error ? _jsx(ErrorCard, { message: state.error }) : null, ctxPct >= 85 ? _jsx(ContextWarning, { pct: ctxPct }) : null, _jsxs(Box, { paddingX: 1, justifyContent: "space-between", children: [_jsxs(Box, { children: [busy ? (_jsxs(_Fragment, { children: [_jsx(Throbber, { color: color }), _jsx(Text, { children: " " })] })) : null, _jsx(Text, { color: color, children: label }), elapsedSec !== undefined ? _jsxs(Text, { dimColor: true, children: [" (", elapsedSec, "s)"] }) : null] }), _jsxs(Box, { children: [_jsxs(Text, { dimColor: true, children: [modelLabel, cwdLabel ? ` · ${cwdLabel}` : "", " \u00B7", " "] }), _jsxs(Text, { color: ctxColor(ctxPct), children: [ctxBar(ctxPct), " ", ctxPct, "%"] }), _jsxs(Text, { dimColor: true, children: [tokRate !== undefined ? ` · ${tokRate} tok/s` : "", " \u00B7 $", formatCost(u.cost.total)] })] })] })] }));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Track how long the agent has been busy. Returns undefined unless the
|
|
71
|
+
* elapsed time has crossed 3 seconds — short turns shouldn't carry an
|
|
72
|
+
* "(0s)" suffix on the status bar. Resets cleanly when the agent
|
|
73
|
+
* goes idle so consecutive turns each start their own timer.
|
|
74
|
+
*/
|
|
75
|
+
function useBusyElapsed(busy) {
|
|
76
|
+
const startRef = useRef(undefined);
|
|
77
|
+
const [tick, setTick] = useState(0);
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (!busy) {
|
|
80
|
+
startRef.current = undefined;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
startRef.current = Date.now();
|
|
84
|
+
const id = setInterval(() => setTick((t) => t + 1), 1000);
|
|
85
|
+
return () => clearInterval(id);
|
|
86
|
+
}, [busy]);
|
|
87
|
+
if (!busy || !startRef.current)
|
|
88
|
+
return undefined;
|
|
89
|
+
const elapsed = Math.floor((Date.now() - startRef.current) / 1000);
|
|
90
|
+
void tick;
|
|
91
|
+
return elapsed >= 3 ? elapsed : undefined;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Pluck the most-recently-started in-flight tool so the status bar can
|
|
95
|
+
* say "Working · shell" instead of just "Working". Falls back to no
|
|
96
|
+
* tool name when the map is empty — keeps the bar terse.
|
|
97
|
+
*/
|
|
98
|
+
function findRunningTool(state) {
|
|
99
|
+
let best;
|
|
100
|
+
for (const tool of state.tools.values()) {
|
|
101
|
+
if (tool.status !== "running")
|
|
102
|
+
continue;
|
|
103
|
+
if (!best || tool.startedAt > best.startedAt) {
|
|
104
|
+
best = { name: tool.name, startedAt: tool.startedAt };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return best?.name;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Estimate the live token-output rate during streaming using a 4-second
|
|
111
|
+
* sliding window over recent character growth. This avoids dragging the
|
|
112
|
+
* rate down with the pre-text wait period — a thinking-heavy model that
|
|
113
|
+
* spent 60s reasoning before emitting its first token should show "120
|
|
114
|
+
* tok/s" once it starts streaming, not "5 tok/s averaged with the wait."
|
|
115
|
+
*
|
|
116
|
+
* Returns undefined when not streaming, or when the window doesn't yet
|
|
117
|
+
* have enough samples / delta for the rate to be meaningful (so the bar
|
|
118
|
+
* doesn't flicker noisy values in the first half-second).
|
|
119
|
+
*/
|
|
120
|
+
function useTokenRate(state) {
|
|
121
|
+
const samplesRef = useRef([]);
|
|
122
|
+
const charsRef = useRef(0);
|
|
123
|
+
const [, setTick] = useState(0);
|
|
124
|
+
const streaming = state.status === "streaming";
|
|
125
|
+
// Keep the latest char count in a ref so the interval callback always
|
|
126
|
+
// reads the live value rather than the closure-captured one.
|
|
127
|
+
charsRef.current = streaming ? streamingChars(state) : 0;
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (!streaming) {
|
|
130
|
+
samplesRef.current = [];
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const sample = () => {
|
|
134
|
+
const now = Date.now();
|
|
135
|
+
samplesRef.current.push({ t: now, c: charsRef.current });
|
|
136
|
+
const cutoff = now - 4000;
|
|
137
|
+
while (samplesRef.current.length > 0 && samplesRef.current[0].t < cutoff) {
|
|
138
|
+
samplesRef.current.shift();
|
|
139
|
+
}
|
|
140
|
+
setTick((n) => n + 1);
|
|
141
|
+
};
|
|
142
|
+
sample(); // seed immediately
|
|
143
|
+
const id = setInterval(sample, 500);
|
|
144
|
+
return () => clearInterval(id);
|
|
145
|
+
}, [streaming]);
|
|
146
|
+
if (!streaming || samplesRef.current.length < 2)
|
|
147
|
+
return undefined;
|
|
148
|
+
const oldest = samplesRef.current[0];
|
|
149
|
+
const newest = samplesRef.current[samplesRef.current.length - 1];
|
|
150
|
+
const dt = (newest.t - oldest.t) / 1000;
|
|
151
|
+
if (dt < 0.5)
|
|
152
|
+
return undefined;
|
|
153
|
+
const dc = newest.c - oldest.c;
|
|
154
|
+
if (dc < 10)
|
|
155
|
+
return undefined;
|
|
156
|
+
return Math.round(dc / CHARS_PER_TOKEN / dt);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Tokens currently in the model's context, for the status-bar fill meter.
|
|
160
|
+
* Prefers the last-turn's reported `input + cacheRead` from pi-ai, since
|
|
161
|
+
* that's literally what the model saw. Falls back to char-based estimation
|
|
162
|
+
* when the provider strips usage (e.g. some OAuth-fronted proxies) so the
|
|
163
|
+
* bar still grows as the conversation grows. Streaming content is added
|
|
164
|
+
* on top of the prior-turn baseline so the bar visibly fills during a turn
|
|
165
|
+
* instead of jumping at message_end.
|
|
166
|
+
*/
|
|
167
|
+
export function estimateContextTokens(state) {
|
|
168
|
+
if (state.turnUsage && state.turnUsage.input + state.turnUsage.cacheRead > 0) {
|
|
169
|
+
const reported = state.turnUsage.input + state.turnUsage.cacheRead;
|
|
170
|
+
const streamingExtra = Math.round(streamingChars(state) / CHARS_PER_TOKEN);
|
|
171
|
+
return reported + streamingExtra;
|
|
172
|
+
}
|
|
173
|
+
let chars = 0;
|
|
174
|
+
for (const msg of state.messages)
|
|
175
|
+
chars += messageChars(msg);
|
|
176
|
+
if (state.streaming)
|
|
177
|
+
chars += messageChars(state.streaming);
|
|
178
|
+
return Math.round(chars / CHARS_PER_TOKEN);
|
|
179
|
+
}
|
|
180
|
+
function messageChars(message) {
|
|
181
|
+
if (typeof message.content === "string")
|
|
182
|
+
return message.content.length;
|
|
183
|
+
if (!Array.isArray(message.content))
|
|
184
|
+
return 0;
|
|
185
|
+
let total = 0;
|
|
186
|
+
for (const block of message.content) {
|
|
187
|
+
if (block.type === "text")
|
|
188
|
+
total += block.text.length;
|
|
189
|
+
else if (block.type === "thinking")
|
|
190
|
+
total += block.thinking.length;
|
|
191
|
+
else if (block.type === "toolCall") {
|
|
192
|
+
total += block.name.length;
|
|
193
|
+
total += JSON.stringify(block.arguments ?? {}).length;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return total;
|
|
197
|
+
}
|
|
198
|
+
/** Sum the visible text length of all text/thinking blocks in the live streaming message. */
|
|
199
|
+
function streamingChars(state) {
|
|
200
|
+
const m = state.streaming;
|
|
201
|
+
if (!m || m.role !== "assistant")
|
|
202
|
+
return 0;
|
|
203
|
+
let total = 0;
|
|
204
|
+
for (const block of m.content) {
|
|
205
|
+
if (block.type === "text")
|
|
206
|
+
total += block.text.length;
|
|
207
|
+
else if (block.type === "thinking")
|
|
208
|
+
total += block.thinking.length;
|
|
209
|
+
}
|
|
210
|
+
return total;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* While the agent is thinking, swap the verb every 3 seconds. We pick
|
|
214
|
+
* the next verb at random (excluding the current one) instead of
|
|
215
|
+
* cycling in order so the same word doesn't reappear at predictable
|
|
216
|
+
* beats. When the status leaves thinking we drop back to the first
|
|
217
|
+
* verb so re-entry starts fresh.
|
|
218
|
+
*/
|
|
219
|
+
function useThinkingVerb(active) {
|
|
220
|
+
const [verb, setVerb] = useState(THINKING_VERBS[0]);
|
|
221
|
+
useEffect(() => {
|
|
222
|
+
if (!active) {
|
|
223
|
+
setVerb(THINKING_VERBS[0]);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const id = setInterval(() => {
|
|
227
|
+
setVerb((current) => {
|
|
228
|
+
let next = current;
|
|
229
|
+
while (next === current) {
|
|
230
|
+
next = THINKING_VERBS[Math.floor(Math.random() * THINKING_VERBS.length)];
|
|
231
|
+
}
|
|
232
|
+
return next;
|
|
233
|
+
});
|
|
234
|
+
}, 3000);
|
|
235
|
+
return () => clearInterval(id);
|
|
236
|
+
}, [active]);
|
|
237
|
+
return verb;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Banner shown when the context window is past 85%. Suggests /compact
|
|
241
|
+
* so the user can take action before auto-compaction kicks in, and
|
|
242
|
+
* shifts to red past 95% where the next turn might actually trip the
|
|
243
|
+
* model's hard limit.
|
|
244
|
+
*/
|
|
245
|
+
function ContextWarning({ pct }) {
|
|
246
|
+
const urgent = pct >= 95;
|
|
247
|
+
return (_jsxs(Box, { paddingX: 1, children: [_jsxs(Text, { color: urgent ? "red" : "yellow", bold: true, children: [urgent ? "⚠" : "•", " ", pct, "% of context used"] }), _jsx(Text, { dimColor: true, children: " \u2014 run /compact to free space" })] }));
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Boxed error card. Headers the error with ERROR + a one-line summary,
|
|
251
|
+
* then shows the rest of the message body (if multi-line) in dim text.
|
|
252
|
+
* Fatal errors need visual weight so the user doesn't miss them in a
|
|
253
|
+
* busy transcript.
|
|
254
|
+
*/
|
|
255
|
+
function ErrorCard({ message }) {
|
|
256
|
+
const lines = message.split("\n");
|
|
257
|
+
const head = lines[0] ?? message;
|
|
258
|
+
const body = lines.slice(1).filter((l) => l.trim().length > 0);
|
|
259
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 1, marginY: 0, children: [_jsxs(Box, { children: [_jsx(Text, { color: "red", bold: true, children: "ERROR" }), _jsx(Text, { children: " " }), _jsx(Text, { children: head })] }), body.length > 0 ? (_jsx(Box, { flexDirection: "column", marginTop: 1, children: body.map((line, i) => (_jsx(Text, { dimColor: true, children: line }, `err-${i}-${line.slice(0, 12)}`))) })) : null] }));
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Render a tiny 6-cell bar for the context-window meter. Eighth-block
|
|
263
|
+
* glyphs give us 48 effective steps in 6 chars — enough resolution
|
|
264
|
+
* that 12% / 25% / 50% all look visibly different. Empty cells stay
|
|
265
|
+
* as a dim track so the bar always reads as a meter, not a slider.
|
|
266
|
+
*/
|
|
267
|
+
function ctxBar(pct) {
|
|
268
|
+
const cells = 6;
|
|
269
|
+
const totalEighths = Math.round((pct / 100) * cells * 8);
|
|
270
|
+
const full = Math.floor(totalEighths / 8);
|
|
271
|
+
const remainder = totalEighths - full * 8;
|
|
272
|
+
const partials = ["", "▏", "▎", "▍", "▌", "▋", "▊", "▉"];
|
|
273
|
+
let out = "█".repeat(Math.min(full, cells));
|
|
274
|
+
if (full < cells && remainder > 0)
|
|
275
|
+
out += partials[remainder] ?? "";
|
|
276
|
+
while (out.length < cells)
|
|
277
|
+
out += "░";
|
|
278
|
+
return out;
|
|
279
|
+
}
|
|
280
|
+
function ctxColor(pct) {
|
|
281
|
+
if (pct >= 90)
|
|
282
|
+
return "red";
|
|
283
|
+
if (pct >= 75)
|
|
284
|
+
return "yellow";
|
|
285
|
+
return "gray";
|
|
26
286
|
}
|
|
27
287
|
function formatCost(value) {
|
|
28
288
|
if (value === 0)
|
package/dist/ui/Status.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Status.js","sourceRoot":"","sources":["../../src/ui/Status.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAMzC,MAAM,YAAY,GAAwC;IACzD,IAAI,EAAE,OAAO;IACb,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,YAAY;IACvB,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;CACd,CAAC;AAEF,MAAM,YAAY,GAAwC;IACzD,IAAI,EAAE,OAAO;IACb,QAAQ,EAAE,QAAQ;IAClB,SAAS,EAAE,MAAM;IACjB,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,KAAK;CACZ,CAAC;AAEF,MAAM,UAAU,MAAM,CAAC,EAAE,KAAK,EAAe;IAC5C,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC;IACpG,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;IAEtB,OAAO,CACN,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CACd,KAAC,GAAG,IAAC,QAAQ,EAAE,CAAC,YACf,MAAC,IAAI,IAAC,KAAK,EAAC,KAAK,mBAAI,KAAK,CAAC,KAAK,IAAQ,GACnC,CACN,CAAC,CAAC,CAAC,IAAI,EACR,MAAC,GAAG,IAAC,QAAQ,EAAE,CAAC,EAAE,cAAc,EAAC,eAAe,aAC/C,MAAC,GAAG,eACF,IAAI,CAAC,CAAC,CAAC,CACP,8BACC,KAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,GAAI,EAC1B,KAAC,IAAI,oBAAS,IACZ,CACH,CAAC,CAAC,CAAC,IAAI,EACR,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,YAAG,KAAK,GAAQ,IAC7B,EACN,KAAC,GAAG,cACH,MAAC,IAAI,IAAC,QAAQ,mBACZ,KAAK,CAAC,KAAK,CAAC,QAAQ,OAAG,KAAK,CAAC,KAAK,CAAC,EAAE,oBAAM,CAAC,CAAC,KAAK,aAAI,CAAC,CAAC,MAAM,QAAI,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IACrF,GACF,IACD,IACD,CACN,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAChC,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IACjC,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1C,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACzB,CAAC"}
|
|
1
|
+
{"version":3,"file":"Status.js","sourceRoot":"","sources":["../../src/ui/Status.tsx"],"names":[],"mappings":"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"}
|
package/dist/ui/Throbber.js
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Text } from "ink";
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
|
-
const FRAMES = ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"];
|
|
5
4
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* 8-frame pulse cycle — the codebase pixel-C "scanning" through brightness
|
|
6
|
+
* levels. The compact (1-char) variant cycles a single block-glyph: ░▒▓█▓▒░.
|
|
7
|
+
* The full pixel-C variant scans a highlight row across the C shape.
|
|
8
|
+
*
|
|
9
|
+
* Self-throttling: owns its own interval so the parent's reducer state
|
|
10
|
+
* doesn't tick on every frame. A hot message_update stream + a 100ms
|
|
11
|
+
* spinner would otherwise compound into full re-renders 10× a second.
|
|
9
12
|
*/
|
|
10
|
-
|
|
13
|
+
const COMPACT_FRAMES = ["░", "▒", "▓", "█", "█", "▓", "▒", "░"];
|
|
14
|
+
export function Throbber({ color = "cyan", intervalMs = 90 }) {
|
|
11
15
|
const [frame, setFrame] = useState(0);
|
|
12
16
|
useEffect(() => {
|
|
13
17
|
const id = setInterval(() => {
|
|
14
|
-
setFrame((f) => (f + 1) %
|
|
18
|
+
setFrame((f) => (f + 1) % COMPACT_FRAMES.length);
|
|
15
19
|
}, intervalMs);
|
|
16
20
|
return () => clearInterval(id);
|
|
17
21
|
}, [intervalMs]);
|
|
18
|
-
return _jsx(Text, { color: color, children:
|
|
22
|
+
return _jsx(Text, { color: color, children: COMPACT_FRAMES[frame] });
|
|
19
23
|
}
|
|
20
24
|
//# sourceMappingURL=Throbber.js.map
|
package/dist/ui/Throbber.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Throbber.js","sourceRoot":"","sources":["../../src/ui/Throbber.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C,MAAM,
|
|
1
|
+
{"version":3,"file":"Throbber.js","sourceRoot":"","sources":["../../src/ui/Throbber.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C;;;;;;;;GAQG;AAEH,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAOhE,MAAM,UAAU,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,EAAE,UAAU,GAAG,EAAE,EAAiB;IAC1E,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEtC,SAAS,CAAC,GAAG,EAAE;QACd,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE;YAC3B,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QAClD,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,YAAG,cAAc,CAAC,KAAK,CAAC,GAAQ,CAAC;AAC3D,CAAC"}
|