casabot 1.1.6 → 1.1.7

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/tui/app.js CHANGED
@@ -20,22 +20,21 @@ function truncateOutput(content, maxLines = 8) {
20
20
  return (lines.slice(0, maxLines).join("\n") +
21
21
  `\n … ${lines.length - maxLines} more lines`);
22
22
  }
23
- function HRule() {
24
- const { stdout } = useStdout();
25
- const width = stdout.columns ?? 80;
26
- return (_jsx(Box, { paddingX: 1, children: _jsx(Text, { dimColor: true, children: "─".repeat(Math.max(width - 4, 10)) }) }));
23
+ function HRule({ columns }) {
24
+ return (_jsx(Box, { paddingX: 1, width: columns, children: _jsx(Text, { dimColor: true, children: "─".repeat(Math.max(columns - 4, 1)) }) }));
27
25
  }
28
- function HeaderBlock() {
29
- return (_jsxs(Box, { flexDirection: "column", paddingTop: 1, children: [_jsx(Box, { paddingX: 2, children: _jsx(Gradient, { name: "vice", children: _jsx(Text, { bold: true, children: "✦ CasAbot" }) }) }), _jsx(Box, { paddingX: 2, children: _jsx(Text, { dimColor: true, children: "Cassiopeia A — Freely creates everything, like a supernova explosion." }) }), _jsx(HRule, {})] }));
26
+ function HeaderBlock({ columns }) {
27
+ return (_jsxs(Box, { flexDirection: "column", paddingTop: 1, width: columns, children: [_jsx(Box, { paddingX: 2, children: _jsx(Gradient, { name: "vice", children: _jsx(Text, { bold: true, children: "✦ CasAbot" }) }) }), _jsx(Box, { paddingX: 2, children: _jsx(Text, { wrap: "wrap", dimColor: true, children: "Cassiopeia A — Freely creates everything, like a supernova explosion." }) }), _jsx(HRule, { columns: columns })] }));
30
28
  }
31
- function UserMessageView({ content }) {
32
- return (_jsxs(Box, { flexDirection: "column", paddingX: 2, marginTop: 1, children: [_jsx(Text, { color: "green", bold: true, children: "▶ You" }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { wrap: "wrap", children: content }) })] }));
29
+ function UserMessageView({ content, columns }) {
30
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 2, marginTop: 1, width: columns, children: [_jsx(Text, { color: "green", bold: true, children: "▶ You" }), _jsx(Box, { marginLeft: 2, width: Math.max(columns - 6, 10), children: _jsx(Text, { wrap: "wrap", children: content }) })] }));
33
31
  }
34
- function AssistantMessageView({ content, }) {
35
- return (_jsxs(Box, { flexDirection: "column", paddingX: 2, marginTop: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: "✦ CasAbot" }), _jsx(Box, { marginLeft: 2, children: _jsx(Text, { wrap: "wrap", children: renderMarkdown(content) }) })] }));
32
+ function AssistantMessageView({ content, columns, }) {
33
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 2, marginTop: 1, width: columns, children: [_jsx(Text, { color: "cyan", bold: true, children: "✦ CasAbot" }), _jsx(Box, { marginLeft: 2, width: Math.max(columns - 6, 10), children: _jsx(Text, { wrap: "wrap", children: renderMarkdown(content) }) })] }));
36
34
  }
37
- function ToolCallsView({ message, }) {
38
- return (_jsxs(Box, { flexDirection: "column", paddingX: 2, marginTop: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: "✦ CasAbot" }), message.content ? (_jsx(Box, { marginLeft: 2, children: _jsx(Text, { wrap: "wrap", children: renderMarkdown(message.content) }) })) : null, _jsxs(Box, { flexDirection: "column", marginLeft: 2, marginTop: 1, borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [_jsx(Text, { color: "yellow", bold: true, children: "⚡ Tool Calls" }), message.toolCalls?.map((tc, i) => {
35
+ function ToolCallsView({ message, columns, }) {
36
+ const boxWidth = Math.max(columns - 6, 10);
37
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 2, marginTop: 1, width: columns, children: [_jsx(Text, { color: "cyan", bold: true, children: "✦ CasAbot" }), message.content ? (_jsx(Box, { marginLeft: 2, width: boxWidth, children: _jsx(Text, { wrap: "wrap", children: renderMarkdown(message.content) }) })) : null, _jsxs(Box, { flexDirection: "column", marginLeft: 2, marginTop: 1, borderStyle: "round", borderColor: "yellow", paddingX: 1, width: boxWidth, overflow: "hidden", children: [_jsx(Text, { color: "yellow", bold: true, children: "⚡ Tool Calls" }), message.toolCalls?.map((tc, i) => {
39
38
  let display = tc.arguments;
40
39
  try {
41
40
  const args = JSON.parse(tc.arguments);
@@ -45,38 +44,45 @@ function ToolCallsView({ message, }) {
45
44
  catch {
46
45
  /* keep raw */
47
46
  }
47
+ const maxArgLen = Math.max(boxWidth - tc.name.length - 8, 20);
48
+ if (display.length > maxArgLen) {
49
+ display = display.slice(0, maxArgLen - 1) + "…";
50
+ }
48
51
  return (_jsxs(Box, { children: [_jsx(Text, { dimColor: true, children: tc.name }), _jsx(Text, { children: " → " }), _jsx(Text, { color: "white", wrap: "wrap", children: display })] }, i));
49
52
  })] })] }));
50
53
  }
51
- function ToolResultView({ content, }) {
52
- return (_jsxs(Box, { flexDirection: "column", marginLeft: 4, marginRight: 2, borderStyle: "round", borderColor: "gray", paddingX: 1, children: [_jsx(Text, { dimColor: true, bold: true, children: "📋 Result" }), _jsx(Text, { dimColor: true, wrap: "wrap", children: truncateOutput(content) })] }));
54
+ function ToolResultView({ content, columns, }) {
55
+ const boxWidth = Math.max(columns - 6, 10);
56
+ return (_jsxs(Box, { flexDirection: "column", marginLeft: 4, marginRight: 2, borderStyle: "round", borderColor: "gray", paddingX: 1, width: boxWidth, overflow: "hidden", children: [_jsx(Text, { dimColor: true, bold: true, children: "📋 Result" }), _jsx(Text, { dimColor: true, wrap: "wrap", children: truncateOutput(content) })] }));
53
57
  }
54
- function MessageView({ message, }) {
58
+ function MessageView({ message, columns, }) {
55
59
  if (message.role === "user") {
56
- return _jsx(UserMessageView, { content: message.content });
60
+ return _jsx(UserMessageView, { content: message.content, columns: columns });
57
61
  }
58
62
  if (message.role === "tool") {
59
- return _jsx(ToolResultView, { content: message.content });
63
+ return _jsx(ToolResultView, { content: message.content, columns: columns });
60
64
  }
61
65
  if (message.role === "assistant" && message.toolCalls?.length) {
62
- return _jsx(ToolCallsView, { message: message });
66
+ return _jsx(ToolCallsView, { message: message, columns: columns });
63
67
  }
64
68
  if (message.role === "assistant") {
65
- return _jsx(AssistantMessageView, { content: message.content });
69
+ return _jsx(AssistantMessageView, { content: message.content, columns: columns });
66
70
  }
67
- return _jsx(Text, { children: message.content });
71
+ return _jsx(Text, { wrap: "wrap", children: message.content });
68
72
  }
69
- function WelcomeHint() {
70
- return (_jsxs(Box, { flexDirection: "column", paddingX: 2, marginTop: 1, marginBottom: 1, children: [_jsx(Text, { dimColor: true, children: "Type a message below to get started." }), _jsx(Text, { dimColor: true, children: "CasAbot will orchestrate agents to help you." })] }));
73
+ function WelcomeHint({ columns }) {
74
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 2, marginTop: 1, marginBottom: 1, width: columns, children: [_jsx(Text, { dimColor: true, children: "Type a message below to get started." }), _jsx(Text, { dimColor: true, children: "CasAbot will orchestrate agents to help you." })] }));
71
75
  }
72
- function ProcessingIndicator() {
73
- return (_jsxs(Box, { paddingX: 2, marginTop: 1, gap: 1, children: [_jsx(Text, { color: "yellow", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { color: "yellow", children: "Thinking…" })] }));
76
+ function ProcessingIndicator({ columns }) {
77
+ return (_jsxs(Box, { paddingX: 2, marginTop: 1, gap: 1, width: columns, children: [_jsx(Text, { color: "yellow", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { color: "yellow", children: "Thinking…" })] }));
74
78
  }
75
79
  function App({ provider, conversation, skills, }) {
76
80
  const [messages, setMessages] = useState([]);
77
81
  const [input, setInput] = useState("");
78
82
  const [isProcessing, setIsProcessing] = useState(false);
79
83
  const { exit } = useApp();
84
+ const { stdout } = useStdout();
85
+ const columns = stdout.columns ?? 80;
80
86
  const handleSubmit = useCallback(async (text) => {
81
87
  const trimmed = text.trim();
82
88
  if (!trimmed || isProcessing)
@@ -114,14 +120,14 @@ function App({ provider, conversation, skills, }) {
114
120
  message: msg,
115
121
  })),
116
122
  ], [messages]);
117
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Static, { items: items, children: (item) => {
123
+ return (_jsxs(Box, { flexDirection: "column", width: columns, children: [_jsx(Static, { items: items, children: (item) => {
118
124
  if (item.type === "header") {
119
- return (_jsx(Box, { flexDirection: "column", children: _jsx(HeaderBlock, {}) }, item.key));
125
+ return (_jsx(Box, { flexDirection: "column", width: columns, children: _jsx(HeaderBlock, { columns: columns }) }, item.key));
120
126
  }
121
- return (_jsx(Box, { flexDirection: "column", children: _jsx(MessageView, { message: item.message }) }, item.key));
122
- } }), messages.length === 0 && !isProcessing && _jsx(WelcomeHint, {}), isProcessing && _jsx(ProcessingIndicator, {}), _jsx(HRule, {}), _jsx(Box, { paddingX: 1, children: _jsxs(Box, { borderStyle: "round", borderColor: isProcessing ? "gray" : "cyan", paddingX: 1, width: "100%", children: [_jsx(Text, { color: "cyan", bold: true, children: "❯ " }), _jsx(TextInput, { value: input, onChange: setInput, onSubmit: (val) => {
127
+ return (_jsx(Box, { flexDirection: "column", width: columns, children: _jsx(MessageView, { message: item.message, columns: columns }) }, item.key));
128
+ } }), messages.length === 0 && !isProcessing && _jsx(WelcomeHint, { columns: columns }), isProcessing && _jsx(ProcessingIndicator, { columns: columns }), _jsx(HRule, { columns: columns }), _jsx(Box, { paddingX: 1, width: columns, children: _jsxs(Box, { borderStyle: "round", borderColor: isProcessing ? "gray" : "cyan", paddingX: 1, width: Math.max(columns - 2, 10), overflow: "hidden", children: [_jsx(Text, { color: "cyan", bold: true, children: "❯ " }), _jsx(TextInput, { value: input, onChange: setInput, onSubmit: (val) => {
123
129
  handleSubmit(val).catch(() => { });
124
- }, placeholder: "Type your message\u2026", focus: !isProcessing, showCursor: true })] }) }), _jsxs(Box, { paddingX: 2, justifyContent: "space-between", children: [_jsx(Text, { dimColor: true, children: "Ctrl+C exit" }), _jsxs(Text, { dimColor: true, children: [userCount, " ", userCount === 1 ? "message" : "messages"] })] })] }));
130
+ }, placeholder: "Type your message\u2026", focus: !isProcessing, showCursor: true })] }) }), _jsxs(Box, { paddingX: 2, width: columns, justifyContent: "space-between", children: [_jsx(Text, { dimColor: true, children: "Ctrl+C exit" }), _jsxs(Text, { dimColor: true, children: [userCount, " ", userCount === 1 ? "message" : "messages"] })] })] }));
125
131
  }
126
132
  export function startTUI(provider, conversation, skills) {
127
133
  render(_jsx(App, { provider: provider, conversation: conversation, skills: skills }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "casabot",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "description": "CasAbot — Skill-driven multi-agent orchestrator system",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/tui/app.tsx CHANGED
@@ -26,41 +26,39 @@ function truncateOutput(content: string, maxLines = 8): string {
26
26
  );
27
27
  }
28
28
 
29
- function HRule(): React.ReactElement {
30
- const { stdout } = useStdout();
31
- const width = stdout.columns ?? 80;
29
+ function HRule({ columns }: { columns: number }): React.ReactElement {
32
30
  return (
33
- <Box paddingX={1}>
34
- <Text dimColor>{"─".repeat(Math.max(width - 4, 10))}</Text>
31
+ <Box paddingX={1} width={columns}>
32
+ <Text dimColor>{"─".repeat(Math.max(columns - 4, 1))}</Text>
35
33
  </Box>
36
34
  );
37
35
  }
38
36
 
39
- function HeaderBlock(): React.ReactElement {
37
+ function HeaderBlock({ columns }: { columns: number }): React.ReactElement {
40
38
  return (
41
- <Box flexDirection="column" paddingTop={1}>
39
+ <Box flexDirection="column" paddingTop={1} width={columns}>
42
40
  <Box paddingX={2}>
43
41
  <Gradient name="vice">
44
42
  <Text bold>{"✦ CasAbot"}</Text>
45
43
  </Gradient>
46
44
  </Box>
47
45
  <Box paddingX={2}>
48
- <Text dimColor>
46
+ <Text wrap="wrap" dimColor>
49
47
  {"Cassiopeia A — Freely creates everything, like a supernova explosion."}
50
48
  </Text>
51
49
  </Box>
52
- <HRule />
50
+ <HRule columns={columns} />
53
51
  </Box>
54
52
  );
55
53
  }
56
54
 
57
- function UserMessageView({ content }: { content: string }): React.ReactElement {
55
+ function UserMessageView({ content, columns }: { content: string; columns: number }): React.ReactElement {
58
56
  return (
59
- <Box flexDirection="column" paddingX={2} marginTop={1}>
57
+ <Box flexDirection="column" paddingX={2} marginTop={1} width={columns}>
60
58
  <Text color="green" bold>
61
59
  {"▶ You"}
62
60
  </Text>
63
- <Box marginLeft={2}>
61
+ <Box marginLeft={2} width={Math.max(columns - 6, 10)}>
64
62
  <Text wrap="wrap">{content}</Text>
65
63
  </Box>
66
64
  </Box>
@@ -69,15 +67,17 @@ function UserMessageView({ content }: { content: string }): React.ReactElement {
69
67
 
70
68
  function AssistantMessageView({
71
69
  content,
70
+ columns,
72
71
  }: {
73
72
  content: string;
73
+ columns: number;
74
74
  }): React.ReactElement {
75
75
  return (
76
- <Box flexDirection="column" paddingX={2} marginTop={1}>
76
+ <Box flexDirection="column" paddingX={2} marginTop={1} width={columns}>
77
77
  <Text color="cyan" bold>
78
78
  {"✦ CasAbot"}
79
79
  </Text>
80
- <Box marginLeft={2}>
80
+ <Box marginLeft={2} width={Math.max(columns - 6, 10)}>
81
81
  <Text wrap="wrap">{renderMarkdown(content)}</Text>
82
82
  </Box>
83
83
  </Box>
@@ -86,16 +86,19 @@ function AssistantMessageView({
86
86
 
87
87
  function ToolCallsView({
88
88
  message,
89
+ columns,
89
90
  }: {
90
91
  message: Message;
92
+ columns: number;
91
93
  }): React.ReactElement {
94
+ const boxWidth = Math.max(columns - 6, 10);
92
95
  return (
93
- <Box flexDirection="column" paddingX={2} marginTop={1}>
96
+ <Box flexDirection="column" paddingX={2} marginTop={1} width={columns}>
94
97
  <Text color="cyan" bold>
95
98
  {"✦ CasAbot"}
96
99
  </Text>
97
100
  {message.content ? (
98
- <Box marginLeft={2}>
101
+ <Box marginLeft={2} width={boxWidth}>
99
102
  <Text wrap="wrap">{renderMarkdown(message.content)}</Text>
100
103
  </Box>
101
104
  ) : null}
@@ -106,6 +109,8 @@ function ToolCallsView({
106
109
  borderStyle="round"
107
110
  borderColor="yellow"
108
111
  paddingX={1}
112
+ width={boxWidth}
113
+ overflow="hidden"
109
114
  >
110
115
  <Text color="yellow" bold>
111
116
  {"⚡ Tool Calls"}
@@ -118,6 +123,10 @@ function ToolCallsView({
118
123
  } catch {
119
124
  /* keep raw */
120
125
  }
126
+ const maxArgLen = Math.max(boxWidth - tc.name.length - 8, 20);
127
+ if (display.length > maxArgLen) {
128
+ display = display.slice(0, maxArgLen - 1) + "…";
129
+ }
121
130
  return (
122
131
  <Box key={i}>
123
132
  <Text dimColor>{tc.name}</Text>
@@ -133,9 +142,12 @@ function ToolCallsView({
133
142
 
134
143
  function ToolResultView({
135
144
  content,
145
+ columns,
136
146
  }: {
137
147
  content: string;
148
+ columns: number;
138
149
  }): React.ReactElement {
150
+ const boxWidth = Math.max(columns - 6, 10);
139
151
  return (
140
152
  <Box
141
153
  flexDirection="column"
@@ -144,6 +156,8 @@ function ToolResultView({
144
156
  borderStyle="round"
145
157
  borderColor="gray"
146
158
  paddingX={1}
159
+ width={boxWidth}
160
+ overflow="hidden"
147
161
  >
148
162
  <Text dimColor bold>
149
163
  {"📋 Result"}
@@ -155,36 +169,38 @@ function ToolResultView({
155
169
 
156
170
  function MessageView({
157
171
  message,
172
+ columns,
158
173
  }: {
159
174
  message: Message;
175
+ columns: number;
160
176
  }): React.ReactElement {
161
177
  if (message.role === "user") {
162
- return <UserMessageView content={message.content} />;
178
+ return <UserMessageView content={message.content} columns={columns} />;
163
179
  }
164
180
  if (message.role === "tool") {
165
- return <ToolResultView content={message.content} />;
181
+ return <ToolResultView content={message.content} columns={columns} />;
166
182
  }
167
183
  if (message.role === "assistant" && message.toolCalls?.length) {
168
- return <ToolCallsView message={message} />;
184
+ return <ToolCallsView message={message} columns={columns} />;
169
185
  }
170
186
  if (message.role === "assistant") {
171
- return <AssistantMessageView content={message.content} />;
187
+ return <AssistantMessageView content={message.content} columns={columns} />;
172
188
  }
173
- return <Text>{message.content}</Text>;
189
+ return <Text wrap="wrap">{message.content}</Text>;
174
190
  }
175
191
 
176
- function WelcomeHint(): React.ReactElement {
192
+ function WelcomeHint({ columns }: { columns: number }): React.ReactElement {
177
193
  return (
178
- <Box flexDirection="column" paddingX={2} marginTop={1} marginBottom={1}>
194
+ <Box flexDirection="column" paddingX={2} marginTop={1} marginBottom={1} width={columns}>
179
195
  <Text dimColor>{"Type a message below to get started."}</Text>
180
196
  <Text dimColor>{"CasAbot will orchestrate agents to help you."}</Text>
181
197
  </Box>
182
198
  );
183
199
  }
184
200
 
185
- function ProcessingIndicator(): React.ReactElement {
201
+ function ProcessingIndicator({ columns }: { columns: number }): React.ReactElement {
186
202
  return (
187
- <Box paddingX={2} marginTop={1} gap={1}>
203
+ <Box paddingX={2} marginTop={1} gap={1} width={columns}>
188
204
  <Text color="yellow">
189
205
  <Spinner type="dots" />
190
206
  </Text>
@@ -212,6 +228,8 @@ function App({
212
228
  const [input, setInput] = useState("");
213
229
  const [isProcessing, setIsProcessing] = useState(false);
214
230
  const { exit } = useApp();
231
+ const { stdout } = useStdout();
232
+ const columns = stdout.columns ?? 80;
215
233
 
216
234
  const handleSubmit = useCallback(
217
235
  async (text: string) => {
@@ -260,35 +278,36 @@ function App({
260
278
  ], [messages]);
261
279
 
262
280
  return (
263
- <Box flexDirection="column">
281
+ <Box flexDirection="column" width={columns}>
264
282
  <Static items={items}>
265
283
  {(item) => {
266
284
  if (item.type === "header") {
267
285
  return (
268
- <Box key={item.key} flexDirection="column">
269
- <HeaderBlock />
286
+ <Box key={item.key} flexDirection="column" width={columns}>
287
+ <HeaderBlock columns={columns} />
270
288
  </Box>
271
289
  );
272
290
  }
273
291
  return (
274
- <Box key={item.key} flexDirection="column">
275
- <MessageView message={item.message} />
292
+ <Box key={item.key} flexDirection="column" width={columns}>
293
+ <MessageView message={item.message} columns={columns} />
276
294
  </Box>
277
295
  );
278
296
  }}
279
297
  </Static>
280
298
 
281
- {messages.length === 0 && !isProcessing && <WelcomeHint />}
282
- {isProcessing && <ProcessingIndicator />}
299
+ {messages.length === 0 && !isProcessing && <WelcomeHint columns={columns} />}
300
+ {isProcessing && <ProcessingIndicator columns={columns} />}
283
301
 
284
- <HRule />
302
+ <HRule columns={columns} />
285
303
 
286
- <Box paddingX={1}>
304
+ <Box paddingX={1} width={columns}>
287
305
  <Box
288
306
  borderStyle="round"
289
307
  borderColor={isProcessing ? "gray" : "cyan"}
290
308
  paddingX={1}
291
- width="100%"
309
+ width={Math.max(columns - 2, 10)}
310
+ overflow="hidden"
292
311
  >
293
312
  <Text color="cyan" bold>
294
313
  {"❯ "}
@@ -306,7 +325,7 @@ function App({
306
325
  </Box>
307
326
  </Box>
308
327
 
309
- <Box paddingX={2} justifyContent="space-between">
328
+ <Box paddingX={2} width={columns} justifyContent="space-between">
310
329
  <Text dimColor>{"Ctrl+C exit"}</Text>
311
330
  <Text dimColor>
312
331
  {userCount} {userCount === 1 ? "message" : "messages"}