@openbat/cli 0.3.0 → 0.4.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.
- package/dist/api-client.js +1 -1
- package/dist/api-client.mjs +1 -1
- package/dist/{chunk-KIY62R3O.mjs → chunk-RA36VFZI.mjs} +1 -1
- package/dist/index.js +125 -23
- package/dist/index.mjs +125 -23
- package/package.json +1 -1
package/dist/api-client.js
CHANGED
|
@@ -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.
|
|
35
|
+
var CLI_VERSION = "0.4.0";
|
|
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>`);
|
package/dist/api-client.mjs
CHANGED
|
@@ -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.
|
|
12
|
+
var CLI_VERSION = "0.4.0";
|
|
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>`);
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,7 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
|
|
|
32
32
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
33
33
|
|
|
34
34
|
// src/index.ts
|
|
35
|
-
var
|
|
35
|
+
var import_commander11 = require("commander");
|
|
36
36
|
|
|
37
37
|
// src/commands/config.ts
|
|
38
38
|
var import_commander = require("commander");
|
|
@@ -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.
|
|
166
|
+
var CLI_VERSION = "0.4.0";
|
|
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>`);
|
|
@@ -946,6 +946,28 @@ function reviewCommand() {
|
|
|
946
946
|
// src/commands/prompts.ts
|
|
947
947
|
var import_commander5 = require("commander");
|
|
948
948
|
var import_node_fs2 = require("fs");
|
|
949
|
+
async function waitForActive(api, chatbotId, versionId) {
|
|
950
|
+
const deadlineMs = Date.now() + 15e3;
|
|
951
|
+
let attempt = 0;
|
|
952
|
+
while (Date.now() < deadlineMs) {
|
|
953
|
+
const res = await api.get(
|
|
954
|
+
`/api/v1/chatbots/${chatbotId}/prompts/active`
|
|
955
|
+
);
|
|
956
|
+
if (res.activeVersionId === versionId) {
|
|
957
|
+
process.stderr.write(
|
|
958
|
+
`
|
|
959
|
+
Confirmed live (server): active version is ${versionId}. Live SDK processes converge within their ~60s fetch-cache TTL.
|
|
960
|
+
`
|
|
961
|
+
);
|
|
962
|
+
return;
|
|
963
|
+
}
|
|
964
|
+
attempt++;
|
|
965
|
+
await new Promise((r) => setTimeout(r, Math.min(500 * attempt, 2e3)));
|
|
966
|
+
}
|
|
967
|
+
process.stderr.write(
|
|
968
|
+
"\nPublished, but timed out (15s) waiting for server confirmation \u2014 the active pointer may still be propagating.\n"
|
|
969
|
+
);
|
|
970
|
+
}
|
|
949
971
|
function promptsCommand() {
|
|
950
972
|
const cmd = new import_commander5.Command("prompts").description(
|
|
951
973
|
"Manage the live published system prompt (list / publish / activate / kill-switch)"
|
|
@@ -962,7 +984,7 @@ function promptsCommand() {
|
|
|
962
984
|
fatal(err instanceof Error ? err.message : String(err));
|
|
963
985
|
}
|
|
964
986
|
});
|
|
965
|
-
cmd.command("publish").description("Publish a template as the LIVE prompt (from --file or --text)").option("--file <path>", "Read the template text from a file").option("--text <text>", "Inline template text (prefer --file for long prompts)").action(async function(opts) {
|
|
987
|
+
cmd.command("publish").description("Publish a template as the LIVE prompt (from --file or --text)").option("--file <path>", "Read the template text from a file").option("--text <text>", "Inline template text (prefer --file for long prompts)").option("--wait", "Block until the server confirms the new version is the active published prompt").action(async function(opts) {
|
|
966
988
|
try {
|
|
967
989
|
let templateText = opts.text;
|
|
968
990
|
if (opts.file) templateText = await import_node_fs2.promises.readFile(opts.file, "utf8");
|
|
@@ -976,9 +998,13 @@ function promptsCommand() {
|
|
|
976
998
|
{ templateText }
|
|
977
999
|
);
|
|
978
1000
|
emit(result, { json: !!this.optsWithGlobals().json });
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1001
|
+
if (opts.wait && result.versionId) {
|
|
1002
|
+
await waitForActive(api, id, result.versionId);
|
|
1003
|
+
} else {
|
|
1004
|
+
process.stderr.write(
|
|
1005
|
+
"\nPublished. Live within ~60s for chatbots that fetch their prompt from OpenBat.\n"
|
|
1006
|
+
);
|
|
1007
|
+
}
|
|
982
1008
|
} catch (err) {
|
|
983
1009
|
fatal(err instanceof Error ? err.message : String(err));
|
|
984
1010
|
}
|
|
@@ -1013,11 +1039,86 @@ function promptsCommand() {
|
|
|
1013
1039
|
fatal(err instanceof Error ? err.message : String(err));
|
|
1014
1040
|
}
|
|
1015
1041
|
});
|
|
1042
|
+
cmd.command("show <versionId>").description("Show a version's full template text (list shows only hashes)").action(async function(versionId) {
|
|
1043
|
+
try {
|
|
1044
|
+
const { api, chatbotFlag } = await client(this.optsWithGlobals());
|
|
1045
|
+
const id = await resolveChatbotId(api, chatbotFlag);
|
|
1046
|
+
const result = await api.get(
|
|
1047
|
+
`/api/v1/chatbots/${id}/prompts/${versionId}`
|
|
1048
|
+
);
|
|
1049
|
+
emit(result, { json: !!this.optsWithGlobals().json });
|
|
1050
|
+
} catch (err) {
|
|
1051
|
+
fatal(err instanceof Error ? err.message : String(err));
|
|
1052
|
+
}
|
|
1053
|
+
});
|
|
1054
|
+
cmd.command("active").description("Show what the server resolves to RIGHT NOW (active version, kill switch)").action(async function() {
|
|
1055
|
+
try {
|
|
1056
|
+
const { api, chatbotFlag } = await client(this.optsWithGlobals());
|
|
1057
|
+
const id = await resolveChatbotId(api, chatbotFlag);
|
|
1058
|
+
const result = await api.get(
|
|
1059
|
+
`/api/v1/chatbots/${id}/prompts/active`
|
|
1060
|
+
);
|
|
1061
|
+
emit(result, { json: !!this.optsWithGlobals().json });
|
|
1062
|
+
} catch (err) {
|
|
1063
|
+
fatal(err instanceof Error ? err.message : String(err));
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1016
1066
|
return cmd;
|
|
1017
1067
|
}
|
|
1018
1068
|
|
|
1019
|
-
// src/commands/
|
|
1069
|
+
// src/commands/backtests.ts
|
|
1020
1070
|
var import_commander6 = require("commander");
|
|
1071
|
+
function backtestsCommand() {
|
|
1072
|
+
const cmd = new import_commander6.Command("backtests").description(
|
|
1073
|
+
"Retest a candidate prompt against flagged conversations (create + poll status)"
|
|
1074
|
+
);
|
|
1075
|
+
cmd.command("create").description("Replay flagged conversations against a candidate prompt version").requiredOption("--name <name>", "Backtest name").requiredOption(
|
|
1076
|
+
"--candidate-prompt <versionId>",
|
|
1077
|
+
"Candidate prompt version id (from `openbat prompts list`)"
|
|
1078
|
+
).requiredOption(
|
|
1079
|
+
"--flags <csv>",
|
|
1080
|
+
"Comma-separated flag values to sample (e.g. churn_risk,billing_issue)"
|
|
1081
|
+
).option("--sample-size <n>", "How many flagged messages to replay (1-500)", "50").option("--from <iso>", "Only sample flags on/after this ISO timestamp").option("--to <iso>", "Only sample flags on/before this ISO timestamp").action(async function(opts) {
|
|
1082
|
+
try {
|
|
1083
|
+
const flagValues = opts.flags.split(",").map((s) => s.trim()).filter(Boolean);
|
|
1084
|
+
if (flagValues.length === 0) {
|
|
1085
|
+
fatal("Provide at least one flag via --flags <csv>.");
|
|
1086
|
+
}
|
|
1087
|
+
const { api, chatbotFlag } = await client(this.optsWithGlobals());
|
|
1088
|
+
const id = await resolveChatbotId(api, chatbotFlag);
|
|
1089
|
+
const result = await api.post(
|
|
1090
|
+
`/api/v1/chatbots/${id}/backtests`,
|
|
1091
|
+
{
|
|
1092
|
+
name: opts.name,
|
|
1093
|
+
candidatePromptId: opts.candidatePrompt,
|
|
1094
|
+
flagValues,
|
|
1095
|
+
sampleSize: Number(opts.sampleSize),
|
|
1096
|
+
timeRangeStart: opts.from,
|
|
1097
|
+
timeRangeEnd: opts.to
|
|
1098
|
+
}
|
|
1099
|
+
);
|
|
1100
|
+
emit(result, { json: !!this.optsWithGlobals().json });
|
|
1101
|
+
process.stderr.write("\nStarted. Poll progress with: openbat backtests status <id>\n");
|
|
1102
|
+
} catch (err) {
|
|
1103
|
+
fatal(err instanceof Error ? err.message : String(err));
|
|
1104
|
+
}
|
|
1105
|
+
});
|
|
1106
|
+
cmd.command("status <backtestId>").description("Show a backtest's progress + verdict tally").action(async function(backtestId) {
|
|
1107
|
+
try {
|
|
1108
|
+
const { api } = await client(this.optsWithGlobals());
|
|
1109
|
+
const result = await api.get(
|
|
1110
|
+
`/api/v1/backtests/${encodeURIComponent(backtestId)}/status`
|
|
1111
|
+
);
|
|
1112
|
+
emit(result, { json: !!this.optsWithGlobals().json });
|
|
1113
|
+
} catch (err) {
|
|
1114
|
+
fatal(err instanceof Error ? err.message : String(err));
|
|
1115
|
+
}
|
|
1116
|
+
});
|
|
1117
|
+
return cmd;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
// src/commands/login.ts
|
|
1121
|
+
var import_commander7 = require("commander");
|
|
1021
1122
|
var import_node_os2 = __toESM(require("os"));
|
|
1022
1123
|
var import_node_readline = __toESM(require("readline"));
|
|
1023
1124
|
|
|
@@ -1160,7 +1261,7 @@ async function runLoopbackServer(opts) {
|
|
|
1160
1261
|
// src/commands/login.ts
|
|
1161
1262
|
var HOSTNAME = import_node_os2.default.hostname();
|
|
1162
1263
|
function loginCommand() {
|
|
1163
|
-
return new
|
|
1264
|
+
return new import_commander7.Command("login").description("Sign in via browser and install an API key on this device").option("--device", "Use the device-code flow (for SSH / headless machines)").option(
|
|
1164
1265
|
"--use <key>",
|
|
1165
1266
|
"Skip the browser; install a PAT plaintext you already have"
|
|
1166
1267
|
).action(async function(opts) {
|
|
@@ -1350,9 +1451,9 @@ You have ${chatbots.length} chatbots. Pick one later with \`openbat use <id>\`.
|
|
|
1350
1451
|
}
|
|
1351
1452
|
|
|
1352
1453
|
// src/commands/logout.ts
|
|
1353
|
-
var
|
|
1454
|
+
var import_commander8 = require("commander");
|
|
1354
1455
|
function logoutCommand() {
|
|
1355
|
-
return new
|
|
1456
|
+
return new import_commander8.Command("logout").description("Revoke the stored API key and clear ~/.openbatrc").action(async function() {
|
|
1356
1457
|
try {
|
|
1357
1458
|
const globals = this.optsWithGlobals();
|
|
1358
1459
|
const cfg = await resolveConfig({
|
|
@@ -1387,7 +1488,7 @@ function logoutCommand() {
|
|
|
1387
1488
|
}
|
|
1388
1489
|
|
|
1389
1490
|
// src/commands/org.ts
|
|
1390
|
-
var
|
|
1491
|
+
var import_commander9 = require("commander");
|
|
1391
1492
|
async function client2(globals) {
|
|
1392
1493
|
const cfg = await resolveConfig({
|
|
1393
1494
|
apiKeyFlag: globals.apiKey ?? null,
|
|
@@ -1402,7 +1503,7 @@ async function client2(globals) {
|
|
|
1402
1503
|
return new ApiClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl });
|
|
1403
1504
|
}
|
|
1404
1505
|
function orgCommand() {
|
|
1405
|
-
const cmd = new
|
|
1506
|
+
const cmd = new import_commander9.Command("org").description(
|
|
1406
1507
|
"Manage the OpenBat tenant org (rename, members, invitations). Requires PAT."
|
|
1407
1508
|
);
|
|
1408
1509
|
cmd.command("list").description("List orgs the current PAT's user belongs to").action(async function() {
|
|
@@ -1510,7 +1611,7 @@ function orgCommand() {
|
|
|
1510
1611
|
}
|
|
1511
1612
|
|
|
1512
1613
|
// src/commands/write.ts
|
|
1513
|
-
var
|
|
1614
|
+
var import_commander10 = require("commander");
|
|
1514
1615
|
async function client3(globals) {
|
|
1515
1616
|
const cfg = await resolveConfig({
|
|
1516
1617
|
apiKeyFlag: globals.apiKey ?? null,
|
|
@@ -1543,7 +1644,7 @@ function surfacePlaintext(plaintext, label) {
|
|
|
1543
1644
|
);
|
|
1544
1645
|
}
|
|
1545
1646
|
function chatbotsCommand() {
|
|
1546
|
-
const cmd = new
|
|
1647
|
+
const cmd = new import_commander10.Command("chatbots").description(
|
|
1547
1648
|
"List, create, delete chatbots in the current scope"
|
|
1548
1649
|
);
|
|
1549
1650
|
cmd.command("list").description("List every chatbot the credential can reach").action(async function() {
|
|
@@ -1591,7 +1692,7 @@ function chatbotsCommand() {
|
|
|
1591
1692
|
return cmd;
|
|
1592
1693
|
}
|
|
1593
1694
|
function webhooksCommand() {
|
|
1594
|
-
const cmd = new
|
|
1695
|
+
const cmd = new import_commander10.Command("webhooks").description("Manage webhooks for a chatbot");
|
|
1595
1696
|
cmd.command("list").action(async function() {
|
|
1596
1697
|
try {
|
|
1597
1698
|
const chatbotId = requireChatbotId(this);
|
|
@@ -1635,7 +1736,7 @@ function webhooksCommand() {
|
|
|
1635
1736
|
return cmd;
|
|
1636
1737
|
}
|
|
1637
1738
|
function settingsCommand() {
|
|
1638
|
-
const cmd = new
|
|
1739
|
+
const cmd = new import_commander10.Command("settings").description(
|
|
1639
1740
|
"Manage chatbot settings + per-chatbot keys"
|
|
1640
1741
|
);
|
|
1641
1742
|
const keys = cmd.command("keys").description("Manage API keys for a chatbot");
|
|
@@ -1729,7 +1830,7 @@ function settingsCommand() {
|
|
|
1729
1830
|
return cmd;
|
|
1730
1831
|
}
|
|
1731
1832
|
function workflowsCommand() {
|
|
1732
|
-
const cmd = new
|
|
1833
|
+
const cmd = new import_commander10.Command("workflows").description("Manage workflows");
|
|
1733
1834
|
cmd.command("list").action(async function() {
|
|
1734
1835
|
try {
|
|
1735
1836
|
const chatbotId = requireChatbotId(this);
|
|
@@ -1769,7 +1870,7 @@ function workflowsCommand() {
|
|
|
1769
1870
|
return cmd;
|
|
1770
1871
|
}
|
|
1771
1872
|
function reportsCommand() {
|
|
1772
|
-
const cmd = new
|
|
1873
|
+
const cmd = new import_commander10.Command("reports").description("Manage AI reports");
|
|
1773
1874
|
cmd.command("list").action(async function() {
|
|
1774
1875
|
try {
|
|
1775
1876
|
const chatbotId = requireChatbotId(this);
|
|
@@ -1807,7 +1908,7 @@ Created report. View it (org members only):
|
|
|
1807
1908
|
return cmd;
|
|
1808
1909
|
}
|
|
1809
1910
|
function analysisCommand() {
|
|
1810
|
-
const cmd = new
|
|
1911
|
+
const cmd = new import_commander10.Command("analysis").description("Manage analysis definitions");
|
|
1811
1912
|
cmd.command("list").option("--type <t>", "intent | flag | assistant_outcome | assistant_issue").option("--pending", "Include pending suggestions").action(async function(opts) {
|
|
1812
1913
|
try {
|
|
1813
1914
|
const chatbotId = requireChatbotId(this);
|
|
@@ -1849,7 +1950,7 @@ function analysisCommand() {
|
|
|
1849
1950
|
return cmd;
|
|
1850
1951
|
}
|
|
1851
1952
|
function usersCommand() {
|
|
1852
|
-
const cmd = new
|
|
1953
|
+
const cmd = new import_commander10.Command("users").description(
|
|
1853
1954
|
"List external users (chatbot customers) with health metrics"
|
|
1854
1955
|
);
|
|
1855
1956
|
cmd.command("list").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) {
|
|
@@ -1882,7 +1983,7 @@ Total: ${result.total}
|
|
|
1882
1983
|
return cmd;
|
|
1883
1984
|
}
|
|
1884
1985
|
function sdkCommand() {
|
|
1885
|
-
const cmd = new
|
|
1986
|
+
const cmd = new import_commander10.Command("sdk").description(
|
|
1886
1987
|
"Help install and verify the OpenBat SDK in a target project"
|
|
1887
1988
|
);
|
|
1888
1989
|
cmd.command("install-instructions").description("Print markdown the calling agent can follow").option(
|
|
@@ -1992,10 +2093,10 @@ Timed out after ${timeoutSec}s \u2014 no events yet. Confirm OPENBAT_API_KEY and
|
|
|
1992
2093
|
}
|
|
1993
2094
|
|
|
1994
2095
|
// src/index.ts
|
|
1995
|
-
var program = new
|
|
2096
|
+
var program = new import_commander11.Command();
|
|
1996
2097
|
program.name("openbat").description(
|
|
1997
2098
|
"Query OpenBat chatbot data \u2014 conversations, sentiment, analytics, exports."
|
|
1998
|
-
).version("0.
|
|
2099
|
+
).version("0.4.0").option("--api-key <key>", "Override the stored Read API key (footgun \u2014 leaks into shell history)").option(
|
|
1999
2100
|
"--base-url <url>",
|
|
2000
2101
|
"Override the OpenBat API base URL (defaults to ~/.openbatrc or https://openbat.dev)"
|
|
2001
2102
|
).option(
|
|
@@ -2016,6 +2117,7 @@ program.addCommand(chatbotsCommand());
|
|
|
2016
2117
|
program.addCommand(conversationsCommand());
|
|
2017
2118
|
program.addCommand(reviewCommand());
|
|
2018
2119
|
program.addCommand(promptsCommand());
|
|
2120
|
+
program.addCommand(backtestsCommand());
|
|
2019
2121
|
program.addCommand(usersCommand());
|
|
2020
2122
|
program.addCommand(settingsCommand());
|
|
2021
2123
|
program.addCommand(webhooksCommand());
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ApiClient
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RA36VFZI.mjs";
|
|
5
5
|
|
|
6
6
|
// src/index.ts
|
|
7
|
-
import { Command as
|
|
7
|
+
import { Command as Command11 } from "commander";
|
|
8
8
|
|
|
9
9
|
// src/commands/config.ts
|
|
10
10
|
import { Command } from "commander";
|
|
@@ -768,6 +768,28 @@ function reviewCommand() {
|
|
|
768
768
|
// src/commands/prompts.ts
|
|
769
769
|
import { Command as Command5 } from "commander";
|
|
770
770
|
import { promises as fs2 } from "fs";
|
|
771
|
+
async function waitForActive(api, chatbotId, versionId) {
|
|
772
|
+
const deadlineMs = Date.now() + 15e3;
|
|
773
|
+
let attempt = 0;
|
|
774
|
+
while (Date.now() < deadlineMs) {
|
|
775
|
+
const res = await api.get(
|
|
776
|
+
`/api/v1/chatbots/${chatbotId}/prompts/active`
|
|
777
|
+
);
|
|
778
|
+
if (res.activeVersionId === versionId) {
|
|
779
|
+
process.stderr.write(
|
|
780
|
+
`
|
|
781
|
+
Confirmed live (server): active version is ${versionId}. Live SDK processes converge within their ~60s fetch-cache TTL.
|
|
782
|
+
`
|
|
783
|
+
);
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
attempt++;
|
|
787
|
+
await new Promise((r) => setTimeout(r, Math.min(500 * attempt, 2e3)));
|
|
788
|
+
}
|
|
789
|
+
process.stderr.write(
|
|
790
|
+
"\nPublished, but timed out (15s) waiting for server confirmation \u2014 the active pointer may still be propagating.\n"
|
|
791
|
+
);
|
|
792
|
+
}
|
|
771
793
|
function promptsCommand() {
|
|
772
794
|
const cmd = new Command5("prompts").description(
|
|
773
795
|
"Manage the live published system prompt (list / publish / activate / kill-switch)"
|
|
@@ -784,7 +806,7 @@ function promptsCommand() {
|
|
|
784
806
|
fatal(err instanceof Error ? err.message : String(err));
|
|
785
807
|
}
|
|
786
808
|
});
|
|
787
|
-
cmd.command("publish").description("Publish a template as the LIVE prompt (from --file or --text)").option("--file <path>", "Read the template text from a file").option("--text <text>", "Inline template text (prefer --file for long prompts)").action(async function(opts) {
|
|
809
|
+
cmd.command("publish").description("Publish a template as the LIVE prompt (from --file or --text)").option("--file <path>", "Read the template text from a file").option("--text <text>", "Inline template text (prefer --file for long prompts)").option("--wait", "Block until the server confirms the new version is the active published prompt").action(async function(opts) {
|
|
788
810
|
try {
|
|
789
811
|
let templateText = opts.text;
|
|
790
812
|
if (opts.file) templateText = await fs2.readFile(opts.file, "utf8");
|
|
@@ -798,9 +820,13 @@ function promptsCommand() {
|
|
|
798
820
|
{ templateText }
|
|
799
821
|
);
|
|
800
822
|
emit(result, { json: !!this.optsWithGlobals().json });
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
823
|
+
if (opts.wait && result.versionId) {
|
|
824
|
+
await waitForActive(api, id, result.versionId);
|
|
825
|
+
} else {
|
|
826
|
+
process.stderr.write(
|
|
827
|
+
"\nPublished. Live within ~60s for chatbots that fetch their prompt from OpenBat.\n"
|
|
828
|
+
);
|
|
829
|
+
}
|
|
804
830
|
} catch (err) {
|
|
805
831
|
fatal(err instanceof Error ? err.message : String(err));
|
|
806
832
|
}
|
|
@@ -835,11 +861,86 @@ function promptsCommand() {
|
|
|
835
861
|
fatal(err instanceof Error ? err.message : String(err));
|
|
836
862
|
}
|
|
837
863
|
});
|
|
864
|
+
cmd.command("show <versionId>").description("Show a version's full template text (list shows only hashes)").action(async function(versionId) {
|
|
865
|
+
try {
|
|
866
|
+
const { api, chatbotFlag } = await client(this.optsWithGlobals());
|
|
867
|
+
const id = await resolveChatbotId(api, chatbotFlag);
|
|
868
|
+
const result = await api.get(
|
|
869
|
+
`/api/v1/chatbots/${id}/prompts/${versionId}`
|
|
870
|
+
);
|
|
871
|
+
emit(result, { json: !!this.optsWithGlobals().json });
|
|
872
|
+
} catch (err) {
|
|
873
|
+
fatal(err instanceof Error ? err.message : String(err));
|
|
874
|
+
}
|
|
875
|
+
});
|
|
876
|
+
cmd.command("active").description("Show what the server resolves to RIGHT NOW (active version, kill switch)").action(async function() {
|
|
877
|
+
try {
|
|
878
|
+
const { api, chatbotFlag } = await client(this.optsWithGlobals());
|
|
879
|
+
const id = await resolveChatbotId(api, chatbotFlag);
|
|
880
|
+
const result = await api.get(
|
|
881
|
+
`/api/v1/chatbots/${id}/prompts/active`
|
|
882
|
+
);
|
|
883
|
+
emit(result, { json: !!this.optsWithGlobals().json });
|
|
884
|
+
} catch (err) {
|
|
885
|
+
fatal(err instanceof Error ? err.message : String(err));
|
|
886
|
+
}
|
|
887
|
+
});
|
|
838
888
|
return cmd;
|
|
839
889
|
}
|
|
840
890
|
|
|
841
|
-
// src/commands/
|
|
891
|
+
// src/commands/backtests.ts
|
|
842
892
|
import { Command as Command6 } from "commander";
|
|
893
|
+
function backtestsCommand() {
|
|
894
|
+
const cmd = new Command6("backtests").description(
|
|
895
|
+
"Retest a candidate prompt against flagged conversations (create + poll status)"
|
|
896
|
+
);
|
|
897
|
+
cmd.command("create").description("Replay flagged conversations against a candidate prompt version").requiredOption("--name <name>", "Backtest name").requiredOption(
|
|
898
|
+
"--candidate-prompt <versionId>",
|
|
899
|
+
"Candidate prompt version id (from `openbat prompts list`)"
|
|
900
|
+
).requiredOption(
|
|
901
|
+
"--flags <csv>",
|
|
902
|
+
"Comma-separated flag values to sample (e.g. churn_risk,billing_issue)"
|
|
903
|
+
).option("--sample-size <n>", "How many flagged messages to replay (1-500)", "50").option("--from <iso>", "Only sample flags on/after this ISO timestamp").option("--to <iso>", "Only sample flags on/before this ISO timestamp").action(async function(opts) {
|
|
904
|
+
try {
|
|
905
|
+
const flagValues = opts.flags.split(",").map((s) => s.trim()).filter(Boolean);
|
|
906
|
+
if (flagValues.length === 0) {
|
|
907
|
+
fatal("Provide at least one flag via --flags <csv>.");
|
|
908
|
+
}
|
|
909
|
+
const { api, chatbotFlag } = await client(this.optsWithGlobals());
|
|
910
|
+
const id = await resolveChatbotId(api, chatbotFlag);
|
|
911
|
+
const result = await api.post(
|
|
912
|
+
`/api/v1/chatbots/${id}/backtests`,
|
|
913
|
+
{
|
|
914
|
+
name: opts.name,
|
|
915
|
+
candidatePromptId: opts.candidatePrompt,
|
|
916
|
+
flagValues,
|
|
917
|
+
sampleSize: Number(opts.sampleSize),
|
|
918
|
+
timeRangeStart: opts.from,
|
|
919
|
+
timeRangeEnd: opts.to
|
|
920
|
+
}
|
|
921
|
+
);
|
|
922
|
+
emit(result, { json: !!this.optsWithGlobals().json });
|
|
923
|
+
process.stderr.write("\nStarted. Poll progress with: openbat backtests status <id>\n");
|
|
924
|
+
} catch (err) {
|
|
925
|
+
fatal(err instanceof Error ? err.message : String(err));
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
cmd.command("status <backtestId>").description("Show a backtest's progress + verdict tally").action(async function(backtestId) {
|
|
929
|
+
try {
|
|
930
|
+
const { api } = await client(this.optsWithGlobals());
|
|
931
|
+
const result = await api.get(
|
|
932
|
+
`/api/v1/backtests/${encodeURIComponent(backtestId)}/status`
|
|
933
|
+
);
|
|
934
|
+
emit(result, { json: !!this.optsWithGlobals().json });
|
|
935
|
+
} catch (err) {
|
|
936
|
+
fatal(err instanceof Error ? err.message : String(err));
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
return cmd;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// src/commands/login.ts
|
|
943
|
+
import { Command as Command7 } from "commander";
|
|
843
944
|
import os from "os";
|
|
844
945
|
import readline from "readline";
|
|
845
946
|
|
|
@@ -982,7 +1083,7 @@ async function runLoopbackServer(opts) {
|
|
|
982
1083
|
// src/commands/login.ts
|
|
983
1084
|
var HOSTNAME = os.hostname();
|
|
984
1085
|
function loginCommand() {
|
|
985
|
-
return new
|
|
1086
|
+
return new Command7("login").description("Sign in via browser and install an API key on this device").option("--device", "Use the device-code flow (for SSH / headless machines)").option(
|
|
986
1087
|
"--use <key>",
|
|
987
1088
|
"Skip the browser; install a PAT plaintext you already have"
|
|
988
1089
|
).action(async function(opts) {
|
|
@@ -1172,9 +1273,9 @@ You have ${chatbots.length} chatbots. Pick one later with \`openbat use <id>\`.
|
|
|
1172
1273
|
}
|
|
1173
1274
|
|
|
1174
1275
|
// src/commands/logout.ts
|
|
1175
|
-
import { Command as
|
|
1276
|
+
import { Command as Command8 } from "commander";
|
|
1176
1277
|
function logoutCommand() {
|
|
1177
|
-
return new
|
|
1278
|
+
return new Command8("logout").description("Revoke the stored API key and clear ~/.openbatrc").action(async function() {
|
|
1178
1279
|
try {
|
|
1179
1280
|
const globals = this.optsWithGlobals();
|
|
1180
1281
|
const cfg = await resolveConfig({
|
|
@@ -1209,7 +1310,7 @@ function logoutCommand() {
|
|
|
1209
1310
|
}
|
|
1210
1311
|
|
|
1211
1312
|
// src/commands/org.ts
|
|
1212
|
-
import { Command as
|
|
1313
|
+
import { Command as Command9 } from "commander";
|
|
1213
1314
|
async function client2(globals) {
|
|
1214
1315
|
const cfg = await resolveConfig({
|
|
1215
1316
|
apiKeyFlag: globals.apiKey ?? null,
|
|
@@ -1224,7 +1325,7 @@ async function client2(globals) {
|
|
|
1224
1325
|
return new ApiClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl });
|
|
1225
1326
|
}
|
|
1226
1327
|
function orgCommand() {
|
|
1227
|
-
const cmd = new
|
|
1328
|
+
const cmd = new Command9("org").description(
|
|
1228
1329
|
"Manage the OpenBat tenant org (rename, members, invitations). Requires PAT."
|
|
1229
1330
|
);
|
|
1230
1331
|
cmd.command("list").description("List orgs the current PAT's user belongs to").action(async function() {
|
|
@@ -1332,7 +1433,7 @@ function orgCommand() {
|
|
|
1332
1433
|
}
|
|
1333
1434
|
|
|
1334
1435
|
// src/commands/write.ts
|
|
1335
|
-
import { Command as
|
|
1436
|
+
import { Command as Command10 } from "commander";
|
|
1336
1437
|
async function client3(globals) {
|
|
1337
1438
|
const cfg = await resolveConfig({
|
|
1338
1439
|
apiKeyFlag: globals.apiKey ?? null,
|
|
@@ -1365,7 +1466,7 @@ function surfacePlaintext(plaintext, label) {
|
|
|
1365
1466
|
);
|
|
1366
1467
|
}
|
|
1367
1468
|
function chatbotsCommand() {
|
|
1368
|
-
const cmd = new
|
|
1469
|
+
const cmd = new Command10("chatbots").description(
|
|
1369
1470
|
"List, create, delete chatbots in the current scope"
|
|
1370
1471
|
);
|
|
1371
1472
|
cmd.command("list").description("List every chatbot the credential can reach").action(async function() {
|
|
@@ -1413,7 +1514,7 @@ function chatbotsCommand() {
|
|
|
1413
1514
|
return cmd;
|
|
1414
1515
|
}
|
|
1415
1516
|
function webhooksCommand() {
|
|
1416
|
-
const cmd = new
|
|
1517
|
+
const cmd = new Command10("webhooks").description("Manage webhooks for a chatbot");
|
|
1417
1518
|
cmd.command("list").action(async function() {
|
|
1418
1519
|
try {
|
|
1419
1520
|
const chatbotId = requireChatbotId(this);
|
|
@@ -1457,7 +1558,7 @@ function webhooksCommand() {
|
|
|
1457
1558
|
return cmd;
|
|
1458
1559
|
}
|
|
1459
1560
|
function settingsCommand() {
|
|
1460
|
-
const cmd = new
|
|
1561
|
+
const cmd = new Command10("settings").description(
|
|
1461
1562
|
"Manage chatbot settings + per-chatbot keys"
|
|
1462
1563
|
);
|
|
1463
1564
|
const keys = cmd.command("keys").description("Manage API keys for a chatbot");
|
|
@@ -1551,7 +1652,7 @@ function settingsCommand() {
|
|
|
1551
1652
|
return cmd;
|
|
1552
1653
|
}
|
|
1553
1654
|
function workflowsCommand() {
|
|
1554
|
-
const cmd = new
|
|
1655
|
+
const cmd = new Command10("workflows").description("Manage workflows");
|
|
1555
1656
|
cmd.command("list").action(async function() {
|
|
1556
1657
|
try {
|
|
1557
1658
|
const chatbotId = requireChatbotId(this);
|
|
@@ -1591,7 +1692,7 @@ function workflowsCommand() {
|
|
|
1591
1692
|
return cmd;
|
|
1592
1693
|
}
|
|
1593
1694
|
function reportsCommand() {
|
|
1594
|
-
const cmd = new
|
|
1695
|
+
const cmd = new Command10("reports").description("Manage AI reports");
|
|
1595
1696
|
cmd.command("list").action(async function() {
|
|
1596
1697
|
try {
|
|
1597
1698
|
const chatbotId = requireChatbotId(this);
|
|
@@ -1629,7 +1730,7 @@ Created report. View it (org members only):
|
|
|
1629
1730
|
return cmd;
|
|
1630
1731
|
}
|
|
1631
1732
|
function analysisCommand() {
|
|
1632
|
-
const cmd = new
|
|
1733
|
+
const cmd = new Command10("analysis").description("Manage analysis definitions");
|
|
1633
1734
|
cmd.command("list").option("--type <t>", "intent | flag | assistant_outcome | assistant_issue").option("--pending", "Include pending suggestions").action(async function(opts) {
|
|
1634
1735
|
try {
|
|
1635
1736
|
const chatbotId = requireChatbotId(this);
|
|
@@ -1671,7 +1772,7 @@ function analysisCommand() {
|
|
|
1671
1772
|
return cmd;
|
|
1672
1773
|
}
|
|
1673
1774
|
function usersCommand() {
|
|
1674
|
-
const cmd = new
|
|
1775
|
+
const cmd = new Command10("users").description(
|
|
1675
1776
|
"List external users (chatbot customers) with health metrics"
|
|
1676
1777
|
);
|
|
1677
1778
|
cmd.command("list").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) {
|
|
@@ -1704,7 +1805,7 @@ Total: ${result.total}
|
|
|
1704
1805
|
return cmd;
|
|
1705
1806
|
}
|
|
1706
1807
|
function sdkCommand() {
|
|
1707
|
-
const cmd = new
|
|
1808
|
+
const cmd = new Command10("sdk").description(
|
|
1708
1809
|
"Help install and verify the OpenBat SDK in a target project"
|
|
1709
1810
|
);
|
|
1710
1811
|
cmd.command("install-instructions").description("Print markdown the calling agent can follow").option(
|
|
@@ -1814,10 +1915,10 @@ Timed out after ${timeoutSec}s \u2014 no events yet. Confirm OPENBAT_API_KEY and
|
|
|
1814
1915
|
}
|
|
1815
1916
|
|
|
1816
1917
|
// src/index.ts
|
|
1817
|
-
var program = new
|
|
1918
|
+
var program = new Command11();
|
|
1818
1919
|
program.name("openbat").description(
|
|
1819
1920
|
"Query OpenBat chatbot data \u2014 conversations, sentiment, analytics, exports."
|
|
1820
|
-
).version("0.
|
|
1921
|
+
).version("0.4.0").option("--api-key <key>", "Override the stored Read API key (footgun \u2014 leaks into shell history)").option(
|
|
1821
1922
|
"--base-url <url>",
|
|
1822
1923
|
"Override the OpenBat API base URL (defaults to ~/.openbatrc or https://openbat.dev)"
|
|
1823
1924
|
).option(
|
|
@@ -1838,6 +1939,7 @@ program.addCommand(chatbotsCommand());
|
|
|
1838
1939
|
program.addCommand(conversationsCommand());
|
|
1839
1940
|
program.addCommand(reviewCommand());
|
|
1840
1941
|
program.addCommand(promptsCommand());
|
|
1942
|
+
program.addCommand(backtestsCommand());
|
|
1841
1943
|
program.addCommand(usersCommand());
|
|
1842
1944
|
program.addCommand(settingsCommand());
|
|
1843
1945
|
program.addCommand(webhooksCommand());
|