@openbat/cli 0.2.1 → 0.2.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.
@@ -32,7 +32,7 @@ __export(api_client_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(api_client_exports);
34
34
  var import_node_url = require("url");
35
- var CLI_VERSION = "0.1.1";
35
+ var CLI_VERSION = "0.2.2";
36
36
  var KEY_REGEX = /ob_(?:live|read|admin|pat)_[0-9a-f]{32}/g;
37
37
  function redact(s) {
38
38
  return s.replace(KEY_REGEX, (k) => `${k.slice(0, 16)}\u2026<hidden>`);
@@ -82,7 +82,7 @@ var ApiClient = class {
82
82
  const msg = err instanceof Error ? err.message : String(err);
83
83
  throw new Error(`Request to ${redact(url)} failed: ${redact(msg)}`);
84
84
  }
85
- return parseResponse(res, url);
85
+ return parseResponse(res, url, "GET");
86
86
  }
87
87
  /** Issue a POST with a JSON body. */
88
88
  async post(path, body) {
@@ -144,12 +144,12 @@ mutate_fn = async function(method, path, body) {
144
144
  const msg = err instanceof Error ? err.message : String(err);
145
145
  throw new Error(`Request to ${redact(url)} failed: ${redact(msg)}`);
146
146
  }
147
- return parseResponse(res, url);
147
+ return parseResponse(res, url, method);
148
148
  };
149
- async function parseResponse(res, url) {
149
+ async function parseResponse(res, url, method) {
150
150
  if (res.status === 401) {
151
151
  throw new Error(
152
- "Unauthorized. The API key was rejected (invalid, wrong kind for this endpoint, expired, or revoked)."
152
+ "Unauthorized. The API key was rejected (invalid, wrong kind for this endpoint, expired, or revoked). Run `openbat login` to refresh credentials."
153
153
  );
154
154
  }
155
155
  if (res.status === 403) {
@@ -170,7 +170,7 @@ async function parseResponse(res, url) {
170
170
  } catch {
171
171
  }
172
172
  throw new Error(
173
- `GET ${redact(url)} \u2192 ${res.status} ${res.statusText}${errBody?.error ? `: ${redact(errBody.error)}` : ""}`
173
+ `${method} ${redact(url)} \u2192 ${res.status} ${res.statusText}${errBody?.error ? `: ${redact(errBody.error)}` : ""}`
174
174
  );
175
175
  }
176
176
  try {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ApiClient
3
- } from "./chunk-NYKJTHHK.mjs";
3
+ } from "./chunk-MCDJLQI2.mjs";
4
4
  export {
5
5
  ApiClient
6
6
  };
@@ -9,7 +9,7 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
9
9
 
10
10
  // src/api-client.ts
11
11
  import { URL } from "url";
12
- var CLI_VERSION = "0.1.1";
12
+ var CLI_VERSION = "0.2.2";
13
13
  var KEY_REGEX = /ob_(?:live|read|admin|pat)_[0-9a-f]{32}/g;
14
14
  function redact(s) {
15
15
  return s.replace(KEY_REGEX, (k) => `${k.slice(0, 16)}\u2026<hidden>`);
@@ -59,7 +59,7 @@ var ApiClient = class {
59
59
  const msg = err instanceof Error ? err.message : String(err);
60
60
  throw new Error(`Request to ${redact(url)} failed: ${redact(msg)}`);
61
61
  }
62
- return parseResponse(res, url);
62
+ return parseResponse(res, url, "GET");
63
63
  }
64
64
  /** Issue a POST with a JSON body. */
65
65
  async post(path, body) {
@@ -121,12 +121,12 @@ mutate_fn = async function(method, path, body) {
121
121
  const msg = err instanceof Error ? err.message : String(err);
122
122
  throw new Error(`Request to ${redact(url)} failed: ${redact(msg)}`);
123
123
  }
124
- return parseResponse(res, url);
124
+ return parseResponse(res, url, method);
125
125
  };
126
- async function parseResponse(res, url) {
126
+ async function parseResponse(res, url, method) {
127
127
  if (res.status === 401) {
128
128
  throw new Error(
129
- "Unauthorized. The API key was rejected (invalid, wrong kind for this endpoint, expired, or revoked)."
129
+ "Unauthorized. The API key was rejected (invalid, wrong kind for this endpoint, expired, or revoked). Run `openbat login` to refresh credentials."
130
130
  );
131
131
  }
132
132
  if (res.status === 403) {
@@ -147,7 +147,7 @@ async function parseResponse(res, url) {
147
147
  } catch {
148
148
  }
149
149
  throw new Error(
150
- `GET ${redact(url)} \u2192 ${res.status} ${res.statusText}${errBody?.error ? `: ${redact(errBody.error)}` : ""}`
150
+ `${method} ${redact(url)} \u2192 ${res.status} ${res.statusText}${errBody?.error ? `: ${redact(errBody.error)}` : ""}`
151
151
  );
152
152
  }
153
153
  try {
package/dist/index.js CHANGED
@@ -163,7 +163,7 @@ function configPath() {
163
163
 
164
164
  // src/api-client.ts
165
165
  var import_node_url = require("url");
166
- var CLI_VERSION = "0.1.1";
166
+ var CLI_VERSION = "0.2.2";
167
167
  var KEY_REGEX = /ob_(?:live|read|admin|pat)_[0-9a-f]{32}/g;
168
168
  function redact(s) {
169
169
  return s.replace(KEY_REGEX, (k) => `${k.slice(0, 16)}\u2026<hidden>`);
@@ -213,7 +213,7 @@ var ApiClient = class {
213
213
  const msg = err instanceof Error ? err.message : String(err);
214
214
  throw new Error(`Request to ${redact(url)} failed: ${redact(msg)}`);
215
215
  }
216
- return parseResponse(res, url);
216
+ return parseResponse(res, url, "GET");
217
217
  }
218
218
  /** Issue a POST with a JSON body. */
219
219
  async post(path, body) {
@@ -275,12 +275,12 @@ mutate_fn = async function(method, path, body) {
275
275
  const msg = err instanceof Error ? err.message : String(err);
276
276
  throw new Error(`Request to ${redact(url)} failed: ${redact(msg)}`);
277
277
  }
278
- return parseResponse(res, url);
278
+ return parseResponse(res, url, method);
279
279
  };
280
- async function parseResponse(res, url) {
280
+ async function parseResponse(res, url, method) {
281
281
  if (res.status === 401) {
282
282
  throw new Error(
283
- "Unauthorized. The API key was rejected (invalid, wrong kind for this endpoint, expired, or revoked)."
283
+ "Unauthorized. The API key was rejected (invalid, wrong kind for this endpoint, expired, or revoked). Run `openbat login` to refresh credentials."
284
284
  );
285
285
  }
286
286
  if (res.status === 403) {
@@ -301,7 +301,7 @@ async function parseResponse(res, url) {
301
301
  } catch {
302
302
  }
303
303
  throw new Error(
304
- `GET ${redact(url)} \u2192 ${res.status} ${res.statusText}${errBody?.error ? `: ${redact(errBody.error)}` : ""}`
304
+ `${method} ${redact(url)} \u2192 ${res.status} ${res.statusText}${errBody?.error ? `: ${redact(errBody.error)}` : ""}`
305
305
  );
306
306
  }
307
307
  try {
@@ -388,7 +388,9 @@ function configCommand() {
388
388
  const cmd = new import_commander.Command("config").description(
389
389
  "Manage the CLI's ~/.openbatrc settings"
390
390
  );
391
- cmd.command("set-key").description("Store your Read API key in ~/.openbatrc").option("--from-stdin", "Read the key from stdin (default and recommended)", true).option(
391
+ cmd.command("set-key").description(
392
+ "Store your API key in ~/.openbatrc. Reads from stdin by default; use --value to pass inline (discouraged \u2014 leaks into shell history)."
393
+ ).option(
392
394
  "--value <key>",
393
395
  "Pass the key inline. Discouraged \u2014 leaks into shell history."
394
396
  ).action(async (opts) => {
@@ -404,13 +406,13 @@ function configCommand() {
404
406
  key = Buffer.concat(chunks).toString("utf8").trim();
405
407
  if (!key) {
406
408
  fatal(
407
- "No key on stdin. Try: echo 'ob_read_...' | openbat config set-key --from-stdin"
409
+ "No key on stdin. Try: echo 'ob_read_...' | openbat config set-key"
408
410
  );
409
411
  }
410
412
  }
411
413
  await setApiKey(key);
412
414
  process.stdout.write(
413
- `Saved Read key to ${configPath()} (mode 0600).
415
+ `Saved key to ${configPath()} (mode 0600).
414
416
  `
415
417
  );
416
418
  } catch (err) {
@@ -529,7 +531,9 @@ async function resolveChatbotId(api, chatbotFlag) {
529
531
  );
530
532
  const chatbots = list.chatbots ?? [];
531
533
  if (chatbots.length === 0) {
532
- fatal("This API key authorizes no chatbots.");
534
+ fatal(
535
+ "No chatbots yet. Run `openbat chatbots create --name <name>`, or ask an org owner to invite you."
536
+ );
533
537
  }
534
538
  if (chatbotFlag) {
535
539
  if (UUID_RE2.test(chatbotFlag)) {
@@ -714,18 +718,6 @@ function exportCommand() {
714
718
 
715
719
  // src/commands/auth.ts
716
720
  var import_commander3 = require("commander");
717
- async function client2(globals) {
718
- const cfg = await resolveConfig({
719
- apiKeyFlag: globals.apiKey ?? null,
720
- baseUrlFlag: globals.baseUrl ?? null
721
- });
722
- if (!cfg.apiKey) {
723
- fatal(
724
- "No API key configured. Run `openbat config set-key`, pass --api-key, or set OPENBAT_API_KEY."
725
- );
726
- }
727
- return new ApiClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl });
728
- }
729
721
  function detectKind(apiKey) {
730
722
  if (apiKey.startsWith("ob_read_")) return "read";
731
723
  if (apiKey.startsWith("ob_admin_")) return "admin";
@@ -777,17 +769,6 @@ function authCommand() {
777
769
  fatal(err instanceof Error ? err.message : String(err));
778
770
  }
779
771
  });
780
- cmd.command("audit-log").description("Show recent audit-log entries for the current user").option("--days <n>", "Look-back window in days", "7").action(async function() {
781
- try {
782
- process.stderr.write(
783
- "audit-log: endpoint not yet exposed via HTTP \u2014 query `select * from api_audit_log` in Supabase Studio for now.\n"
784
- );
785
- const _c = await client2(this.optsWithGlobals());
786
- void _c;
787
- } catch (err) {
788
- fatal(err instanceof Error ? err.message : String(err));
789
- }
790
- });
791
772
  return cmd;
792
773
  }
793
774
 
@@ -1074,7 +1055,15 @@ async function pickDefaultChatbot(token, baseUrl) {
1074
1055
  return;
1075
1056
  }
1076
1057
  if (chatbots.length === 0) {
1077
- process.stdout.write("\nNo chatbots reachable yet. Create one from the dashboard.\n");
1058
+ process.stdout.write(
1059
+ [
1060
+ "",
1061
+ "No chatbots yet. To get one:",
1062
+ " \u2022 Create one: openbat chatbots create --name <name>",
1063
+ " \u2022 Or ask an org owner to invite you, then run `openbat login` again",
1064
+ ""
1065
+ ].join("\n")
1066
+ );
1078
1067
  return;
1079
1068
  }
1080
1069
  if (chatbots.length === 1) {
@@ -1142,7 +1131,7 @@ function logoutCommand() {
1142
1131
  }
1143
1132
  } else {
1144
1133
  process.stderr.write(
1145
- "Note: read/admin keys can't self-revoke. Visit the dashboard to revoke; this command will just clear the local config.\n"
1134
+ "Note: read/admin keys can't self-revoke server-side. Revoke them in the dashboard if needed; clearing local config only.\n"
1146
1135
  );
1147
1136
  }
1148
1137
  await clearApiKey();
@@ -1155,7 +1144,7 @@ function logoutCommand() {
1155
1144
 
1156
1145
  // src/commands/org.ts
1157
1146
  var import_commander6 = require("commander");
1158
- async function client3(globals) {
1147
+ async function client2(globals) {
1159
1148
  const cfg = await resolveConfig({
1160
1149
  apiKeyFlag: globals.apiKey ?? null,
1161
1150
  baseUrlFlag: globals.baseUrl ?? null
@@ -1175,7 +1164,7 @@ function orgCommand() {
1175
1164
  cmd.command("list").description("List orgs the current PAT's user belongs to").action(async function() {
1176
1165
  try {
1177
1166
  const globals = this.optsWithGlobals();
1178
- const c = await client3(globals);
1167
+ const c = await client2(globals);
1179
1168
  const result = await c.get("/api/v1/orgs");
1180
1169
  emit(result.orgs, { json: !!globals.json });
1181
1170
  } catch (err) {
@@ -1185,7 +1174,7 @@ function orgCommand() {
1185
1174
  cmd.command("show").description("Show the active org (id, name, members)").action(async function() {
1186
1175
  try {
1187
1176
  const globals = this.optsWithGlobals();
1188
- const c = await client3(globals);
1177
+ const c = await client2(globals);
1189
1178
  const result = await c.get(
1190
1179
  "/api/v1/orgs/active"
1191
1180
  );
@@ -1200,7 +1189,7 @@ function orgCommand() {
1200
1189
  cmd.command("rename").description("Rename an org (owner only)").requiredOption("--id <orgId>", "Org id").requiredOption("--name <name>", "New name").action(async function(opts) {
1201
1190
  try {
1202
1191
  const globals = this.optsWithGlobals();
1203
- const c = await client3(globals);
1192
+ const c = await client2(globals);
1204
1193
  await c.patch(`/api/v1/orgs/${opts.id}`, { name: opts.name });
1205
1194
  emit({ ok: true, renamed: opts.id }, { json: !!globals.json });
1206
1195
  } catch (err) {
@@ -1211,7 +1200,7 @@ function orgCommand() {
1211
1200
  members.command("list").requiredOption("--id <orgId>", "Org id").action(async function(opts) {
1212
1201
  try {
1213
1202
  const globals = this.optsWithGlobals();
1214
- const c = await client3(globals);
1203
+ const c = await client2(globals);
1215
1204
  const result = await c.get(
1216
1205
  `/api/v1/orgs/${opts.id}/members`
1217
1206
  );
@@ -1223,7 +1212,7 @@ function orgCommand() {
1223
1212
  members.command("invite").requiredOption("--id <orgId>", "Org id").requiredOption("--email <email>", "Invitee email").option("--role <role>", "member | admin", "member").action(async function(opts) {
1224
1213
  try {
1225
1214
  const globals = this.optsWithGlobals();
1226
- const c = await client3(globals);
1215
+ const c = await client2(globals);
1227
1216
  const result = await c.post(
1228
1217
  `/api/v1/orgs/${opts.id}/members`,
1229
1218
  { email: opts.email, role: opts.role }
@@ -1241,7 +1230,7 @@ function orgCommand() {
1241
1230
  members.command("set-role").requiredOption("--id <orgId>", "Org id").requiredOption("--member <memberId>", "Member id").requiredOption("--role <role>", "admin | member").action(async function(opts) {
1242
1231
  try {
1243
1232
  const globals = this.optsWithGlobals();
1244
- const c = await client3(globals);
1233
+ const c = await client2(globals);
1245
1234
  await c.patch(`/api/v1/orgs/${opts.id}/members/${opts.member}`, {
1246
1235
  role: opts.role
1247
1236
  });
@@ -1253,7 +1242,7 @@ function orgCommand() {
1253
1242
  members.command("remove").requiredOption("--id <orgId>", "Org id").requiredOption("--member <memberId>", "Member id").action(async function(opts) {
1254
1243
  try {
1255
1244
  const globals = this.optsWithGlobals();
1256
- const c = await client3(globals);
1245
+ const c = await client2(globals);
1257
1246
  await c.delete(`/api/v1/orgs/${opts.id}/members/${opts.member}`);
1258
1247
  emit({ ok: true }, { json: !!globals.json });
1259
1248
  } catch (err) {
@@ -1264,7 +1253,7 @@ function orgCommand() {
1264
1253
  invitations.command("list").requiredOption("--id <orgId>", "Org id").action(async function(opts) {
1265
1254
  try {
1266
1255
  const globals = this.optsWithGlobals();
1267
- const c = await client3(globals);
1256
+ const c = await client2(globals);
1268
1257
  const result = await c.get(
1269
1258
  `/api/v1/orgs/${opts.id}/invitations`
1270
1259
  );
@@ -1278,7 +1267,7 @@ function orgCommand() {
1278
1267
 
1279
1268
  // src/commands/write.ts
1280
1269
  var import_commander7 = require("commander");
1281
- async function client4(globals) {
1270
+ async function client3(globals) {
1282
1271
  const cfg = await resolveConfig({
1283
1272
  apiKeyFlag: globals.apiKey ?? null,
1284
1273
  baseUrlFlag: globals.baseUrl ?? null
@@ -1307,7 +1296,7 @@ function chatbotsCommand() {
1307
1296
  cmd.command("list").description("List every chatbot the credential can reach").action(async function() {
1308
1297
  try {
1309
1298
  const globals = this.optsWithGlobals();
1310
- const c = await client4(globals);
1299
+ const c = await client3(globals);
1311
1300
  const result = await c.get(
1312
1301
  "/api/v1/chatbots"
1313
1302
  );
@@ -1319,7 +1308,7 @@ function chatbotsCommand() {
1319
1308
  cmd.command("create").description("Create a new chatbot (PAT scope required)").requiredOption("--name <name>", "Chatbot name").option("--website <url>").option("--docs-url <url>").option("--mcp-url <url>").option("--language <code>", "Primary language code (default: en)", "en").action(async function(opts) {
1320
1309
  try {
1321
1310
  const globals = this.optsWithGlobals();
1322
- const c = await client4(globals);
1311
+ const c = await client3(globals);
1323
1312
  const result = await c.post("/api/v1/chatbots", {
1324
1313
  name: opts.name,
1325
1314
  websiteUrl: opts.website,
@@ -1339,7 +1328,7 @@ function chatbotsCommand() {
1339
1328
  cmd.command("delete <chatbotId>").description("Delete a chatbot (irreversible \u2014 cascade-deletes everything)").action(async function(chatbotId) {
1340
1329
  try {
1341
1330
  const globals = this.optsWithGlobals();
1342
- const c = await client4(globals);
1331
+ const c = await client3(globals);
1343
1332
  await c.delete(`/api/v1/chatbots/${chatbotId}`);
1344
1333
  emit({ ok: true, deleted: chatbotId }, { json: !!globals.json });
1345
1334
  } catch (err) {
@@ -1353,7 +1342,7 @@ function webhooksCommand() {
1353
1342
  cmd.command("list").requiredOption("--chatbot <id>", "Chatbot id").action(async function(opts) {
1354
1343
  try {
1355
1344
  const globals = this.optsWithGlobals();
1356
- const c = await client4(globals);
1345
+ const c = await client3(globals);
1357
1346
  const result = await c.get(
1358
1347
  `/api/v1/chatbots/${opts.chatbot}/webhooks`
1359
1348
  );
@@ -1365,7 +1354,7 @@ function webhooksCommand() {
1365
1354
  cmd.command("create").requiredOption("--chatbot <id>", "Chatbot id").requiredOption("--name <name>").requiredOption("--url <url>").option("--type <type>", "discord | slack | custom", "custom").action(async function(opts) {
1366
1355
  try {
1367
1356
  const globals = this.optsWithGlobals();
1368
- const c = await client4(globals);
1357
+ const c = await client3(globals);
1369
1358
  const result = await c.post(`/api/v1/chatbots/${opts.chatbot}/webhooks`, {
1370
1359
  name: opts.name,
1371
1360
  url: opts.url,
@@ -1380,7 +1369,7 @@ function webhooksCommand() {
1380
1369
  cmd.command("delete").requiredOption("--chatbot <id>", "Chatbot id").requiredOption("--webhook <id>", "Webhook id").action(async function(opts) {
1381
1370
  try {
1382
1371
  const globals = this.optsWithGlobals();
1383
- const c = await client4(globals);
1372
+ const c = await client3(globals);
1384
1373
  await c.delete(`/api/v1/chatbots/${opts.chatbot}/webhooks/${opts.webhook}`);
1385
1374
  emit({ ok: true, deleted: opts.webhook }, { json: !!globals.json });
1386
1375
  } catch (err) {
@@ -1397,7 +1386,7 @@ function settingsCommand() {
1397
1386
  keys.command("rotate-ingest").requiredOption("--chatbot <id>", "Chatbot id").action(async function(opts) {
1398
1387
  try {
1399
1388
  const globals = this.optsWithGlobals();
1400
- const c = await client4(globals);
1389
+ const c = await client3(globals);
1401
1390
  const result = await c.post(
1402
1391
  `/api/v1/chatbots/${opts.chatbot}/keys/ingest/rotate`,
1403
1392
  {}
@@ -1411,7 +1400,7 @@ function settingsCommand() {
1411
1400
  keys.command("generate-read").requiredOption("--chatbot <id>", "Chatbot id").action(async function(opts) {
1412
1401
  try {
1413
1402
  const globals = this.optsWithGlobals();
1414
- const c = await client4(globals);
1403
+ const c = await client3(globals);
1415
1404
  const result = await c.post(
1416
1405
  `/api/v1/chatbots/${opts.chatbot}/keys/read`,
1417
1406
  {}
@@ -1425,7 +1414,7 @@ function settingsCommand() {
1425
1414
  keys.command("generate-admin").requiredOption("--chatbot <id>", "Chatbot id").requiredOption("--name <name>", "Human-friendly name (e.g. 'CI key')").option("--expires-in-days <n>", "Auto-expire after N days").action(async function(opts) {
1426
1415
  try {
1427
1416
  const globals = this.optsWithGlobals();
1428
- const c = await client4(globals);
1417
+ const c = await client3(globals);
1429
1418
  const result = await c.post(`/api/v1/chatbots/${opts.chatbot}/admin-keys`, {
1430
1419
  name: opts.name,
1431
1420
  expiresInDays: opts.expiresInDays ? Number(opts.expiresInDays) : void 0
@@ -1439,7 +1428,7 @@ function settingsCommand() {
1439
1428
  keys.command("list-admin").requiredOption("--chatbot <id>", "Chatbot id").action(async function(opts) {
1440
1429
  try {
1441
1430
  const globals = this.optsWithGlobals();
1442
- const c = await client4(globals);
1431
+ const c = await client3(globals);
1443
1432
  const result = await c.get(
1444
1433
  `/api/v1/chatbots/${opts.chatbot}/admin-keys`
1445
1434
  );
@@ -1451,7 +1440,7 @@ function settingsCommand() {
1451
1440
  keys.command("revoke-admin").requiredOption("--chatbot <id>", "Chatbot id").requiredOption("--key <keyId>", "Admin key id").action(async function(opts) {
1452
1441
  try {
1453
1442
  const globals = this.optsWithGlobals();
1454
- const c = await client4(globals);
1443
+ const c = await client3(globals);
1455
1444
  await c.delete(`/api/v1/chatbots/${opts.chatbot}/admin-keys/${opts.key}`);
1456
1445
  emit({ ok: true, revoked: opts.key }, { json: !!globals.json });
1457
1446
  } catch (err) {
@@ -1468,7 +1457,7 @@ function settingsCommand() {
1468
1457
  fatal("Provide at least one setting to update.");
1469
1458
  }
1470
1459
  const globals = this.optsWithGlobals();
1471
- const c = await client4(globals);
1460
+ const c = await client3(globals);
1472
1461
  await c.patch(`/api/v1/chatbots/${opts.chatbot}/settings`, { settings });
1473
1462
  emit({ ok: true }, { json: !!globals.json });
1474
1463
  } catch (err) {
@@ -1482,7 +1471,7 @@ function workflowsCommand() {
1482
1471
  cmd.command("list").requiredOption("--chatbot <id>", "Chatbot id").action(async function(opts) {
1483
1472
  try {
1484
1473
  const globals = this.optsWithGlobals();
1485
- const c = await client4(globals);
1474
+ const c = await client3(globals);
1486
1475
  const result = await c.get(
1487
1476
  `/api/v1/chatbots/${opts.chatbot}/workflows`
1488
1477
  );
@@ -1500,7 +1489,7 @@ function workflowsCommand() {
1500
1489
  ).requiredOption("--webhook <id>", "Webhook id to fire").option("--message <tpl>", "Message template (supports {{user.id}}, etc.)").action(async function(opts) {
1501
1490
  try {
1502
1491
  const globals = this.optsWithGlobals();
1503
- const c = await client4(globals);
1492
+ const c = await client3(globals);
1504
1493
  const result = await c.post(`/api/v1/chatbots/${opts.chatbot}/workflows`, {
1505
1494
  name: opts.name,
1506
1495
  template: opts.template,
@@ -1520,7 +1509,7 @@ function reportsCommand() {
1520
1509
  cmd.command("list").requiredOption("--chatbot <id>", "Chatbot id").action(async function(opts) {
1521
1510
  try {
1522
1511
  const globals = this.optsWithGlobals();
1523
- const c = await client4(globals);
1512
+ const c = await client3(globals);
1524
1513
  const result = await c.get(
1525
1514
  `/api/v1/chatbots/${opts.chatbot}/reports`
1526
1515
  );
@@ -1532,7 +1521,7 @@ function reportsCommand() {
1532
1521
  cmd.command("create").description("Create a new AI report; returns the org-private dashboard URL").requiredOption("--chatbot <id>", "Chatbot id").option("--name <name>", "Report name", "Untitled Report").action(async function(opts) {
1533
1522
  try {
1534
1523
  const globals = this.optsWithGlobals();
1535
- const c = await client4(globals);
1524
+ const c = await client3(globals);
1536
1525
  const result = await c.post(`/api/v1/chatbots/${opts.chatbot}/reports`, { name: opts.name });
1537
1526
  process.stderr.write(
1538
1527
  `
@@ -1556,7 +1545,7 @@ function analysisCommand() {
1556
1545
  cmd.command("list").requiredOption("--chatbot <id>", "Chatbot id").option("--type <t>", "intent | flag | assistant_outcome | assistant_issue").option("--pending", "Include pending suggestions").action(async function(opts) {
1557
1546
  try {
1558
1547
  const globals = this.optsWithGlobals();
1559
- const c = await client4(globals);
1548
+ const c = await client3(globals);
1560
1549
  const qs = new URLSearchParams();
1561
1550
  if (opts.type) qs.set("type", opts.type);
1562
1551
  if (opts.pending) qs.set("pending", "true");
@@ -1574,7 +1563,7 @@ function analysisCommand() {
1574
1563
  ).requiredOption("--name <slug>", "snake_case slug").requiredOption("--display-name <text>").requiredOption("--description <text>").action(async function(opts) {
1575
1564
  try {
1576
1565
  const globals = this.optsWithGlobals();
1577
- const c = await client4(globals);
1566
+ const c = await client3(globals);
1578
1567
  const result = await c.post(
1579
1568
  `/api/v1/chatbots/${opts.chatbot}/analysis-definitions`,
1580
1569
  {
@@ -1598,7 +1587,7 @@ function usersCommand() {
1598
1587
  cmd.command("list").requiredOption("--chatbot <id>", "Chatbot id").option("--from <iso>").option("--to <iso>").option("--days <n>", "Convenience: last N days").option("--search <q>").option("--limit <n>", "Page size", "20").action(async function(opts) {
1599
1588
  try {
1600
1589
  const globals = this.optsWithGlobals();
1601
- const c = await client4(globals);
1590
+ const c = await client3(globals);
1602
1591
  const qs = new URLSearchParams();
1603
1592
  let from = opts.from;
1604
1593
  if (!from && opts.days) {
@@ -1629,7 +1618,7 @@ function sdkCommand() {
1629
1618
  );
1630
1619
  cmd.command("install-instructions").description("Print markdown the calling agent can follow").option(
1631
1620
  "--framework <name>",
1632
- "next | node | vercel-ai-sdk (default: next)",
1621
+ "next | vercel-ai-sdk (default: next)",
1633
1622
  "next"
1634
1623
  ).option("--chatbot <id>", "Chatbot id (for the example snippet)").action(async function(opts) {
1635
1624
  const chatbotId = opts.chatbot ?? "<chatbotId>";
@@ -1689,24 +1678,36 @@ function sdkCommand() {
1689
1678
  cmd.command("verify").description("Check whether any event has arrived for the chatbot yet").requiredOption("--chatbot <id>", "Chatbot id").option("--timeout <n>", "Seconds to wait (default: 60)", "60").action(async function(opts) {
1690
1679
  try {
1691
1680
  const globals = this.optsWithGlobals();
1692
- const c = await client4(globals);
1693
- const deadline = Date.now() + Number(opts.timeout) * 1e3;
1681
+ const c = await client3(globals);
1682
+ const timeoutSec = Number(opts.timeout);
1683
+ const deadline = Date.now() + timeoutSec * 1e3;
1684
+ const params = new URLSearchParams({
1685
+ chatbotId: opts.chatbot,
1686
+ limit: "1"
1687
+ });
1688
+ process.stderr.write(
1689
+ `Waiting for first event on chatbot ${opts.chatbot} (timeout ${timeoutSec}s)\u2026
1690
+ `
1691
+ );
1692
+ let lastTick = Date.now();
1694
1693
  while (Date.now() < deadline) {
1695
- try {
1696
- const result = await c.get(`/api/v1/conversations?limit=1`);
1697
- if (result.total > 0) {
1698
- process.stderr.write(
1699
- `\u2713 First event detected. ${result.total} conversation(s) ingested.
1694
+ const result = await c.get(`/api/v1/conversations?${params}`);
1695
+ if (result.total > 0) {
1696
+ process.stderr.write(
1697
+ `First event detected. ${result.total} conversation(s) ingested.
1700
1698
  `
1701
- );
1702
- return;
1703
- }
1704
- } catch {
1699
+ );
1700
+ return;
1701
+ }
1702
+ if (Date.now() - lastTick >= 5e3) {
1703
+ process.stderr.write(".");
1704
+ lastTick = Date.now();
1705
1705
  }
1706
1706
  await new Promise((r) => setTimeout(r, 2e3));
1707
1707
  }
1708
1708
  process.stderr.write(
1709
- `Timed out after ${opts.timeout}s \u2014 no events yet. Confirm OPENBAT_API_KEY and that recordMessages is being called.
1709
+ `
1710
+ Timed out after ${timeoutSec}s \u2014 no events yet. Confirm OPENBAT_API_KEY and that recordMessages is being called.
1710
1711
  `
1711
1712
  );
1712
1713
  process.exit(2);
@@ -1721,7 +1722,7 @@ function sdkCommand() {
1721
1722
  var program = new import_commander8.Command();
1722
1723
  program.name("openbat").description(
1723
1724
  "Query OpenBat chatbot data \u2014 conversations, sentiment, analytics, exports."
1724
- ).version("0.2.1").option("--api-key <key>", "Override the stored Read API key (footgun \u2014 leaks into shell history)").option(
1725
+ ).version("0.2.2").option("--api-key <key>", "Override the stored Read API key (footgun \u2014 leaks into shell history)").option(
1725
1726
  "--base-url <url>",
1726
1727
  "Override the OpenBat API base URL (defaults to ~/.openbatrc or https://openbat.dev)"
1727
1728
  ).option(
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ApiClient
4
- } from "./chunk-NYKJTHHK.mjs";
4
+ } from "./chunk-MCDJLQI2.mjs";
5
5
 
6
6
  // src/index.ts
7
7
  import { Command as Command8 } from "commander";
@@ -210,7 +210,9 @@ function configCommand() {
210
210
  const cmd = new Command("config").description(
211
211
  "Manage the CLI's ~/.openbatrc settings"
212
212
  );
213
- cmd.command("set-key").description("Store your Read API key in ~/.openbatrc").option("--from-stdin", "Read the key from stdin (default and recommended)", true).option(
213
+ cmd.command("set-key").description(
214
+ "Store your API key in ~/.openbatrc. Reads from stdin by default; use --value to pass inline (discouraged \u2014 leaks into shell history)."
215
+ ).option(
214
216
  "--value <key>",
215
217
  "Pass the key inline. Discouraged \u2014 leaks into shell history."
216
218
  ).action(async (opts) => {
@@ -226,13 +228,13 @@ function configCommand() {
226
228
  key = Buffer.concat(chunks).toString("utf8").trim();
227
229
  if (!key) {
228
230
  fatal(
229
- "No key on stdin. Try: echo 'ob_read_...' | openbat config set-key --from-stdin"
231
+ "No key on stdin. Try: echo 'ob_read_...' | openbat config set-key"
230
232
  );
231
233
  }
232
234
  }
233
235
  await setApiKey(key);
234
236
  process.stdout.write(
235
- `Saved Read key to ${configPath()} (mode 0600).
237
+ `Saved key to ${configPath()} (mode 0600).
236
238
  `
237
239
  );
238
240
  } catch (err) {
@@ -351,7 +353,9 @@ async function resolveChatbotId(api, chatbotFlag) {
351
353
  );
352
354
  const chatbots = list.chatbots ?? [];
353
355
  if (chatbots.length === 0) {
354
- fatal("This API key authorizes no chatbots.");
356
+ fatal(
357
+ "No chatbots yet. Run `openbat chatbots create --name <name>`, or ask an org owner to invite you."
358
+ );
355
359
  }
356
360
  if (chatbotFlag) {
357
361
  if (UUID_RE2.test(chatbotFlag)) {
@@ -536,18 +540,6 @@ function exportCommand() {
536
540
 
537
541
  // src/commands/auth.ts
538
542
  import { Command as Command3 } from "commander";
539
- async function client2(globals) {
540
- const cfg = await resolveConfig({
541
- apiKeyFlag: globals.apiKey ?? null,
542
- baseUrlFlag: globals.baseUrl ?? null
543
- });
544
- if (!cfg.apiKey) {
545
- fatal(
546
- "No API key configured. Run `openbat config set-key`, pass --api-key, or set OPENBAT_API_KEY."
547
- );
548
- }
549
- return new ApiClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl });
550
- }
551
543
  function detectKind(apiKey) {
552
544
  if (apiKey.startsWith("ob_read_")) return "read";
553
545
  if (apiKey.startsWith("ob_admin_")) return "admin";
@@ -599,17 +591,6 @@ function authCommand() {
599
591
  fatal(err instanceof Error ? err.message : String(err));
600
592
  }
601
593
  });
602
- cmd.command("audit-log").description("Show recent audit-log entries for the current user").option("--days <n>", "Look-back window in days", "7").action(async function() {
603
- try {
604
- process.stderr.write(
605
- "audit-log: endpoint not yet exposed via HTTP \u2014 query `select * from api_audit_log` in Supabase Studio for now.\n"
606
- );
607
- const _c = await client2(this.optsWithGlobals());
608
- void _c;
609
- } catch (err) {
610
- fatal(err instanceof Error ? err.message : String(err));
611
- }
612
- });
613
594
  return cmd;
614
595
  }
615
596
 
@@ -896,7 +877,15 @@ async function pickDefaultChatbot(token, baseUrl) {
896
877
  return;
897
878
  }
898
879
  if (chatbots.length === 0) {
899
- process.stdout.write("\nNo chatbots reachable yet. Create one from the dashboard.\n");
880
+ process.stdout.write(
881
+ [
882
+ "",
883
+ "No chatbots yet. To get one:",
884
+ " \u2022 Create one: openbat chatbots create --name <name>",
885
+ " \u2022 Or ask an org owner to invite you, then run `openbat login` again",
886
+ ""
887
+ ].join("\n")
888
+ );
900
889
  return;
901
890
  }
902
891
  if (chatbots.length === 1) {
@@ -964,7 +953,7 @@ function logoutCommand() {
964
953
  }
965
954
  } else {
966
955
  process.stderr.write(
967
- "Note: read/admin keys can't self-revoke. Visit the dashboard to revoke; this command will just clear the local config.\n"
956
+ "Note: read/admin keys can't self-revoke server-side. Revoke them in the dashboard if needed; clearing local config only.\n"
968
957
  );
969
958
  }
970
959
  await clearApiKey();
@@ -977,7 +966,7 @@ function logoutCommand() {
977
966
 
978
967
  // src/commands/org.ts
979
968
  import { Command as Command6 } from "commander";
980
- async function client3(globals) {
969
+ async function client2(globals) {
981
970
  const cfg = await resolveConfig({
982
971
  apiKeyFlag: globals.apiKey ?? null,
983
972
  baseUrlFlag: globals.baseUrl ?? null
@@ -997,7 +986,7 @@ function orgCommand() {
997
986
  cmd.command("list").description("List orgs the current PAT's user belongs to").action(async function() {
998
987
  try {
999
988
  const globals = this.optsWithGlobals();
1000
- const c = await client3(globals);
989
+ const c = await client2(globals);
1001
990
  const result = await c.get("/api/v1/orgs");
1002
991
  emit(result.orgs, { json: !!globals.json });
1003
992
  } catch (err) {
@@ -1007,7 +996,7 @@ function orgCommand() {
1007
996
  cmd.command("show").description("Show the active org (id, name, members)").action(async function() {
1008
997
  try {
1009
998
  const globals = this.optsWithGlobals();
1010
- const c = await client3(globals);
999
+ const c = await client2(globals);
1011
1000
  const result = await c.get(
1012
1001
  "/api/v1/orgs/active"
1013
1002
  );
@@ -1022,7 +1011,7 @@ function orgCommand() {
1022
1011
  cmd.command("rename").description("Rename an org (owner only)").requiredOption("--id <orgId>", "Org id").requiredOption("--name <name>", "New name").action(async function(opts) {
1023
1012
  try {
1024
1013
  const globals = this.optsWithGlobals();
1025
- const c = await client3(globals);
1014
+ const c = await client2(globals);
1026
1015
  await c.patch(`/api/v1/orgs/${opts.id}`, { name: opts.name });
1027
1016
  emit({ ok: true, renamed: opts.id }, { json: !!globals.json });
1028
1017
  } catch (err) {
@@ -1033,7 +1022,7 @@ function orgCommand() {
1033
1022
  members.command("list").requiredOption("--id <orgId>", "Org id").action(async function(opts) {
1034
1023
  try {
1035
1024
  const globals = this.optsWithGlobals();
1036
- const c = await client3(globals);
1025
+ const c = await client2(globals);
1037
1026
  const result = await c.get(
1038
1027
  `/api/v1/orgs/${opts.id}/members`
1039
1028
  );
@@ -1045,7 +1034,7 @@ function orgCommand() {
1045
1034
  members.command("invite").requiredOption("--id <orgId>", "Org id").requiredOption("--email <email>", "Invitee email").option("--role <role>", "member | admin", "member").action(async function(opts) {
1046
1035
  try {
1047
1036
  const globals = this.optsWithGlobals();
1048
- const c = await client3(globals);
1037
+ const c = await client2(globals);
1049
1038
  const result = await c.post(
1050
1039
  `/api/v1/orgs/${opts.id}/members`,
1051
1040
  { email: opts.email, role: opts.role }
@@ -1063,7 +1052,7 @@ function orgCommand() {
1063
1052
  members.command("set-role").requiredOption("--id <orgId>", "Org id").requiredOption("--member <memberId>", "Member id").requiredOption("--role <role>", "admin | member").action(async function(opts) {
1064
1053
  try {
1065
1054
  const globals = this.optsWithGlobals();
1066
- const c = await client3(globals);
1055
+ const c = await client2(globals);
1067
1056
  await c.patch(`/api/v1/orgs/${opts.id}/members/${opts.member}`, {
1068
1057
  role: opts.role
1069
1058
  });
@@ -1075,7 +1064,7 @@ function orgCommand() {
1075
1064
  members.command("remove").requiredOption("--id <orgId>", "Org id").requiredOption("--member <memberId>", "Member id").action(async function(opts) {
1076
1065
  try {
1077
1066
  const globals = this.optsWithGlobals();
1078
- const c = await client3(globals);
1067
+ const c = await client2(globals);
1079
1068
  await c.delete(`/api/v1/orgs/${opts.id}/members/${opts.member}`);
1080
1069
  emit({ ok: true }, { json: !!globals.json });
1081
1070
  } catch (err) {
@@ -1086,7 +1075,7 @@ function orgCommand() {
1086
1075
  invitations.command("list").requiredOption("--id <orgId>", "Org id").action(async function(opts) {
1087
1076
  try {
1088
1077
  const globals = this.optsWithGlobals();
1089
- const c = await client3(globals);
1078
+ const c = await client2(globals);
1090
1079
  const result = await c.get(
1091
1080
  `/api/v1/orgs/${opts.id}/invitations`
1092
1081
  );
@@ -1100,7 +1089,7 @@ function orgCommand() {
1100
1089
 
1101
1090
  // src/commands/write.ts
1102
1091
  import { Command as Command7 } from "commander";
1103
- async function client4(globals) {
1092
+ async function client3(globals) {
1104
1093
  const cfg = await resolveConfig({
1105
1094
  apiKeyFlag: globals.apiKey ?? null,
1106
1095
  baseUrlFlag: globals.baseUrl ?? null
@@ -1129,7 +1118,7 @@ function chatbotsCommand() {
1129
1118
  cmd.command("list").description("List every chatbot the credential can reach").action(async function() {
1130
1119
  try {
1131
1120
  const globals = this.optsWithGlobals();
1132
- const c = await client4(globals);
1121
+ const c = await client3(globals);
1133
1122
  const result = await c.get(
1134
1123
  "/api/v1/chatbots"
1135
1124
  );
@@ -1141,7 +1130,7 @@ function chatbotsCommand() {
1141
1130
  cmd.command("create").description("Create a new chatbot (PAT scope required)").requiredOption("--name <name>", "Chatbot name").option("--website <url>").option("--docs-url <url>").option("--mcp-url <url>").option("--language <code>", "Primary language code (default: en)", "en").action(async function(opts) {
1142
1131
  try {
1143
1132
  const globals = this.optsWithGlobals();
1144
- const c = await client4(globals);
1133
+ const c = await client3(globals);
1145
1134
  const result = await c.post("/api/v1/chatbots", {
1146
1135
  name: opts.name,
1147
1136
  websiteUrl: opts.website,
@@ -1161,7 +1150,7 @@ function chatbotsCommand() {
1161
1150
  cmd.command("delete <chatbotId>").description("Delete a chatbot (irreversible \u2014 cascade-deletes everything)").action(async function(chatbotId) {
1162
1151
  try {
1163
1152
  const globals = this.optsWithGlobals();
1164
- const c = await client4(globals);
1153
+ const c = await client3(globals);
1165
1154
  await c.delete(`/api/v1/chatbots/${chatbotId}`);
1166
1155
  emit({ ok: true, deleted: chatbotId }, { json: !!globals.json });
1167
1156
  } catch (err) {
@@ -1175,7 +1164,7 @@ function webhooksCommand() {
1175
1164
  cmd.command("list").requiredOption("--chatbot <id>", "Chatbot id").action(async function(opts) {
1176
1165
  try {
1177
1166
  const globals = this.optsWithGlobals();
1178
- const c = await client4(globals);
1167
+ const c = await client3(globals);
1179
1168
  const result = await c.get(
1180
1169
  `/api/v1/chatbots/${opts.chatbot}/webhooks`
1181
1170
  );
@@ -1187,7 +1176,7 @@ function webhooksCommand() {
1187
1176
  cmd.command("create").requiredOption("--chatbot <id>", "Chatbot id").requiredOption("--name <name>").requiredOption("--url <url>").option("--type <type>", "discord | slack | custom", "custom").action(async function(opts) {
1188
1177
  try {
1189
1178
  const globals = this.optsWithGlobals();
1190
- const c = await client4(globals);
1179
+ const c = await client3(globals);
1191
1180
  const result = await c.post(`/api/v1/chatbots/${opts.chatbot}/webhooks`, {
1192
1181
  name: opts.name,
1193
1182
  url: opts.url,
@@ -1202,7 +1191,7 @@ function webhooksCommand() {
1202
1191
  cmd.command("delete").requiredOption("--chatbot <id>", "Chatbot id").requiredOption("--webhook <id>", "Webhook id").action(async function(opts) {
1203
1192
  try {
1204
1193
  const globals = this.optsWithGlobals();
1205
- const c = await client4(globals);
1194
+ const c = await client3(globals);
1206
1195
  await c.delete(`/api/v1/chatbots/${opts.chatbot}/webhooks/${opts.webhook}`);
1207
1196
  emit({ ok: true, deleted: opts.webhook }, { json: !!globals.json });
1208
1197
  } catch (err) {
@@ -1219,7 +1208,7 @@ function settingsCommand() {
1219
1208
  keys.command("rotate-ingest").requiredOption("--chatbot <id>", "Chatbot id").action(async function(opts) {
1220
1209
  try {
1221
1210
  const globals = this.optsWithGlobals();
1222
- const c = await client4(globals);
1211
+ const c = await client3(globals);
1223
1212
  const result = await c.post(
1224
1213
  `/api/v1/chatbots/${opts.chatbot}/keys/ingest/rotate`,
1225
1214
  {}
@@ -1233,7 +1222,7 @@ function settingsCommand() {
1233
1222
  keys.command("generate-read").requiredOption("--chatbot <id>", "Chatbot id").action(async function(opts) {
1234
1223
  try {
1235
1224
  const globals = this.optsWithGlobals();
1236
- const c = await client4(globals);
1225
+ const c = await client3(globals);
1237
1226
  const result = await c.post(
1238
1227
  `/api/v1/chatbots/${opts.chatbot}/keys/read`,
1239
1228
  {}
@@ -1247,7 +1236,7 @@ function settingsCommand() {
1247
1236
  keys.command("generate-admin").requiredOption("--chatbot <id>", "Chatbot id").requiredOption("--name <name>", "Human-friendly name (e.g. 'CI key')").option("--expires-in-days <n>", "Auto-expire after N days").action(async function(opts) {
1248
1237
  try {
1249
1238
  const globals = this.optsWithGlobals();
1250
- const c = await client4(globals);
1239
+ const c = await client3(globals);
1251
1240
  const result = await c.post(`/api/v1/chatbots/${opts.chatbot}/admin-keys`, {
1252
1241
  name: opts.name,
1253
1242
  expiresInDays: opts.expiresInDays ? Number(opts.expiresInDays) : void 0
@@ -1261,7 +1250,7 @@ function settingsCommand() {
1261
1250
  keys.command("list-admin").requiredOption("--chatbot <id>", "Chatbot id").action(async function(opts) {
1262
1251
  try {
1263
1252
  const globals = this.optsWithGlobals();
1264
- const c = await client4(globals);
1253
+ const c = await client3(globals);
1265
1254
  const result = await c.get(
1266
1255
  `/api/v1/chatbots/${opts.chatbot}/admin-keys`
1267
1256
  );
@@ -1273,7 +1262,7 @@ function settingsCommand() {
1273
1262
  keys.command("revoke-admin").requiredOption("--chatbot <id>", "Chatbot id").requiredOption("--key <keyId>", "Admin key id").action(async function(opts) {
1274
1263
  try {
1275
1264
  const globals = this.optsWithGlobals();
1276
- const c = await client4(globals);
1265
+ const c = await client3(globals);
1277
1266
  await c.delete(`/api/v1/chatbots/${opts.chatbot}/admin-keys/${opts.key}`);
1278
1267
  emit({ ok: true, revoked: opts.key }, { json: !!globals.json });
1279
1268
  } catch (err) {
@@ -1290,7 +1279,7 @@ function settingsCommand() {
1290
1279
  fatal("Provide at least one setting to update.");
1291
1280
  }
1292
1281
  const globals = this.optsWithGlobals();
1293
- const c = await client4(globals);
1282
+ const c = await client3(globals);
1294
1283
  await c.patch(`/api/v1/chatbots/${opts.chatbot}/settings`, { settings });
1295
1284
  emit({ ok: true }, { json: !!globals.json });
1296
1285
  } catch (err) {
@@ -1304,7 +1293,7 @@ function workflowsCommand() {
1304
1293
  cmd.command("list").requiredOption("--chatbot <id>", "Chatbot id").action(async function(opts) {
1305
1294
  try {
1306
1295
  const globals = this.optsWithGlobals();
1307
- const c = await client4(globals);
1296
+ const c = await client3(globals);
1308
1297
  const result = await c.get(
1309
1298
  `/api/v1/chatbots/${opts.chatbot}/workflows`
1310
1299
  );
@@ -1322,7 +1311,7 @@ function workflowsCommand() {
1322
1311
  ).requiredOption("--webhook <id>", "Webhook id to fire").option("--message <tpl>", "Message template (supports {{user.id}}, etc.)").action(async function(opts) {
1323
1312
  try {
1324
1313
  const globals = this.optsWithGlobals();
1325
- const c = await client4(globals);
1314
+ const c = await client3(globals);
1326
1315
  const result = await c.post(`/api/v1/chatbots/${opts.chatbot}/workflows`, {
1327
1316
  name: opts.name,
1328
1317
  template: opts.template,
@@ -1342,7 +1331,7 @@ function reportsCommand() {
1342
1331
  cmd.command("list").requiredOption("--chatbot <id>", "Chatbot id").action(async function(opts) {
1343
1332
  try {
1344
1333
  const globals = this.optsWithGlobals();
1345
- const c = await client4(globals);
1334
+ const c = await client3(globals);
1346
1335
  const result = await c.get(
1347
1336
  `/api/v1/chatbots/${opts.chatbot}/reports`
1348
1337
  );
@@ -1354,7 +1343,7 @@ function reportsCommand() {
1354
1343
  cmd.command("create").description("Create a new AI report; returns the org-private dashboard URL").requiredOption("--chatbot <id>", "Chatbot id").option("--name <name>", "Report name", "Untitled Report").action(async function(opts) {
1355
1344
  try {
1356
1345
  const globals = this.optsWithGlobals();
1357
- const c = await client4(globals);
1346
+ const c = await client3(globals);
1358
1347
  const result = await c.post(`/api/v1/chatbots/${opts.chatbot}/reports`, { name: opts.name });
1359
1348
  process.stderr.write(
1360
1349
  `
@@ -1378,7 +1367,7 @@ function analysisCommand() {
1378
1367
  cmd.command("list").requiredOption("--chatbot <id>", "Chatbot id").option("--type <t>", "intent | flag | assistant_outcome | assistant_issue").option("--pending", "Include pending suggestions").action(async function(opts) {
1379
1368
  try {
1380
1369
  const globals = this.optsWithGlobals();
1381
- const c = await client4(globals);
1370
+ const c = await client3(globals);
1382
1371
  const qs = new URLSearchParams();
1383
1372
  if (opts.type) qs.set("type", opts.type);
1384
1373
  if (opts.pending) qs.set("pending", "true");
@@ -1396,7 +1385,7 @@ function analysisCommand() {
1396
1385
  ).requiredOption("--name <slug>", "snake_case slug").requiredOption("--display-name <text>").requiredOption("--description <text>").action(async function(opts) {
1397
1386
  try {
1398
1387
  const globals = this.optsWithGlobals();
1399
- const c = await client4(globals);
1388
+ const c = await client3(globals);
1400
1389
  const result = await c.post(
1401
1390
  `/api/v1/chatbots/${opts.chatbot}/analysis-definitions`,
1402
1391
  {
@@ -1420,7 +1409,7 @@ function usersCommand() {
1420
1409
  cmd.command("list").requiredOption("--chatbot <id>", "Chatbot id").option("--from <iso>").option("--to <iso>").option("--days <n>", "Convenience: last N days").option("--search <q>").option("--limit <n>", "Page size", "20").action(async function(opts) {
1421
1410
  try {
1422
1411
  const globals = this.optsWithGlobals();
1423
- const c = await client4(globals);
1412
+ const c = await client3(globals);
1424
1413
  const qs = new URLSearchParams();
1425
1414
  let from = opts.from;
1426
1415
  if (!from && opts.days) {
@@ -1451,7 +1440,7 @@ function sdkCommand() {
1451
1440
  );
1452
1441
  cmd.command("install-instructions").description("Print markdown the calling agent can follow").option(
1453
1442
  "--framework <name>",
1454
- "next | node | vercel-ai-sdk (default: next)",
1443
+ "next | vercel-ai-sdk (default: next)",
1455
1444
  "next"
1456
1445
  ).option("--chatbot <id>", "Chatbot id (for the example snippet)").action(async function(opts) {
1457
1446
  const chatbotId = opts.chatbot ?? "<chatbotId>";
@@ -1511,24 +1500,36 @@ function sdkCommand() {
1511
1500
  cmd.command("verify").description("Check whether any event has arrived for the chatbot yet").requiredOption("--chatbot <id>", "Chatbot id").option("--timeout <n>", "Seconds to wait (default: 60)", "60").action(async function(opts) {
1512
1501
  try {
1513
1502
  const globals = this.optsWithGlobals();
1514
- const c = await client4(globals);
1515
- const deadline = Date.now() + Number(opts.timeout) * 1e3;
1503
+ const c = await client3(globals);
1504
+ const timeoutSec = Number(opts.timeout);
1505
+ const deadline = Date.now() + timeoutSec * 1e3;
1506
+ const params = new URLSearchParams({
1507
+ chatbotId: opts.chatbot,
1508
+ limit: "1"
1509
+ });
1510
+ process.stderr.write(
1511
+ `Waiting for first event on chatbot ${opts.chatbot} (timeout ${timeoutSec}s)\u2026
1512
+ `
1513
+ );
1514
+ let lastTick = Date.now();
1516
1515
  while (Date.now() < deadline) {
1517
- try {
1518
- const result = await c.get(`/api/v1/conversations?limit=1`);
1519
- if (result.total > 0) {
1520
- process.stderr.write(
1521
- `\u2713 First event detected. ${result.total} conversation(s) ingested.
1516
+ const result = await c.get(`/api/v1/conversations?${params}`);
1517
+ if (result.total > 0) {
1518
+ process.stderr.write(
1519
+ `First event detected. ${result.total} conversation(s) ingested.
1522
1520
  `
1523
- );
1524
- return;
1525
- }
1526
- } catch {
1521
+ );
1522
+ return;
1523
+ }
1524
+ if (Date.now() - lastTick >= 5e3) {
1525
+ process.stderr.write(".");
1526
+ lastTick = Date.now();
1527
1527
  }
1528
1528
  await new Promise((r) => setTimeout(r, 2e3));
1529
1529
  }
1530
1530
  process.stderr.write(
1531
- `Timed out after ${opts.timeout}s \u2014 no events yet. Confirm OPENBAT_API_KEY and that recordMessages is being called.
1531
+ `
1532
+ Timed out after ${timeoutSec}s \u2014 no events yet. Confirm OPENBAT_API_KEY and that recordMessages is being called.
1532
1533
  `
1533
1534
  );
1534
1535
  process.exit(2);
@@ -1543,7 +1544,7 @@ function sdkCommand() {
1543
1544
  var program = new Command8();
1544
1545
  program.name("openbat").description(
1545
1546
  "Query OpenBat chatbot data \u2014 conversations, sentiment, analytics, exports."
1546
- ).version("0.2.1").option("--api-key <key>", "Override the stored Read API key (footgun \u2014 leaks into shell history)").option(
1547
+ ).version("0.2.2").option("--api-key <key>", "Override the stored Read API key (footgun \u2014 leaks into shell history)").option(
1547
1548
  "--base-url <url>",
1548
1549
  "Override the OpenBat API base URL (defaults to ~/.openbatrc or https://openbat.dev)"
1549
1550
  ).option(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openbat/cli",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Command-line tool for querying OpenBat chatbot data — conversations, sentiment, analytics, exports",
5
5
  "bin": {
6
6
  "openbat": "bin/openbat"