calabasas 0.14.0 → 0.16.0

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,165 @@
1
+ import {
2
+ build_default,
3
+ relativeTime
4
+ } from "./index-8gymgyxd.js";
5
+ import"./index-tre7d3f1.js";
6
+ import {
7
+ __toESM
8
+ } from "./index-sdksp5px.js";
9
+ import {
10
+ Box_default,
11
+ Text
12
+ } from "./index-4rn9k8et.js";
13
+ import {
14
+ cliApi,
15
+ require_jsx_dev_runtime,
16
+ useQuery
17
+ } from "./convex-1z1jsz1n.js";
18
+ import"./index-vmy4gfe1.js";
19
+
20
+ // src/components/StatusBadge.tsx
21
+ var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
22
+ var STATUS_CONFIG = {
23
+ connected: { color: "green", dot: "●" },
24
+ connecting: { color: "yellow", dot: "●" },
25
+ error: { color: "red", dot: "●" },
26
+ disconnected: { color: "gray", dot: "●" }
27
+ };
28
+ function StatusBadge({ status, width = 0 }) {
29
+ const config = STATUS_CONFIG[status];
30
+ const label = `${config.dot} ${status}`;
31
+ const padded = width > 0 ? label.padEnd(width) : label;
32
+ return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
33
+ children: [
34
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
35
+ color: config.color,
36
+ children: config.dot
37
+ }, undefined, false, undefined, this),
38
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
39
+ children: padded.slice(1)
40
+ }, undefined, false, undefined, this)
41
+ ]
42
+ }, undefined, true, undefined, this);
43
+ }
44
+
45
+ // src/components/BotList.tsx
46
+ var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
47
+ function BotList({
48
+ apiKey,
49
+ selectedIndex,
50
+ onSelect
51
+ }) {
52
+ const bots = useQuery(cliApi.listBots, { apiKey });
53
+ if (bots === undefined) {
54
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
55
+ children: [
56
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
57
+ color: "cyan",
58
+ children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(build_default, {
59
+ type: "dots"
60
+ }, undefined, false, undefined, this)
61
+ }, undefined, false, undefined, this),
62
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
63
+ children: " Loading bots..."
64
+ }, undefined, false, undefined, this)
65
+ ]
66
+ }, undefined, true, undefined, this);
67
+ }
68
+ if (bots.length === 0) {
69
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
70
+ children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
71
+ dimColor: true,
72
+ children: "No bots found. Run `calabasas bot add` to create one."
73
+ }, undefined, false, undefined, this)
74
+ }, undefined, false, undefined, this);
75
+ }
76
+ const COL = { name: 30, status: 16, appId: 22, env: 8, last: 16 };
77
+ function truncate(str, max) {
78
+ if (str.length <= max)
79
+ return str.padEnd(max);
80
+ return str.slice(0, max - 1) + "…";
81
+ }
82
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
83
+ flexDirection: "column",
84
+ children: [
85
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
86
+ marginBottom: 1,
87
+ children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
88
+ bold: true,
89
+ children: [
90
+ " ",
91
+ "Name".padEnd(COL.name),
92
+ "Status".padEnd(COL.status),
93
+ "Discord App ID".padEnd(COL.appId),
94
+ "Env".padEnd(COL.env),
95
+ "Last Connected"
96
+ ]
97
+ }, undefined, true, undefined, this)
98
+ }, undefined, false, undefined, this),
99
+ bots.map((bot, i) => {
100
+ const isSelected = selectedIndex === i;
101
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
102
+ flexDirection: "column",
103
+ children: [
104
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
105
+ children: [
106
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
107
+ color: isSelected ? "cyan" : undefined,
108
+ children: isSelected ? "→ " : " "
109
+ }, undefined, false, undefined, this),
110
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
111
+ bold: isSelected,
112
+ children: truncate(bot.name, COL.name)
113
+ }, undefined, false, undefined, this),
114
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(StatusBadge, {
115
+ status: bot.status,
116
+ width: COL.status
117
+ }, undefined, false, undefined, this),
118
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
119
+ dimColor: true,
120
+ children: bot.discordAppId.padEnd(COL.appId)
121
+ }, undefined, false, undefined, this),
122
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
123
+ dimColor: true,
124
+ children: bot.environment.padEnd(COL.env)
125
+ }, undefined, false, undefined, this),
126
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
127
+ dimColor: true,
128
+ children: relativeTime(bot.lastConnectedAt)
129
+ }, undefined, false, undefined, this)
130
+ ]
131
+ }, undefined, true, undefined, this),
132
+ bot.errorMessage && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
133
+ marginLeft: 4,
134
+ children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
135
+ color: "red",
136
+ dimColor: true,
137
+ children: [
138
+ "└",
139
+ " ",
140
+ bot.errorMessage
141
+ ]
142
+ }, undefined, true, undefined, this)
143
+ }, undefined, false, undefined, this),
144
+ !bot.errorMessage && bot.disconnectReason && /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
145
+ marginLeft: 4,
146
+ children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
147
+ dimColor: true,
148
+ children: [
149
+ "└",
150
+ " ",
151
+ bot.disconnectReason
152
+ ]
153
+ }, undefined, true, undefined, this)
154
+ }, undefined, false, undefined, this)
155
+ ]
156
+ }, bot._id, true, undefined, this);
157
+ })
158
+ ]
159
+ }, undefined, true, undefined, this);
160
+ }
161
+ export {
162
+ BotList
163
+ };
164
+
165
+ ;
package/dist/config.d.ts CHANGED
@@ -7,6 +7,7 @@ export type SyncConfig = {
7
7
  roles?: boolean;
8
8
  members?: boolean;
9
9
  presence?: boolean;
10
+ emojis?: boolean;
10
11
  };
11
12
 
12
13
  export type DiscordEventName =
@@ -0,0 +1,235 @@
1
+ import {
2
+ LogViewer
3
+ } from "./index-b0cp0nch.js";
4
+ import {
5
+ getConvexUrl,
6
+ resolveEnv,
7
+ resolvePlatformApiKey
8
+ } from "./index-a8vtmtf9.js";
9
+ import {
10
+ build_default,
11
+ formatLatency,
12
+ formatNumber
13
+ } from "./index-8gymgyxd.js";
14
+ import"./index-tre7d3f1.js";
15
+ import {
16
+ __toESM
17
+ } from "./index-sdksp5px.js";
18
+ import {
19
+ BotList
20
+ } from "./BotList-pbt2yxmj.js";
21
+ import {
22
+ Box_default,
23
+ Text,
24
+ render_default,
25
+ use_app_default,
26
+ use_input_default
27
+ } from "./index-4rn9k8et.js";
28
+ import {
29
+ ConvexProvider,
30
+ cliApi,
31
+ createConvexClient,
32
+ require_jsx_dev_runtime,
33
+ useQuery
34
+ } from "./convex-1z1jsz1n.js";
35
+ import {
36
+ require_react
37
+ } from "./index-vmy4gfe1.js";
38
+
39
+ // src/components/Dashboard.tsx
40
+ var import_react2 = __toESM(require_react(), 1);
41
+
42
+ // src/components/Header.tsx
43
+ var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
44
+ function Header({
45
+ botCount,
46
+ env
47
+ }) {
48
+ return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
49
+ marginBottom: 1,
50
+ children: [
51
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
52
+ bold: true,
53
+ color: "magenta",
54
+ children: "calabasas"
55
+ }, undefined, false, undefined, this),
56
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
57
+ dimColor: true,
58
+ children: " v0.1.12"
59
+ }, undefined, false, undefined, this),
60
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
61
+ dimColor: true,
62
+ children: " · "
63
+ }, undefined, false, undefined, this),
64
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
65
+ children: [
66
+ botCount,
67
+ " bot",
68
+ botCount !== 1 ? "s" : ""
69
+ ]
70
+ }, undefined, true, undefined, this),
71
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
72
+ dimColor: true,
73
+ children: " · "
74
+ }, undefined, false, undefined, this),
75
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
76
+ color: env === "dev" ? "yellow" : "green",
77
+ children: env
78
+ }, undefined, false, undefined, this),
79
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
80
+ dimColor: true,
81
+ children: " · Press "
82
+ }, undefined, false, undefined, this),
83
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
84
+ bold: true,
85
+ children: "q"
86
+ }, undefined, false, undefined, this),
87
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
88
+ dimColor: true,
89
+ children: " to quit"
90
+ }, undefined, false, undefined, this)
91
+ ]
92
+ }, undefined, true, undefined, this);
93
+ }
94
+
95
+ // src/components/StatsPanel.tsx
96
+ var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
97
+ var ONE_HOUR = 60 * 60 * 1000;
98
+ function StatsPanel({
99
+ apiKey,
100
+ botId
101
+ }) {
102
+ const stats = useQuery(cliApi.botStats, {
103
+ apiKey,
104
+ botId,
105
+ since: Date.now() - ONE_HOUR
106
+ });
107
+ if (stats === undefined) {
108
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
109
+ children: [
110
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
111
+ color: "cyan",
112
+ children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(build_default, {
113
+ type: "dots"
114
+ }, undefined, false, undefined, this)
115
+ }, undefined, false, undefined, this),
116
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
117
+ children: " Loading stats..."
118
+ }, undefined, false, undefined, this)
119
+ ]
120
+ }, undefined, true, undefined, this);
121
+ }
122
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
123
+ gap: 2,
124
+ marginBottom: 1,
125
+ children: [
126
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
127
+ dimColor: true,
128
+ children: "Events (1h):"
129
+ }, undefined, false, undefined, this),
130
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
131
+ bold: true,
132
+ children: formatNumber(stats.total)
133
+ }, undefined, false, undefined, this),
134
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
135
+ color: "green",
136
+ children: [
137
+ formatNumber(stats.success),
138
+ " ok"
139
+ ]
140
+ }, undefined, true, undefined, this),
141
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
142
+ color: "red",
143
+ children: [
144
+ formatNumber(stats.failed),
145
+ " failed"
146
+ ]
147
+ }, undefined, true, undefined, this),
148
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
149
+ dimColor: true,
150
+ children: [
151
+ "avg ",
152
+ formatLatency(stats.avgLatencyMs)
153
+ ]
154
+ }, undefined, true, undefined, this)
155
+ ]
156
+ }, undefined, true, undefined, this);
157
+ }
158
+
159
+ // src/components/Dashboard.tsx
160
+ var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
161
+ function Dashboard({
162
+ apiKey,
163
+ env
164
+ }) {
165
+ const { exit } = use_app_default();
166
+ const [selectedIndex, setSelectedIndex] = import_react2.useState(0);
167
+ const bots = useQuery(cliApi.listBots, { apiKey });
168
+ const botCount = bots?.length ?? 0;
169
+ const selectedBot = bots?.[selectedIndex];
170
+ use_input_default(import_react2.useCallback((input, key) => {
171
+ if (input === "q") {
172
+ exit();
173
+ return;
174
+ }
175
+ if ((input === "j" || key.downArrow) && botCount > 0) {
176
+ setSelectedIndex((i) => Math.min(i, botCount - 1) === botCount - 1 ? 0 : i + 1);
177
+ }
178
+ if ((input === "k" || key.upArrow) && botCount > 0) {
179
+ setSelectedIndex((i) => i === 0 ? botCount - 1 : i - 1);
180
+ }
181
+ }, [botCount, exit]));
182
+ return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
183
+ flexDirection: "column",
184
+ children: [
185
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Header, {
186
+ botCount,
187
+ env
188
+ }, undefined, false, undefined, this),
189
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(BotList, {
190
+ apiKey,
191
+ selectedIndex
192
+ }, undefined, false, undefined, this),
193
+ selectedBot && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
194
+ flexDirection: "column",
195
+ marginTop: 1,
196
+ children: [
197
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(StatsPanel, {
198
+ apiKey,
199
+ botId: selectedBot._id
200
+ }, undefined, false, undefined, this),
201
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(LogViewer, {
202
+ apiKey,
203
+ botId: selectedBot._id
204
+ }, undefined, false, undefined, this)
205
+ ]
206
+ }, undefined, true, undefined, this)
207
+ ]
208
+ }, undefined, true, undefined, this);
209
+ }
210
+
211
+ // src/commands/dashboard.tsx
212
+ var jsx_dev_runtime4 = __toESM(require_jsx_dev_runtime(), 1);
213
+ async function dashboard(options) {
214
+ const env = resolveEnv(options);
215
+ const resolved = resolvePlatformApiKey({}, env);
216
+ if (!resolved) {
217
+ console.log("Not logged in. Run `calabasas login` first.");
218
+ return;
219
+ }
220
+ const apiKey = resolved.key;
221
+ const convexUrl = getConvexUrl(env);
222
+ const client = createConvexClient(convexUrl);
223
+ const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(ConvexProvider, {
224
+ client,
225
+ children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Dashboard, {
226
+ apiKey,
227
+ env
228
+ }, undefined, false, undefined, this)
229
+ }, undefined, false, undefined, this));
230
+ await waitUntilExit();
231
+ await client.close();
232
+ }
233
+ export {
234
+ dashboard
235
+ };
@@ -0,0 +1,235 @@
1
+ import {
2
+ LogViewer
3
+ } from "./index-b0cp0nch.js";
4
+ import {
5
+ getConvexUrl,
6
+ resolveEnv,
7
+ resolvePlatformApiKey
8
+ } from "./index-a8vtmtf9.js";
9
+ import {
10
+ build_default,
11
+ formatLatency,
12
+ formatNumber
13
+ } from "./index-8gymgyxd.js";
14
+ import"./index-tre7d3f1.js";
15
+ import {
16
+ __toESM
17
+ } from "./index-sdksp5px.js";
18
+ import {
19
+ BotList
20
+ } from "./BotList-gmtf52xh.js";
21
+ import {
22
+ Box_default,
23
+ Text,
24
+ render_default,
25
+ use_app_default,
26
+ use_input_default
27
+ } from "./index-4rn9k8et.js";
28
+ import {
29
+ ConvexProvider,
30
+ cliApi,
31
+ createConvexClient,
32
+ require_jsx_dev_runtime,
33
+ useQuery
34
+ } from "./convex-1z1jsz1n.js";
35
+ import {
36
+ require_react
37
+ } from "./index-vmy4gfe1.js";
38
+
39
+ // src/components/Dashboard.tsx
40
+ var import_react2 = __toESM(require_react(), 1);
41
+
42
+ // src/components/Header.tsx
43
+ var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
44
+ function Header({
45
+ botCount,
46
+ env
47
+ }) {
48
+ return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
49
+ marginBottom: 1,
50
+ children: [
51
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
52
+ bold: true,
53
+ color: "magenta",
54
+ children: "calabasas"
55
+ }, undefined, false, undefined, this),
56
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
57
+ dimColor: true,
58
+ children: " v0.1.12"
59
+ }, undefined, false, undefined, this),
60
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
61
+ dimColor: true,
62
+ children: " · "
63
+ }, undefined, false, undefined, this),
64
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
65
+ children: [
66
+ botCount,
67
+ " bot",
68
+ botCount !== 1 ? "s" : ""
69
+ ]
70
+ }, undefined, true, undefined, this),
71
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
72
+ dimColor: true,
73
+ children: " · "
74
+ }, undefined, false, undefined, this),
75
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
76
+ color: env === "dev" ? "yellow" : "green",
77
+ children: env
78
+ }, undefined, false, undefined, this),
79
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
80
+ dimColor: true,
81
+ children: " · Press "
82
+ }, undefined, false, undefined, this),
83
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
84
+ bold: true,
85
+ children: "q"
86
+ }, undefined, false, undefined, this),
87
+ /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
88
+ dimColor: true,
89
+ children: " to quit"
90
+ }, undefined, false, undefined, this)
91
+ ]
92
+ }, undefined, true, undefined, this);
93
+ }
94
+
95
+ // src/components/StatsPanel.tsx
96
+ var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
97
+ var ONE_HOUR = 60 * 60 * 1000;
98
+ function StatsPanel({
99
+ apiKey,
100
+ botId
101
+ }) {
102
+ const stats = useQuery(cliApi.botStats, {
103
+ apiKey,
104
+ botId,
105
+ since: Date.now() - ONE_HOUR
106
+ });
107
+ if (stats === undefined) {
108
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
109
+ children: [
110
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
111
+ color: "cyan",
112
+ children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(build_default, {
113
+ type: "dots"
114
+ }, undefined, false, undefined, this)
115
+ }, undefined, false, undefined, this),
116
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
117
+ children: " Loading stats..."
118
+ }, undefined, false, undefined, this)
119
+ ]
120
+ }, undefined, true, undefined, this);
121
+ }
122
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
123
+ gap: 2,
124
+ marginBottom: 1,
125
+ children: [
126
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
127
+ dimColor: true,
128
+ children: "Events (1h):"
129
+ }, undefined, false, undefined, this),
130
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
131
+ bold: true,
132
+ children: formatNumber(stats.total)
133
+ }, undefined, false, undefined, this),
134
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
135
+ color: "green",
136
+ children: [
137
+ formatNumber(stats.success),
138
+ " ok"
139
+ ]
140
+ }, undefined, true, undefined, this),
141
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
142
+ color: "red",
143
+ children: [
144
+ formatNumber(stats.failed),
145
+ " failed"
146
+ ]
147
+ }, undefined, true, undefined, this),
148
+ /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
149
+ dimColor: true,
150
+ children: [
151
+ "avg ",
152
+ formatLatency(stats.avgLatencyMs)
153
+ ]
154
+ }, undefined, true, undefined, this)
155
+ ]
156
+ }, undefined, true, undefined, this);
157
+ }
158
+
159
+ // src/components/Dashboard.tsx
160
+ var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
161
+ function Dashboard({
162
+ apiKey,
163
+ env
164
+ }) {
165
+ const { exit } = use_app_default();
166
+ const [selectedIndex, setSelectedIndex] = import_react2.useState(0);
167
+ const bots = useQuery(cliApi.listBots, { apiKey });
168
+ const botCount = bots?.length ?? 0;
169
+ const selectedBot = bots?.[selectedIndex];
170
+ use_input_default(import_react2.useCallback((input, key) => {
171
+ if (input === "q") {
172
+ exit();
173
+ return;
174
+ }
175
+ if ((input === "j" || key.downArrow) && botCount > 0) {
176
+ setSelectedIndex((i) => Math.min(i, botCount - 1) === botCount - 1 ? 0 : i + 1);
177
+ }
178
+ if ((input === "k" || key.upArrow) && botCount > 0) {
179
+ setSelectedIndex((i) => i === 0 ? botCount - 1 : i - 1);
180
+ }
181
+ }, [botCount, exit]));
182
+ return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
183
+ flexDirection: "column",
184
+ children: [
185
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Header, {
186
+ botCount,
187
+ env
188
+ }, undefined, false, undefined, this),
189
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(BotList, {
190
+ apiKey,
191
+ selectedIndex
192
+ }, undefined, false, undefined, this),
193
+ selectedBot && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
194
+ flexDirection: "column",
195
+ marginTop: 1,
196
+ children: [
197
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(StatsPanel, {
198
+ apiKey,
199
+ botId: selectedBot._id
200
+ }, undefined, false, undefined, this),
201
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(LogViewer, {
202
+ apiKey,
203
+ botId: selectedBot._id
204
+ }, undefined, false, undefined, this)
205
+ ]
206
+ }, undefined, true, undefined, this)
207
+ ]
208
+ }, undefined, true, undefined, this);
209
+ }
210
+
211
+ // src/commands/dashboard.tsx
212
+ var jsx_dev_runtime4 = __toESM(require_jsx_dev_runtime(), 1);
213
+ async function dashboard(options) {
214
+ const env = resolveEnv(options);
215
+ const resolved = resolvePlatformApiKey({}, env);
216
+ if (!resolved) {
217
+ console.log("Not logged in. Run `calabasas login` first.");
218
+ return;
219
+ }
220
+ const apiKey = resolved.key;
221
+ const convexUrl = getConvexUrl(env);
222
+ const client = createConvexClient(convexUrl);
223
+ const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(ConvexProvider, {
224
+ client,
225
+ children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Dashboard, {
226
+ apiKey,
227
+ env
228
+ }, undefined, false, undefined, this)
229
+ }, undefined, false, undefined, this));
230
+ await waitUntilExit();
231
+ await client.close();
232
+ }
233
+ export {
234
+ dashboard
235
+ };