@agent-nexus/cli 0.1.11 → 0.1.13
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/README.md +1 -1
- package/dist/index.js +1196 -91
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -166,7 +166,7 @@ var require_package = __commonJS({
|
|
|
166
166
|
"package.json"(exports2, module2) {
|
|
167
167
|
module2.exports = {
|
|
168
168
|
name: "@agent-nexus/cli",
|
|
169
|
-
version: "0.1.
|
|
169
|
+
version: "0.1.13",
|
|
170
170
|
description: "Official CLI for the Nexus AI agent platform.",
|
|
171
171
|
license: "MIT",
|
|
172
172
|
keywords: [
|
|
@@ -695,6 +695,24 @@ var AgentsResource = class extends BaseResource {
|
|
|
695
695
|
return this.http.request("POST", `/agents/${agentId}/generate-profile-picture`, { body });
|
|
696
696
|
}
|
|
697
697
|
};
|
|
698
|
+
var AnalyticsResource = class extends BaseResource {
|
|
699
|
+
async getOverview(params) {
|
|
700
|
+
return this.http.request("GET", "/analytics/overview", {
|
|
701
|
+
query: params
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
async exportCsv(params) {
|
|
705
|
+
return this.http.requestRaw("GET", "/analytics/export", {
|
|
706
|
+
query: params
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
async listFeedback(params) {
|
|
710
|
+
const { data, meta } = await this.http.requestWithMeta("GET", "/analytics/feedback", {
|
|
711
|
+
query: params
|
|
712
|
+
});
|
|
713
|
+
return { data, meta };
|
|
714
|
+
}
|
|
715
|
+
};
|
|
698
716
|
var ChannelsResource = class extends BaseResource {
|
|
699
717
|
// ===========================================================================
|
|
700
718
|
// Setup Orchestrator
|
|
@@ -748,23 +766,37 @@ var ChannelsResource = class extends BaseResource {
|
|
|
748
766
|
async getWhatsAppSender(senderId) {
|
|
749
767
|
return this.http.request("GET", `/channels/whatsapp-senders/${senderId}`);
|
|
750
768
|
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
769
|
+
// ===========================================================================
|
|
770
|
+
// WhatsApp Templates
|
|
771
|
+
// ===========================================================================
|
|
772
|
+
async listWhatsAppTemplates(params) {
|
|
773
|
+
return this.http.request("GET", "/channels/whatsapp-templates", {
|
|
755
774
|
query: params
|
|
756
775
|
});
|
|
757
776
|
}
|
|
758
|
-
async
|
|
759
|
-
return this.http.
|
|
760
|
-
query: params
|
|
761
|
-
});
|
|
777
|
+
async createWhatsAppTemplate(body) {
|
|
778
|
+
return this.http.request("POST", "/channels/whatsapp-templates", { body });
|
|
762
779
|
}
|
|
763
|
-
async
|
|
764
|
-
|
|
780
|
+
async getWhatsAppTemplate(templateId) {
|
|
781
|
+
return this.http.request("GET", `/channels/whatsapp-templates/${templateId}`);
|
|
782
|
+
}
|
|
783
|
+
async deleteWhatsAppTemplate(templateId) {
|
|
784
|
+
return this.http.request(
|
|
785
|
+
"DELETE",
|
|
786
|
+
`/channels/whatsapp-templates/${templateId}`
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
async listTemplateApprovals(params) {
|
|
790
|
+
return this.http.request("GET", "/channels/whatsapp-templates/approvals", {
|
|
765
791
|
query: params
|
|
766
792
|
});
|
|
767
|
-
|
|
793
|
+
}
|
|
794
|
+
async submitTemplateApproval(body) {
|
|
795
|
+
return this.http.request(
|
|
796
|
+
"POST",
|
|
797
|
+
"/channels/whatsapp-templates/approvals",
|
|
798
|
+
{ body }
|
|
799
|
+
);
|
|
768
800
|
}
|
|
769
801
|
};
|
|
770
802
|
var CloudImportsResource = class extends BaseResource {
|
|
@@ -898,6 +930,42 @@ var DeploymentsResource = class extends BaseResource {
|
|
|
898
930
|
async updateEmbedConfig(deploymentId, body) {
|
|
899
931
|
return this.http.request("PATCH", `/deployments/${deploymentId}/embed-config`, { body });
|
|
900
932
|
}
|
|
933
|
+
// ===========================================================================
|
|
934
|
+
// WhatsApp Deployment Templates
|
|
935
|
+
// ===========================================================================
|
|
936
|
+
async listDeploymentTemplates(deploymentId) {
|
|
937
|
+
return this.http.request(
|
|
938
|
+
"GET",
|
|
939
|
+
`/deployments/${deploymentId}/whatsapp-templates`
|
|
940
|
+
);
|
|
941
|
+
}
|
|
942
|
+
async attachDeploymentTemplate(deploymentId, body) {
|
|
943
|
+
return this.http.request(
|
|
944
|
+
"POST",
|
|
945
|
+
`/deployments/${deploymentId}/whatsapp-templates`,
|
|
946
|
+
{ body }
|
|
947
|
+
);
|
|
948
|
+
}
|
|
949
|
+
async updateDeploymentTemplate(deploymentId, templateId, body) {
|
|
950
|
+
return this.http.request(
|
|
951
|
+
"PATCH",
|
|
952
|
+
`/deployments/${deploymentId}/whatsapp-templates/${templateId}`,
|
|
953
|
+
{ body }
|
|
954
|
+
);
|
|
955
|
+
}
|
|
956
|
+
async detachDeploymentTemplate(deploymentId, templateId) {
|
|
957
|
+
return this.http.request(
|
|
958
|
+
"DELETE",
|
|
959
|
+
`/deployments/${deploymentId}/whatsapp-templates/${templateId}`
|
|
960
|
+
);
|
|
961
|
+
}
|
|
962
|
+
async updateDeploymentTemplateSettings(deploymentId, body) {
|
|
963
|
+
return this.http.request(
|
|
964
|
+
"PATCH",
|
|
965
|
+
`/deployments/${deploymentId}/whatsapp-templates/settings`,
|
|
966
|
+
{ body }
|
|
967
|
+
);
|
|
968
|
+
}
|
|
901
969
|
};
|
|
902
970
|
var DocumentTemplateFoldersResource = class extends BaseResource {
|
|
903
971
|
async list() {
|
|
@@ -1988,6 +2056,64 @@ var ToolDiscoveryResource = class extends BaseResource {
|
|
|
1988
2056
|
);
|
|
1989
2057
|
}
|
|
1990
2058
|
};
|
|
2059
|
+
var TracingResource = class extends BaseResource {
|
|
2060
|
+
// ── Traces ──────────────────────────────────────────────────────────────
|
|
2061
|
+
async listTraces(params) {
|
|
2062
|
+
const { data, meta } = await this.http.requestWithMeta(
|
|
2063
|
+
"GET",
|
|
2064
|
+
"/tracing/traces",
|
|
2065
|
+
{ query: params }
|
|
2066
|
+
);
|
|
2067
|
+
return { data, meta };
|
|
2068
|
+
}
|
|
2069
|
+
async getTrace(traceId) {
|
|
2070
|
+
return this.http.request("GET", `/tracing/traces/${traceId}`);
|
|
2071
|
+
}
|
|
2072
|
+
async deleteTrace(traceId) {
|
|
2073
|
+
return this.http.request("DELETE", `/tracing/traces/${traceId}`);
|
|
2074
|
+
}
|
|
2075
|
+
// ── Generations ─────────────────────────────────────────────────────────
|
|
2076
|
+
async listGenerations(params) {
|
|
2077
|
+
const { data, meta } = await this.http.requestWithMeta(
|
|
2078
|
+
"GET",
|
|
2079
|
+
"/tracing/generations",
|
|
2080
|
+
{ query: params }
|
|
2081
|
+
);
|
|
2082
|
+
return { data, meta };
|
|
2083
|
+
}
|
|
2084
|
+
async getGeneration(generationId) {
|
|
2085
|
+
return this.http.request("GET", `/tracing/generations/${generationId}`);
|
|
2086
|
+
}
|
|
2087
|
+
// ── Models ──────────────────────────────────────────────────────────────
|
|
2088
|
+
async listModels() {
|
|
2089
|
+
return this.http.request("GET", "/tracing/models");
|
|
2090
|
+
}
|
|
2091
|
+
// ── Analytics ───────────────────────────────────────────────────────────
|
|
2092
|
+
async getSummary(params) {
|
|
2093
|
+
return this.http.request("GET", "/tracing/analytics/summary", {
|
|
2094
|
+
query: params
|
|
2095
|
+
});
|
|
2096
|
+
}
|
|
2097
|
+
async getCostBreakdown(params) {
|
|
2098
|
+
return this.http.request("GET", "/tracing/analytics/cost-breakdown", {
|
|
2099
|
+
query: params
|
|
2100
|
+
});
|
|
2101
|
+
}
|
|
2102
|
+
async getTimeline(params) {
|
|
2103
|
+
return this.http.request("GET", "/tracing/analytics/timeline", {
|
|
2104
|
+
query: params
|
|
2105
|
+
});
|
|
2106
|
+
}
|
|
2107
|
+
// ── Export ──────────────────────────────────────────────────────────────
|
|
2108
|
+
async exportTrace(traceId, params) {
|
|
2109
|
+
return this.http.request("POST", `/tracing/traces/${traceId}/export`, {
|
|
2110
|
+
body: params
|
|
2111
|
+
});
|
|
2112
|
+
}
|
|
2113
|
+
async bulkExport(params) {
|
|
2114
|
+
return this.http.request("POST", "/tracing/export", { body: params });
|
|
2115
|
+
}
|
|
2116
|
+
};
|
|
1991
2117
|
var WorkflowExecutionsResource = class extends BaseResource {
|
|
1992
2118
|
async list(params) {
|
|
1993
2119
|
const { data, meta } = await this.http.requestWithMeta("GET", "/workflows/executions", {
|
|
@@ -2460,6 +2586,7 @@ var NexusClient = class {
|
|
|
2460
2586
|
this.phoneNumbers = new PhoneNumbersResource(http);
|
|
2461
2587
|
this.tickets = new TicketsResource(http);
|
|
2462
2588
|
this.channels = new ChannelsResource(http);
|
|
2589
|
+
this.tracing = new TracingResource(http);
|
|
2463
2590
|
}
|
|
2464
2591
|
};
|
|
2465
2592
|
|
|
@@ -2471,6 +2598,10 @@ var URL_MAP = {
|
|
|
2471
2598
|
production: "https://api.nexusgpt.io",
|
|
2472
2599
|
dev: "http://localhost:3001"
|
|
2473
2600
|
};
|
|
2601
|
+
var DASHBOARD_URL_MAP = {
|
|
2602
|
+
production: "https://gpt.nexus",
|
|
2603
|
+
dev: "http://localhost:3000"
|
|
2604
|
+
};
|
|
2474
2605
|
var CONFIG_DIR = import_node_path.default.join(import_node_os.default.homedir(), ".nexus-mcp");
|
|
2475
2606
|
var CONFIG_FILE = import_node_path.default.join(CONFIG_DIR, "config.json");
|
|
2476
2607
|
var NEXUSRC_FILENAME = ".nexusrc";
|
|
@@ -2657,6 +2788,17 @@ function resolveBaseUrl(override) {
|
|
|
2657
2788
|
const env = process.env.NEXUS_ENV ?? "production";
|
|
2658
2789
|
return URL_MAP[env] ?? URL_MAP.production;
|
|
2659
2790
|
}
|
|
2791
|
+
function resolveDashboardUrl(override) {
|
|
2792
|
+
if (override) return override;
|
|
2793
|
+
if (process.env.NEXUS_DASHBOARD_URL) return process.env.NEXUS_DASHBOARD_URL;
|
|
2794
|
+
try {
|
|
2795
|
+
const resolved = resolveProfile();
|
|
2796
|
+
if (resolved.profile.dashboardUrl) return resolved.profile.dashboardUrl;
|
|
2797
|
+
} catch {
|
|
2798
|
+
}
|
|
2799
|
+
const env = process.env.NEXUS_ENV ?? "production";
|
|
2800
|
+
return DASHBOARD_URL_MAP[env] ?? DASHBOARD_URL_MAP.production;
|
|
2801
|
+
}
|
|
2660
2802
|
|
|
2661
2803
|
// src/client.ts
|
|
2662
2804
|
var _lastResolved = null;
|
|
@@ -3275,8 +3417,10 @@ Notes:
|
|
|
3275
3417
|
Run "nexus auth list" to see all profiles, "nexus auth switch <name>" to change active.`
|
|
3276
3418
|
).action(async (opts) => {
|
|
3277
3419
|
let baseUrl;
|
|
3420
|
+
let dashboardUrl;
|
|
3278
3421
|
if (opts.env === "dev") {
|
|
3279
3422
|
baseUrl = "http://localhost:3001";
|
|
3423
|
+
dashboardUrl = "http://localhost:3000";
|
|
3280
3424
|
}
|
|
3281
3425
|
const resolvedBaseUrl = baseUrl ?? resolveBaseUrl();
|
|
3282
3426
|
let apiKey = opts.apiKey;
|
|
@@ -3368,6 +3512,7 @@ Notes:
|
|
|
3368
3512
|
saveProfile(profileName, {
|
|
3369
3513
|
apiKey,
|
|
3370
3514
|
...baseUrl ? { baseUrl } : {},
|
|
3515
|
+
...dashboardUrl ? { dashboardUrl } : {},
|
|
3371
3516
|
...orgName ? { orgName } : {},
|
|
3372
3517
|
...orgId ? { orgId } : {}
|
|
3373
3518
|
});
|
|
@@ -3570,7 +3715,43 @@ function openUrl(url) {
|
|
|
3570
3715
|
|
|
3571
3716
|
// src/commands/channel.ts
|
|
3572
3717
|
var import_node_child_process2 = require("child_process");
|
|
3718
|
+
var import_node_fs2 = require("fs");
|
|
3573
3719
|
init_output();
|
|
3720
|
+
var VARIABLE_PATTERN = /\{\{\d+\}\}/g;
|
|
3721
|
+
function warnIfHighVariableDensity(types) {
|
|
3722
|
+
let warned = false;
|
|
3723
|
+
function checkField(text, fieldLabel) {
|
|
3724
|
+
const matches = text.match(VARIABLE_PATTERN) ?? [];
|
|
3725
|
+
if (matches.length === 0) return;
|
|
3726
|
+
const variableCharsLength = matches.reduce((sum, m) => sum + m.length, 0);
|
|
3727
|
+
const staticLength = text.length - variableCharsLength;
|
|
3728
|
+
if (staticLength < matches.length * 3) {
|
|
3729
|
+
console.warn(
|
|
3730
|
+
color.yellow("\u26A0 Warning:") + ` ${fieldLabel} has very high variable density (${staticLength} static chars, ${matches.length} variable(s)). Meta may reject this with "too many variables for its length."`
|
|
3731
|
+
);
|
|
3732
|
+
warned = true;
|
|
3733
|
+
}
|
|
3734
|
+
}
|
|
3735
|
+
for (const [typeKey, typeValue] of Object.entries(types)) {
|
|
3736
|
+
if (!typeValue || typeof typeValue !== "object") continue;
|
|
3737
|
+
const tv = typeValue;
|
|
3738
|
+
if (typeof tv.body === "string") checkField(tv.body, `${typeKey} body`);
|
|
3739
|
+
if (typeof tv.title === "string") checkField(tv.title, `${typeKey} title`);
|
|
3740
|
+
if (typeof tv.subtitle === "string") checkField(tv.subtitle, `${typeKey} subtitle`);
|
|
3741
|
+
if (Array.isArray(tv.cards)) {
|
|
3742
|
+
tv.cards.forEach((card, i) => {
|
|
3743
|
+
if (typeof card?.body === "string") checkField(card.body, `${typeKey} card[${i}] body`);
|
|
3744
|
+
if (typeof card?.title === "string") checkField(card.title, `${typeKey} card[${i}] title`);
|
|
3745
|
+
});
|
|
3746
|
+
}
|
|
3747
|
+
}
|
|
3748
|
+
if (warned) {
|
|
3749
|
+
console.warn(
|
|
3750
|
+
color.yellow(" Tip:") + " Add more descriptive static text around {{N}} placeholders to avoid Meta rejection.\n"
|
|
3751
|
+
);
|
|
3752
|
+
}
|
|
3753
|
+
return warned;
|
|
3754
|
+
}
|
|
3574
3755
|
function openUrl2(url) {
|
|
3575
3756
|
const platform = process.platform;
|
|
3576
3757
|
const cmd = platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open";
|
|
@@ -3578,7 +3759,10 @@ function openUrl2(url) {
|
|
|
3578
3759
|
}
|
|
3579
3760
|
function registerChannelCommands(program2) {
|
|
3580
3761
|
const channel = program2.command("channel").description("Set up deployment channels: connections, phone numbers, WhatsApp senders");
|
|
3581
|
-
channel.command("setup").description("Check or auto-provision channel setup prerequisites").requiredOption(
|
|
3762
|
+
channel.command("setup").description("Check or auto-provision channel setup prerequisites").requiredOption(
|
|
3763
|
+
"--type <type>",
|
|
3764
|
+
"Deployment type (WHATSAPP, TWILIO_SMS, TWILIO_VOICE, EMBED, etc.)"
|
|
3765
|
+
).option("--auto", "Auto-provision what is possible (e.g., create messaging connection)").option("--region <region>", "Region for auto-provisioning (us1 or ie1)", "us1").addHelpText(
|
|
3582
3766
|
"after",
|
|
3583
3767
|
`
|
|
3584
3768
|
Examples:
|
|
@@ -3622,8 +3806,8 @@ Examples:
|
|
|
3622
3806
|
$ nexus channel connect-waba`
|
|
3623
3807
|
).action(async () => {
|
|
3624
3808
|
try {
|
|
3625
|
-
const dashboardUrl =
|
|
3626
|
-
const url = `${dashboardUrl}/app/
|
|
3809
|
+
const dashboardUrl = resolveDashboardUrl(program2.optsWithGlobals().dashboardUrl);
|
|
3810
|
+
const url = `${dashboardUrl}/app/connect-waba`;
|
|
3627
3811
|
console.log(`Opening ${color.cyan(url)} ...`);
|
|
3628
3812
|
console.log("");
|
|
3629
3813
|
console.log('Complete the "Connect with Meta" flow in your browser, then verify:');
|
|
@@ -3727,6 +3911,292 @@ Examples:
|
|
|
3727
3911
|
process.exitCode = handleError(err);
|
|
3728
3912
|
}
|
|
3729
3913
|
});
|
|
3914
|
+
const waTemplate = channel.command("whatsapp-template").description("Manage WhatsApp message templates (Twilio Content API)");
|
|
3915
|
+
waTemplate.command("list").description("List WhatsApp message templates").option("--connection-id <id>", "Filter by messaging connection ID").addHelpText(
|
|
3916
|
+
"after",
|
|
3917
|
+
`
|
|
3918
|
+
Examples:
|
|
3919
|
+
$ nexus channel whatsapp-template list
|
|
3920
|
+
$ nexus channel whatsapp-template list --connection-id abc --json`
|
|
3921
|
+
).action(async (opts) => {
|
|
3922
|
+
try {
|
|
3923
|
+
const client = createClient(program2.optsWithGlobals());
|
|
3924
|
+
const result = await client.channels.listWhatsAppTemplates({
|
|
3925
|
+
connectionId: opts.connectionId
|
|
3926
|
+
});
|
|
3927
|
+
const data = result?.data ?? result;
|
|
3928
|
+
printTable(Array.isArray(data) ? data : [data], [
|
|
3929
|
+
{ key: "id", label: "ID", width: 38 },
|
|
3930
|
+
{ key: "friendly_name", label: "FRIENDLY NAME", width: 25 },
|
|
3931
|
+
{ key: "language", label: "LANG", width: 8 }
|
|
3932
|
+
]);
|
|
3933
|
+
} catch (err) {
|
|
3934
|
+
process.exitCode = handleError(err);
|
|
3935
|
+
}
|
|
3936
|
+
});
|
|
3937
|
+
waTemplate.command("get").description("Get WhatsApp template details").argument("<templateId>", "Template ID (Twilio SID)").action(async (templateId) => {
|
|
3938
|
+
try {
|
|
3939
|
+
const client = createClient(program2.optsWithGlobals());
|
|
3940
|
+
const result = await client.channels.getWhatsAppTemplate(templateId);
|
|
3941
|
+
const data = result?.data ?? result;
|
|
3942
|
+
printRecord(data, [
|
|
3943
|
+
{ key: "id", label: "ID" },
|
|
3944
|
+
{ key: "friendly_name", label: "Friendly Name" },
|
|
3945
|
+
{ key: "language", label: "Language" },
|
|
3946
|
+
{ key: "types", label: "Types" },
|
|
3947
|
+
{ key: "variables", label: "Variables" },
|
|
3948
|
+
{ key: "created_at", label: "Created At" }
|
|
3949
|
+
]);
|
|
3950
|
+
} catch (err) {
|
|
3951
|
+
process.exitCode = handleError(err);
|
|
3952
|
+
}
|
|
3953
|
+
});
|
|
3954
|
+
waTemplate.command("create").description("Create a WhatsApp message template").requiredOption("--connection-id <id>", "Messaging connection ID").requiredOption("--friendly-name <name>", "Template name (e.g., order_confirmation)").requiredOption("--language <lang>", "Language code (e.g., en, en_US)").option("--body <text>", "Template body text (auto-wraps as twilio/text type)").option("--body-file <path>", "Path to JSON file with full Twilio Types object").option("--type <type>", "Twilio type key when using --body", "twilio/text").option("--variables <json>", `Template variables as JSON (e.g., '{"1":"default"}')`).option("--submit", "Also submit for Meta approval after creation").option(
|
|
3955
|
+
"--category <category>",
|
|
3956
|
+
"Approval category (required with --submit): UTILITY, MARKETING, AUTHENTICATION"
|
|
3957
|
+
).addHelpText(
|
|
3958
|
+
"after",
|
|
3959
|
+
`
|
|
3960
|
+
Examples:
|
|
3961
|
+
$ nexus channel whatsapp-template create --connection-id abc --friendly-name welcome --language en --body "Hello {{1}}, welcome!"
|
|
3962
|
+
$ nexus channel whatsapp-template create --connection-id abc --friendly-name promo --language en --body-file template.json
|
|
3963
|
+
$ nexus channel whatsapp-template create --connection-id abc --friendly-name order --language en --body "Order {{1}} confirmed" --submit --category UTILITY`
|
|
3964
|
+
).action(async (opts) => {
|
|
3965
|
+
try {
|
|
3966
|
+
if (!opts.body && !opts.bodyFile) {
|
|
3967
|
+
console.error("Error: Either --body or --body-file is required.");
|
|
3968
|
+
process.exitCode = 1;
|
|
3969
|
+
return;
|
|
3970
|
+
}
|
|
3971
|
+
if (opts.body && opts.bodyFile) {
|
|
3972
|
+
console.error("Error: Cannot use both --body and --body-file.");
|
|
3973
|
+
process.exitCode = 1;
|
|
3974
|
+
return;
|
|
3975
|
+
}
|
|
3976
|
+
if (opts.submit && !opts.category) {
|
|
3977
|
+
console.error("Error: --category is required when using --submit.");
|
|
3978
|
+
process.exitCode = 1;
|
|
3979
|
+
return;
|
|
3980
|
+
}
|
|
3981
|
+
let types;
|
|
3982
|
+
if (opts.bodyFile) {
|
|
3983
|
+
try {
|
|
3984
|
+
const content = (0, import_node_fs2.readFileSync)(opts.bodyFile, "utf-8");
|
|
3985
|
+
types = JSON.parse(content);
|
|
3986
|
+
} catch (e) {
|
|
3987
|
+
console.error(
|
|
3988
|
+
`Error reading --body-file: ${e instanceof Error ? e.message : String(e)}`
|
|
3989
|
+
);
|
|
3990
|
+
process.exitCode = 1;
|
|
3991
|
+
return;
|
|
3992
|
+
}
|
|
3993
|
+
} else {
|
|
3994
|
+
types = { [opts.type]: { body: opts.body } };
|
|
3995
|
+
}
|
|
3996
|
+
let variables;
|
|
3997
|
+
if (opts.variables) {
|
|
3998
|
+
try {
|
|
3999
|
+
variables = JSON.parse(opts.variables);
|
|
4000
|
+
} catch {
|
|
4001
|
+
console.error("Error: --variables must be valid JSON.");
|
|
4002
|
+
process.exitCode = 1;
|
|
4003
|
+
return;
|
|
4004
|
+
}
|
|
4005
|
+
}
|
|
4006
|
+
warnIfHighVariableDensity(types);
|
|
4007
|
+
const client = createClient(program2.optsWithGlobals());
|
|
4008
|
+
const result = await client.channels.createWhatsAppTemplate({
|
|
4009
|
+
connectionId: opts.connectionId,
|
|
4010
|
+
friendlyName: opts.friendlyName,
|
|
4011
|
+
language: opts.language,
|
|
4012
|
+
types,
|
|
4013
|
+
variables
|
|
4014
|
+
});
|
|
4015
|
+
const data = result?.data ?? result;
|
|
4016
|
+
printRecord(data, [
|
|
4017
|
+
{ key: "id", label: "ID" },
|
|
4018
|
+
{ key: "friendly_name", label: "Friendly Name" },
|
|
4019
|
+
{ key: "language", label: "Language" },
|
|
4020
|
+
{ key: "created_at", label: "Created At" }
|
|
4021
|
+
]);
|
|
4022
|
+
printSuccess("WhatsApp template created.");
|
|
4023
|
+
if (opts.submit) {
|
|
4024
|
+
console.log("");
|
|
4025
|
+
console.log("Submitting for Meta approval...");
|
|
4026
|
+
const approval = await client.channels.submitTemplateApproval({
|
|
4027
|
+
connectionId: opts.connectionId,
|
|
4028
|
+
templateId: data.id,
|
|
4029
|
+
name: opts.friendlyName,
|
|
4030
|
+
category: opts.category
|
|
4031
|
+
});
|
|
4032
|
+
const approvalData = approval?.data ?? approval;
|
|
4033
|
+
printRecord(approvalData, [
|
|
4034
|
+
{ key: "sid", label: "Approval SID" },
|
|
4035
|
+
{ key: "status", label: "Status" }
|
|
4036
|
+
]);
|
|
4037
|
+
printSuccess("Template submitted for Meta approval.");
|
|
4038
|
+
const pollMaxMs = 3e4;
|
|
4039
|
+
const pollIntervalMs = 5e3;
|
|
4040
|
+
const pollStart = Date.now();
|
|
4041
|
+
let resolved = false;
|
|
4042
|
+
console.log("Checking approval status...");
|
|
4043
|
+
while (Date.now() - pollStart < pollMaxMs) {
|
|
4044
|
+
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
|
4045
|
+
try {
|
|
4046
|
+
const approvals = await client.channels.listTemplateApprovals({
|
|
4047
|
+
connectionId: opts.connectionId
|
|
4048
|
+
});
|
|
4049
|
+
const approvalsArr = approvals?.data ?? approvals;
|
|
4050
|
+
const items = Array.isArray(approvalsArr) ? approvalsArr : [approvalsArr];
|
|
4051
|
+
const match = items.find((a) => a.sid === data.id);
|
|
4052
|
+
if (match?.approvalRequests?.status) {
|
|
4053
|
+
const status = match.approvalRequests.status;
|
|
4054
|
+
if (status === "rejected") {
|
|
4055
|
+
console.log(color.red(`\u2717 Template rejected by Meta: ${status}`));
|
|
4056
|
+
if (match.approvalRequests.rejection_reason) {
|
|
4057
|
+
console.log(` Reason: ${match.approvalRequests.rejection_reason}`);
|
|
4058
|
+
}
|
|
4059
|
+
resolved = true;
|
|
4060
|
+
process.exitCode = 1;
|
|
4061
|
+
break;
|
|
4062
|
+
} else if (status === "approved") {
|
|
4063
|
+
console.log(color.green(`\u2713 Template approved by Meta.`));
|
|
4064
|
+
resolved = true;
|
|
4065
|
+
break;
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
} catch {
|
|
4069
|
+
}
|
|
4070
|
+
}
|
|
4071
|
+
if (!resolved) {
|
|
4072
|
+
console.log(
|
|
4073
|
+
`Status still pending. Check later: ${color.dim("nexus channel whatsapp-template approvals")}`
|
|
4074
|
+
);
|
|
4075
|
+
}
|
|
4076
|
+
}
|
|
4077
|
+
} catch (err) {
|
|
4078
|
+
process.exitCode = handleError(err);
|
|
4079
|
+
}
|
|
4080
|
+
});
|
|
4081
|
+
waTemplate.command("delete").description("Delete a WhatsApp template").argument("<templateId>", "Template ID (Twilio SID)").option("--yes", "Skip confirmation prompt").action(async (templateId, opts) => {
|
|
4082
|
+
try {
|
|
4083
|
+
if (!opts.yes && process.stdin.isTTY) {
|
|
4084
|
+
const readline2 = await import("readline");
|
|
4085
|
+
const rl = readline2.createInterface({
|
|
4086
|
+
input: process.stdin,
|
|
4087
|
+
output: process.stdout
|
|
4088
|
+
});
|
|
4089
|
+
const answer = await new Promise((resolve) => {
|
|
4090
|
+
rl.question(`Delete template ${templateId}? (y/N) `, resolve);
|
|
4091
|
+
});
|
|
4092
|
+
rl.close();
|
|
4093
|
+
if (answer.toLowerCase() !== "y") {
|
|
4094
|
+
console.log("Cancelled.");
|
|
4095
|
+
return;
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
const client = createClient(program2.optsWithGlobals());
|
|
4099
|
+
await client.channels.deleteWhatsAppTemplate(templateId);
|
|
4100
|
+
printSuccess("WhatsApp template deleted.", { id: templateId });
|
|
4101
|
+
} catch (err) {
|
|
4102
|
+
process.exitCode = handleError(err);
|
|
4103
|
+
}
|
|
4104
|
+
});
|
|
4105
|
+
waTemplate.command("approvals").description("List template approval status from Meta").option("--connection-id <id>", "Filter by messaging connection ID").addHelpText(
|
|
4106
|
+
"after",
|
|
4107
|
+
`
|
|
4108
|
+
Examples:
|
|
4109
|
+
$ nexus channel whatsapp-template approvals
|
|
4110
|
+
$ nexus channel whatsapp-template approvals --json`
|
|
4111
|
+
).action(async (opts) => {
|
|
4112
|
+
try {
|
|
4113
|
+
const client = createClient(program2.optsWithGlobals());
|
|
4114
|
+
const result = await client.channels.listTemplateApprovals({
|
|
4115
|
+
connectionId: opts.connectionId
|
|
4116
|
+
});
|
|
4117
|
+
const data = result?.data ?? result;
|
|
4118
|
+
const items = Array.isArray(data) ? data : [data];
|
|
4119
|
+
const rows = items.map((item) => ({
|
|
4120
|
+
sid: item.sid,
|
|
4121
|
+
name: item.approvalRequests?.name ?? "",
|
|
4122
|
+
category: item.approvalRequests?.category ?? "",
|
|
4123
|
+
status: item.approvalRequests?.status ?? "",
|
|
4124
|
+
rejection_reason: item.approvalRequests?.rejection_reason ?? ""
|
|
4125
|
+
}));
|
|
4126
|
+
printTable(rows, [
|
|
4127
|
+
{ key: "sid", label: "SID", width: 38 },
|
|
4128
|
+
{ key: "name", label: "NAME", width: 20 },
|
|
4129
|
+
{ key: "category", label: "CATEGORY", width: 15 },
|
|
4130
|
+
{ key: "status", label: "STATUS", width: 12 },
|
|
4131
|
+
{ key: "rejection_reason", label: "REJECTION REASON", width: 30 }
|
|
4132
|
+
]);
|
|
4133
|
+
} catch (err) {
|
|
4134
|
+
process.exitCode = handleError(err);
|
|
4135
|
+
}
|
|
4136
|
+
});
|
|
4137
|
+
waTemplate.command("submit-approval").description("Submit a template for Meta WhatsApp approval").requiredOption("--connection-id <id>", "Messaging connection ID").requiredOption("--template-id <id>", "Template ID (Twilio SID)").requiredOption("--name <name>", "Template name for approval").requiredOption(
|
|
4138
|
+
"--category <category>",
|
|
4139
|
+
"Approval category: UTILITY, MARKETING, or AUTHENTICATION"
|
|
4140
|
+
).option("--wait", "Poll approval status until resolved (up to 2 minutes)").addHelpText(
|
|
4141
|
+
"after",
|
|
4142
|
+
`
|
|
4143
|
+
Examples:
|
|
4144
|
+
$ nexus channel whatsapp-template submit-approval --connection-id abc --template-id HX123 --name welcome --category UTILITY
|
|
4145
|
+
$ nexus channel whatsapp-template submit-approval --connection-id abc --template-id HX123 --name promo --category MARKETING --wait`
|
|
4146
|
+
).action(async (opts) => {
|
|
4147
|
+
try {
|
|
4148
|
+
const client = createClient(program2.optsWithGlobals());
|
|
4149
|
+
const result = await client.channels.submitTemplateApproval({
|
|
4150
|
+
connectionId: opts.connectionId,
|
|
4151
|
+
templateId: opts.templateId,
|
|
4152
|
+
name: opts.name,
|
|
4153
|
+
category: opts.category
|
|
4154
|
+
});
|
|
4155
|
+
const data = result?.data ?? result;
|
|
4156
|
+
printRecord(data, [
|
|
4157
|
+
{ key: "sid", label: "Approval SID" },
|
|
4158
|
+
{ key: "status", label: "Status" }
|
|
4159
|
+
]);
|
|
4160
|
+
printSuccess("Template submitted for Meta approval.");
|
|
4161
|
+
if (opts.wait) {
|
|
4162
|
+
const maxWaitMs = 12e4;
|
|
4163
|
+
const intervalMs = 5e3;
|
|
4164
|
+
const startTime = Date.now();
|
|
4165
|
+
let finalStatus = data.status;
|
|
4166
|
+
console.log("Waiting for approval...");
|
|
4167
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
4168
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
4169
|
+
const approvals = await client.channels.listTemplateApprovals({
|
|
4170
|
+
connectionId: opts.connectionId
|
|
4171
|
+
});
|
|
4172
|
+
const approvalsData = approvals?.data ?? approvals;
|
|
4173
|
+
const items = Array.isArray(approvalsData) ? approvalsData : [approvalsData];
|
|
4174
|
+
const match = items.find((a) => a.sid === opts.templateId);
|
|
4175
|
+
if (match?.approvalRequests?.status) {
|
|
4176
|
+
finalStatus = match.approvalRequests.status;
|
|
4177
|
+
if (finalStatus !== "pending" && finalStatus !== "unsubmitted") {
|
|
4178
|
+
console.log(`Approval resolved: ${color.cyan(finalStatus)}`);
|
|
4179
|
+
if (finalStatus === "rejected" && match.approvalRequests.rejection_reason) {
|
|
4180
|
+
console.log(`Reason: ${match.approvalRequests.rejection_reason}`);
|
|
4181
|
+
}
|
|
4182
|
+
break;
|
|
4183
|
+
}
|
|
4184
|
+
}
|
|
4185
|
+
}
|
|
4186
|
+
if (finalStatus === "pending" || finalStatus === "unsubmitted") {
|
|
4187
|
+
console.log(
|
|
4188
|
+
`Still ${finalStatus} after 2m. Check again: ${color.dim("nexus channel whatsapp-template approvals")}`
|
|
4189
|
+
);
|
|
4190
|
+
}
|
|
4191
|
+
}
|
|
4192
|
+
console.log(
|
|
4193
|
+
`
|
|
4194
|
+
Next: Attach to deployment: ${color.dim("nexus deployment template attach <depId> --template-id ...")}`
|
|
4195
|
+
);
|
|
4196
|
+
} catch (err) {
|
|
4197
|
+
process.exitCode = handleError(err);
|
|
4198
|
+
}
|
|
4199
|
+
});
|
|
3730
4200
|
}
|
|
3731
4201
|
|
|
3732
4202
|
// src/commands/collection.ts
|
|
@@ -4371,57 +4841,294 @@ Examples:
|
|
|
4371
4841
|
).action(async (id, opts) => {
|
|
4372
4842
|
try {
|
|
4373
4843
|
const client = createClient(program2.optsWithGlobals());
|
|
4374
|
-
const base = await resolveBody(opts.body);
|
|
4375
|
-
const body = mergeBodyWithFlags(base, {
|
|
4376
|
-
...opts.name !== void 0 && { name: opts.name }
|
|
4844
|
+
const base = await resolveBody(opts.body);
|
|
4845
|
+
const body = mergeBodyWithFlags(base, {
|
|
4846
|
+
...opts.name !== void 0 && { name: opts.name }
|
|
4847
|
+
});
|
|
4848
|
+
await client.deploymentFolders.update(id, body);
|
|
4849
|
+
printSuccess("Deployment folder updated.", { id });
|
|
4850
|
+
} catch (err) {
|
|
4851
|
+
process.exitCode = handleError(err);
|
|
4852
|
+
}
|
|
4853
|
+
});
|
|
4854
|
+
depFolder.command("delete").description("Delete a deployment folder").argument("<id>", "Folder ID").option("--yes", "Skip confirmation").addHelpText(
|
|
4855
|
+
"after",
|
|
4856
|
+
`
|
|
4857
|
+
Examples:
|
|
4858
|
+
$ nexus deployment folder delete fld-123
|
|
4859
|
+
$ nexus deployment folder delete fld-123 --yes`
|
|
4860
|
+
).action(async (id, opts) => {
|
|
4861
|
+
try {
|
|
4862
|
+
const client = createClient(program2.optsWithGlobals());
|
|
4863
|
+
if (!opts.yes && process.stdout.isTTY) {
|
|
4864
|
+
const readline2 = await import("readline/promises");
|
|
4865
|
+
const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
4866
|
+
const answer = await rl.question(`Delete deployment folder ${id}? [y/N] `);
|
|
4867
|
+
rl.close();
|
|
4868
|
+
if (answer.toLowerCase() !== "y") {
|
|
4869
|
+
console.log("Aborted.");
|
|
4870
|
+
return;
|
|
4871
|
+
}
|
|
4872
|
+
}
|
|
4873
|
+
await client.deploymentFolders.delete(id);
|
|
4874
|
+
printSuccess("Deployment folder deleted.", { id });
|
|
4875
|
+
} catch (err) {
|
|
4876
|
+
process.exitCode = handleError(err);
|
|
4877
|
+
}
|
|
4878
|
+
});
|
|
4879
|
+
depFolder.command("assign").description("Assign a deployment to a folder").requiredOption("--deployment-id <id>", "Deployment ID").requiredOption("--folder-id <id>", "Folder ID").addHelpText(
|
|
4880
|
+
"after",
|
|
4881
|
+
`
|
|
4882
|
+
Examples:
|
|
4883
|
+
$ nexus deployment folder assign --deployment-id dep-123 --folder-id fld-456`
|
|
4884
|
+
).action(async (opts) => {
|
|
4885
|
+
try {
|
|
4886
|
+
const client = createClient(program2.optsWithGlobals());
|
|
4887
|
+
await client.deploymentFolders.assign({
|
|
4888
|
+
deploymentId: opts.deploymentId,
|
|
4889
|
+
folderId: opts.folderId
|
|
4890
|
+
});
|
|
4891
|
+
printSuccess("Deployment assigned to folder.", {
|
|
4892
|
+
deploymentId: opts.deploymentId,
|
|
4893
|
+
folderId: opts.folderId
|
|
4894
|
+
});
|
|
4895
|
+
} catch (err) {
|
|
4896
|
+
process.exitCode = handleError(err);
|
|
4897
|
+
}
|
|
4898
|
+
});
|
|
4899
|
+
const depTemplate = deployment.command("template").description("Manage WhatsApp templates attached to a deployment");
|
|
4900
|
+
depTemplate.command("list").description("List templates attached to a WhatsApp deployment").argument("<deploymentId>", "Deployment ID").addHelpText(
|
|
4901
|
+
"after",
|
|
4902
|
+
`
|
|
4903
|
+
Examples:
|
|
4904
|
+
$ nexus deployment template list dep-123
|
|
4905
|
+
$ nexus deployment template list dep-123 --json`
|
|
4906
|
+
).action(async (deploymentId) => {
|
|
4907
|
+
try {
|
|
4908
|
+
const client = createClient(program2.optsWithGlobals());
|
|
4909
|
+
const result = await client.deployments.listDeploymentTemplates(deploymentId);
|
|
4910
|
+
const data = result?.data ?? result;
|
|
4911
|
+
const items = Array.isArray(data) ? data : [data];
|
|
4912
|
+
const rows = items.map((t) => ({
|
|
4913
|
+
templateId: t.templateId,
|
|
4914
|
+
name: t.name,
|
|
4915
|
+
type: t.type ?? "template",
|
|
4916
|
+
variables: Object.keys(t.variables ?? {}).length,
|
|
4917
|
+
multiLang: t.enableMultiLanguage ? "yes" : "no"
|
|
4918
|
+
}));
|
|
4919
|
+
printTable(rows, [
|
|
4920
|
+
{ key: "templateId", label: "TEMPLATE ID", width: 38 },
|
|
4921
|
+
{ key: "name", label: "NAME", width: 20 },
|
|
4922
|
+
{ key: "type", label: "TYPE", width: 10 },
|
|
4923
|
+
{ key: "variables", label: "VARS", width: 6 },
|
|
4924
|
+
{ key: "multiLang", label: "MULTI-LANG", width: 10 }
|
|
4925
|
+
]);
|
|
4926
|
+
} catch (err) {
|
|
4927
|
+
process.exitCode = handleError(err);
|
|
4928
|
+
}
|
|
4929
|
+
});
|
|
4930
|
+
depTemplate.command("attach").description("Attach a WhatsApp template to a deployment").argument("<deploymentId>", "Deployment ID").requiredOption("--template-id <id>", "Template ID (Twilio SID)").requiredOption("--name <name>", "Display name for this template").requiredOption("--description <text>", "Description of what this template does").option(
|
|
4931
|
+
"--variables <json>",
|
|
4932
|
+
'Variables JSON: {"1":{"description":"Name","isBodyVariable":true}}'
|
|
4933
|
+
).option("--type <type>", "Template type: template, card, or carousel", "template").option("--enable-multi-language", "Enable multi-language support").option("--enable-dynamic-size", "Enable dynamic carousel size (carousel only)").option(
|
|
4934
|
+
"--carousel-template-group <json>",
|
|
4935
|
+
"Carousel template group JSON with size variants (carousel only)"
|
|
4936
|
+
).option(
|
|
4937
|
+
"--single-item-card-template-id <id>",
|
|
4938
|
+
"Fallback card template ID for single-item carousels"
|
|
4939
|
+
).option(
|
|
4940
|
+
"--single-item-card-template-group <json>",
|
|
4941
|
+
"Single-item card template group JSON for multi-language fallback"
|
|
4942
|
+
).addHelpText(
|
|
4943
|
+
"after",
|
|
4944
|
+
`
|
|
4945
|
+
Examples:
|
|
4946
|
+
$ nexus deployment template attach dep-123 --template-id HX456 --name welcome --description "Welcome message"
|
|
4947
|
+
$ nexus deployment template attach dep-123 --template-id HX456 --name order --description "Order confirmation" --variables '{"1":{"description":"Customer name","isBodyVariable":true}}'
|
|
4948
|
+
$ nexus deployment template attach dep-123 --template-id HX456 --name products --description "Product carousel" --type carousel --enable-dynamic-size --carousel-template-group '{"baseName":"products","availableTemplates":[{"language":"en","carouselSize":3,"templateId":"HX111"},{"language":"en","carouselSize":5,"templateId":"HX222"}],"minCarouselSize":3,"maxCarouselSize":5}'`
|
|
4949
|
+
).action(async (deploymentId, opts) => {
|
|
4950
|
+
try {
|
|
4951
|
+
let variables;
|
|
4952
|
+
if (opts.variables) {
|
|
4953
|
+
try {
|
|
4954
|
+
variables = JSON.parse(opts.variables);
|
|
4955
|
+
} catch {
|
|
4956
|
+
console.error("Error: --variables must be valid JSON.");
|
|
4957
|
+
process.exitCode = 1;
|
|
4958
|
+
return;
|
|
4959
|
+
}
|
|
4960
|
+
}
|
|
4961
|
+
let carouselTemplateGroup;
|
|
4962
|
+
if (opts.carouselTemplateGroup) {
|
|
4963
|
+
try {
|
|
4964
|
+
carouselTemplateGroup = JSON.parse(opts.carouselTemplateGroup);
|
|
4965
|
+
} catch {
|
|
4966
|
+
console.error("Error: --carousel-template-group must be valid JSON.");
|
|
4967
|
+
process.exitCode = 1;
|
|
4968
|
+
return;
|
|
4969
|
+
}
|
|
4970
|
+
}
|
|
4971
|
+
let singleItemCardTemplateGroup;
|
|
4972
|
+
if (opts.singleItemCardTemplateGroup) {
|
|
4973
|
+
try {
|
|
4974
|
+
singleItemCardTemplateGroup = JSON.parse(opts.singleItemCardTemplateGroup);
|
|
4975
|
+
} catch {
|
|
4976
|
+
console.error("Error: --single-item-card-template-group must be valid JSON.");
|
|
4977
|
+
process.exitCode = 1;
|
|
4978
|
+
return;
|
|
4979
|
+
}
|
|
4980
|
+
}
|
|
4981
|
+
const client = createClient(program2.optsWithGlobals());
|
|
4982
|
+
const result = await client.deployments.attachDeploymentTemplate(deploymentId, {
|
|
4983
|
+
templateId: opts.templateId,
|
|
4984
|
+
name: opts.name,
|
|
4985
|
+
description: opts.description,
|
|
4986
|
+
variables,
|
|
4987
|
+
type: opts.type,
|
|
4988
|
+
enableMultiLanguage: opts.enableMultiLanguage,
|
|
4989
|
+
enableDynamicSize: opts.enableDynamicSize,
|
|
4990
|
+
carouselTemplateGroup,
|
|
4991
|
+
singleItemCardTemplateId: opts.singleItemCardTemplateId,
|
|
4992
|
+
singleItemCardTemplateGroup
|
|
4377
4993
|
});
|
|
4378
|
-
|
|
4379
|
-
|
|
4994
|
+
const data = result?.data ?? result;
|
|
4995
|
+
printRecord(data, [
|
|
4996
|
+
{ key: "templateId", label: "Template ID" },
|
|
4997
|
+
{ key: "name", label: "Name" },
|
|
4998
|
+
{ key: "description", label: "Description" },
|
|
4999
|
+
{ key: "type", label: "Type" }
|
|
5000
|
+
]);
|
|
5001
|
+
printSuccess("Template attached to deployment.");
|
|
5002
|
+
} catch (err) {
|
|
5003
|
+
process.exitCode = handleError(err);
|
|
5004
|
+
}
|
|
5005
|
+
});
|
|
5006
|
+
depTemplate.command("update").description("Update a template's configuration on a deployment").argument("<deploymentId>", "Deployment ID").argument("<templateId>", "Template ID (Twilio SID)").option("--name <name>", "New display name").option("--description <text>", "New description").option("--variables <json>", "Updated variables JSON").option("--enable-multi-language", "Enable multi-language support").option("--no-multi-language", "Disable multi-language support").option("--enable-dynamic-size", "Enable dynamic carousel size (carousel only)").option("--no-dynamic-size", "Disable dynamic carousel size").option(
|
|
5007
|
+
"--carousel-template-group <json>",
|
|
5008
|
+
"Carousel template group JSON with size variants (carousel only)"
|
|
5009
|
+
).option(
|
|
5010
|
+
"--single-item-card-template-id <id>",
|
|
5011
|
+
"Fallback card template ID for single-item carousels"
|
|
5012
|
+
).option(
|
|
5013
|
+
"--single-item-card-template-group <json>",
|
|
5014
|
+
"Single-item card template group JSON for multi-language fallback"
|
|
5015
|
+
).addHelpText(
|
|
5016
|
+
"after",
|
|
5017
|
+
`
|
|
5018
|
+
Examples:
|
|
5019
|
+
$ nexus deployment template update dep-123 HX456 --name "Updated Welcome"
|
|
5020
|
+
$ nexus deployment template update dep-123 HX456 --variables '{"1":{"description":"Full name"}}'
|
|
5021
|
+
$ nexus deployment template update dep-123 HX456 --enable-dynamic-size --carousel-template-group '{"baseName":"products","availableTemplates":[...]}'`
|
|
5022
|
+
).action(async (deploymentId, templateId, opts) => {
|
|
5023
|
+
try {
|
|
5024
|
+
const body = {};
|
|
5025
|
+
if (opts.name !== void 0) body.name = opts.name;
|
|
5026
|
+
if (opts.description !== void 0) body.description = opts.description;
|
|
5027
|
+
if (opts.enableMultiLanguage !== void 0)
|
|
5028
|
+
body.enableMultiLanguage = opts.enableMultiLanguage;
|
|
5029
|
+
if (opts.enableDynamicSize !== void 0)
|
|
5030
|
+
body.enableDynamicSize = opts.enableDynamicSize;
|
|
5031
|
+
if (opts.singleItemCardTemplateId !== void 0)
|
|
5032
|
+
body.singleItemCardTemplateId = opts.singleItemCardTemplateId;
|
|
5033
|
+
if (opts.variables) {
|
|
5034
|
+
try {
|
|
5035
|
+
body.variables = JSON.parse(opts.variables);
|
|
5036
|
+
} catch {
|
|
5037
|
+
console.error("Error: --variables must be valid JSON.");
|
|
5038
|
+
process.exitCode = 1;
|
|
5039
|
+
return;
|
|
5040
|
+
}
|
|
5041
|
+
}
|
|
5042
|
+
if (opts.carouselTemplateGroup) {
|
|
5043
|
+
try {
|
|
5044
|
+
body.carouselTemplateGroup = JSON.parse(opts.carouselTemplateGroup);
|
|
5045
|
+
} catch {
|
|
5046
|
+
console.error("Error: --carousel-template-group must be valid JSON.");
|
|
5047
|
+
process.exitCode = 1;
|
|
5048
|
+
return;
|
|
5049
|
+
}
|
|
5050
|
+
}
|
|
5051
|
+
if (opts.singleItemCardTemplateGroup) {
|
|
5052
|
+
try {
|
|
5053
|
+
body.singleItemCardTemplateGroup = JSON.parse(opts.singleItemCardTemplateGroup);
|
|
5054
|
+
} catch {
|
|
5055
|
+
console.error("Error: --single-item-card-template-group must be valid JSON.");
|
|
5056
|
+
process.exitCode = 1;
|
|
5057
|
+
return;
|
|
5058
|
+
}
|
|
5059
|
+
}
|
|
5060
|
+
const client = createClient(program2.optsWithGlobals());
|
|
5061
|
+
const result = await client.deployments.updateDeploymentTemplate(
|
|
5062
|
+
deploymentId,
|
|
5063
|
+
templateId,
|
|
5064
|
+
body
|
|
5065
|
+
);
|
|
5066
|
+
const data = result?.data ?? result;
|
|
5067
|
+
printRecord(data, [
|
|
5068
|
+
{ key: "templateId", label: "Template ID" },
|
|
5069
|
+
{ key: "name", label: "Name" },
|
|
5070
|
+
{ key: "description", label: "Description" }
|
|
5071
|
+
]);
|
|
5072
|
+
printSuccess("Deployment template updated.");
|
|
4380
5073
|
} catch (err) {
|
|
4381
5074
|
process.exitCode = handleError(err);
|
|
4382
5075
|
}
|
|
4383
5076
|
});
|
|
4384
|
-
|
|
4385
|
-
"after",
|
|
4386
|
-
`
|
|
4387
|
-
Examples:
|
|
4388
|
-
$ nexus deployment folder delete fld-123
|
|
4389
|
-
$ nexus deployment folder delete fld-123 --yes`
|
|
4390
|
-
).action(async (id, opts) => {
|
|
5077
|
+
depTemplate.command("detach").description("Detach a template from a deployment").argument("<deploymentId>", "Deployment ID").argument("<templateId>", "Template ID (Twilio SID)").option("--yes", "Skip confirmation prompt").action(async (deploymentId, templateId, opts) => {
|
|
4391
5078
|
try {
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
const
|
|
4395
|
-
|
|
4396
|
-
|
|
5079
|
+
if (!opts.yes && process.stdin.isTTY) {
|
|
5080
|
+
const readline2 = await import("readline");
|
|
5081
|
+
const rl = readline2.createInterface({
|
|
5082
|
+
input: process.stdin,
|
|
5083
|
+
output: process.stdout
|
|
5084
|
+
});
|
|
5085
|
+
const answer = await new Promise((resolve) => {
|
|
5086
|
+
rl.question(
|
|
5087
|
+
`Detach template ${templateId} from deployment ${deploymentId}? (y/N) `,
|
|
5088
|
+
resolve
|
|
5089
|
+
);
|
|
5090
|
+
});
|
|
4397
5091
|
rl.close();
|
|
4398
5092
|
if (answer.toLowerCase() !== "y") {
|
|
4399
|
-
console.log("
|
|
5093
|
+
console.log("Cancelled.");
|
|
4400
5094
|
return;
|
|
4401
5095
|
}
|
|
4402
5096
|
}
|
|
4403
|
-
|
|
4404
|
-
|
|
5097
|
+
const client = createClient(program2.optsWithGlobals());
|
|
5098
|
+
await client.deployments.detachDeploymentTemplate(deploymentId, templateId);
|
|
5099
|
+
printSuccess("Template detached from deployment.", { templateId });
|
|
4405
5100
|
} catch (err) {
|
|
4406
5101
|
process.exitCode = handleError(err);
|
|
4407
5102
|
}
|
|
4408
5103
|
});
|
|
4409
|
-
|
|
5104
|
+
depTemplate.command("settings").description("View or update deployment template settings").argument("<deploymentId>", "Deployment ID").option(
|
|
5105
|
+
"--allow-dynamic-templates <bool>",
|
|
5106
|
+
"Allow agent to dynamically create and send templates (true/false)"
|
|
5107
|
+
).addHelpText(
|
|
4410
5108
|
"after",
|
|
4411
5109
|
`
|
|
4412
5110
|
Examples:
|
|
4413
|
-
$ nexus deployment
|
|
4414
|
-
|
|
5111
|
+
$ nexus deployment template settings dep-123
|
|
5112
|
+
$ nexus deployment template settings dep-123 --allow-dynamic-templates true`
|
|
5113
|
+
).action(async (deploymentId, opts) => {
|
|
4415
5114
|
try {
|
|
4416
5115
|
const client = createClient(program2.optsWithGlobals());
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
5116
|
+
if (opts.allowDynamicTemplates !== void 0) {
|
|
5117
|
+
const value = opts.allowDynamicTemplates === "true";
|
|
5118
|
+
await client.deployments.updateDeploymentTemplateSettings(deploymentId, {
|
|
5119
|
+
allowAgentToCreateAndSendTemplates: value
|
|
5120
|
+
});
|
|
5121
|
+
printSuccess(
|
|
5122
|
+
`Dynamic template creation ${value ? "enabled" : "disabled"} for deployment.`
|
|
5123
|
+
);
|
|
5124
|
+
} else {
|
|
5125
|
+
const result = await client.deployments.listDeploymentTemplates(deploymentId);
|
|
5126
|
+
const data = result?.data ?? result;
|
|
5127
|
+
console.log(`Templates attached: ${Array.isArray(data) ? data.length : 0}`);
|
|
5128
|
+
console.log(
|
|
5129
|
+
`Tip: Use --allow-dynamic-templates true/false to toggle agent template creation.`
|
|
5130
|
+
);
|
|
5131
|
+
}
|
|
4425
5132
|
} catch (err) {
|
|
4426
5133
|
process.exitCode = handleError(err);
|
|
4427
5134
|
}
|
|
@@ -4905,7 +5612,7 @@ All commands follow the pattern: \`nexus <group> <action> [arguments] [options]\
|
|
|
4905
5612
|
| [\`eval\`](docs/command-reference.md#nexus-eval) | (subgroups: \`session\`, \`dataset\`, \`execute\`, \`judge\`, \`results\`, \`formats\`, \`judges\`) | AI task evaluation |
|
|
4906
5613
|
| [\`ticket\`](docs/command-reference.md#nexus-ticket) | \`list\` \`get\` \`create\` \`update\` \`comment\` \`comments\` | Bug and feature tracking |
|
|
4907
5614
|
| [\`phone-number\`](docs/command-reference.md#nexus-phone-number) | \`search\` \`buy\` \`list\` \`get\` \`release\` | Phone number management |
|
|
4908
|
-
| [\`channel\`](docs/command-reference.md#nexus-channel) | \`setup\` \`connection list\\|create\` \`whatsapp-sender list\\|create\\|get\`
|
|
5615
|
+
| [\`channel\`](docs/command-reference.md#nexus-channel) | \`setup\` \`connection list\\|create\` \`whatsapp-sender list\\|create\\|get\` | Channel setup orchestrator |
|
|
4909
5616
|
| [\`prompt-assistant\`](docs/command-reference.md#nexus-prompt-assistant) | \`chat\` \`get-thread\` \`delete-thread\` | AI-assisted prompt writing |
|
|
4910
5617
|
|
|
4911
5618
|
### Utility
|
|
@@ -5933,12 +6640,12 @@ List deployments.
|
|
|
5933
6640
|
nexus deployment list [options]
|
|
5934
6641
|
\`\`\`
|
|
5935
6642
|
|
|
5936
|
-
| Option | Description
|
|
5937
|
-
| ------------------ |
|
|
5938
|
-
| \`--agent-id <id>\` | Filter by agent ID
|
|
6643
|
+
| Option | Description |
|
|
6644
|
+
| ------------------ | --------------------------------------------------------------- |
|
|
6645
|
+
| \`--agent-id <id>\` | Filter by agent ID |
|
|
5939
6646
|
| \`--type <type>\` | Filter by type (\`EMBED\`, \`API\`, \`WHATSAPP\`, \`TWILIO_SMS\`, etc.) |
|
|
5940
|
-
| \`--page <number>\` | Page number
|
|
5941
|
-
| \`--limit <number>\` | Items per page
|
|
6647
|
+
| \`--page <number>\` | Page number |
|
|
6648
|
+
| \`--limit <number>\` | Items per page |
|
|
5942
6649
|
|
|
5943
6650
|
\`\`\`bash
|
|
5944
6651
|
nexus deployment list
|
|
@@ -5975,13 +6682,13 @@ Create a new deployment.
|
|
|
5975
6682
|
nexus deployment create [options]
|
|
5976
6683
|
\`\`\`
|
|
5977
6684
|
|
|
5978
|
-
| Option | Required | Description
|
|
5979
|
-
| ---------------------- | -------- |
|
|
5980
|
-
| \`--name <name>\` | Yes | Deployment name
|
|
6685
|
+
| Option | Required | Description |
|
|
6686
|
+
| ---------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------- |
|
|
6687
|
+
| \`--name <name>\` | Yes | Deployment name |
|
|
5981
6688
|
| \`--type <type>\` | Yes | Deployment type: \`EMBED\`, \`API\`, \`WHATSAPP\`, \`TWILIO_SMS\`, \`TWILIO_VOICE\`, \`TELEGRAM\`, \`SLACK\`, \`GMAIL\`, \`OUTLOOK\`, \`TEAMS\` |
|
|
5982
|
-
| \`--agent-id <id>\` | No | Agent ID
|
|
5983
|
-
| \`--description <text>\` | No | Deployment description
|
|
5984
|
-
| \`--body <json>\` | No | Request body as JSON, \`.json\` file, or \`-\` for stdin
|
|
6689
|
+
| \`--agent-id <id>\` | No | Agent ID |
|
|
6690
|
+
| \`--description <text>\` | No | Deployment description |
|
|
6691
|
+
| \`--body <json>\` | No | Request body as JSON, \`.json\` file, or \`-\` for stdin |
|
|
5985
6692
|
|
|
5986
6693
|
**Important:** Channel deployments (WhatsApp, SMS, Voice, etc.) have prerequisites. Run \`nexus channel setup --type <TYPE>\` first to see what's needed.
|
|
5987
6694
|
|
|
@@ -8697,11 +9404,11 @@ Check or auto-provision channel setup prerequisites. Returns a step-by-step chec
|
|
|
8697
9404
|
nexus channel setup [options]
|
|
8698
9405
|
\`\`\`
|
|
8699
9406
|
|
|
8700
|
-
| Option
|
|
8701
|
-
|
|
|
8702
|
-
| \`--type <type>\`
|
|
8703
|
-
| \`--auto\`
|
|
8704
|
-
| \`--region <region>\` | No
|
|
9407
|
+
| Option | Required | Description |
|
|
9408
|
+
| ------------------- | -------- | ------------------------------------------------------------------- |
|
|
9409
|
+
| \`--type <type>\` | Yes | Deployment type (\`WHATSAPP\`, \`TWILIO_SMS\`, \`TWILIO_VOICE\`, etc.) |
|
|
9410
|
+
| \`--auto\` | No | Auto-provision what is possible (e.g., create messaging connection) |
|
|
9411
|
+
| \`--region <region>\` | No | Region for auto-provisioning: \`us1\` or \`ie1\` (default: \`us1\`) |
|
|
8705
9412
|
|
|
8706
9413
|
\`\`\`bash
|
|
8707
9414
|
nexus channel setup --type WHATSAPP
|
|
@@ -8719,7 +9426,7 @@ Open the browser to connect your WhatsApp Business Account via Meta's Embedded S
|
|
|
8719
9426
|
nexus channel connect-waba
|
|
8720
9427
|
\`\`\`
|
|
8721
9428
|
|
|
8722
|
-
Opens \`{NEXUS_DASHBOARD_URL}/app/
|
|
9429
|
+
Opens \`{NEXUS_DASHBOARD_URL}/app/connect-waba\` in your default browser \u2014 a dedicated page with a single "Connect with Meta" button. Complete the flow, then verify with \`nexus channel setup --type WHATSAPP\`.
|
|
8723
9430
|
|
|
8724
9431
|
\`\`\`bash
|
|
8725
9432
|
nexus channel connect-waba
|
|
@@ -8749,8 +9456,8 @@ Create a messaging connection (max 1 per organization via the API).
|
|
|
8749
9456
|
nexus channel connection create [options]
|
|
8750
9457
|
\`\`\`
|
|
8751
9458
|
|
|
8752
|
-
| Option
|
|
8753
|
-
|
|
|
9459
|
+
| Option | Description |
|
|
9460
|
+
| ------------------- | --------------------------------------- |
|
|
8754
9461
|
| \`--region <region>\` | Region: \`us1\` or \`ie1\` (default: \`us1\`) |
|
|
8755
9462
|
|
|
8756
9463
|
\`\`\`bash
|
|
@@ -8782,12 +9489,12 @@ Create a WhatsApp sender (registers a phone number with WhatsApp Business via Me
|
|
|
8782
9489
|
nexus channel whatsapp-sender create [options]
|
|
8783
9490
|
\`\`\`
|
|
8784
9491
|
|
|
8785
|
-
| Option
|
|
8786
|
-
|
|
|
8787
|
-
| \`--connection-id <id>\`
|
|
8788
|
-
| \`--phone-number-id <id>\`
|
|
8789
|
-
| \`--sender-name <name>\`
|
|
8790
|
-
| \`--waba-id <id>\`
|
|
9492
|
+
| Option | Required | Description |
|
|
9493
|
+
| ------------------------ | -------- | --------------------------------------------------------------- |
|
|
9494
|
+
| \`--connection-id <id>\` | Yes | Messaging connection ID |
|
|
9495
|
+
| \`--phone-number-id <id>\` | Yes | Phone number ID |
|
|
9496
|
+
| \`--sender-name <name>\` | Yes | Display name for the WhatsApp sender |
|
|
9497
|
+
| \`--waba-id <id>\` | No | WhatsApp Business Account ID (reads from connection if omitted) |
|
|
8791
9498
|
|
|
8792
9499
|
\`\`\`bash
|
|
8793
9500
|
nexus channel whatsapp-sender create \\
|
|
@@ -10257,7 +10964,7 @@ ${"\u2550".repeat(72)}`);
|
|
|
10257
10964
|
}
|
|
10258
10965
|
|
|
10259
10966
|
// src/commands/document.ts
|
|
10260
|
-
var
|
|
10967
|
+
var import_node_fs3 = __toESM(require("fs"));
|
|
10261
10968
|
var import_node_path2 = __toESM(require("path"));
|
|
10262
10969
|
init_output();
|
|
10263
10970
|
function registerDocumentCommands(program2) {
|
|
@@ -10323,12 +11030,12 @@ Examples:
|
|
|
10323
11030
|
try {
|
|
10324
11031
|
const client = createClient(program2.optsWithGlobals());
|
|
10325
11032
|
const absPath = import_node_path2.default.resolve(filePath);
|
|
10326
|
-
if (!
|
|
11033
|
+
if (!import_node_fs3.default.existsSync(absPath)) {
|
|
10327
11034
|
console.error(`Error: File not found: ${absPath}`);
|
|
10328
11035
|
process.exitCode = 1;
|
|
10329
11036
|
return;
|
|
10330
11037
|
}
|
|
10331
|
-
const buffer =
|
|
11038
|
+
const buffer = import_node_fs3.default.readFileSync(absPath);
|
|
10332
11039
|
const blob = new Blob([buffer]);
|
|
10333
11040
|
const fileName = import_node_path2.default.basename(absPath);
|
|
10334
11041
|
const doc = await client.documents.uploadFile(blob, fileName, opts.description);
|
|
@@ -11626,7 +12333,7 @@ Notes:
|
|
|
11626
12333
|
}
|
|
11627
12334
|
|
|
11628
12335
|
// src/commands/template.ts
|
|
11629
|
-
var
|
|
12336
|
+
var import_node_fs4 = __toESM(require("fs"));
|
|
11630
12337
|
var import_node_path3 = __toESM(require("path"));
|
|
11631
12338
|
init_output();
|
|
11632
12339
|
function registerTemplateCommands(program2) {
|
|
@@ -11712,12 +12419,12 @@ Examples:
|
|
|
11712
12419
|
try {
|
|
11713
12420
|
const client = createClient(program2.optsWithGlobals());
|
|
11714
12421
|
const absPath = import_node_path3.default.resolve(opts.file);
|
|
11715
|
-
if (!
|
|
12422
|
+
if (!import_node_fs4.default.existsSync(absPath)) {
|
|
11716
12423
|
console.error(`Error: File not found: ${absPath}`);
|
|
11717
12424
|
process.exitCode = 1;
|
|
11718
12425
|
return;
|
|
11719
12426
|
}
|
|
11720
|
-
const buffer =
|
|
12427
|
+
const buffer = import_node_fs4.default.readFileSync(absPath);
|
|
11721
12428
|
const blob = new Blob([buffer]);
|
|
11722
12429
|
const fileName = import_node_path3.default.basename(absPath);
|
|
11723
12430
|
const result = await client.skills.uploadDocumentTemplateFile(id, blob, fileName);
|
|
@@ -12030,15 +12737,387 @@ Examples:
|
|
|
12030
12737
|
});
|
|
12031
12738
|
}
|
|
12032
12739
|
|
|
12740
|
+
// src/commands/tracing.ts
|
|
12741
|
+
init_output();
|
|
12742
|
+
function registerTracingCommands(program2) {
|
|
12743
|
+
const tracing = program2.command("tracing").description("View LLM traces and analytics");
|
|
12744
|
+
addPaginationOptions(
|
|
12745
|
+
tracing.command("traces").description("List LLM traces").option("--status <status>", "Filter by status (IN_PROGRESS, COMPLETED, FAILED)").option("--agent-id <id>", "Filter by agent ID").option("--workflow-id <id>", "Filter by workflow ID").option("--model <name>", "Filter by model name").option("--start-date <iso>", "Filter from date (ISO 8601)").option("--end-date <iso>", "Filter to date (ISO 8601)").option(
|
|
12746
|
+
"--sort-by <field>",
|
|
12747
|
+
"Sort by field (startedAt, totalCostUsd, totalDurationMs)",
|
|
12748
|
+
"startedAt"
|
|
12749
|
+
).option("--order <dir>", "Sort order (asc, desc)", "desc").addHelpText(
|
|
12750
|
+
"after",
|
|
12751
|
+
`
|
|
12752
|
+
Examples:
|
|
12753
|
+
$ nexus tracing traces
|
|
12754
|
+
$ nexus tracing traces --status FAILED --limit 10
|
|
12755
|
+
$ nexus tracing traces --agent-id abc --start-date 2026-03-01 --json`
|
|
12756
|
+
)
|
|
12757
|
+
).action(async (opts) => {
|
|
12758
|
+
try {
|
|
12759
|
+
const client = createClient(program2.optsWithGlobals());
|
|
12760
|
+
const { data, meta } = await client.tracing.listTraces({
|
|
12761
|
+
...getPaginationParams(opts),
|
|
12762
|
+
status: opts.status,
|
|
12763
|
+
agentId: opts.agentId,
|
|
12764
|
+
workflowId: opts.workflowId,
|
|
12765
|
+
model: opts.model,
|
|
12766
|
+
startDate: opts.startDate,
|
|
12767
|
+
endDate: opts.endDate,
|
|
12768
|
+
sortBy: opts.sortBy,
|
|
12769
|
+
order: opts.order
|
|
12770
|
+
});
|
|
12771
|
+
printList(data, meta, [
|
|
12772
|
+
{ key: "id", label: "ID", width: 36 },
|
|
12773
|
+
{ key: "status", label: "STATUS", width: 12, format: formatStatus },
|
|
12774
|
+
{ key: "agentName", label: "AGENT", width: 20 },
|
|
12775
|
+
{ key: "workflowName", label: "WORKFLOW", width: 20 },
|
|
12776
|
+
{
|
|
12777
|
+
key: "totalCostUsd",
|
|
12778
|
+
label: "COST ($)",
|
|
12779
|
+
width: 10,
|
|
12780
|
+
format: (v) => v != null ? `$${Number(v).toFixed(4)}` : "-"
|
|
12781
|
+
},
|
|
12782
|
+
{
|
|
12783
|
+
key: "totalDurationMs",
|
|
12784
|
+
label: "DURATION",
|
|
12785
|
+
width: 10,
|
|
12786
|
+
format: (v) => v != null ? `${Number(v)}ms` : "-"
|
|
12787
|
+
},
|
|
12788
|
+
{ key: "generationCount", label: "GENS", width: 5 },
|
|
12789
|
+
{ key: "startedAt", label: "STARTED", width: 20 }
|
|
12790
|
+
]);
|
|
12791
|
+
} catch (err) {
|
|
12792
|
+
process.exitCode = handleError(err);
|
|
12793
|
+
}
|
|
12794
|
+
});
|
|
12795
|
+
tracing.command("trace").description("Get trace details with generations").argument("<id>", "Trace ID").addHelpText(
|
|
12796
|
+
"after",
|
|
12797
|
+
`
|
|
12798
|
+
Examples:
|
|
12799
|
+
$ nexus tracing trace abc-123
|
|
12800
|
+
$ nexus tracing trace abc-123 --json`
|
|
12801
|
+
).action(async (id) => {
|
|
12802
|
+
try {
|
|
12803
|
+
const client = createClient(program2.optsWithGlobals());
|
|
12804
|
+
const trace = await client.tracing.getTrace(id);
|
|
12805
|
+
printRecord(trace, [
|
|
12806
|
+
{ key: "id", label: "ID" },
|
|
12807
|
+
{ key: "status", label: "Status" },
|
|
12808
|
+
{ key: "agentName", label: "Agent" },
|
|
12809
|
+
{ key: "workflowName", label: "Workflow" },
|
|
12810
|
+
{ key: "totalCostUsd", label: "Cost ($)", format: (v) => v != null ? `$${Number(v).toFixed(4)}` : "-" },
|
|
12811
|
+
{ key: "totalInputTokens", label: "Input Tokens" },
|
|
12812
|
+
{ key: "totalOutputTokens", label: "Output Tokens" },
|
|
12813
|
+
{ key: "totalDurationMs", label: "Duration (ms)" },
|
|
12814
|
+
{ key: "startedAt", label: "Started" },
|
|
12815
|
+
{ key: "completedAt", label: "Completed" }
|
|
12816
|
+
]);
|
|
12817
|
+
const gens = trace.generations;
|
|
12818
|
+
if (gens && gens.length > 0) {
|
|
12819
|
+
console.log(`
|
|
12820
|
+
${color.bold("Generations")} (${gens.length}):
|
|
12821
|
+
`);
|
|
12822
|
+
printList(gens, void 0, [
|
|
12823
|
+
{ key: "id", label: "ID", width: 36 },
|
|
12824
|
+
{ key: "modelName", label: "MODEL", width: 25 },
|
|
12825
|
+
{ key: "status", label: "STATUS", width: 12, format: formatStatus },
|
|
12826
|
+
{
|
|
12827
|
+
key: "costUsd",
|
|
12828
|
+
label: "COST ($)",
|
|
12829
|
+
width: 10,
|
|
12830
|
+
format: (v) => v != null ? `$${Number(v).toFixed(6)}` : "-"
|
|
12831
|
+
},
|
|
12832
|
+
{
|
|
12833
|
+
key: "durationMs",
|
|
12834
|
+
label: "DURATION",
|
|
12835
|
+
width: 10,
|
|
12836
|
+
format: (v) => v != null ? `${v}ms` : "-"
|
|
12837
|
+
}
|
|
12838
|
+
]);
|
|
12839
|
+
}
|
|
12840
|
+
} catch (err) {
|
|
12841
|
+
process.exitCode = handleError(err);
|
|
12842
|
+
}
|
|
12843
|
+
});
|
|
12844
|
+
tracing.command("delete").description("Delete a trace and its generations").argument("<id>", "Trace ID").addHelpText(
|
|
12845
|
+
"after",
|
|
12846
|
+
`
|
|
12847
|
+
Examples:
|
|
12848
|
+
$ nexus tracing delete abc-123`
|
|
12849
|
+
).action(async (id) => {
|
|
12850
|
+
try {
|
|
12851
|
+
const client = createClient(program2.optsWithGlobals());
|
|
12852
|
+
await client.tracing.deleteTrace(id);
|
|
12853
|
+
printSuccess("Trace deleted.", { id });
|
|
12854
|
+
} catch (err) {
|
|
12855
|
+
process.exitCode = handleError(err);
|
|
12856
|
+
}
|
|
12857
|
+
});
|
|
12858
|
+
addPaginationOptions(
|
|
12859
|
+
tracing.command("generations").description("List LLM generations across traces").option("--trace-id <id>", "Filter by trace ID").option("--provider <provider>", "Filter by provider (OPEN_AI, ANTHROPIC, GOOGLE_AI)").option("--model <name>", "Filter by model name").option("--status <status>", "Filter by status (PENDING, RUNNING, COMPLETED, FAILED)").option("--agent-id <id>", "Filter by agent ID").option("--task-id <id>", "Filter by task ID").option("--start-date <iso>", "Filter from date").option("--end-date <iso>", "Filter to date").option("--min-cost <usd>", "Minimum cost in USD").option("--max-cost <usd>", "Maximum cost in USD").addHelpText(
|
|
12860
|
+
"after",
|
|
12861
|
+
`
|
|
12862
|
+
Examples:
|
|
12863
|
+
$ nexus tracing generations
|
|
12864
|
+
$ nexus tracing generations --provider ANTHROPIC --status FAILED
|
|
12865
|
+
$ nexus tracing generations --trace-id abc-123 --json`
|
|
12866
|
+
)
|
|
12867
|
+
).action(async (opts) => {
|
|
12868
|
+
try {
|
|
12869
|
+
const client = createClient(program2.optsWithGlobals());
|
|
12870
|
+
const { data, meta } = await client.tracing.listGenerations({
|
|
12871
|
+
...getPaginationParams(opts),
|
|
12872
|
+
traceId: opts.traceId,
|
|
12873
|
+
provider: opts.provider,
|
|
12874
|
+
modelName: opts.model,
|
|
12875
|
+
status: opts.status,
|
|
12876
|
+
agentId: opts.agentId,
|
|
12877
|
+
taskId: opts.taskId,
|
|
12878
|
+
startDate: opts.startDate,
|
|
12879
|
+
endDate: opts.endDate,
|
|
12880
|
+
minCostUsd: opts.minCost ? parseFloat(opts.minCost) : void 0,
|
|
12881
|
+
maxCostUsd: opts.maxCost ? parseFloat(opts.maxCost) : void 0
|
|
12882
|
+
});
|
|
12883
|
+
printList(data, meta, [
|
|
12884
|
+
{ key: "id", label: "ID", width: 36 },
|
|
12885
|
+
{ key: "traceId", label: "TRACE", width: 36 },
|
|
12886
|
+
{ key: "modelName", label: "MODEL", width: 25 },
|
|
12887
|
+
{ key: "status", label: "STATUS", width: 12, format: formatStatus },
|
|
12888
|
+
{
|
|
12889
|
+
key: "costUsd",
|
|
12890
|
+
label: "COST ($)",
|
|
12891
|
+
width: 10,
|
|
12892
|
+
format: (v) => v != null ? `$${Number(v).toFixed(6)}` : "-"
|
|
12893
|
+
},
|
|
12894
|
+
{
|
|
12895
|
+
key: "durationMs",
|
|
12896
|
+
label: "DURATION",
|
|
12897
|
+
width: 10,
|
|
12898
|
+
format: (v) => v != null ? `${v}ms` : "-"
|
|
12899
|
+
}
|
|
12900
|
+
]);
|
|
12901
|
+
} catch (err) {
|
|
12902
|
+
process.exitCode = handleError(err);
|
|
12903
|
+
}
|
|
12904
|
+
});
|
|
12905
|
+
tracing.command("generation").description("Get generation details including prompt and response").argument("<id>", "Generation ID").addHelpText(
|
|
12906
|
+
"after",
|
|
12907
|
+
`
|
|
12908
|
+
Examples:
|
|
12909
|
+
$ nexus tracing generation gen-123
|
|
12910
|
+
$ nexus tracing generation gen-123 --json`
|
|
12911
|
+
).action(async (id) => {
|
|
12912
|
+
try {
|
|
12913
|
+
const client = createClient(program2.optsWithGlobals());
|
|
12914
|
+
const gen = await client.tracing.getGeneration(id);
|
|
12915
|
+
printRecord(gen, [
|
|
12916
|
+
{ key: "id", label: "ID" },
|
|
12917
|
+
{ key: "traceId", label: "Trace ID" },
|
|
12918
|
+
{ key: "provider", label: "Provider" },
|
|
12919
|
+
{ key: "modelName", label: "Model" },
|
|
12920
|
+
{ key: "status", label: "Status" },
|
|
12921
|
+
{ key: "inputTokens", label: "Input Tokens" },
|
|
12922
|
+
{ key: "outputTokens", label: "Output Tokens" },
|
|
12923
|
+
{
|
|
12924
|
+
key: "costUsd",
|
|
12925
|
+
label: "Cost ($)",
|
|
12926
|
+
format: (v) => v != null ? `$${Number(v).toFixed(6)}` : "-"
|
|
12927
|
+
},
|
|
12928
|
+
{ key: "durationMs", label: "Duration (ms)" },
|
|
12929
|
+
{ key: "temperature", label: "Temperature" },
|
|
12930
|
+
{ key: "taskName", label: "Task" },
|
|
12931
|
+
{ key: "startedAt", label: "Started" },
|
|
12932
|
+
{ key: "completedAt", label: "Completed" },
|
|
12933
|
+
{ key: "errorMessage", label: "Error" }
|
|
12934
|
+
]);
|
|
12935
|
+
} catch (err) {
|
|
12936
|
+
process.exitCode = handleError(err);
|
|
12937
|
+
}
|
|
12938
|
+
});
|
|
12939
|
+
tracing.command("models").description("List distinct model names used in traces").addHelpText(
|
|
12940
|
+
"after",
|
|
12941
|
+
`
|
|
12942
|
+
Examples:
|
|
12943
|
+
$ nexus tracing models`
|
|
12944
|
+
).action(async () => {
|
|
12945
|
+
try {
|
|
12946
|
+
const client = createClient(program2.optsWithGlobals());
|
|
12947
|
+
const models = await client.tracing.listModels();
|
|
12948
|
+
if (Array.isArray(models) && models.length > 0) {
|
|
12949
|
+
for (const m of models) console.log(m);
|
|
12950
|
+
} else {
|
|
12951
|
+
console.log("No models found.");
|
|
12952
|
+
}
|
|
12953
|
+
} catch (err) {
|
|
12954
|
+
process.exitCode = handleError(err);
|
|
12955
|
+
}
|
|
12956
|
+
});
|
|
12957
|
+
tracing.command("summary").description("Get tracing analytics summary").option("--start-date <iso>", "Period start (ISO 8601)").option("--end-date <iso>", "Period end (ISO 8601)").addHelpText(
|
|
12958
|
+
"after",
|
|
12959
|
+
`
|
|
12960
|
+
Examples:
|
|
12961
|
+
$ nexus tracing summary
|
|
12962
|
+
$ nexus tracing summary --start-date 2026-03-01 --end-date 2026-03-30
|
|
12963
|
+
$ nexus tracing summary --json`
|
|
12964
|
+
).action(async (opts) => {
|
|
12965
|
+
try {
|
|
12966
|
+
const client = createClient(program2.optsWithGlobals());
|
|
12967
|
+
const summary = await client.tracing.getSummary({
|
|
12968
|
+
startDate: opts.startDate,
|
|
12969
|
+
endDate: opts.endDate
|
|
12970
|
+
});
|
|
12971
|
+
printRecord(summary, [
|
|
12972
|
+
{ key: "totalTraces", label: "Total Traces" },
|
|
12973
|
+
{ key: "completedTraces", label: "Completed" },
|
|
12974
|
+
{ key: "failedTraces", label: "Failed" },
|
|
12975
|
+
{ key: "inProgressTraces", label: "In Progress" },
|
|
12976
|
+
{
|
|
12977
|
+
key: "totalCostUsd",
|
|
12978
|
+
label: "Total Cost ($)",
|
|
12979
|
+
format: (v) => `$${Number(v).toFixed(4)}`
|
|
12980
|
+
},
|
|
12981
|
+
{ key: "totalInputTokens", label: "Input Tokens" },
|
|
12982
|
+
{ key: "totalOutputTokens", label: "Output Tokens" },
|
|
12983
|
+
{
|
|
12984
|
+
key: "avgDurationMs",
|
|
12985
|
+
label: "Avg Duration",
|
|
12986
|
+
format: (v) => v != null ? `${Number(v).toFixed(0)}ms` : "-"
|
|
12987
|
+
},
|
|
12988
|
+
{ key: "distinctModelCount", label: "Distinct Models" }
|
|
12989
|
+
]);
|
|
12990
|
+
} catch (err) {
|
|
12991
|
+
process.exitCode = handleError(err);
|
|
12992
|
+
}
|
|
12993
|
+
});
|
|
12994
|
+
tracing.command("cost-breakdown").description("Get cost breakdown by model, agent, or workflow").option("--group-by <key>", "Group by (model, agent, workflow)", "model").option("--start-date <iso>", "Period start").option("--end-date <iso>", "Period end").addHelpText(
|
|
12995
|
+
"after",
|
|
12996
|
+
`
|
|
12997
|
+
Examples:
|
|
12998
|
+
$ nexus tracing cost-breakdown
|
|
12999
|
+
$ nexus tracing cost-breakdown --group-by agent
|
|
13000
|
+
$ nexus tracing cost-breakdown --group-by workflow --json`
|
|
13001
|
+
).action(async (opts) => {
|
|
13002
|
+
try {
|
|
13003
|
+
const client = createClient(program2.optsWithGlobals());
|
|
13004
|
+
const result = await client.tracing.getCostBreakdown({
|
|
13005
|
+
groupBy: opts.groupBy,
|
|
13006
|
+
startDate: opts.startDate,
|
|
13007
|
+
endDate: opts.endDate
|
|
13008
|
+
});
|
|
13009
|
+
const entries = result.entries ?? [];
|
|
13010
|
+
printList(entries, void 0, [
|
|
13011
|
+
{ key: "groupKey", label: "KEY", width: 36 },
|
|
13012
|
+
{ key: "groupLabel", label: "LABEL", width: 25 },
|
|
13013
|
+
{
|
|
13014
|
+
key: "totalCostUsd",
|
|
13015
|
+
label: "COST ($)",
|
|
13016
|
+
width: 12,
|
|
13017
|
+
format: (v) => `$${Number(v).toFixed(4)}`
|
|
13018
|
+
},
|
|
13019
|
+
{ key: "traceCount", label: "TRACES", width: 8 },
|
|
13020
|
+
{ key: "generationCount", label: "GENS", width: 8 },
|
|
13021
|
+
{ key: "totalInputTokens", label: "IN TOKENS", width: 12 },
|
|
13022
|
+
{ key: "totalOutputTokens", label: "OUT TOKENS", width: 12 }
|
|
13023
|
+
]);
|
|
13024
|
+
} catch (err) {
|
|
13025
|
+
process.exitCode = handleError(err);
|
|
13026
|
+
}
|
|
13027
|
+
});
|
|
13028
|
+
tracing.command("timeline").description("Get tracing timeline data").option("--granularity <g>", "Granularity (hour, day, week)", "day").option("--start-date <iso>", "Period start").option("--end-date <iso>", "Period end").addHelpText(
|
|
13029
|
+
"after",
|
|
13030
|
+
`
|
|
13031
|
+
Examples:
|
|
13032
|
+
$ nexus tracing timeline
|
|
13033
|
+
$ nexus tracing timeline --granularity hour --start-date 2026-03-29 --json`
|
|
13034
|
+
).action(async (opts) => {
|
|
13035
|
+
try {
|
|
13036
|
+
const client = createClient(program2.optsWithGlobals());
|
|
13037
|
+
const result = await client.tracing.getTimeline({
|
|
13038
|
+
granularity: opts.granularity,
|
|
13039
|
+
startDate: opts.startDate,
|
|
13040
|
+
endDate: opts.endDate
|
|
13041
|
+
});
|
|
13042
|
+
const points = result.points ?? [];
|
|
13043
|
+
printList(points, void 0, [
|
|
13044
|
+
{ key: "date", label: "DATE", width: 22 },
|
|
13045
|
+
{ key: "traceCount", label: "TRACES", width: 8 },
|
|
13046
|
+
{ key: "generationCount", label: "GENS", width: 8 },
|
|
13047
|
+
{
|
|
13048
|
+
key: "totalCostUsd",
|
|
13049
|
+
label: "COST ($)",
|
|
13050
|
+
width: 12,
|
|
13051
|
+
format: (v) => `$${Number(v).toFixed(4)}`
|
|
13052
|
+
},
|
|
13053
|
+
{
|
|
13054
|
+
key: "avgDurationMs",
|
|
13055
|
+
label: "AVG DUR",
|
|
13056
|
+
width: 10,
|
|
13057
|
+
format: (v) => v != null ? `${Number(v).toFixed(0)}ms` : "-"
|
|
13058
|
+
}
|
|
13059
|
+
]);
|
|
13060
|
+
} catch (err) {
|
|
13061
|
+
process.exitCode = handleError(err);
|
|
13062
|
+
}
|
|
13063
|
+
});
|
|
13064
|
+
tracing.command("export").description("Export a single trace").argument("<id>", "Trace ID").option("--format <fmt>", "Output format (json, csv)", "json").addHelpText(
|
|
13065
|
+
"after",
|
|
13066
|
+
`
|
|
13067
|
+
Examples:
|
|
13068
|
+
$ nexus tracing export abc-123
|
|
13069
|
+
$ nexus tracing export abc-123 --format csv > trace.csv`
|
|
13070
|
+
).action(async (id, opts) => {
|
|
13071
|
+
try {
|
|
13072
|
+
const client = createClient(program2.optsWithGlobals());
|
|
13073
|
+
const result = await client.tracing.exportTrace(id, { format: opts.format });
|
|
13074
|
+
console.log(result.content);
|
|
13075
|
+
} catch (err) {
|
|
13076
|
+
process.exitCode = handleError(err);
|
|
13077
|
+
}
|
|
13078
|
+
});
|
|
13079
|
+
tracing.command("export-bulk").description("Bulk export traces (max 1000)").option("--format <fmt>", "Output format (json, csv)", "json").option("--status <status>", "Filter by status").option("--agent-id <id>", "Filter by agent ID").option("--workflow-id <id>", "Filter by workflow ID").option("--start-date <iso>", "Filter from date").option("--end-date <iso>", "Filter to date").option("--limit <n>", "Max traces to export", "100").addHelpText(
|
|
13080
|
+
"after",
|
|
13081
|
+
`
|
|
13082
|
+
Examples:
|
|
13083
|
+
$ nexus tracing export-bulk --format csv > traces.csv
|
|
13084
|
+
$ nexus tracing export-bulk --status FAILED --limit 50`
|
|
13085
|
+
).action(async (opts) => {
|
|
13086
|
+
try {
|
|
13087
|
+
const client = createClient(program2.optsWithGlobals());
|
|
13088
|
+
const result = await client.tracing.bulkExport({
|
|
13089
|
+
format: opts.format,
|
|
13090
|
+
status: opts.status,
|
|
13091
|
+
agentId: opts.agentId,
|
|
13092
|
+
workflowId: opts.workflowId,
|
|
13093
|
+
startDate: opts.startDate,
|
|
13094
|
+
endDate: opts.endDate,
|
|
13095
|
+
limit: parseInt(opts.limit, 10)
|
|
13096
|
+
});
|
|
13097
|
+
console.log(result.content);
|
|
13098
|
+
} catch (err) {
|
|
13099
|
+
process.exitCode = handleError(err);
|
|
13100
|
+
}
|
|
13101
|
+
});
|
|
13102
|
+
}
|
|
13103
|
+
function formatStatus(v) {
|
|
13104
|
+
const s = String(v);
|
|
13105
|
+
if (s === "COMPLETED") return color.green(s);
|
|
13106
|
+
if (s === "FAILED") return color.red(s);
|
|
13107
|
+
if (s === "IN_PROGRESS" || s === "RUNNING") return color.yellow(s);
|
|
13108
|
+
if (s === "PENDING") return color.dim(s);
|
|
13109
|
+
return s;
|
|
13110
|
+
}
|
|
13111
|
+
|
|
12033
13112
|
// src/commands/upgrade.ts
|
|
12034
13113
|
var import_node_child_process3 = require("child_process");
|
|
12035
13114
|
init_output();
|
|
12036
13115
|
|
|
12037
13116
|
// src/util/package-manager.ts
|
|
12038
|
-
var
|
|
13117
|
+
var import_node_fs5 = __toESM(require("fs"));
|
|
12039
13118
|
function detectPackageManager() {
|
|
12040
13119
|
try {
|
|
12041
|
-
const resolved =
|
|
13120
|
+
const resolved = import_node_fs5.default.realpathSync(process.argv[1]).replace(/\\/g, "/");
|
|
12042
13121
|
if (/[/]\.?pnpm[/]/.test(resolved)) return "pnpm";
|
|
12043
13122
|
if (/[/]\.yarn[/]/.test(resolved)) return "yarn";
|
|
12044
13123
|
} catch {
|
|
@@ -12069,7 +13148,7 @@ function getGlobalUpdateHint(pkg) {
|
|
|
12069
13148
|
}
|
|
12070
13149
|
|
|
12071
13150
|
// src/util/version-check.ts
|
|
12072
|
-
var
|
|
13151
|
+
var import_node_fs6 = __toESM(require("fs"));
|
|
12073
13152
|
var import_node_os2 = __toESM(require("os"));
|
|
12074
13153
|
var import_node_path4 = __toESM(require("path"));
|
|
12075
13154
|
var PACKAGE_NAME = "@agent-nexus/cli";
|
|
@@ -12078,7 +13157,7 @@ var FETCH_TIMEOUT_MS = 3e3;
|
|
|
12078
13157
|
var CACHE_FILE = import_node_path4.default.join(import_node_os2.default.homedir(), ".nexus-mcp", "version-check.json");
|
|
12079
13158
|
function loadCache() {
|
|
12080
13159
|
try {
|
|
12081
|
-
return JSON.parse(
|
|
13160
|
+
return JSON.parse(import_node_fs6.default.readFileSync(CACHE_FILE, "utf-8"));
|
|
12082
13161
|
} catch {
|
|
12083
13162
|
return null;
|
|
12084
13163
|
}
|
|
@@ -12086,8 +13165,8 @@ function loadCache() {
|
|
|
12086
13165
|
function saveCache(cache) {
|
|
12087
13166
|
try {
|
|
12088
13167
|
const dir = import_node_path4.default.dirname(CACHE_FILE);
|
|
12089
|
-
|
|
12090
|
-
|
|
13168
|
+
import_node_fs6.default.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
13169
|
+
import_node_fs6.default.writeFileSync(CACHE_FILE, JSON.stringify(cache), { mode: 384 });
|
|
12091
13170
|
} catch {
|
|
12092
13171
|
}
|
|
12093
13172
|
}
|
|
@@ -12174,11 +13253,29 @@ async function autoUpdate(currentVersion) {
|
|
|
12174
13253
|
|
|
12175
13254
|
// src/commands/upgrade.ts
|
|
12176
13255
|
var PACKAGE_NAME2 = "@agent-nexus/cli";
|
|
13256
|
+
var UPGRADE_ALIASES = [
|
|
13257
|
+
"update",
|
|
13258
|
+
"latest",
|
|
13259
|
+
"up",
|
|
13260
|
+
"install",
|
|
13261
|
+
"reinstall",
|
|
13262
|
+
"refresh",
|
|
13263
|
+
"fetch",
|
|
13264
|
+
"pull",
|
|
13265
|
+
"sync",
|
|
13266
|
+
"get",
|
|
13267
|
+
"download",
|
|
13268
|
+
"self-update",
|
|
13269
|
+
"selfupdate",
|
|
13270
|
+
"self-upgrade",
|
|
13271
|
+
"selfupgrade",
|
|
13272
|
+
"new",
|
|
13273
|
+
"patch",
|
|
13274
|
+
"bump"
|
|
13275
|
+
];
|
|
12177
13276
|
function registerUpgradeCommand(program2) {
|
|
12178
13277
|
const currentVersion = require_package().version;
|
|
12179
|
-
|
|
12180
|
-
Examples:
|
|
12181
|
-
$ nexus upgrade`).action(async () => {
|
|
13278
|
+
const upgradeAction = async () => {
|
|
12182
13279
|
process.stderr.write(`Current version: ${color.cyan(currentVersion)}
|
|
12183
13280
|
`);
|
|
12184
13281
|
process.stderr.write("Checking for updates\u2026\n");
|
|
@@ -12208,7 +13305,13 @@ Upgrade failed. Try running manually:
|
|
|
12208
13305
|
);
|
|
12209
13306
|
process.exitCode = 1;
|
|
12210
13307
|
}
|
|
12211
|
-
}
|
|
13308
|
+
};
|
|
13309
|
+
program2.command("upgrade").description("Upgrade the Nexus CLI to the latest version").addHelpText("after", `
|
|
13310
|
+
Examples:
|
|
13311
|
+
$ nexus upgrade`).action(upgradeAction);
|
|
13312
|
+
for (const alias of UPGRADE_ALIASES) {
|
|
13313
|
+
program2.command(alias, { hidden: true }).action(upgradeAction);
|
|
13314
|
+
}
|
|
12212
13315
|
}
|
|
12213
13316
|
|
|
12214
13317
|
// src/commands/version.ts
|
|
@@ -12993,7 +14096,7 @@ Examples:
|
|
|
12993
14096
|
// src/index.ts
|
|
12994
14097
|
init_output();
|
|
12995
14098
|
var { version: VERSION } = require_package();
|
|
12996
|
-
var program = new import_commander.Command().name("nexus").description("Official CLI for the Nexus AI agent platform").version(VERSION, "-v, --version").option("--json", "Output as JSON").option("--api-key <key>", "Override API key for this invocation").option("--base-url <url>", "Override API base URL").option("--profile <name>", "Use a specific named profile").option("--no-auto-update", "Disable automatic updates when a new version is detected").hook("preAction", (thisCommand) => {
|
|
14099
|
+
var program = new import_commander.Command().name("nexus").description("Official CLI for the Nexus AI agent platform").version(VERSION, "-v, --version").option("--json", "Output as JSON").option("--api-key <key>", "Override API key for this invocation").option("--base-url <url>", "Override API base URL").option("--dashboard-url <url>", "Override dashboard URL (for browser links)").option("--profile <name>", "Use a specific named profile").option("--no-auto-update", "Disable automatic updates when a new version is detected").hook("preAction", (thisCommand) => {
|
|
12997
14100
|
const opts = thisCommand.optsWithGlobals();
|
|
12998
14101
|
if (opts.json) setJsonMode(true);
|
|
12999
14102
|
const cmdName = thisCommand.name();
|
|
@@ -13009,7 +14112,8 @@ var program = new import_commander.Command().name("nexus").description("Official
|
|
|
13009
14112
|
"pin",
|
|
13010
14113
|
"unpin",
|
|
13011
14114
|
"status",
|
|
13012
|
-
"docs"
|
|
14115
|
+
"docs",
|
|
14116
|
+
...UPGRADE_ALIASES
|
|
13013
14117
|
].includes(cmdName);
|
|
13014
14118
|
if (!skipBanner && !isJsonMode()) {
|
|
13015
14119
|
try {
|
|
@@ -13054,6 +14158,7 @@ registerModelCommands(program);
|
|
|
13054
14158
|
registerCustomModelCommands(program);
|
|
13055
14159
|
registerPhoneNumberCommands(program);
|
|
13056
14160
|
registerChannelCommands(program);
|
|
14161
|
+
registerTracingCommands(program);
|
|
13057
14162
|
registerUpgradeCommand(program);
|
|
13058
14163
|
registerDocsCommand(program);
|
|
13059
14164
|
if (process.argv.length <= 2) {
|
|
@@ -13062,7 +14167,7 @@ if (process.argv.length <= 2) {
|
|
|
13062
14167
|
program.parseAsync(process.argv).then(async () => {
|
|
13063
14168
|
if (isJsonMode()) return;
|
|
13064
14169
|
const ranCommand = process.argv[2];
|
|
13065
|
-
if (ranCommand === "upgrade") return;
|
|
14170
|
+
if (ranCommand === "upgrade" || UPGRADE_ALIASES.includes(ranCommand)) return;
|
|
13066
14171
|
const opts = program.opts();
|
|
13067
14172
|
if (opts.autoUpdate) {
|
|
13068
14173
|
const msg = await autoUpdate(VERSION);
|