sentisense 0.63.0 → 0.63.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/README.md CHANGED
@@ -157,7 +157,7 @@ const client = new SentiSense({
157
157
  | `apiKey` | none | Sent as `X-SentiSense-API-Key`. Required by every endpoint. |
158
158
  | `baseUrl` | `https://app.sentisense.ai` | Override for a non-production host. |
159
159
  | `timeout` | `30000` | Per-request timeout in milliseconds. |
160
- | `maxRetries` | `3` | Retries on 429 and 5xx, honouring `Retry-After`. Set `0` to fail fast. |
160
+ | `maxRetries` | `3` | Retries the per-minute 429 and 5xx, honouring `Retry-After`. The monthly-allowance 429 is never retried. Set `0` to fail fast. |
161
161
  | `userAgentSuffix` | none | Appended to the User-Agent, after `sentisense-node/{version}`. |
162
162
 
163
163
  `userAgentSuffix` is how you say what is calling on top of the SDK, so your traffic is legible in your own logs and in ours. A tool name and version works (`"my-bot/1.4"`), optionally with an agent label (`"my-bot/1.4 agent/research-desk"`). Node only, since browsers set the header themselves. Newlines are collapsed and an empty value is ignored.
@@ -636,7 +636,12 @@ try {
636
636
  if (error instanceof AuthenticationError) {
637
637
  // 401 or 403: invalid/missing API key or insufficient tier
638
638
  } else if (error instanceof RateLimitError) {
639
- // 429: quota exceeded
639
+ if (error.code === "quota_exceeded") {
640
+ // 429: monthly allowance used up. Not retried; error.message says when it resets.
641
+ } else {
642
+ // 429: per-minute limit ("rate_limit_exceeded"), thrown once retries are used up.
643
+ // error.retryAfter is the server's wait in seconds.
644
+ }
640
645
  }
641
646
  }
642
647
  ```
@@ -645,7 +650,7 @@ try {
645
650
  |------------|-------------|------|
646
651
  | `AuthenticationError` | 401, 403 | Invalid API key or insufficient tier |
647
652
  | `NotFoundError` | 404 | Resource not found |
648
- | `RateLimitError` | 429 | Quota exceeded |
653
+ | `RateLimitError` | 429 | Per-minute limit (`code: "rate_limit_exceeded"`, retried first) or monthly allowance used up (`code: "quota_exceeded"`, thrown immediately) |
649
654
  | `APIError` | Other 4xx/5xx | General API error |
650
655
 
651
656
  All errors extend `SentiSenseError` and include `status`, `code`, and `message` properties.
package/dist/cli.cjs CHANGED
@@ -66,10 +66,12 @@ var EXIT_TABLE = [
66
66
  [EXIT.USAGE, "bad usage, caught before any request was sent"],
67
67
  [EXIT.AUTH, "missing or rejected API key"],
68
68
  [EXIT.NOT_FOUND, "no data for that symbol or identifier"],
69
- [EXIT.RATE_LIMIT, "rate limited"],
69
+ [EXIT.RATE_LIMIT, "rate limited, or the monthly request allowance is used up"],
70
70
  [EXIT.NETWORK, "network failure or timeout"]
71
71
  ];
72
72
  var KEY_URL = "https://app.sentisense.ai/get-api-key";
73
+ var PRICING_URL = "https://app.sentisense.ai/pricing";
74
+ var QUOTA_EXCEEDED = "quota_exceeded";
73
75
  var CliUsageError = class extends Error {
74
76
  constructor(message, hint) {
75
77
  super(message);
@@ -158,6 +160,15 @@ function classify(error, command) {
158
160
  };
159
161
  }
160
162
  if (error instanceof RateLimitError) {
163
+ if (error.code === QUOTA_EXCEEDED) {
164
+ return {
165
+ exitCode: EXIT.RATE_LIMIT,
166
+ lines: [
167
+ `error: monthly request allowance used up: ${error.message}`,
168
+ `next: the free monthly allowance resets at the start of next month, so running it again before then will not help. PRO has no monthly cap: ${PRICING_URL}`
169
+ ]
170
+ };
171
+ }
161
172
  const wait = error.retryAfter ? Math.ceil(error.retryAfter) : 60;
162
173
  return {
163
174
  exitCode: EXIT.RATE_LIMIT,
@@ -1345,7 +1356,7 @@ var flowsCommand = {
1345
1356
  };
1346
1357
 
1347
1358
  // src/version.ts
1348
- var VERSION = "0.63.0";
1359
+ var VERSION = "0.63.1";
1349
1360
 
1350
1361
  // src/resources/analyst.ts
1351
1362
  var Analyst = class {
@@ -2668,6 +2679,15 @@ var DEEP_HISTORY_FALLBACK_WAIT_S = 3;
2668
2679
  var MAX_DEEP_HISTORY_WAIT_S = 30;
2669
2680
  var MAX_RATE_LIMIT_WAIT_S = 120;
2670
2681
  var RATE_LIMIT_FALLBACK_WAIT_S = 60;
2682
+ var QUOTA_EXCEEDED_CODE = "quota_exceeded";
2683
+ async function isQuotaExceeded(response) {
2684
+ try {
2685
+ const body = await response.clone().json();
2686
+ return body?.error === QUOTA_EXCEEDED_CODE;
2687
+ } catch {
2688
+ return false;
2689
+ }
2690
+ }
2671
2691
  function clampRetryAfter(raw, maxWaitS) {
2672
2692
  if (!raw) return void 0;
2673
2693
  const parsed = Number(raw);
@@ -2753,6 +2773,9 @@ var SentiSense = class {
2753
2773
  );
2754
2774
  }
2755
2775
  if (!response.ok) {
2776
+ if (response.status === 429 && await isQuotaExceeded(response)) {
2777
+ await this.handleErrorResponse(response);
2778
+ }
2756
2779
  const isRetryable = response.status === 429 || response.status >= 500;
2757
2780
  if (isRetryable && attempt < this.maxRetries) {
2758
2781
  if (response.status === 429 || response.status === 503) {
package/dist/index.cjs CHANGED
@@ -1394,7 +1394,7 @@ var Trackers = class {
1394
1394
  };
1395
1395
 
1396
1396
  // src/version.ts
1397
- var VERSION = "0.63.0";
1397
+ var VERSION = "0.63.1";
1398
1398
 
1399
1399
  // src/client.ts
1400
1400
  var DEFAULT_BASE_URL = "https://app.sentisense.ai";
@@ -1406,6 +1406,15 @@ var DEEP_HISTORY_FALLBACK_WAIT_S = 3;
1406
1406
  var MAX_DEEP_HISTORY_WAIT_S = 30;
1407
1407
  var MAX_RATE_LIMIT_WAIT_S = 120;
1408
1408
  var RATE_LIMIT_FALLBACK_WAIT_S = 60;
1409
+ var QUOTA_EXCEEDED_CODE = "quota_exceeded";
1410
+ async function isQuotaExceeded(response) {
1411
+ try {
1412
+ const body = await response.clone().json();
1413
+ return body?.error === QUOTA_EXCEEDED_CODE;
1414
+ } catch {
1415
+ return false;
1416
+ }
1417
+ }
1409
1418
  function clampRetryAfter(raw, maxWaitS) {
1410
1419
  if (!raw) return void 0;
1411
1420
  const parsed = Number(raw);
@@ -1491,6 +1500,9 @@ var SentiSense = class {
1491
1500
  );
1492
1501
  }
1493
1502
  if (!response.ok) {
1503
+ if (response.status === 429 && await isQuotaExceeded(response)) {
1504
+ await this.handleErrorResponse(response);
1505
+ }
1494
1506
  const isRetryable = response.status === 429 || response.status >= 500;
1495
1507
  if (isRetryable && attempt < this.maxRetries) {
1496
1508
  if (response.status === 429 || response.status === 503) {