@togglhq/cli 1.8.0 → 1.8.1

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/build/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as CommanderError, i as shutdownCliTelemetry, n as captureCliException, r as initCliTelemetry, t as createProgram } from "./program-B6EuV2vO.js";
2
+ import { a as CommanderError, i as shutdownCliTelemetry, n as captureCliException, r as initCliTelemetry, t as createProgram } from "./program-CH5epPVt.js";
3
3
  import { readFileSync } from "node:fs";
4
4
  import { dirname, join } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
package/build/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { t as createProgram } from "./program-B6EuV2vO.js";
1
+ import { t as createProgram } from "./program-CH5epPVt.js";
2
2
  export { createProgram };
@@ -12618,6 +12618,51 @@ function switchCliWorkspace(workspaceId, profile) {
12618
12618
  saveDeveloperToolsConfig(dev);
12619
12619
  return target;
12620
12620
  }
12621
+ const CLI_GENERIC_ERROR_CATEGORY = "cli.command_error";
12622
+ const MCP_GENERIC_ERROR_CATEGORY = "mcp.tool_error";
12623
+ const ERROR_CATEGORY_SET = new Set([
12624
+ "cli.validation_error",
12625
+ "cli.api_error",
12626
+ CLI_GENERIC_ERROR_CATEGORY,
12627
+ "mcp.validation_error",
12628
+ "mcp.api_error",
12629
+ "mcp.auth_error",
12630
+ MCP_GENERIC_ERROR_CATEGORY
12631
+ ]);
12632
+ function isDeclaredErrorCategory(value) {
12633
+ return typeof value === "string" && ERROR_CATEGORY_SET.has(value);
12634
+ }
12635
+ function firstToolResultText(source) {
12636
+ if (!source || typeof source !== "object") return null;
12637
+ const content = source.content;
12638
+ if (!Array.isArray(content)) return null;
12639
+ const first = content[0];
12640
+ if (first?.type === "text" && typeof first.text === "string") return first.text;
12641
+ return null;
12642
+ }
12643
+ function errorTextForClassification(source) {
12644
+ if (source instanceof Error) return source.message;
12645
+ if (typeof source === "string") return source;
12646
+ const toolText = firstToolResultText(source);
12647
+ if (toolText !== null) return toolText;
12648
+ return "";
12649
+ }
12650
+ function classifyCli(message) {
12651
+ if (message.startsWith("Invalid input:") || message.startsWith("Invalid input ")) return "cli.validation_error";
12652
+ if (/^\d{3}:\s/.test(message)) return "cli.api_error";
12653
+ return CLI_GENERIC_ERROR_CATEGORY;
12654
+ }
12655
+ function classifyMcp(message) {
12656
+ if (message.startsWith("Invalid input:") || message.startsWith("Invalid input ")) return "mcp.validation_error";
12657
+ if (message.startsWith("API Error (")) return "mcp.api_error";
12658
+ if (message.startsWith("Authentication failed:") || message.startsWith("Not authenticated.")) return "mcp.auth_error";
12659
+ return MCP_GENERIC_ERROR_CATEGORY;
12660
+ }
12661
+ function classifyErrorCategory(client, source) {
12662
+ const message = errorTextForClassification(source);
12663
+ if (isDeclaredErrorCategory(message) && message.startsWith(`${client}.`)) return message;
12664
+ return client === "cli" ? classifyCli(message) : classifyMcp(message);
12665
+ }
12621
12666
  /**
12622
12667
  * Exception messages are the one channel `sendDefaultPii: false` does not cover,
12623
12668
  * and this repo's errors put user data in them: validation failures embed the
@@ -12629,15 +12674,14 @@ function switchCliWorkspace(workspaceId, profile) {
12629
12674
  * Shared between the CLI and the public MCP build so the two cannot drift.
12630
12675
  */
12631
12676
  /**
12632
- * Fixed categories are `<surface>.<snake_case>` — anchored at both ends, because
12633
- * a prefix test would pass anything that merely *starts* that way. A real message
12634
- * like `cli.ts:12: unexpected token "secret"` begins with `cli.` and would
12635
- * otherwise sail through unredacted.
12677
+ * Fixed categories are the seven declared `<surface>.<snake_case>` values, not
12678
+ * a `cli|mcp` prefix regex. A prefix or regex test would pass a caught message
12679
+ * like `cli.customer_name`. A real filename message such as
12680
+ * `cli.ts:12: unexpected token "secret"` would also begin with `cli.`.
12636
12681
  */
12637
- const SAFE_CATEGORY_PATTERN = /^(?:cli|mcp)\.[a-z][a-z0-9_]*$/;
12638
12682
  const REDACTED_SENTRY_MESSAGE = "redacted";
12639
12683
  function isSafeSentryMessage(value) {
12640
- return typeof value === "string" && SAFE_CATEGORY_PATTERN.test(value);
12684
+ return isDeclaredErrorCategory(value);
12641
12685
  }
12642
12686
  /**
12643
12687
  * Replace every exception message that is not a known category, and any top-level
@@ -12719,7 +12763,7 @@ function normalizeAction(action) {
12719
12763
  /** Strict allowlist — never accept args/results. */
12720
12764
  function captureToolInvocation(event) {
12721
12765
  if (!enabled || !apiKey) return;
12722
- const task = sendCapture(TOOL_INVOCATION_EVENT, {
12766
+ const properties = {
12723
12767
  tool_name: event.toolName,
12724
12768
  action: normalizeAction(event.action),
12725
12769
  outcome: event.outcome,
@@ -12727,7 +12771,9 @@ function captureToolInvocation(event) {
12727
12771
  client,
12728
12772
  session_id: sessionId,
12729
12773
  package_version: packageVersion
12730
- }, event.distinctId).finally(() => {
12774
+ };
12775
+ if (event.outcome === "error") properties.error_category = classifyErrorCategory(client, event.error);
12776
+ const task = sendCapture(TOOL_INVOCATION_EVENT, properties, event.distinctId).finally(() => {
12731
12777
  pending.delete(task);
12732
12778
  });
12733
12779
  pending.add(task);
@@ -24981,6 +25027,7 @@ function envEnabled(raw) {
24981
25027
  }
24982
25028
  let sentryEnabled = false;
24983
25029
  let productAnalyticsEnabled = false;
25030
+ let lastCommandError;
24984
25031
  function initCliTelemetry(packageVersion) {
24985
25032
  productAnalyticsEnabled = initProductAnalytics({
24986
25033
  client: "cli",
@@ -25014,17 +25061,17 @@ function initCliTelemetry(packageVersion) {
25014
25061
  */
25015
25062
  function recordCliCommand(commandName, action, success) {
25016
25063
  if (!productAnalyticsEnabled) return;
25064
+ const error = success ? void 0 : lastCommandError;
25065
+ lastCommandError = void 0;
25017
25066
  captureToolInvocation({
25018
25067
  toolName: commandName,
25019
25068
  action,
25020
- outcome: success ? "success" : "error"
25069
+ outcome: success ? "success" : "error",
25070
+ error
25021
25071
  });
25022
25072
  }
25023
25073
  function classifyCliSentryError(error) {
25024
- const message = error instanceof Error ? error.message : String(error);
25025
- if (message.startsWith("Invalid input:") || message.startsWith("Invalid input ")) return "cli.validation_error";
25026
- if (/^\d{3}:\s/.test(message)) return "cli.api_error";
25027
- return "cli.command_error";
25074
+ return classifyErrorCategory("cli", error);
25028
25075
  }
25029
25076
  function toSentrySafeCliError(error) {
25030
25077
  const category = classifyCliSentryError(error);
@@ -25034,6 +25081,7 @@ function toSentrySafeCliError(error) {
25034
25081
  return safe;
25035
25082
  }
25036
25083
  function captureCliException(error) {
25084
+ lastCommandError = error;
25037
25085
  if (!sentryEnabled) return;
25038
25086
  const category = classifyCliSentryError(error);
25039
25087
  Sentry.withScope((scope) => {
@@ -25048,6 +25096,7 @@ async function shutdownCliTelemetry() {
25048
25096
  if (tasks.length > 0) await Promise.allSettled(tasks);
25049
25097
  sentryEnabled = false;
25050
25098
  productAnalyticsEnabled = false;
25099
+ lastCommandError = void 0;
25051
25100
  }
25052
25101
  //#endregion
25053
25102
  //#region src/output.ts
@@ -25624,4 +25673,4 @@ Common commands:
25624
25673
  //#endregion
25625
25674
  export { CommanderError as a, shutdownCliTelemetry as i, captureCliException as n, initCliTelemetry as r, createProgram as t };
25626
25675
 
25627
- //# sourceMappingURL=program-B6EuV2vO.js.map
25676
+ //# sourceMappingURL=program-CH5epPVt.js.map
package/build/program.js CHANGED
@@ -1,2 +1,2 @@
1
- import { t as createProgram } from "./program-B6EuV2vO.js";
1
+ import { t as createProgram } from "./program-CH5epPVt.js";
2
2
  export { createProgram };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@togglhq/cli",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Toggl CLI for Toggl 2.0 API operations.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",