@wayai/cli 0.3.92 → 0.3.93

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 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);
@@ -8780,7 +8789,8 @@ var init_utils = __esm({
8780
8789
  "eval",
8781
8790
  "admin",
8782
8791
  "report",
8783
- "conversations"
8792
+ "conversations",
8793
+ "alerts"
8784
8794
  ]);
8785
8795
  }
8786
8796
  });
@@ -15998,6 +16008,183 @@ var init_conversations = __esm({
15998
16008
  }
15999
16009
  });
16000
16010
 
16011
+ // src/lib/hub-alerts.ts
16012
+ function severityGlyph(severity) {
16013
+ switch (severity) {
16014
+ case "critical":
16015
+ return "\u2716";
16016
+ case "warn":
16017
+ return "\u26A0";
16018
+ default:
16019
+ return "\u2139";
16020
+ }
16021
+ }
16022
+ function formatProviderBits(alert) {
16023
+ return [alert.provider, alert.status_code != null ? `${alert.status_code}` : null].filter(Boolean).join(" ");
16024
+ }
16025
+ function formatAlertTarget(alert, resolveLabel) {
16026
+ if (alert.connection_id) {
16027
+ return resolveLabel?.(alert.connection_id) ?? `connection ${alert.connection_id}`;
16028
+ }
16029
+ if (alert.channel_id) return `channel ${alert.channel_id}`;
16030
+ return "\u2014";
16031
+ }
16032
+ function describeCategory(category) {
16033
+ switch (category) {
16034
+ case "connection_auth":
16035
+ return {
16036
+ label: "Credential rejected",
16037
+ hint: "The provider rejected this connection's credential (auth). Update the API key/credential on the connection."
16038
+ };
16039
+ case "connection_quota":
16040
+ return {
16041
+ label: "Quota / rate limit",
16042
+ hint: "The provider returned a quota or rate-limit error. Check the provider account's usage/billing."
16043
+ };
16044
+ case "channel_token":
16045
+ return {
16046
+ label: "Channel token invalid",
16047
+ hint: "The channel token is expired or revoked. Reconnect the channel to refresh it."
16048
+ };
16049
+ case "tool_auth":
16050
+ return {
16051
+ label: "Tool auth failed",
16052
+ hint: "An external tool/MCP server rejected auth. Re-authorize the tool connection."
16053
+ };
16054
+ case "production_credential_missing":
16055
+ return {
16056
+ label: "Production credential missing",
16057
+ hint: "A production connection has no credential. Set it with `wayai set-connection-credential`."
16058
+ };
16059
+ default:
16060
+ if (category.startsWith("provider:")) {
16061
+ return {
16062
+ label: "Provider degraded",
16063
+ hint: "An upstream provider is degraded (platform-level). Usually clears on its own once the provider recovers."
16064
+ };
16065
+ }
16066
+ return { label: category, hint: "Tenant-actionable connection/credential alert \u2014 inspect the connection in the hub UI." };
16067
+ }
16068
+ }
16069
+ function activeAlerts(alerts) {
16070
+ return alerts.filter((a) => a.status === "active");
16071
+ }
16072
+ function summarizeActiveAlertsForReport(alerts) {
16073
+ const active = activeAlerts(alerts);
16074
+ if (active.length === 0) return null;
16075
+ const lines = active.map((a) => {
16076
+ const { label } = describeCategory(a.category);
16077
+ const target = formatAlertTarget(a);
16078
+ const providerBits = formatProviderBits(a);
16079
+ return `- [${a.severity}] ${a.category} (${label}) \xB7 ${target}${providerBits ? ` \xB7 ${providerBits}` : ""} \xB7 seen ${a.count}\xD7`;
16080
+ });
16081
+ return `Active hub alerts at report time (${active.length}):
16082
+ ${lines.join("\n")}`;
16083
+ }
16084
+ var init_hub_alerts = __esm({
16085
+ "src/lib/hub-alerts.ts"() {
16086
+ "use strict";
16087
+ }
16088
+ });
16089
+
16090
+ // src/commands/alerts.ts
16091
+ var alerts_exports = {};
16092
+ __export(alerts_exports, {
16093
+ alertsCommand: () => alertsCommand
16094
+ });
16095
+ function printAlertsHelp() {
16096
+ console.error(`
16097
+ wayai alerts \u2014 show a hub's active operational alerts (Status & Notices)
16098
+
16099
+ Usage:
16100
+ wayai alerts Active alerts for the active hub
16101
+ wayai alerts --hub <uuid|name> For a specific hub (accepts a raw uuid without a workspace)
16102
+ wayai alerts --json Raw JSON output
16103
+
16104
+ Alerts are tenant-actionable connection/credential health signals raised at
16105
+ runtime \u2014 e.g. a provider rejecting a bad/expired key (\`connection_auth\`),
16106
+ a rate/quota limit (\`connection_quota\`), an expired channel token
16107
+ (\`channel_token\`), or a missing production credential. Run this FIRST when a
16108
+ hub misbehaves (audio/TTS not delivered, agent not replying, a tool failing)
16109
+ before reading code or filing a report.
16110
+ `.trim());
16111
+ }
16112
+ function fmtTime(iso) {
16113
+ const d = new Date(iso);
16114
+ return Number.isNaN(d.getTime()) ? iso : d.toLocaleString();
16115
+ }
16116
+ async function alertsCommand(args2) {
16117
+ if (wantsHelp(args2)) {
16118
+ printAlertsHelp();
16119
+ return;
16120
+ }
16121
+ const jsonIdx = args2.indexOf("--json");
16122
+ const jsonOutput = jsonIdx !== -1;
16123
+ if (jsonOutput) args2.splice(jsonIdx, 1);
16124
+ const hubId = resolveActiveHubId(args2);
16125
+ const { config, accessToken } = await requireAuth();
16126
+ const client = new ApiClient({ apiUrl: config.api_url, accessToken });
16127
+ let alerts;
16128
+ try {
16129
+ ({ alerts } = await client.getHubAlerts(hubId));
16130
+ } catch (err) {
16131
+ if (err instanceof ApiError && err.status === 404) {
16132
+ console.error(`Hub ${hubId} not found, or you lack read access to it.`);
16133
+ process.exit(1);
16134
+ }
16135
+ if (err instanceof ApiError && err.status === 403) {
16136
+ console.error(`You don't have read access to hub ${hubId}.`);
16137
+ process.exit(1);
16138
+ }
16139
+ throw err;
16140
+ }
16141
+ const active = activeAlerts(alerts);
16142
+ if (jsonOutput) {
16143
+ console.log(JSON.stringify({ hub_id: hubId, alerts: active }, null, 2));
16144
+ return;
16145
+ }
16146
+ if (active.length === 0) {
16147
+ console.log(`Hub ${hubId} \u2014 no active alerts \u2713`);
16148
+ return;
16149
+ }
16150
+ const connLabels = /* @__PURE__ */ new Map();
16151
+ try {
16152
+ const { connections } = await client.listConnections(hubId);
16153
+ for (const conn of connections) {
16154
+ if (!conn.connection_id) continue;
16155
+ const name = conn.connection_display_name || conn.connector_name;
16156
+ connLabels.set(conn.connection_id, `${name} (${conn.connector_type})`);
16157
+ }
16158
+ } catch {
16159
+ }
16160
+ const noun = active.length === 1 ? "alert" : "alerts";
16161
+ console.log(`Hub ${hubId} \u2014 ${active.length} active ${noun}
16162
+ `);
16163
+ for (const a of active) {
16164
+ const { label, hint } = describeCategory(a.category);
16165
+ const target = formatAlertTarget(a, (id) => connLabels.get(id));
16166
+ const providerBits = formatProviderBits(a);
16167
+ console.log(`${severityGlyph(a.severity)} ${a.severity} ${a.category} \u2014 ${label}`);
16168
+ console.log(` ${target}${providerBits ? ` \xB7 ${providerBits}` : ""}`);
16169
+ console.log(` ${hint}`);
16170
+ if (a.org_credential_id) {
16171
+ console.log(` Shared org credential \u2014 fix it once at the org credential (\`wayai update-credential\`); it fans out to every hub linking it.`);
16172
+ }
16173
+ console.log(` seen ${a.count}\xD7 \xB7 first ${fmtTime(a.first_seen_at)} \xB7 last ${fmtTime(a.last_seen_at)}`);
16174
+ console.log("");
16175
+ }
16176
+ }
16177
+ var init_alerts = __esm({
16178
+ "src/commands/alerts.ts"() {
16179
+ "use strict";
16180
+ init_auth();
16181
+ init_workspace();
16182
+ init_api_client();
16183
+ init_utils();
16184
+ init_hub_alerts();
16185
+ }
16186
+ });
16187
+
16001
16188
  // src/commands/delete-history.ts
16002
16189
  var delete_history_exports = {};
16003
16190
  __export(delete_history_exports, {
@@ -20445,6 +20632,19 @@ async function reportCreateCommand(args2, cliVersion = null) {
20445
20632
  const client = new ApiClient({ apiUrl: config.api_url, accessToken });
20446
20633
  const repoConfig = readRepoConfig();
20447
20634
  const organizationId = repoConfig?.organization_id;
20635
+ let contextWithAlerts = context;
20636
+ if (hubId) {
20637
+ try {
20638
+ const { alerts } = await client.getHubAlerts(hubId);
20639
+ const alertSummary = summarizeActiveAlertsForReport(alerts);
20640
+ if (alertSummary) {
20641
+ contextWithAlerts = context ? `${context}
20642
+
20643
+ ${alertSummary}` : alertSummary;
20644
+ }
20645
+ } catch {
20646
+ }
20647
+ }
20448
20648
  try {
20449
20649
  const result = await client.submitReport({
20450
20650
  title,
@@ -20457,7 +20657,7 @@ async function reportCreateCommand(args2, cliVersion = null) {
20457
20657
  conversation_id: conversationId,
20458
20658
  error_message: errorMessage,
20459
20659
  steps_to_reproduce: steps,
20460
- additional_context: context,
20660
+ additional_context: contextWithAlerts,
20461
20661
  client_version: clientVersion
20462
20662
  });
20463
20663
  if (result.created) {
@@ -20488,6 +20688,7 @@ var init_report_create = __esm({
20488
20688
  init_auth();
20489
20689
  init_repo_config();
20490
20690
  init_api_client();
20691
+ init_hub_alerts();
20491
20692
  init_version_status();
20492
20693
  }
20493
20694
  });
@@ -21054,6 +21255,11 @@ async function main() {
21054
21255
  await conversationsCommand2(args);
21055
21256
  break;
21056
21257
  }
21258
+ case "alerts": {
21259
+ const { alertsCommand: alertsCommand2 } = await Promise.resolve().then(() => (init_alerts(), alerts_exports));
21260
+ await alertsCommand2(args);
21261
+ break;
21262
+ }
21057
21263
  case "delete-history": {
21058
21264
  const { deleteHistoryCommand: deleteHistoryCommand2 } = await Promise.resolve().then(() => (init_delete_history(), delete_history_exports));
21059
21265
  await deleteHistoryCommand2(args);
@@ -21187,6 +21393,7 @@ Commands:
21187
21393
  unbind Clear the worktree hub binding
21188
21394
  send-message Send a test message to a hub (preview or production)
21189
21395
  conversations List or inspect conversations
21396
+ alerts Show a hub's active connection/credential alerts (run this FIRST when a hub misbehaves)
21190
21397
  analytics Show analytics summary and metrics (use \`analytics query\` for structured ClickHouse queries)
21191
21398
  delete-history Delete your conversations on a hub (--conversation-id <id> for just one)
21192
21399
  evals List evaluation scenarios for the current hub (use \`evals sql\` for read-only SQL on eval results)