aden-ts 0.2.0 → 0.2.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.
Files changed (3) hide show
  1. package/dist/index.js +139 -120
  2. package/dist/index.mjs +139 -120
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1856,6 +1856,101 @@ function isAnthropicInstrumented() {
1856
1856
  // src/control-agent.ts
1857
1857
  var import_crypto6 = require("crypto");
1858
1858
  var import_ws = __toESM(require("ws"));
1859
+
1860
+ // src/logging.ts
1861
+ var LOG_LEVEL_PRIORITY = {
1862
+ debug: 0,
1863
+ info: 1,
1864
+ warn: 2,
1865
+ error: 3,
1866
+ silent: 4
1867
+ };
1868
+ var currentConfig = {
1869
+ level: parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
1870
+ metricsLevel: parseLogLevel(process.env.ADEN_METRICS_LOG_LEVEL) ?? parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
1871
+ handler: console
1872
+ };
1873
+ function parseLogLevel(level) {
1874
+ if (!level) return void 0;
1875
+ const normalized = level.toLowerCase();
1876
+ if (normalized in LOG_LEVEL_PRIORITY) {
1877
+ return normalized;
1878
+ }
1879
+ return void 0;
1880
+ }
1881
+ function shouldLog(level, configLevel) {
1882
+ return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[configLevel];
1883
+ }
1884
+ function configureLogging(config) {
1885
+ if (config.level !== void 0) {
1886
+ currentConfig.level = config.level;
1887
+ if (config.metricsLevel === void 0) {
1888
+ currentConfig.metricsLevel = config.level;
1889
+ }
1890
+ }
1891
+ if (config.metricsLevel !== void 0) {
1892
+ currentConfig.metricsLevel = config.metricsLevel;
1893
+ }
1894
+ if (config.handler !== void 0) {
1895
+ currentConfig.handler = config.handler;
1896
+ }
1897
+ }
1898
+ function getLoggingConfig() {
1899
+ return { ...currentConfig };
1900
+ }
1901
+ function resetLoggingConfig() {
1902
+ currentConfig = {
1903
+ level: parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
1904
+ metricsLevel: parseLogLevel(process.env.ADEN_METRICS_LOG_LEVEL) ?? parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
1905
+ handler: console
1906
+ };
1907
+ }
1908
+ var logger = {
1909
+ debug(message, ...args) {
1910
+ if (shouldLog("debug", currentConfig.level)) {
1911
+ currentConfig.handler.debug(`[aden] ${message}`, ...args);
1912
+ }
1913
+ },
1914
+ info(message, ...args) {
1915
+ if (shouldLog("info", currentConfig.level)) {
1916
+ currentConfig.handler.info(`[aden] ${message}`, ...args);
1917
+ }
1918
+ },
1919
+ warn(message, ...args) {
1920
+ if (shouldLog("warn", currentConfig.level)) {
1921
+ currentConfig.handler.warn(`[aden] ${message}`, ...args);
1922
+ }
1923
+ },
1924
+ error(message, ...args) {
1925
+ if (shouldLog("error", currentConfig.level)) {
1926
+ currentConfig.handler.error(`[aden] ${message}`, ...args);
1927
+ }
1928
+ }
1929
+ };
1930
+ var metricsLogger = {
1931
+ debug(message, ...args) {
1932
+ if (shouldLog("debug", currentConfig.metricsLevel)) {
1933
+ currentConfig.handler.debug(`[aden.metrics] ${message}`, ...args);
1934
+ }
1935
+ },
1936
+ info(message, ...args) {
1937
+ if (shouldLog("info", currentConfig.metricsLevel)) {
1938
+ currentConfig.handler.info(`[aden.metrics] ${message}`, ...args);
1939
+ }
1940
+ },
1941
+ warn(message, ...args) {
1942
+ if (shouldLog("warn", currentConfig.metricsLevel)) {
1943
+ currentConfig.handler.warn(`[aden.metrics] ${message}`, ...args);
1944
+ }
1945
+ },
1946
+ error(message, ...args) {
1947
+ if (shouldLog("error", currentConfig.metricsLevel)) {
1948
+ currentConfig.handler.error(`[aden.metrics] ${message}`, ...args);
1949
+ }
1950
+ }
1951
+ };
1952
+
1953
+ // src/control-agent.ts
1859
1954
  var SDK_VERSION = "0.1.0";
1860
1955
  var ControlAgent = class {
1861
1956
  constructor(options) {
@@ -1903,9 +1998,11 @@ var ControlAgent = class {
1903
1998
  */
1904
1999
  async connect() {
1905
2000
  const url = this.options.serverUrl;
2001
+ logger.debug(`Connecting to control server: ${url}`);
1906
2002
  if (url.startsWith("wss://") || url.startsWith("ws://")) {
1907
2003
  await this.connectWebSocket();
1908
2004
  } else {
2005
+ logger.debug("Using HTTP polling mode (no WebSocket URL)");
1909
2006
  this.startPolling();
1910
2007
  }
1911
2008
  this.startHeartbeat();
@@ -1921,6 +2018,7 @@ var ControlAgent = class {
1921
2018
  };
1922
2019
  try {
1923
2020
  const wsUrl = `${this.options.serverUrl}/v1/control/ws`;
2021
+ logger.debug(`Attempting WebSocket connection to: ${wsUrl}`);
1924
2022
  this.ws = new import_ws.default(wsUrl, {
1925
2023
  headers: {
1926
2024
  Authorization: `Bearer ${this.options.apiKey}`,
@@ -1930,7 +2028,7 @@ var ControlAgent = class {
1930
2028
  this.ws.on("open", () => {
1931
2029
  this.connected = true;
1932
2030
  this.reconnectAttempts = 0;
1933
- console.log("[aden] WebSocket connected to control server");
2031
+ logger.info("WebSocket connected to control server");
1934
2032
  this.flushEventQueue();
1935
2033
  resolve();
1936
2034
  });
@@ -1939,12 +2037,12 @@ var ControlAgent = class {
1939
2037
  });
1940
2038
  this.ws.on("close", () => {
1941
2039
  this.connected = false;
1942
- console.log("[aden] WebSocket disconnected, falling back to polling");
2040
+ logger.info("WebSocket disconnected, falling back to polling");
1943
2041
  this.scheduleReconnect();
1944
2042
  this.startPolling();
1945
2043
  });
1946
2044
  this.ws.on("error", (error) => {
1947
- console.warn("[aden] WebSocket error:", error.message);
2045
+ logger.warn("WebSocket error:", error.message);
1948
2046
  this.errorsSinceLastHeartbeat++;
1949
2047
  if (!this.connected) {
1950
2048
  fallbackToPolling();
@@ -1952,12 +2050,12 @@ var ControlAgent = class {
1952
2050
  });
1953
2051
  setTimeout(() => {
1954
2052
  if (!this.connected) {
1955
- console.warn("[aden] WebSocket connection timeout, using polling");
2053
+ logger.warn("WebSocket connection timeout, using polling");
1956
2054
  fallbackToPolling();
1957
2055
  }
1958
2056
  }, this.options.timeoutMs);
1959
2057
  } catch (error) {
1960
- console.warn("[aden] WebSocket setup failed:", error);
2058
+ logger.warn("WebSocket setup failed:", error);
1961
2059
  fallbackToPolling();
1962
2060
  }
1963
2061
  });
@@ -1968,7 +2066,7 @@ var ControlAgent = class {
1968
2066
  scheduleReconnect() {
1969
2067
  if (this.reconnectTimer) return;
1970
2068
  if (this.reconnectAttempts >= this.maxReconnectAttempts) {
1971
- console.warn("[aden] Max reconnect attempts reached, using polling only");
2069
+ logger.warn("Max reconnect attempts reached, using polling only");
1972
2070
  return;
1973
2071
  }
1974
2072
  const delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts), 3e4);
@@ -1989,12 +2087,12 @@ var ControlAgent = class {
1989
2087
  if (message.type === "policy") {
1990
2088
  this.cachedPolicy = message.policy;
1991
2089
  this.lastPolicyFetch = Date.now();
1992
- console.log("[aden] Policy updated:", this.cachedPolicy.version);
2090
+ logger.info("Policy updated:", this.cachedPolicy.version);
1993
2091
  } else if (message.type === "command") {
1994
- console.log("[aden] Command received:", message);
2092
+ logger.info("Command received:", message);
1995
2093
  }
1996
2094
  } catch (error) {
1997
- console.warn("[aden] Failed to parse message:", error);
2095
+ logger.warn("Failed to parse message:", error);
1998
2096
  }
1999
2097
  }
2000
2098
  /**
@@ -2003,6 +2101,7 @@ var ControlAgent = class {
2003
2101
  */
2004
2102
  async startPolling() {
2005
2103
  if (this.pollingTimer) return;
2104
+ logger.debug(`Starting HTTP polling (interval: ${this.options.pollingIntervalMs}ms)`);
2006
2105
  await this.fetchPolicy();
2007
2106
  this.pollingTimer = setInterval(() => {
2008
2107
  if (!this.connected) {
@@ -2023,15 +2122,19 @@ var ControlAgent = class {
2023
2122
  * Fetch policy via HTTP
2024
2123
  */
2025
2124
  async fetchPolicy() {
2125
+ logger.debug("Fetching policy from server...");
2026
2126
  try {
2027
2127
  const response = await this.httpRequest("/v1/control/policy", "GET");
2028
2128
  if (response.ok) {
2029
2129
  const policy = await response.json();
2030
2130
  this.cachedPolicy = policy;
2031
2131
  this.lastPolicyFetch = Date.now();
2132
+ logger.debug(`Policy fetched successfully (version: ${policy.version}, budgets: ${policy.budgets?.length ?? 0})`);
2133
+ } else {
2134
+ logger.debug(`Policy fetch returned status ${response.status}`);
2032
2135
  }
2033
2136
  } catch (error) {
2034
- console.warn("[aden] Failed to fetch policy:", error);
2137
+ logger.warn("Failed to fetch policy:", error);
2035
2138
  }
2036
2139
  }
2037
2140
  /**
@@ -2039,6 +2142,7 @@ var ControlAgent = class {
2039
2142
  */
2040
2143
  startHeartbeat() {
2041
2144
  if (this.heartbeatTimer) return;
2145
+ logger.debug(`Starting heartbeat (interval: ${this.options.heartbeatIntervalMs}ms)`);
2042
2146
  this.heartbeatTimer = setInterval(() => {
2043
2147
  this.sendHeartbeat();
2044
2148
  }, this.options.heartbeatIntervalMs);
@@ -2075,6 +2179,7 @@ var ControlAgent = class {
2075
2179
  * Disconnect from the control server
2076
2180
  */
2077
2181
  async disconnect() {
2182
+ logger.debug("Disconnecting from control server...");
2078
2183
  this.stopPolling();
2079
2184
  this.stopHeartbeat();
2080
2185
  if (this.reconnectTimer) {
@@ -2086,6 +2191,7 @@ var ControlAgent = class {
2086
2191
  this.ws = null;
2087
2192
  }
2088
2193
  this.connected = false;
2194
+ logger.debug("Disconnected from control server");
2089
2195
  }
2090
2196
  /**
2091
2197
  * Get a control decision for a request
@@ -2215,7 +2321,7 @@ var ControlAgent = class {
2215
2321
  timestamp: /* @__PURE__ */ new Date()
2216
2322
  };
2217
2323
  Promise.resolve(this.options.onAlert(alertEvent)).catch((err) => {
2218
- console.warn("[aden] Alert callback error:", err);
2324
+ logger.warn("Alert callback error:", err);
2219
2325
  });
2220
2326
  return {
2221
2327
  action: "alert",
@@ -2522,8 +2628,8 @@ var ControlAgent = class {
2522
2628
  }
2523
2629
  if (this.options.adaptiveThresholdEnabled) {
2524
2630
  if (remainingBudgetUsd <= this.options.adaptiveMinRemainingUsd) {
2525
- console.debug(
2526
- `[aden] Remaining budget $${remainingBudgetUsd.toFixed(4)} <= $${this.options.adaptiveMinRemainingUsd.toFixed(2)}, forcing validation`
2631
+ logger.debug(
2632
+ `Remaining budget $${remainingBudgetUsd.toFixed(4)} <= $${this.options.adaptiveMinRemainingUsd.toFixed(2)}, forcing validation`
2527
2633
  );
2528
2634
  return true;
2529
2635
  }
@@ -2532,13 +2638,13 @@ var ControlAgent = class {
2532
2638
  const samplingRate = this.calculateSamplingRate(budgetUsagePercent);
2533
2639
  const shouldSample = Math.random() < samplingRate;
2534
2640
  if (!shouldSample) {
2535
- console.debug(
2536
- `[aden] Skipping validation (sampling rate: ${(samplingRate * 100).toFixed(1)}%, usage: ${budgetUsagePercent.toFixed(1)}%)`
2641
+ logger.debug(
2642
+ `Skipping validation (sampling rate: ${(samplingRate * 100).toFixed(1)}%, usage: ${budgetUsagePercent.toFixed(1)}%)`
2537
2643
  );
2538
2644
  return false;
2539
2645
  }
2540
- console.debug(
2541
- `[aden] Sampled for validation (rate: ${(samplingRate * 100).toFixed(1)}%, usage: ${budgetUsagePercent.toFixed(1)}%)`
2646
+ logger.debug(
2647
+ `Sampled for validation (rate: ${(samplingRate * 100).toFixed(1)}%, usage: ${budgetUsagePercent.toFixed(1)}%)`
2542
2648
  );
2543
2649
  return true;
2544
2650
  }
@@ -2596,8 +2702,8 @@ var ControlAgent = class {
2596
2702
  });
2597
2703
  if (response.ok) {
2598
2704
  const data = await response.json();
2599
- console.debug(
2600
- `[aden] Server validation response: allowed=${data.allowed}, action=${data.action}, reason=${data.reason}`
2705
+ logger.debug(
2706
+ `Server validation response: allowed=${data.allowed}, action=${data.action}, reason=${data.reason}`
2601
2707
  );
2602
2708
  return {
2603
2709
  allowed: data.allowed ?? true,
@@ -2612,14 +2718,14 @@ var ControlAgent = class {
2612
2718
  degradeToModel: data.degrade_to_model
2613
2719
  };
2614
2720
  } else {
2615
- console.warn(`[aden] Server validation returned status ${response.status}`);
2721
+ logger.warn(`Server validation returned status ${response.status}`);
2616
2722
  return null;
2617
2723
  }
2618
2724
  } finally {
2619
2725
  clearTimeout(timeoutId);
2620
2726
  }
2621
2727
  } catch (error) {
2622
- console.warn(`[aden] Server validation failed: ${error}`);
2728
+ logger.warn(`Server validation failed: ${error}`);
2623
2729
  return null;
2624
2730
  }
2625
2731
  }
@@ -2659,8 +2765,8 @@ var ControlAgent = class {
2659
2765
  }
2660
2766
  }
2661
2767
  if (this.shouldValidateWithServer(usagePercent, remaining, limit)) {
2662
- console.debug(
2663
- `[aden] Budget '${budget.name}' at ${usagePercent.toFixed(1)}% ($${currentSpend.toFixed(6)}/$${limit.toFixed(6)}), validating with server`
2768
+ logger.debug(
2769
+ `Budget '${budget.name}' at ${usagePercent.toFixed(1)}% ($${currentSpend.toFixed(6)}/$${limit.toFixed(6)}), validating with server`
2664
2770
  );
2665
2771
  const validation = await this.validateBudgetWithServer(
2666
2772
  budget.id,
@@ -2670,8 +2776,8 @@ var ControlAgent = class {
2670
2776
  if (validation) {
2671
2777
  return this.applyServerValidationResult(validation, budget.id);
2672
2778
  } else {
2673
- console.warn(
2674
- `[aden] Server validation failed for budget '${budget.id}', using local enforcement`
2779
+ logger.warn(
2780
+ `Server validation failed for budget '${budget.id}', using local enforcement`
2675
2781
  );
2676
2782
  if (!this.options.failOpen) {
2677
2783
  return {
@@ -2733,12 +2839,14 @@ var ControlAgent = class {
2733
2839
  if (this.connected && this.ws?.readyState === import_ws.default.OPEN) {
2734
2840
  try {
2735
2841
  this.ws.send(JSON.stringify(event));
2842
+ logger.debug(`Event sent via WebSocket: ${event.event_type}`);
2736
2843
  return;
2737
2844
  } catch (error) {
2738
- console.warn("[aden] WebSocket send failed, queuing event");
2845
+ logger.warn("WebSocket send failed, queuing event");
2739
2846
  }
2740
2847
  }
2741
2848
  this.queueEvent(event);
2849
+ logger.debug(`Event queued: ${event.event_type} (queue size: ${this.eventQueue.length})`);
2742
2850
  if (!this.connected) {
2743
2851
  await this.flushEventQueue();
2744
2852
  }
@@ -2757,7 +2865,9 @@ var ControlAgent = class {
2757
2865
  */
2758
2866
  async flushEventQueue() {
2759
2867
  if (this.eventQueue.length === 0) return;
2868
+ const eventCount = this.eventQueue.length;
2760
2869
  if (this.connected && this.ws?.readyState === import_ws.default.OPEN) {
2870
+ logger.debug(`Flushing ${eventCount} events via WebSocket`);
2761
2871
  const events = [...this.eventQueue];
2762
2872
  this.eventQueue = [];
2763
2873
  for (const event of events) {
@@ -2769,12 +2879,14 @@ var ControlAgent = class {
2769
2879
  }
2770
2880
  return;
2771
2881
  }
2882
+ logger.debug(`Flushing ${eventCount} events via HTTP`);
2772
2883
  try {
2773
2884
  const events = [...this.eventQueue];
2774
2885
  this.eventQueue = [];
2775
2886
  await this.httpRequest("/v1/control/events", "POST", { events });
2887
+ logger.debug(`Successfully sent ${eventCount} events via HTTP`);
2776
2888
  } catch (error) {
2777
- console.warn("[aden] Failed to flush event queue:", error);
2889
+ logger.warn("Failed to flush event queue:", error);
2778
2890
  }
2779
2891
  }
2780
2892
  /**
@@ -6646,99 +6758,6 @@ function createReportEmitter(builder) {
6646
6758
  builder.recordEvent(event);
6647
6759
  };
6648
6760
  }
6649
-
6650
- // src/logging.ts
6651
- var LOG_LEVEL_PRIORITY = {
6652
- debug: 0,
6653
- info: 1,
6654
- warn: 2,
6655
- error: 3,
6656
- silent: 4
6657
- };
6658
- var currentConfig = {
6659
- level: parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
6660
- metricsLevel: parseLogLevel(process.env.ADEN_METRICS_LOG_LEVEL) ?? parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
6661
- handler: console
6662
- };
6663
- function parseLogLevel(level) {
6664
- if (!level) return void 0;
6665
- const normalized = level.toLowerCase();
6666
- if (normalized in LOG_LEVEL_PRIORITY) {
6667
- return normalized;
6668
- }
6669
- return void 0;
6670
- }
6671
- function shouldLog(level, configLevel) {
6672
- return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[configLevel];
6673
- }
6674
- function configureLogging(config) {
6675
- if (config.level !== void 0) {
6676
- currentConfig.level = config.level;
6677
- if (config.metricsLevel === void 0) {
6678
- currentConfig.metricsLevel = config.level;
6679
- }
6680
- }
6681
- if (config.metricsLevel !== void 0) {
6682
- currentConfig.metricsLevel = config.metricsLevel;
6683
- }
6684
- if (config.handler !== void 0) {
6685
- currentConfig.handler = config.handler;
6686
- }
6687
- }
6688
- function getLoggingConfig() {
6689
- return { ...currentConfig };
6690
- }
6691
- function resetLoggingConfig() {
6692
- currentConfig = {
6693
- level: parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
6694
- metricsLevel: parseLogLevel(process.env.ADEN_METRICS_LOG_LEVEL) ?? parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
6695
- handler: console
6696
- };
6697
- }
6698
- var logger = {
6699
- debug(message, ...args) {
6700
- if (shouldLog("debug", currentConfig.level)) {
6701
- currentConfig.handler.debug(`[aden] ${message}`, ...args);
6702
- }
6703
- },
6704
- info(message, ...args) {
6705
- if (shouldLog("info", currentConfig.level)) {
6706
- currentConfig.handler.info(`[aden] ${message}`, ...args);
6707
- }
6708
- },
6709
- warn(message, ...args) {
6710
- if (shouldLog("warn", currentConfig.level)) {
6711
- currentConfig.handler.warn(`[aden] ${message}`, ...args);
6712
- }
6713
- },
6714
- error(message, ...args) {
6715
- if (shouldLog("error", currentConfig.level)) {
6716
- currentConfig.handler.error(`[aden] ${message}`, ...args);
6717
- }
6718
- }
6719
- };
6720
- var metricsLogger = {
6721
- debug(message, ...args) {
6722
- if (shouldLog("debug", currentConfig.metricsLevel)) {
6723
- currentConfig.handler.debug(`[aden.metrics] ${message}`, ...args);
6724
- }
6725
- },
6726
- info(message, ...args) {
6727
- if (shouldLog("info", currentConfig.metricsLevel)) {
6728
- currentConfig.handler.info(`[aden.metrics] ${message}`, ...args);
6729
- }
6730
- },
6731
- warn(message, ...args) {
6732
- if (shouldLog("warn", currentConfig.metricsLevel)) {
6733
- currentConfig.handler.warn(`[aden.metrics] ${message}`, ...args);
6734
- }
6735
- },
6736
- error(message, ...args) {
6737
- if (shouldLog("error", currentConfig.metricsLevel)) {
6738
- currentConfig.handler.error(`[aden.metrics] ${message}`, ...args);
6739
- }
6740
- }
6741
- };
6742
6761
  // Annotate the CommonJS export names for ESM import in node:
6743
6762
  0 && (module.exports = {
6744
6763
  AnalyticsEngine,
package/dist/index.mjs CHANGED
@@ -1739,6 +1739,101 @@ function isAnthropicInstrumented() {
1739
1739
  // src/control-agent.ts
1740
1740
  import { randomUUID as randomUUID6 } from "crypto";
1741
1741
  import WebSocket from "ws";
1742
+
1743
+ // src/logging.ts
1744
+ var LOG_LEVEL_PRIORITY = {
1745
+ debug: 0,
1746
+ info: 1,
1747
+ warn: 2,
1748
+ error: 3,
1749
+ silent: 4
1750
+ };
1751
+ var currentConfig = {
1752
+ level: parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
1753
+ metricsLevel: parseLogLevel(process.env.ADEN_METRICS_LOG_LEVEL) ?? parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
1754
+ handler: console
1755
+ };
1756
+ function parseLogLevel(level) {
1757
+ if (!level) return void 0;
1758
+ const normalized = level.toLowerCase();
1759
+ if (normalized in LOG_LEVEL_PRIORITY) {
1760
+ return normalized;
1761
+ }
1762
+ return void 0;
1763
+ }
1764
+ function shouldLog(level, configLevel) {
1765
+ return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[configLevel];
1766
+ }
1767
+ function configureLogging(config) {
1768
+ if (config.level !== void 0) {
1769
+ currentConfig.level = config.level;
1770
+ if (config.metricsLevel === void 0) {
1771
+ currentConfig.metricsLevel = config.level;
1772
+ }
1773
+ }
1774
+ if (config.metricsLevel !== void 0) {
1775
+ currentConfig.metricsLevel = config.metricsLevel;
1776
+ }
1777
+ if (config.handler !== void 0) {
1778
+ currentConfig.handler = config.handler;
1779
+ }
1780
+ }
1781
+ function getLoggingConfig() {
1782
+ return { ...currentConfig };
1783
+ }
1784
+ function resetLoggingConfig() {
1785
+ currentConfig = {
1786
+ level: parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
1787
+ metricsLevel: parseLogLevel(process.env.ADEN_METRICS_LOG_LEVEL) ?? parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
1788
+ handler: console
1789
+ };
1790
+ }
1791
+ var logger = {
1792
+ debug(message, ...args) {
1793
+ if (shouldLog("debug", currentConfig.level)) {
1794
+ currentConfig.handler.debug(`[aden] ${message}`, ...args);
1795
+ }
1796
+ },
1797
+ info(message, ...args) {
1798
+ if (shouldLog("info", currentConfig.level)) {
1799
+ currentConfig.handler.info(`[aden] ${message}`, ...args);
1800
+ }
1801
+ },
1802
+ warn(message, ...args) {
1803
+ if (shouldLog("warn", currentConfig.level)) {
1804
+ currentConfig.handler.warn(`[aden] ${message}`, ...args);
1805
+ }
1806
+ },
1807
+ error(message, ...args) {
1808
+ if (shouldLog("error", currentConfig.level)) {
1809
+ currentConfig.handler.error(`[aden] ${message}`, ...args);
1810
+ }
1811
+ }
1812
+ };
1813
+ var metricsLogger = {
1814
+ debug(message, ...args) {
1815
+ if (shouldLog("debug", currentConfig.metricsLevel)) {
1816
+ currentConfig.handler.debug(`[aden.metrics] ${message}`, ...args);
1817
+ }
1818
+ },
1819
+ info(message, ...args) {
1820
+ if (shouldLog("info", currentConfig.metricsLevel)) {
1821
+ currentConfig.handler.info(`[aden.metrics] ${message}`, ...args);
1822
+ }
1823
+ },
1824
+ warn(message, ...args) {
1825
+ if (shouldLog("warn", currentConfig.metricsLevel)) {
1826
+ currentConfig.handler.warn(`[aden.metrics] ${message}`, ...args);
1827
+ }
1828
+ },
1829
+ error(message, ...args) {
1830
+ if (shouldLog("error", currentConfig.metricsLevel)) {
1831
+ currentConfig.handler.error(`[aden.metrics] ${message}`, ...args);
1832
+ }
1833
+ }
1834
+ };
1835
+
1836
+ // src/control-agent.ts
1742
1837
  var SDK_VERSION = "0.1.0";
1743
1838
  var ControlAgent = class {
1744
1839
  constructor(options) {
@@ -1786,9 +1881,11 @@ var ControlAgent = class {
1786
1881
  */
1787
1882
  async connect() {
1788
1883
  const url = this.options.serverUrl;
1884
+ logger.debug(`Connecting to control server: ${url}`);
1789
1885
  if (url.startsWith("wss://") || url.startsWith("ws://")) {
1790
1886
  await this.connectWebSocket();
1791
1887
  } else {
1888
+ logger.debug("Using HTTP polling mode (no WebSocket URL)");
1792
1889
  this.startPolling();
1793
1890
  }
1794
1891
  this.startHeartbeat();
@@ -1804,6 +1901,7 @@ var ControlAgent = class {
1804
1901
  };
1805
1902
  try {
1806
1903
  const wsUrl = `${this.options.serverUrl}/v1/control/ws`;
1904
+ logger.debug(`Attempting WebSocket connection to: ${wsUrl}`);
1807
1905
  this.ws = new WebSocket(wsUrl, {
1808
1906
  headers: {
1809
1907
  Authorization: `Bearer ${this.options.apiKey}`,
@@ -1813,7 +1911,7 @@ var ControlAgent = class {
1813
1911
  this.ws.on("open", () => {
1814
1912
  this.connected = true;
1815
1913
  this.reconnectAttempts = 0;
1816
- console.log("[aden] WebSocket connected to control server");
1914
+ logger.info("WebSocket connected to control server");
1817
1915
  this.flushEventQueue();
1818
1916
  resolve();
1819
1917
  });
@@ -1822,12 +1920,12 @@ var ControlAgent = class {
1822
1920
  });
1823
1921
  this.ws.on("close", () => {
1824
1922
  this.connected = false;
1825
- console.log("[aden] WebSocket disconnected, falling back to polling");
1923
+ logger.info("WebSocket disconnected, falling back to polling");
1826
1924
  this.scheduleReconnect();
1827
1925
  this.startPolling();
1828
1926
  });
1829
1927
  this.ws.on("error", (error) => {
1830
- console.warn("[aden] WebSocket error:", error.message);
1928
+ logger.warn("WebSocket error:", error.message);
1831
1929
  this.errorsSinceLastHeartbeat++;
1832
1930
  if (!this.connected) {
1833
1931
  fallbackToPolling();
@@ -1835,12 +1933,12 @@ var ControlAgent = class {
1835
1933
  });
1836
1934
  setTimeout(() => {
1837
1935
  if (!this.connected) {
1838
- console.warn("[aden] WebSocket connection timeout, using polling");
1936
+ logger.warn("WebSocket connection timeout, using polling");
1839
1937
  fallbackToPolling();
1840
1938
  }
1841
1939
  }, this.options.timeoutMs);
1842
1940
  } catch (error) {
1843
- console.warn("[aden] WebSocket setup failed:", error);
1941
+ logger.warn("WebSocket setup failed:", error);
1844
1942
  fallbackToPolling();
1845
1943
  }
1846
1944
  });
@@ -1851,7 +1949,7 @@ var ControlAgent = class {
1851
1949
  scheduleReconnect() {
1852
1950
  if (this.reconnectTimer) return;
1853
1951
  if (this.reconnectAttempts >= this.maxReconnectAttempts) {
1854
- console.warn("[aden] Max reconnect attempts reached, using polling only");
1952
+ logger.warn("Max reconnect attempts reached, using polling only");
1855
1953
  return;
1856
1954
  }
1857
1955
  const delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts), 3e4);
@@ -1872,12 +1970,12 @@ var ControlAgent = class {
1872
1970
  if (message.type === "policy") {
1873
1971
  this.cachedPolicy = message.policy;
1874
1972
  this.lastPolicyFetch = Date.now();
1875
- console.log("[aden] Policy updated:", this.cachedPolicy.version);
1973
+ logger.info("Policy updated:", this.cachedPolicy.version);
1876
1974
  } else if (message.type === "command") {
1877
- console.log("[aden] Command received:", message);
1975
+ logger.info("Command received:", message);
1878
1976
  }
1879
1977
  } catch (error) {
1880
- console.warn("[aden] Failed to parse message:", error);
1978
+ logger.warn("Failed to parse message:", error);
1881
1979
  }
1882
1980
  }
1883
1981
  /**
@@ -1886,6 +1984,7 @@ var ControlAgent = class {
1886
1984
  */
1887
1985
  async startPolling() {
1888
1986
  if (this.pollingTimer) return;
1987
+ logger.debug(`Starting HTTP polling (interval: ${this.options.pollingIntervalMs}ms)`);
1889
1988
  await this.fetchPolicy();
1890
1989
  this.pollingTimer = setInterval(() => {
1891
1990
  if (!this.connected) {
@@ -1906,15 +2005,19 @@ var ControlAgent = class {
1906
2005
  * Fetch policy via HTTP
1907
2006
  */
1908
2007
  async fetchPolicy() {
2008
+ logger.debug("Fetching policy from server...");
1909
2009
  try {
1910
2010
  const response = await this.httpRequest("/v1/control/policy", "GET");
1911
2011
  if (response.ok) {
1912
2012
  const policy = await response.json();
1913
2013
  this.cachedPolicy = policy;
1914
2014
  this.lastPolicyFetch = Date.now();
2015
+ logger.debug(`Policy fetched successfully (version: ${policy.version}, budgets: ${policy.budgets?.length ?? 0})`);
2016
+ } else {
2017
+ logger.debug(`Policy fetch returned status ${response.status}`);
1915
2018
  }
1916
2019
  } catch (error) {
1917
- console.warn("[aden] Failed to fetch policy:", error);
2020
+ logger.warn("Failed to fetch policy:", error);
1918
2021
  }
1919
2022
  }
1920
2023
  /**
@@ -1922,6 +2025,7 @@ var ControlAgent = class {
1922
2025
  */
1923
2026
  startHeartbeat() {
1924
2027
  if (this.heartbeatTimer) return;
2028
+ logger.debug(`Starting heartbeat (interval: ${this.options.heartbeatIntervalMs}ms)`);
1925
2029
  this.heartbeatTimer = setInterval(() => {
1926
2030
  this.sendHeartbeat();
1927
2031
  }, this.options.heartbeatIntervalMs);
@@ -1958,6 +2062,7 @@ var ControlAgent = class {
1958
2062
  * Disconnect from the control server
1959
2063
  */
1960
2064
  async disconnect() {
2065
+ logger.debug("Disconnecting from control server...");
1961
2066
  this.stopPolling();
1962
2067
  this.stopHeartbeat();
1963
2068
  if (this.reconnectTimer) {
@@ -1969,6 +2074,7 @@ var ControlAgent = class {
1969
2074
  this.ws = null;
1970
2075
  }
1971
2076
  this.connected = false;
2077
+ logger.debug("Disconnected from control server");
1972
2078
  }
1973
2079
  /**
1974
2080
  * Get a control decision for a request
@@ -2098,7 +2204,7 @@ var ControlAgent = class {
2098
2204
  timestamp: /* @__PURE__ */ new Date()
2099
2205
  };
2100
2206
  Promise.resolve(this.options.onAlert(alertEvent)).catch((err) => {
2101
- console.warn("[aden] Alert callback error:", err);
2207
+ logger.warn("Alert callback error:", err);
2102
2208
  });
2103
2209
  return {
2104
2210
  action: "alert",
@@ -2405,8 +2511,8 @@ var ControlAgent = class {
2405
2511
  }
2406
2512
  if (this.options.adaptiveThresholdEnabled) {
2407
2513
  if (remainingBudgetUsd <= this.options.adaptiveMinRemainingUsd) {
2408
- console.debug(
2409
- `[aden] Remaining budget $${remainingBudgetUsd.toFixed(4)} <= $${this.options.adaptiveMinRemainingUsd.toFixed(2)}, forcing validation`
2514
+ logger.debug(
2515
+ `Remaining budget $${remainingBudgetUsd.toFixed(4)} <= $${this.options.adaptiveMinRemainingUsd.toFixed(2)}, forcing validation`
2410
2516
  );
2411
2517
  return true;
2412
2518
  }
@@ -2415,13 +2521,13 @@ var ControlAgent = class {
2415
2521
  const samplingRate = this.calculateSamplingRate(budgetUsagePercent);
2416
2522
  const shouldSample = Math.random() < samplingRate;
2417
2523
  if (!shouldSample) {
2418
- console.debug(
2419
- `[aden] Skipping validation (sampling rate: ${(samplingRate * 100).toFixed(1)}%, usage: ${budgetUsagePercent.toFixed(1)}%)`
2524
+ logger.debug(
2525
+ `Skipping validation (sampling rate: ${(samplingRate * 100).toFixed(1)}%, usage: ${budgetUsagePercent.toFixed(1)}%)`
2420
2526
  );
2421
2527
  return false;
2422
2528
  }
2423
- console.debug(
2424
- `[aden] Sampled for validation (rate: ${(samplingRate * 100).toFixed(1)}%, usage: ${budgetUsagePercent.toFixed(1)}%)`
2529
+ logger.debug(
2530
+ `Sampled for validation (rate: ${(samplingRate * 100).toFixed(1)}%, usage: ${budgetUsagePercent.toFixed(1)}%)`
2425
2531
  );
2426
2532
  return true;
2427
2533
  }
@@ -2479,8 +2585,8 @@ var ControlAgent = class {
2479
2585
  });
2480
2586
  if (response.ok) {
2481
2587
  const data = await response.json();
2482
- console.debug(
2483
- `[aden] Server validation response: allowed=${data.allowed}, action=${data.action}, reason=${data.reason}`
2588
+ logger.debug(
2589
+ `Server validation response: allowed=${data.allowed}, action=${data.action}, reason=${data.reason}`
2484
2590
  );
2485
2591
  return {
2486
2592
  allowed: data.allowed ?? true,
@@ -2495,14 +2601,14 @@ var ControlAgent = class {
2495
2601
  degradeToModel: data.degrade_to_model
2496
2602
  };
2497
2603
  } else {
2498
- console.warn(`[aden] Server validation returned status ${response.status}`);
2604
+ logger.warn(`Server validation returned status ${response.status}`);
2499
2605
  return null;
2500
2606
  }
2501
2607
  } finally {
2502
2608
  clearTimeout(timeoutId);
2503
2609
  }
2504
2610
  } catch (error) {
2505
- console.warn(`[aden] Server validation failed: ${error}`);
2611
+ logger.warn(`Server validation failed: ${error}`);
2506
2612
  return null;
2507
2613
  }
2508
2614
  }
@@ -2542,8 +2648,8 @@ var ControlAgent = class {
2542
2648
  }
2543
2649
  }
2544
2650
  if (this.shouldValidateWithServer(usagePercent, remaining, limit)) {
2545
- console.debug(
2546
- `[aden] Budget '${budget.name}' at ${usagePercent.toFixed(1)}% ($${currentSpend.toFixed(6)}/$${limit.toFixed(6)}), validating with server`
2651
+ logger.debug(
2652
+ `Budget '${budget.name}' at ${usagePercent.toFixed(1)}% ($${currentSpend.toFixed(6)}/$${limit.toFixed(6)}), validating with server`
2547
2653
  );
2548
2654
  const validation = await this.validateBudgetWithServer(
2549
2655
  budget.id,
@@ -2553,8 +2659,8 @@ var ControlAgent = class {
2553
2659
  if (validation) {
2554
2660
  return this.applyServerValidationResult(validation, budget.id);
2555
2661
  } else {
2556
- console.warn(
2557
- `[aden] Server validation failed for budget '${budget.id}', using local enforcement`
2662
+ logger.warn(
2663
+ `Server validation failed for budget '${budget.id}', using local enforcement`
2558
2664
  );
2559
2665
  if (!this.options.failOpen) {
2560
2666
  return {
@@ -2616,12 +2722,14 @@ var ControlAgent = class {
2616
2722
  if (this.connected && this.ws?.readyState === WebSocket.OPEN) {
2617
2723
  try {
2618
2724
  this.ws.send(JSON.stringify(event));
2725
+ logger.debug(`Event sent via WebSocket: ${event.event_type}`);
2619
2726
  return;
2620
2727
  } catch (error) {
2621
- console.warn("[aden] WebSocket send failed, queuing event");
2728
+ logger.warn("WebSocket send failed, queuing event");
2622
2729
  }
2623
2730
  }
2624
2731
  this.queueEvent(event);
2732
+ logger.debug(`Event queued: ${event.event_type} (queue size: ${this.eventQueue.length})`);
2625
2733
  if (!this.connected) {
2626
2734
  await this.flushEventQueue();
2627
2735
  }
@@ -2640,7 +2748,9 @@ var ControlAgent = class {
2640
2748
  */
2641
2749
  async flushEventQueue() {
2642
2750
  if (this.eventQueue.length === 0) return;
2751
+ const eventCount = this.eventQueue.length;
2643
2752
  if (this.connected && this.ws?.readyState === WebSocket.OPEN) {
2753
+ logger.debug(`Flushing ${eventCount} events via WebSocket`);
2644
2754
  const events = [...this.eventQueue];
2645
2755
  this.eventQueue = [];
2646
2756
  for (const event of events) {
@@ -2652,12 +2762,14 @@ var ControlAgent = class {
2652
2762
  }
2653
2763
  return;
2654
2764
  }
2765
+ logger.debug(`Flushing ${eventCount} events via HTTP`);
2655
2766
  try {
2656
2767
  const events = [...this.eventQueue];
2657
2768
  this.eventQueue = [];
2658
2769
  await this.httpRequest("/v1/control/events", "POST", { events });
2770
+ logger.debug(`Successfully sent ${eventCount} events via HTTP`);
2659
2771
  } catch (error) {
2660
- console.warn("[aden] Failed to flush event queue:", error);
2772
+ logger.warn("Failed to flush event queue:", error);
2661
2773
  }
2662
2774
  }
2663
2775
  /**
@@ -6529,99 +6641,6 @@ function createReportEmitter(builder) {
6529
6641
  builder.recordEvent(event);
6530
6642
  };
6531
6643
  }
6532
-
6533
- // src/logging.ts
6534
- var LOG_LEVEL_PRIORITY = {
6535
- debug: 0,
6536
- info: 1,
6537
- warn: 2,
6538
- error: 3,
6539
- silent: 4
6540
- };
6541
- var currentConfig = {
6542
- level: parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
6543
- metricsLevel: parseLogLevel(process.env.ADEN_METRICS_LOG_LEVEL) ?? parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
6544
- handler: console
6545
- };
6546
- function parseLogLevel(level) {
6547
- if (!level) return void 0;
6548
- const normalized = level.toLowerCase();
6549
- if (normalized in LOG_LEVEL_PRIORITY) {
6550
- return normalized;
6551
- }
6552
- return void 0;
6553
- }
6554
- function shouldLog(level, configLevel) {
6555
- return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[configLevel];
6556
- }
6557
- function configureLogging(config) {
6558
- if (config.level !== void 0) {
6559
- currentConfig.level = config.level;
6560
- if (config.metricsLevel === void 0) {
6561
- currentConfig.metricsLevel = config.level;
6562
- }
6563
- }
6564
- if (config.metricsLevel !== void 0) {
6565
- currentConfig.metricsLevel = config.metricsLevel;
6566
- }
6567
- if (config.handler !== void 0) {
6568
- currentConfig.handler = config.handler;
6569
- }
6570
- }
6571
- function getLoggingConfig() {
6572
- return { ...currentConfig };
6573
- }
6574
- function resetLoggingConfig() {
6575
- currentConfig = {
6576
- level: parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
6577
- metricsLevel: parseLogLevel(process.env.ADEN_METRICS_LOG_LEVEL) ?? parseLogLevel(process.env.ADEN_LOG_LEVEL) ?? "info",
6578
- handler: console
6579
- };
6580
- }
6581
- var logger = {
6582
- debug(message, ...args) {
6583
- if (shouldLog("debug", currentConfig.level)) {
6584
- currentConfig.handler.debug(`[aden] ${message}`, ...args);
6585
- }
6586
- },
6587
- info(message, ...args) {
6588
- if (shouldLog("info", currentConfig.level)) {
6589
- currentConfig.handler.info(`[aden] ${message}`, ...args);
6590
- }
6591
- },
6592
- warn(message, ...args) {
6593
- if (shouldLog("warn", currentConfig.level)) {
6594
- currentConfig.handler.warn(`[aden] ${message}`, ...args);
6595
- }
6596
- },
6597
- error(message, ...args) {
6598
- if (shouldLog("error", currentConfig.level)) {
6599
- currentConfig.handler.error(`[aden] ${message}`, ...args);
6600
- }
6601
- }
6602
- };
6603
- var metricsLogger = {
6604
- debug(message, ...args) {
6605
- if (shouldLog("debug", currentConfig.metricsLevel)) {
6606
- currentConfig.handler.debug(`[aden.metrics] ${message}`, ...args);
6607
- }
6608
- },
6609
- info(message, ...args) {
6610
- if (shouldLog("info", currentConfig.metricsLevel)) {
6611
- currentConfig.handler.info(`[aden.metrics] ${message}`, ...args);
6612
- }
6613
- },
6614
- warn(message, ...args) {
6615
- if (shouldLog("warn", currentConfig.metricsLevel)) {
6616
- currentConfig.handler.warn(`[aden.metrics] ${message}`, ...args);
6617
- }
6618
- },
6619
- error(message, ...args) {
6620
- if (shouldLog("error", currentConfig.metricsLevel)) {
6621
- currentConfig.handler.error(`[aden.metrics] ${message}`, ...args);
6622
- }
6623
- }
6624
- };
6625
6644
  export {
6626
6645
  AnalyticsEngine,
6627
6646
  BudgetExceededError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aden-ts",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "LLM Observability & Cost Control SDK - Real-time usage tracking, budget enforcement, and cost control for OpenAI, Anthropic, and Gemini",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",