@wayai/cli 0.3.92 → 0.3.94
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/index.js +227 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -561,6 +561,15 @@ var init_api_client = __esm({
|
|
|
561
561
|
const qs = new URLSearchParams({ hub_id: hubId });
|
|
562
562
|
return this.request("GET", `/api/setup/connections?${qs.toString()}`);
|
|
563
563
|
}
|
|
564
|
+
/**
|
|
565
|
+
* Active operational alerts (Status & Notices) for a hub — the same runtime
|
|
566
|
+
* connection/credential-health surface the web app shows. Requires `hub:read`.
|
|
567
|
+
* The read surface never carries a provider error body (only provider +
|
|
568
|
+
* status_code + category + counts), so it's safe to print verbatim.
|
|
569
|
+
*/
|
|
570
|
+
async getHubAlerts(hubId) {
|
|
571
|
+
return this.request("GET", `/api/hubs/${encodeURIComponent(hubId)}/alerts`);
|
|
572
|
+
}
|
|
564
573
|
/** Set a credential on a PREVIEW connection (direct secret or org-credential link). */
|
|
565
574
|
async setPreviewConnectionCredential(connectionId, body) {
|
|
566
575
|
return this.request("PATCH", `/api/setup/connections/${connectionId}`, body);
|
|
@@ -5475,10 +5484,11 @@ var init_dist = __esm({
|
|
|
5475
5484
|
};
|
|
5476
5485
|
LLM_PROVIDER_HTTP_BRAND = /* @__PURE__ */ Symbol.for("wayai.LlmProviderHttpError");
|
|
5477
5486
|
LlmProviderHttpError = class extends Error {
|
|
5478
|
-
constructor(message, status, provider) {
|
|
5487
|
+
constructor(message, status, provider, providerError) {
|
|
5479
5488
|
super(message);
|
|
5480
5489
|
this.status = status;
|
|
5481
5490
|
this.provider = provider;
|
|
5491
|
+
this.providerError = providerError;
|
|
5482
5492
|
this.name = "LlmProviderHttpError";
|
|
5483
5493
|
}
|
|
5484
5494
|
[LLM_PROVIDER_HTTP_BRAND] = true;
|
|
@@ -7906,6 +7916,10 @@ var init_dist = __esm({
|
|
|
7906
7916
|
category: external_exports.string(),
|
|
7907
7917
|
provider: external_exports.string().nullable(),
|
|
7908
7918
|
status_code: external_exports.number().nullable(),
|
|
7919
|
+
// Credential-safe structured reason (type/code/param, e.g. "invalid_request_error ·
|
|
7920
|
+
// response_format") — NEVER the provider error body. Null when the producer had no
|
|
7921
|
+
// structured detail. gh #3164.
|
|
7922
|
+
detail: external_exports.string().nullable(),
|
|
7909
7923
|
severity: hubAlertSeverity,
|
|
7910
7924
|
status: external_exports.enum(["active", "resolved"]),
|
|
7911
7925
|
count: external_exports.number(),
|
|
@@ -8780,7 +8794,8 @@ var init_utils = __esm({
|
|
|
8780
8794
|
"eval",
|
|
8781
8795
|
"admin",
|
|
8782
8796
|
"report",
|
|
8783
|
-
"conversations"
|
|
8797
|
+
"conversations",
|
|
8798
|
+
"alerts"
|
|
8784
8799
|
]);
|
|
8785
8800
|
}
|
|
8786
8801
|
});
|
|
@@ -14797,6 +14812,10 @@ var init_contracts = __esm({
|
|
|
14797
14812
|
category: external_exports.string(),
|
|
14798
14813
|
provider: external_exports.string().nullable(),
|
|
14799
14814
|
status_code: external_exports.number().nullable(),
|
|
14815
|
+
// Credential-safe structured reason (type/code/param, e.g. "invalid_request_error ·
|
|
14816
|
+
// response_format") — NEVER the provider error body. Null when the producer had no
|
|
14817
|
+
// structured detail. gh #3164.
|
|
14818
|
+
detail: external_exports.string().nullable(),
|
|
14800
14819
|
severity: hubAlertSeverity2,
|
|
14801
14820
|
status: external_exports.enum(["active", "resolved"]),
|
|
14802
14821
|
count: external_exports.number(),
|
|
@@ -15998,6 +16017,191 @@ var init_conversations = __esm({
|
|
|
15998
16017
|
}
|
|
15999
16018
|
});
|
|
16000
16019
|
|
|
16020
|
+
// src/lib/hub-alerts.ts
|
|
16021
|
+
function severityGlyph(severity) {
|
|
16022
|
+
switch (severity) {
|
|
16023
|
+
case "critical":
|
|
16024
|
+
return "\u2716";
|
|
16025
|
+
case "warn":
|
|
16026
|
+
return "\u26A0";
|
|
16027
|
+
default:
|
|
16028
|
+
return "\u2139";
|
|
16029
|
+
}
|
|
16030
|
+
}
|
|
16031
|
+
function formatProviderBits(alert) {
|
|
16032
|
+
return [alert.provider, alert.status_code != null ? `${alert.status_code}` : null].filter(Boolean).join(" ");
|
|
16033
|
+
}
|
|
16034
|
+
function formatAlertTarget(alert, resolveLabel) {
|
|
16035
|
+
if (alert.connection_id) {
|
|
16036
|
+
return resolveLabel?.(alert.connection_id) ?? `connection ${alert.connection_id}`;
|
|
16037
|
+
}
|
|
16038
|
+
if (alert.channel_id) return `channel ${alert.channel_id}`;
|
|
16039
|
+
return "\u2014";
|
|
16040
|
+
}
|
|
16041
|
+
function describeCategory(category) {
|
|
16042
|
+
switch (category) {
|
|
16043
|
+
case "connection_auth":
|
|
16044
|
+
return {
|
|
16045
|
+
label: "Credential rejected",
|
|
16046
|
+
hint: "The provider rejected this connection's credential (auth). Update the API key/credential on the connection."
|
|
16047
|
+
};
|
|
16048
|
+
case "connection_quota":
|
|
16049
|
+
return {
|
|
16050
|
+
label: "Quota / rate limit",
|
|
16051
|
+
hint: "The provider returned a quota or rate-limit error. Check the provider account's usage/billing."
|
|
16052
|
+
};
|
|
16053
|
+
// gh #3164 — a 400 is a request/config rejection, NOT a bad credential. Labeling
|
|
16054
|
+
// it "Credential rejected" points admins at rotating a healthy key.
|
|
16055
|
+
case "connection_config":
|
|
16056
|
+
return {
|
|
16057
|
+
label: "Request config rejected",
|
|
16058
|
+
hint: "The provider rejected the request configuration (400). Check the connection's model or settings (e.g. an unsupported response_format) \u2014 the credential is fine."
|
|
16059
|
+
};
|
|
16060
|
+
case "channel_token":
|
|
16061
|
+
return {
|
|
16062
|
+
label: "Channel token invalid",
|
|
16063
|
+
hint: "The channel token is expired or revoked. Reconnect the channel to refresh it."
|
|
16064
|
+
};
|
|
16065
|
+
case "tool_auth":
|
|
16066
|
+
return {
|
|
16067
|
+
label: "Tool auth failed",
|
|
16068
|
+
hint: "An external tool/MCP server rejected auth. Re-authorize the tool connection."
|
|
16069
|
+
};
|
|
16070
|
+
case "production_credential_missing":
|
|
16071
|
+
return {
|
|
16072
|
+
label: "Production credential missing",
|
|
16073
|
+
hint: "A production connection has no credential. Set it with `wayai set-connection-credential`."
|
|
16074
|
+
};
|
|
16075
|
+
default:
|
|
16076
|
+
if (category.startsWith("provider:")) {
|
|
16077
|
+
return {
|
|
16078
|
+
label: "Provider degraded",
|
|
16079
|
+
hint: "An upstream provider is degraded (platform-level). Usually clears on its own once the provider recovers."
|
|
16080
|
+
};
|
|
16081
|
+
}
|
|
16082
|
+
return { label: category, hint: "Tenant-actionable connection/credential alert \u2014 inspect the connection in the hub UI." };
|
|
16083
|
+
}
|
|
16084
|
+
}
|
|
16085
|
+
function activeAlerts(alerts) {
|
|
16086
|
+
return alerts.filter((a) => a.status === "active");
|
|
16087
|
+
}
|
|
16088
|
+
function summarizeActiveAlertsForReport(alerts) {
|
|
16089
|
+
const active = activeAlerts(alerts);
|
|
16090
|
+
if (active.length === 0) return null;
|
|
16091
|
+
const lines = active.map((a) => {
|
|
16092
|
+
const { label } = describeCategory(a.category);
|
|
16093
|
+
const target = formatAlertTarget(a);
|
|
16094
|
+
const providerBits = formatProviderBits(a);
|
|
16095
|
+
const detailBit = a.detail ? ` \xB7 ${a.detail}` : "";
|
|
16096
|
+
return `- [${a.severity}] ${a.category} (${label}) \xB7 ${target}${providerBits ? ` \xB7 ${providerBits}` : ""}${detailBit} \xB7 seen ${a.count}\xD7`;
|
|
16097
|
+
});
|
|
16098
|
+
return `Active hub alerts at report time (${active.length}):
|
|
16099
|
+
${lines.join("\n")}`;
|
|
16100
|
+
}
|
|
16101
|
+
var init_hub_alerts = __esm({
|
|
16102
|
+
"src/lib/hub-alerts.ts"() {
|
|
16103
|
+
"use strict";
|
|
16104
|
+
}
|
|
16105
|
+
});
|
|
16106
|
+
|
|
16107
|
+
// src/commands/alerts.ts
|
|
16108
|
+
var alerts_exports = {};
|
|
16109
|
+
__export(alerts_exports, {
|
|
16110
|
+
alertsCommand: () => alertsCommand
|
|
16111
|
+
});
|
|
16112
|
+
function printAlertsHelp() {
|
|
16113
|
+
console.error(`
|
|
16114
|
+
wayai alerts \u2014 show a hub's active operational alerts (Status & Notices)
|
|
16115
|
+
|
|
16116
|
+
Usage:
|
|
16117
|
+
wayai alerts Active alerts for the active hub
|
|
16118
|
+
wayai alerts --hub <uuid|name> For a specific hub (accepts a raw uuid without a workspace)
|
|
16119
|
+
wayai alerts --json Raw JSON output
|
|
16120
|
+
|
|
16121
|
+
Alerts are tenant-actionable connection/credential health signals raised at
|
|
16122
|
+
runtime \u2014 e.g. a provider rejecting a bad/expired key (\`connection_auth\`),
|
|
16123
|
+
a rate/quota limit (\`connection_quota\`), an expired channel token
|
|
16124
|
+
(\`channel_token\`), or a missing production credential. Run this FIRST when a
|
|
16125
|
+
hub misbehaves (audio/TTS not delivered, agent not replying, a tool failing)
|
|
16126
|
+
before reading code or filing a report.
|
|
16127
|
+
`.trim());
|
|
16128
|
+
}
|
|
16129
|
+
function fmtTime(iso) {
|
|
16130
|
+
const d = new Date(iso);
|
|
16131
|
+
return Number.isNaN(d.getTime()) ? iso : d.toLocaleString();
|
|
16132
|
+
}
|
|
16133
|
+
async function alertsCommand(args2) {
|
|
16134
|
+
if (wantsHelp(args2)) {
|
|
16135
|
+
printAlertsHelp();
|
|
16136
|
+
return;
|
|
16137
|
+
}
|
|
16138
|
+
const jsonIdx = args2.indexOf("--json");
|
|
16139
|
+
const jsonOutput = jsonIdx !== -1;
|
|
16140
|
+
if (jsonOutput) args2.splice(jsonIdx, 1);
|
|
16141
|
+
const hubId = resolveActiveHubId(args2);
|
|
16142
|
+
const { config, accessToken } = await requireAuth();
|
|
16143
|
+
const client = new ApiClient({ apiUrl: config.api_url, accessToken });
|
|
16144
|
+
let alerts;
|
|
16145
|
+
try {
|
|
16146
|
+
({ alerts } = await client.getHubAlerts(hubId));
|
|
16147
|
+
} catch (err) {
|
|
16148
|
+
if (err instanceof ApiError && err.status === 404) {
|
|
16149
|
+
console.error(`Hub ${hubId} not found, or you lack read access to it.`);
|
|
16150
|
+
process.exit(1);
|
|
16151
|
+
}
|
|
16152
|
+
if (err instanceof ApiError && err.status === 403) {
|
|
16153
|
+
console.error(`You don't have read access to hub ${hubId}.`);
|
|
16154
|
+
process.exit(1);
|
|
16155
|
+
}
|
|
16156
|
+
throw err;
|
|
16157
|
+
}
|
|
16158
|
+
const active = activeAlerts(alerts);
|
|
16159
|
+
if (jsonOutput) {
|
|
16160
|
+
console.log(JSON.stringify({ hub_id: hubId, alerts: active }, null, 2));
|
|
16161
|
+
return;
|
|
16162
|
+
}
|
|
16163
|
+
if (active.length === 0) {
|
|
16164
|
+
console.log(`Hub ${hubId} \u2014 no active alerts \u2713`);
|
|
16165
|
+
return;
|
|
16166
|
+
}
|
|
16167
|
+
const connLabels = /* @__PURE__ */ new Map();
|
|
16168
|
+
try {
|
|
16169
|
+
const { connections } = await client.listConnections(hubId);
|
|
16170
|
+
for (const conn of connections) {
|
|
16171
|
+
if (!conn.connection_id) continue;
|
|
16172
|
+
const name = conn.connection_display_name || conn.connector_name;
|
|
16173
|
+
connLabels.set(conn.connection_id, `${name} (${conn.connector_type})`);
|
|
16174
|
+
}
|
|
16175
|
+
} catch {
|
|
16176
|
+
}
|
|
16177
|
+
const noun = active.length === 1 ? "alert" : "alerts";
|
|
16178
|
+
console.log(`Hub ${hubId} \u2014 ${active.length} active ${noun}
|
|
16179
|
+
`);
|
|
16180
|
+
for (const a of active) {
|
|
16181
|
+
const { label, hint } = describeCategory(a.category);
|
|
16182
|
+
const target = formatAlertTarget(a, (id) => connLabels.get(id));
|
|
16183
|
+
const providerBits = formatProviderBits(a);
|
|
16184
|
+
console.log(`${severityGlyph(a.severity)} ${a.severity} ${a.category} \u2014 ${label}`);
|
|
16185
|
+
console.log(` ${target}${providerBits ? ` \xB7 ${providerBits}` : ""}${a.detail ? ` \xB7 ${a.detail}` : ""}`);
|
|
16186
|
+
console.log(` ${hint}`);
|
|
16187
|
+
if (a.org_credential_id) {
|
|
16188
|
+
console.log(` Shared org credential \u2014 fix it once at the org credential (\`wayai update-credential\`); it fans out to every hub linking it.`);
|
|
16189
|
+
}
|
|
16190
|
+
console.log(` seen ${a.count}\xD7 \xB7 first ${fmtTime(a.first_seen_at)} \xB7 last ${fmtTime(a.last_seen_at)}`);
|
|
16191
|
+
console.log("");
|
|
16192
|
+
}
|
|
16193
|
+
}
|
|
16194
|
+
var init_alerts = __esm({
|
|
16195
|
+
"src/commands/alerts.ts"() {
|
|
16196
|
+
"use strict";
|
|
16197
|
+
init_auth();
|
|
16198
|
+
init_workspace();
|
|
16199
|
+
init_api_client();
|
|
16200
|
+
init_utils();
|
|
16201
|
+
init_hub_alerts();
|
|
16202
|
+
}
|
|
16203
|
+
});
|
|
16204
|
+
|
|
16001
16205
|
// src/commands/delete-history.ts
|
|
16002
16206
|
var delete_history_exports = {};
|
|
16003
16207
|
__export(delete_history_exports, {
|
|
@@ -20445,6 +20649,19 @@ async function reportCreateCommand(args2, cliVersion = null) {
|
|
|
20445
20649
|
const client = new ApiClient({ apiUrl: config.api_url, accessToken });
|
|
20446
20650
|
const repoConfig = readRepoConfig();
|
|
20447
20651
|
const organizationId = repoConfig?.organization_id;
|
|
20652
|
+
let contextWithAlerts = context;
|
|
20653
|
+
if (hubId) {
|
|
20654
|
+
try {
|
|
20655
|
+
const { alerts } = await client.getHubAlerts(hubId);
|
|
20656
|
+
const alertSummary = summarizeActiveAlertsForReport(alerts);
|
|
20657
|
+
if (alertSummary) {
|
|
20658
|
+
contextWithAlerts = context ? `${context}
|
|
20659
|
+
|
|
20660
|
+
${alertSummary}` : alertSummary;
|
|
20661
|
+
}
|
|
20662
|
+
} catch {
|
|
20663
|
+
}
|
|
20664
|
+
}
|
|
20448
20665
|
try {
|
|
20449
20666
|
const result = await client.submitReport({
|
|
20450
20667
|
title,
|
|
@@ -20457,7 +20674,7 @@ async function reportCreateCommand(args2, cliVersion = null) {
|
|
|
20457
20674
|
conversation_id: conversationId,
|
|
20458
20675
|
error_message: errorMessage,
|
|
20459
20676
|
steps_to_reproduce: steps,
|
|
20460
|
-
additional_context:
|
|
20677
|
+
additional_context: contextWithAlerts,
|
|
20461
20678
|
client_version: clientVersion
|
|
20462
20679
|
});
|
|
20463
20680
|
if (result.created) {
|
|
@@ -20488,6 +20705,7 @@ var init_report_create = __esm({
|
|
|
20488
20705
|
init_auth();
|
|
20489
20706
|
init_repo_config();
|
|
20490
20707
|
init_api_client();
|
|
20708
|
+
init_hub_alerts();
|
|
20491
20709
|
init_version_status();
|
|
20492
20710
|
}
|
|
20493
20711
|
});
|
|
@@ -21054,6 +21272,11 @@ async function main() {
|
|
|
21054
21272
|
await conversationsCommand2(args);
|
|
21055
21273
|
break;
|
|
21056
21274
|
}
|
|
21275
|
+
case "alerts": {
|
|
21276
|
+
const { alertsCommand: alertsCommand2 } = await Promise.resolve().then(() => (init_alerts(), alerts_exports));
|
|
21277
|
+
await alertsCommand2(args);
|
|
21278
|
+
break;
|
|
21279
|
+
}
|
|
21057
21280
|
case "delete-history": {
|
|
21058
21281
|
const { deleteHistoryCommand: deleteHistoryCommand2 } = await Promise.resolve().then(() => (init_delete_history(), delete_history_exports));
|
|
21059
21282
|
await deleteHistoryCommand2(args);
|
|
@@ -21187,6 +21410,7 @@ Commands:
|
|
|
21187
21410
|
unbind Clear the worktree hub binding
|
|
21188
21411
|
send-message Send a test message to a hub (preview or production)
|
|
21189
21412
|
conversations List or inspect conversations
|
|
21413
|
+
alerts Show a hub's active connection/credential alerts (run this FIRST when a hub misbehaves)
|
|
21190
21414
|
analytics Show analytics summary and metrics (use \`analytics query\` for structured ClickHouse queries)
|
|
21191
21415
|
delete-history Delete your conversations on a hub (--conversation-id <id> for just one)
|
|
21192
21416
|
evals List evaluation scenarios for the current hub (use \`evals sql\` for read-only SQL on eval results)
|