calabasas 0.19.0 → 0.19.2
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/dashboard-hebbbc6d.js +221 -0
- package/dist/index-rb2tds4a.js +196 -0
- package/dist/index.js +86 -17
- package/dist/logs-v149b3tb.js +111 -0
- package/package.json +1 -1
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LogViewer
|
|
3
|
+
} from "./index-b0cp0nch.js";
|
|
4
|
+
import {
|
|
5
|
+
getConvexUrl,
|
|
6
|
+
resolvePlatformApiKey
|
|
7
|
+
} from "./index-rb2tds4a.js";
|
|
8
|
+
import {
|
|
9
|
+
build_default,
|
|
10
|
+
formatLatency,
|
|
11
|
+
formatNumber
|
|
12
|
+
} from "./index-8gymgyxd.js";
|
|
13
|
+
import"./index-tre7d3f1.js";
|
|
14
|
+
import {
|
|
15
|
+
__toESM
|
|
16
|
+
} from "./index-sdksp5px.js";
|
|
17
|
+
import {
|
|
18
|
+
BotList
|
|
19
|
+
} from "./BotList-metq47qv.js";
|
|
20
|
+
import {
|
|
21
|
+
Box_default,
|
|
22
|
+
Text,
|
|
23
|
+
render_default,
|
|
24
|
+
use_app_default,
|
|
25
|
+
use_input_default
|
|
26
|
+
} from "./index-4rn9k8et.js";
|
|
27
|
+
import {
|
|
28
|
+
ConvexProvider,
|
|
29
|
+
cliApi,
|
|
30
|
+
createConvexClient,
|
|
31
|
+
require_jsx_dev_runtime,
|
|
32
|
+
useQuery
|
|
33
|
+
} from "./convex-1z1jsz1n.js";
|
|
34
|
+
import {
|
|
35
|
+
require_react
|
|
36
|
+
} from "./index-vmy4gfe1.js";
|
|
37
|
+
|
|
38
|
+
// src/components/Dashboard.tsx
|
|
39
|
+
var import_react2 = __toESM(require_react(), 1);
|
|
40
|
+
|
|
41
|
+
// src/components/Header.tsx
|
|
42
|
+
var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
|
|
43
|
+
function Header({
|
|
44
|
+
botCount
|
|
45
|
+
}) {
|
|
46
|
+
return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
|
|
47
|
+
marginBottom: 1,
|
|
48
|
+
children: [
|
|
49
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
50
|
+
bold: true,
|
|
51
|
+
color: "magenta",
|
|
52
|
+
children: "calabasas"
|
|
53
|
+
}, undefined, false, undefined, this),
|
|
54
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
55
|
+
dimColor: true,
|
|
56
|
+
children: " v0.1.12"
|
|
57
|
+
}, undefined, false, undefined, this),
|
|
58
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
59
|
+
dimColor: true,
|
|
60
|
+
children: " · "
|
|
61
|
+
}, undefined, false, undefined, this),
|
|
62
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
63
|
+
children: [
|
|
64
|
+
botCount,
|
|
65
|
+
" bot",
|
|
66
|
+
botCount !== 1 ? "s" : ""
|
|
67
|
+
]
|
|
68
|
+
}, undefined, true, undefined, this),
|
|
69
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
70
|
+
dimColor: true,
|
|
71
|
+
children: " · Press "
|
|
72
|
+
}, undefined, false, undefined, this),
|
|
73
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
74
|
+
bold: true,
|
|
75
|
+
children: "q"
|
|
76
|
+
}, undefined, false, undefined, this),
|
|
77
|
+
/* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
|
|
78
|
+
dimColor: true,
|
|
79
|
+
children: " to quit"
|
|
80
|
+
}, undefined, false, undefined, this)
|
|
81
|
+
]
|
|
82
|
+
}, undefined, true, undefined, this);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/components/StatsPanel.tsx
|
|
86
|
+
var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
87
|
+
var ONE_HOUR = 60 * 60 * 1000;
|
|
88
|
+
function StatsPanel({
|
|
89
|
+
apiKey,
|
|
90
|
+
botId
|
|
91
|
+
}) {
|
|
92
|
+
const stats = useQuery(cliApi.botStats, {
|
|
93
|
+
apiKey,
|
|
94
|
+
botId,
|
|
95
|
+
since: Date.now() - ONE_HOUR
|
|
96
|
+
});
|
|
97
|
+
if (stats === undefined) {
|
|
98
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
99
|
+
children: [
|
|
100
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
101
|
+
color: "cyan",
|
|
102
|
+
children: /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(build_default, {
|
|
103
|
+
type: "dots"
|
|
104
|
+
}, undefined, false, undefined, this)
|
|
105
|
+
}, undefined, false, undefined, this),
|
|
106
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
107
|
+
children: " Loading stats..."
|
|
108
|
+
}, undefined, false, undefined, this)
|
|
109
|
+
]
|
|
110
|
+
}, undefined, true, undefined, this);
|
|
111
|
+
}
|
|
112
|
+
return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Box_default, {
|
|
113
|
+
gap: 2,
|
|
114
|
+
marginBottom: 1,
|
|
115
|
+
children: [
|
|
116
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
117
|
+
dimColor: true,
|
|
118
|
+
children: "Events (1h):"
|
|
119
|
+
}, undefined, false, undefined, this),
|
|
120
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
121
|
+
bold: true,
|
|
122
|
+
children: formatNumber(stats.total)
|
|
123
|
+
}, undefined, false, undefined, this),
|
|
124
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
125
|
+
color: "green",
|
|
126
|
+
children: [
|
|
127
|
+
formatNumber(stats.success),
|
|
128
|
+
" ok"
|
|
129
|
+
]
|
|
130
|
+
}, undefined, true, undefined, this),
|
|
131
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
132
|
+
color: "red",
|
|
133
|
+
children: [
|
|
134
|
+
formatNumber(stats.failed),
|
|
135
|
+
" failed"
|
|
136
|
+
]
|
|
137
|
+
}, undefined, true, undefined, this),
|
|
138
|
+
/* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
|
|
139
|
+
dimColor: true,
|
|
140
|
+
children: [
|
|
141
|
+
"avg ",
|
|
142
|
+
formatLatency(stats.avgLatencyMs)
|
|
143
|
+
]
|
|
144
|
+
}, undefined, true, undefined, this)
|
|
145
|
+
]
|
|
146
|
+
}, undefined, true, undefined, this);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/components/Dashboard.tsx
|
|
150
|
+
var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
|
|
151
|
+
function Dashboard({
|
|
152
|
+
apiKey
|
|
153
|
+
}) {
|
|
154
|
+
const { exit } = use_app_default();
|
|
155
|
+
const [selectedIndex, setSelectedIndex] = import_react2.useState(0);
|
|
156
|
+
const bots = useQuery(cliApi.listBots, { apiKey });
|
|
157
|
+
const botCount = bots?.length ?? 0;
|
|
158
|
+
const selectedBot = bots?.[selectedIndex];
|
|
159
|
+
use_input_default(import_react2.useCallback((input, key) => {
|
|
160
|
+
if (input === "q") {
|
|
161
|
+
exit();
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if ((input === "j" || key.downArrow) && botCount > 0) {
|
|
165
|
+
setSelectedIndex((i) => Math.min(i, botCount - 1) === botCount - 1 ? 0 : i + 1);
|
|
166
|
+
}
|
|
167
|
+
if ((input === "k" || key.upArrow) && botCount > 0) {
|
|
168
|
+
setSelectedIndex((i) => i === 0 ? botCount - 1 : i - 1);
|
|
169
|
+
}
|
|
170
|
+
}, [botCount, exit]));
|
|
171
|
+
return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
172
|
+
flexDirection: "column",
|
|
173
|
+
children: [
|
|
174
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Header, {
|
|
175
|
+
botCount
|
|
176
|
+
}, undefined, false, undefined, this),
|
|
177
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(BotList, {
|
|
178
|
+
apiKey,
|
|
179
|
+
selectedIndex
|
|
180
|
+
}, undefined, false, undefined, this),
|
|
181
|
+
selectedBot && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
|
|
182
|
+
flexDirection: "column",
|
|
183
|
+
marginTop: 1,
|
|
184
|
+
children: [
|
|
185
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(StatsPanel, {
|
|
186
|
+
apiKey,
|
|
187
|
+
botId: selectedBot._id
|
|
188
|
+
}, undefined, false, undefined, this),
|
|
189
|
+
/* @__PURE__ */ jsx_dev_runtime3.jsxDEV(LogViewer, {
|
|
190
|
+
apiKey,
|
|
191
|
+
botId: selectedBot._id
|
|
192
|
+
}, undefined, false, undefined, this)
|
|
193
|
+
]
|
|
194
|
+
}, undefined, true, undefined, this)
|
|
195
|
+
]
|
|
196
|
+
}, undefined, true, undefined, this);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// src/commands/dashboard.tsx
|
|
200
|
+
var jsx_dev_runtime4 = __toESM(require_jsx_dev_runtime(), 1);
|
|
201
|
+
async function dashboard() {
|
|
202
|
+
const resolved = resolvePlatformApiKey({});
|
|
203
|
+
if (!resolved) {
|
|
204
|
+
console.log("Not logged in. Run `calabasas login` first.");
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const apiKey = resolved.key;
|
|
208
|
+
const convexUrl = getConvexUrl();
|
|
209
|
+
const client = createConvexClient(convexUrl);
|
|
210
|
+
const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(ConvexProvider, {
|
|
211
|
+
client,
|
|
212
|
+
children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Dashboard, {
|
|
213
|
+
apiKey
|
|
214
|
+
}, undefined, false, undefined, this)
|
|
215
|
+
}, undefined, false, undefined, this));
|
|
216
|
+
await waitUntilExit();
|
|
217
|
+
await client.close();
|
|
218
|
+
}
|
|
219
|
+
export {
|
|
220
|
+
dashboard
|
|
221
|
+
};
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__require,
|
|
3
|
+
__toESM
|
|
4
|
+
} from "./index-sdksp5px.js";
|
|
5
|
+
|
|
6
|
+
// src/lib/config.ts
|
|
7
|
+
import * as fs from "fs";
|
|
8
|
+
import * as path from "path";
|
|
9
|
+
import * as os from "os";
|
|
10
|
+
var CONFIG_DIR = path.join(os.homedir(), ".calabasas");
|
|
11
|
+
var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
12
|
+
var API_URL = "https://sensible-starfish-338.convex.site";
|
|
13
|
+
var CONVEX_URL = "https://sensible-starfish-338.convex.cloud";
|
|
14
|
+
var WEB_URL = "https://calabasas-web.vercel.app";
|
|
15
|
+
function getConfig() {
|
|
16
|
+
try {
|
|
17
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
const content = fs.readFileSync(CONFIG_FILE, "utf-8");
|
|
21
|
+
return JSON.parse(content);
|
|
22
|
+
} catch {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function saveConfig(config) {
|
|
27
|
+
const existing = getConfig();
|
|
28
|
+
const merged = { ...existing, ...config };
|
|
29
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
30
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2));
|
|
33
|
+
}
|
|
34
|
+
function clearConfig() {
|
|
35
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
|
36
|
+
fs.unlinkSync(CONFIG_FILE);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function isAuthenticated() {
|
|
40
|
+
const config = getConfig();
|
|
41
|
+
return !!config.apiKey;
|
|
42
|
+
}
|
|
43
|
+
function getApiUrl() {
|
|
44
|
+
const config = getConfig();
|
|
45
|
+
return config.apiUrl || API_URL;
|
|
46
|
+
}
|
|
47
|
+
function getWebUrl() {
|
|
48
|
+
return WEB_URL;
|
|
49
|
+
}
|
|
50
|
+
function getConvexUrl() {
|
|
51
|
+
return CONVEX_URL;
|
|
52
|
+
}
|
|
53
|
+
function parseEnvLocal() {
|
|
54
|
+
const envPath = path.join(process.cwd(), ".env.local");
|
|
55
|
+
if (!fs.existsSync(envPath))
|
|
56
|
+
return {};
|
|
57
|
+
const content = fs.readFileSync(envPath, "utf-8");
|
|
58
|
+
const result = {};
|
|
59
|
+
for (const line of content.split(`
|
|
60
|
+
`)) {
|
|
61
|
+
const trimmed = line.trim();
|
|
62
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
63
|
+
continue;
|
|
64
|
+
const eqIndex = trimmed.indexOf("=");
|
|
65
|
+
if (eqIndex === -1)
|
|
66
|
+
continue;
|
|
67
|
+
const key = trimmed.slice(0, eqIndex).trim();
|
|
68
|
+
let value = trimmed.slice(eqIndex + 1).trim();
|
|
69
|
+
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
70
|
+
value = value.slice(1, -1);
|
|
71
|
+
}
|
|
72
|
+
result[key] = value;
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
async function resolveBot(options, apiKey, apiUrl) {
|
|
77
|
+
if (options.bot)
|
|
78
|
+
return options.bot;
|
|
79
|
+
const envLocal = parseEnvLocal();
|
|
80
|
+
const botId = envLocal["CALABASAS_BOT_ID"];
|
|
81
|
+
if (botId)
|
|
82
|
+
return botId;
|
|
83
|
+
const isPlatformKey = apiKey.startsWith("cpk_");
|
|
84
|
+
const endpoint = isPlatformKey ? "/api/sdk/bots" : "/api/cli/bots";
|
|
85
|
+
const response = await fetch(`${apiUrl}${endpoint}`, {
|
|
86
|
+
method: "GET",
|
|
87
|
+
headers: {
|
|
88
|
+
"Content-Type": "application/json",
|
|
89
|
+
Authorization: `Bearer ${apiKey}`
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
console.error("Error fetching bots: " + await response.text());
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
const { bots } = await response.json();
|
|
97
|
+
if (!bots || bots.length === 0) {
|
|
98
|
+
console.error("No bots found. Add a bot first with `calabasas bot add`.");
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
if (bots.length === 1) {
|
|
102
|
+
return bots[0]._id;
|
|
103
|
+
}
|
|
104
|
+
const p = await import("@clack/prompts");
|
|
105
|
+
const selected = await p.select({
|
|
106
|
+
message: "Select a bot",
|
|
107
|
+
options: bots.map((bot) => ({
|
|
108
|
+
value: bot._id,
|
|
109
|
+
label: bot.name
|
|
110
|
+
}))
|
|
111
|
+
});
|
|
112
|
+
if (p.isCancel(selected)) {
|
|
113
|
+
p.cancel("Cancelled.");
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
return selected;
|
|
117
|
+
}
|
|
118
|
+
function resolvePlatformApiKey(options) {
|
|
119
|
+
if (options.platformKey) {
|
|
120
|
+
return { key: options.platformKey, source: "flag", isPlatformKey: true };
|
|
121
|
+
}
|
|
122
|
+
const envLocal = parseEnvLocal();
|
|
123
|
+
const platformKey = envLocal["CALABASAS_PLATFORM_API_KEY"];
|
|
124
|
+
if (platformKey) {
|
|
125
|
+
return { key: platformKey, source: "env", isPlatformKey: true };
|
|
126
|
+
}
|
|
127
|
+
const config = getConfig();
|
|
128
|
+
if (config.apiKey) {
|
|
129
|
+
return { key: config.apiKey, source: "user", isPlatformKey: false };
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
async function platformApiRequest(method, path2, platformApiKey, body, extraHeaders) {
|
|
134
|
+
const url = `${getApiUrl()}${path2}`;
|
|
135
|
+
const response = await fetch(url, {
|
|
136
|
+
method,
|
|
137
|
+
headers: {
|
|
138
|
+
"Content-Type": "application/json",
|
|
139
|
+
Authorization: `Bearer ${platformApiKey}`,
|
|
140
|
+
...extraHeaders
|
|
141
|
+
},
|
|
142
|
+
body: body ? JSON.stringify(body) : undefined
|
|
143
|
+
});
|
|
144
|
+
const data = await response.json();
|
|
145
|
+
return { ok: response.ok, data, status: response.status };
|
|
146
|
+
}
|
|
147
|
+
function appendToEnvLocal(entries) {
|
|
148
|
+
const envPath = path.join(process.cwd(), ".env.local");
|
|
149
|
+
let lines = [];
|
|
150
|
+
if (fs.existsSync(envPath)) {
|
|
151
|
+
lines = fs.readFileSync(envPath, "utf-8").split(`
|
|
152
|
+
`);
|
|
153
|
+
}
|
|
154
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
155
|
+
const lineIndex = lines.findIndex((l) => {
|
|
156
|
+
const trimmed = l.trim();
|
|
157
|
+
return trimmed.startsWith(`${key}=`) || trimmed.startsWith(`${key} =`);
|
|
158
|
+
});
|
|
159
|
+
if (lineIndex !== -1) {
|
|
160
|
+
lines[lineIndex] = `${key}=${value}`;
|
|
161
|
+
} else {
|
|
162
|
+
if (!lines.some((l) => l.trim() === "# Calabasas")) {
|
|
163
|
+
if (lines.length > 0 && lines[lines.length - 1].trim() !== "") {
|
|
164
|
+
lines.push("");
|
|
165
|
+
}
|
|
166
|
+
lines.push("# Calabasas");
|
|
167
|
+
}
|
|
168
|
+
lines.push(`${key}=${value}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
fs.writeFileSync(envPath, lines.join(`
|
|
172
|
+
`));
|
|
173
|
+
}
|
|
174
|
+
async function showPlatformContext(apiKey) {
|
|
175
|
+
try {
|
|
176
|
+
const isPlatformKey = apiKey.startsWith("cpk_");
|
|
177
|
+
const endpoint = isPlatformKey ? "/api/sdk/platform" : "/api/cli/platform";
|
|
178
|
+
const url = `${getApiUrl()}${endpoint}`;
|
|
179
|
+
const response = await fetch(url, {
|
|
180
|
+
method: "GET",
|
|
181
|
+
headers: {
|
|
182
|
+
"Content-Type": "application/json",
|
|
183
|
+
Authorization: `Bearer ${apiKey}`
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
if (!response.ok)
|
|
187
|
+
return;
|
|
188
|
+
const data = await response.json();
|
|
189
|
+
if (data.name) {
|
|
190
|
+
const pc = await import("picocolors");
|
|
191
|
+
console.log(`${pc.default.magenta("◆")} Platform: ${pc.default.bold(data.name)}`);
|
|
192
|
+
}
|
|
193
|
+
} catch {}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export { getConfig, saveConfig, clearConfig, isAuthenticated, getApiUrl, getWebUrl, getConvexUrl, resolveBot, resolvePlatformApiKey, platformApiRequest, appendToEnvLocal, showPlatformContext };
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
resolvePlatformApiKey,
|
|
13
13
|
saveConfig,
|
|
14
14
|
showPlatformContext
|
|
15
|
-
} from "./index-
|
|
15
|
+
} from "./index-rb2tds4a.js";
|
|
16
16
|
import {
|
|
17
17
|
__commonJS,
|
|
18
18
|
__require,
|
|
@@ -2422,19 +2422,31 @@ async function push(options) {
|
|
|
2422
2422
|
p4.log.warn(`Privileged intents: ${privilegedUsed.join(", ")} — make sure these are enabled in the Discord Developer Portal.`);
|
|
2423
2423
|
}
|
|
2424
2424
|
const bitfield = intentsToBitfield(intents);
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2425
|
+
if (resolved.isPlatformKey) {
|
|
2426
|
+
const { ok: intentsOk, data: intentsData } = await platformApiRequest("PATCH", "/api/sdk/bots/config", apiKey, {
|
|
2427
|
+
botId,
|
|
2428
|
+
intents: bitfield
|
|
2429
|
+
});
|
|
2430
|
+
if (!intentsOk) {
|
|
2431
|
+
s.stop("Intents push failed");
|
|
2432
|
+
p4.cancel(`Error: ${JSON.stringify(intentsData)}`);
|
|
2433
|
+
process.exit(1);
|
|
2434
|
+
}
|
|
2435
|
+
} else {
|
|
2436
|
+
const intentsResponse = await fetch(`${apiUrl}/api/cli/bots`, {
|
|
2437
|
+
method: "PATCH",
|
|
2438
|
+
headers: {
|
|
2439
|
+
"Content-Type": "application/json",
|
|
2440
|
+
Authorization: `Bearer ${apiKey}`
|
|
2441
|
+
},
|
|
2442
|
+
body: JSON.stringify({ botId, intents: bitfield })
|
|
2443
|
+
});
|
|
2444
|
+
if (!intentsResponse.ok) {
|
|
2445
|
+
const error = await intentsResponse.text();
|
|
2446
|
+
s.stop("Intents push failed");
|
|
2447
|
+
p4.cancel(`Error: ${error}`);
|
|
2448
|
+
process.exit(1);
|
|
2449
|
+
}
|
|
2438
2450
|
}
|
|
2439
2451
|
}
|
|
2440
2452
|
s.stop("Config pushed!");
|
|
@@ -6997,7 +7009,7 @@ async function botEdit(botId, options) {
|
|
|
6997
7009
|
}
|
|
6998
7010
|
const s = p10.spinner();
|
|
6999
7011
|
s.start("Updating bot...");
|
|
7000
|
-
const { ok, data, status } = await apiRequest("PATCH", "/api/cli/bots", updates);
|
|
7012
|
+
const { ok, data, status } = auth.isPlatformKey ? await platformApiRequest("PATCH", "/api/cli/bots", auth.key, updates) : await apiRequest("PATCH", "/api/cli/bots", updates);
|
|
7001
7013
|
if (!ok) {
|
|
7002
7014
|
s.stop("Failed to update bot");
|
|
7003
7015
|
p10.cancel(`${data.error || `HTTP ${status}`}`);
|
|
@@ -7103,6 +7115,62 @@ Add this as CALABASAS_SECRET in your Convex environment.`, "Platform Secret");
|
|
|
7103
7115
|
}
|
|
7104
7116
|
p11.outro("Platform created successfully!");
|
|
7105
7117
|
}
|
|
7118
|
+
async function platformConnect() {
|
|
7119
|
+
if (!isAuthenticated()) {
|
|
7120
|
+
console.log("Not logged in. Run `calabasas login` first.");
|
|
7121
|
+
return;
|
|
7122
|
+
}
|
|
7123
|
+
p11.intro("calabasas platform connect");
|
|
7124
|
+
const s = p11.spinner();
|
|
7125
|
+
s.start("Fetching platforms...");
|
|
7126
|
+
const { ok, data, status } = await apiRequest2("GET", "/api/cli/platforms");
|
|
7127
|
+
if (!ok) {
|
|
7128
|
+
s.stop("Failed to fetch platforms");
|
|
7129
|
+
p11.cancel(`${data.error || `HTTP ${status}`}`);
|
|
7130
|
+
return;
|
|
7131
|
+
}
|
|
7132
|
+
const { platforms } = data;
|
|
7133
|
+
s.stop("Fetched platforms");
|
|
7134
|
+
if (platforms.length === 0) {
|
|
7135
|
+
p11.cancel("No platforms found. Run `calabasas platform create` to create one.");
|
|
7136
|
+
return;
|
|
7137
|
+
}
|
|
7138
|
+
let selectedPlatform;
|
|
7139
|
+
if (platforms.length === 1) {
|
|
7140
|
+
selectedPlatform = platforms[0];
|
|
7141
|
+
p11.log.info(`Using platform: ${pc2.bold(selectedPlatform.name)}`);
|
|
7142
|
+
} else {
|
|
7143
|
+
const choice = await p11.select({
|
|
7144
|
+
message: "Select a platform to connect to",
|
|
7145
|
+
options: platforms.map((platform) => ({
|
|
7146
|
+
value: platform._id,
|
|
7147
|
+
label: platform.name,
|
|
7148
|
+
hint: platform.convexProject ?? undefined
|
|
7149
|
+
}))
|
|
7150
|
+
});
|
|
7151
|
+
if (p11.isCancel(choice)) {
|
|
7152
|
+
p11.cancel("Cancelled.");
|
|
7153
|
+
return;
|
|
7154
|
+
}
|
|
7155
|
+
selectedPlatform = platforms.find((pl) => pl._id === choice);
|
|
7156
|
+
}
|
|
7157
|
+
const keySpinner = p11.spinner();
|
|
7158
|
+
keySpinner.start("Generating API key...");
|
|
7159
|
+
const { ok: rotateOk, data: rotateData, status: rotateStatus } = await apiRequest2("PATCH", "/api/cli/platform", { platformId: selectedPlatform._id, rotateApiKey: true });
|
|
7160
|
+
if (!rotateOk) {
|
|
7161
|
+
keySpinner.stop("Failed to generate API key");
|
|
7162
|
+
p11.cancel(`${rotateData.error || `HTTP ${rotateStatus}`}`);
|
|
7163
|
+
return;
|
|
7164
|
+
}
|
|
7165
|
+
keySpinner.stop("API key generated");
|
|
7166
|
+
const { platformApiKey } = rotateData;
|
|
7167
|
+
if (selectedPlatform.hasApiKey) {
|
|
7168
|
+
p11.log.warn("This replaces the previous API key for this platform.");
|
|
7169
|
+
}
|
|
7170
|
+
appendToEnvLocal({ CALABASAS_PLATFORM_API_KEY: platformApiKey });
|
|
7171
|
+
p11.note(`CALABASAS_PLATFORM_API_KEY=${platformApiKey}`, "Saved to .env.local");
|
|
7172
|
+
p11.outro(`Connected to ${pc2.bold(selectedPlatform.name)}!`);
|
|
7173
|
+
}
|
|
7106
7174
|
async function platformList() {
|
|
7107
7175
|
if (!isAuthenticated()) {
|
|
7108
7176
|
console.log("Not logged in. Run `calabasas login` first.");
|
|
@@ -7626,11 +7694,11 @@ Run ${pc3.cyan("`calabasas init`")} first.`);
|
|
|
7626
7694
|
|
|
7627
7695
|
// src/index.ts
|
|
7628
7696
|
var dashboard = async () => {
|
|
7629
|
-
const mod = await import("./dashboard-
|
|
7697
|
+
const mod = await import("./dashboard-hebbbc6d.js");
|
|
7630
7698
|
return mod.dashboard();
|
|
7631
7699
|
};
|
|
7632
7700
|
var logs = async (...args) => {
|
|
7633
|
-
const mod = await import("./logs-
|
|
7701
|
+
const mod = await import("./logs-v149b3tb.js");
|
|
7634
7702
|
return mod.logs(args[0]);
|
|
7635
7703
|
};
|
|
7636
7704
|
var program2 = new Command;
|
|
@@ -7653,6 +7721,7 @@ bot.command("remove <botId>").alias("rm").description("Remove a Discord bot").op
|
|
|
7653
7721
|
bot.command("edit <botId>").description("Edit a Discord bot").option("-n, --name <name>", "New bot name").option("-t, --token <token>", "New bot token").option("-i, --intents <intents>", "New intents value").action(botEdit);
|
|
7654
7722
|
var platformCmd = program2.command("platform").description("Manage your Calabasas platform");
|
|
7655
7723
|
platformCmd.command("create").description("Create a new platform with Convex project configuration").option("-n, --name <name>", "Platform name").option("-p, --project <project>", "Convex project name (e.g. diligent-swordfish-752)").action(platformCreate);
|
|
7724
|
+
platformCmd.command("connect").description("Connect this project to an existing platform (saves API key to .env.local)").action(platformConnect);
|
|
7656
7725
|
platformCmd.command("list").alias("ls").description("List all your platforms").action(platformList);
|
|
7657
7726
|
platformCmd.command("info").description("Show platform info (secret, URL, API key status)").action(platformInfo);
|
|
7658
7727
|
platformCmd.command("set-url").description("Set Convex URL for your platform").action(platformSetUrl);
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LogViewer
|
|
3
|
+
} from "./index-b0cp0nch.js";
|
|
4
|
+
import {
|
|
5
|
+
getConvexUrl,
|
|
6
|
+
platformApiRequest,
|
|
7
|
+
resolvePlatformApiKey
|
|
8
|
+
} from "./index-rb2tds4a.js";
|
|
9
|
+
import {
|
|
10
|
+
formatLatency
|
|
11
|
+
} from "./index-8gymgyxd.js";
|
|
12
|
+
import"./index-tre7d3f1.js";
|
|
13
|
+
import {
|
|
14
|
+
__toESM
|
|
15
|
+
} from "./index-sdksp5px.js";
|
|
16
|
+
import {
|
|
17
|
+
render_default,
|
|
18
|
+
use_app_default,
|
|
19
|
+
use_input_default
|
|
20
|
+
} from "./index-4rn9k8et.js";
|
|
21
|
+
import {
|
|
22
|
+
ConvexProvider,
|
|
23
|
+
createConvexClient,
|
|
24
|
+
require_jsx_dev_runtime
|
|
25
|
+
} from "./convex-1z1jsz1n.js";
|
|
26
|
+
import"./index-vmy4gfe1.js";
|
|
27
|
+
|
|
28
|
+
// src/commands/logs.tsx
|
|
29
|
+
import pc from "picocolors";
|
|
30
|
+
var jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
|
|
31
|
+
function LogsApp({ apiKey, botId, limit, successFilter }) {
|
|
32
|
+
const { exit } = use_app_default();
|
|
33
|
+
use_input_default((input) => {
|
|
34
|
+
if (input === "q") {
|
|
35
|
+
exit();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(LogViewer, {
|
|
39
|
+
apiKey,
|
|
40
|
+
botId,
|
|
41
|
+
limit,
|
|
42
|
+
successFilter
|
|
43
|
+
}, undefined, false, undefined, this);
|
|
44
|
+
}
|
|
45
|
+
function formatTimestamp(ts) {
|
|
46
|
+
const d = new Date(ts);
|
|
47
|
+
return d.toLocaleTimeString("en-US", { hour12: false });
|
|
48
|
+
}
|
|
49
|
+
async function logs(options) {
|
|
50
|
+
if (options.errors && options.success) {
|
|
51
|
+
console.error("Error: Cannot use both --errors and --success flags.");
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
const resolved = resolvePlatformApiKey({});
|
|
55
|
+
if (!resolved) {
|
|
56
|
+
console.log("Not logged in. Run `calabasas login` first.");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const apiKey = resolved.key;
|
|
60
|
+
const limit = options.limit ? parseInt(options.limit, 10) : 50;
|
|
61
|
+
const successFilter = options.errors ? false : options.success ? true : undefined;
|
|
62
|
+
const botId = options.bot;
|
|
63
|
+
if (options.once || !process.stdin.isTTY) {
|
|
64
|
+
const params = new URLSearchParams;
|
|
65
|
+
if (botId)
|
|
66
|
+
params.set("botId", botId);
|
|
67
|
+
params.set("limit", String(limit));
|
|
68
|
+
if (successFilter !== undefined)
|
|
69
|
+
params.set("success", String(successFilter));
|
|
70
|
+
const queryString = params.toString();
|
|
71
|
+
const path = `/api/sdk/logs${queryString ? `?${queryString}` : ""}`;
|
|
72
|
+
const { ok, data, status } = await platformApiRequest("GET", path, apiKey);
|
|
73
|
+
if (!ok) {
|
|
74
|
+
console.error(`Failed to fetch logs: ${data.error || `HTTP ${status}`}`);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
const { logs: entries } = data;
|
|
78
|
+
if (entries.length === 0) {
|
|
79
|
+
console.log("No events found.");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const uniqueBots = new Set(entries.map((l) => l.botName));
|
|
83
|
+
const multiBot = uniqueBots.size > 1 || !botId;
|
|
84
|
+
for (const log of entries) {
|
|
85
|
+
const time = pc.dim(formatTimestamp(log.timestamp));
|
|
86
|
+
const status2 = log.success ? pc.green("✓") : pc.red("✗");
|
|
87
|
+
const event = pc.bold(log.eventType);
|
|
88
|
+
const latency = pc.dim(formatLatency(log.latencyMs));
|
|
89
|
+
const botLabel = multiBot ? pc.cyan(`[${log.botName}]`) + " " : "";
|
|
90
|
+
const error = log.error ? ` ${pc.red(log.error)}` : "";
|
|
91
|
+
console.log(`${time} ${status2} ${botLabel}${event} ${latency}${error}`);
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const convexUrl = getConvexUrl();
|
|
96
|
+
const client = createConvexClient(convexUrl);
|
|
97
|
+
const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime.jsxDEV(ConvexProvider, {
|
|
98
|
+
client,
|
|
99
|
+
children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(LogsApp, {
|
|
100
|
+
apiKey,
|
|
101
|
+
botId,
|
|
102
|
+
limit,
|
|
103
|
+
successFilter
|
|
104
|
+
}, undefined, false, undefined, this)
|
|
105
|
+
}, undefined, false, undefined, this));
|
|
106
|
+
await waitUntilExit();
|
|
107
|
+
await client.close();
|
|
108
|
+
}
|
|
109
|
+
export {
|
|
110
|
+
logs
|
|
111
|
+
};
|