caplyr 0.2.2 → 0.2.3

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
@@ -176,14 +176,18 @@ var Heartbeat = class {
176
176
  const data = await res.json();
177
177
  const localDailyUsed = this.budgetStatus.daily_used;
178
178
  const localMonthlyUsed = this.budgetStatus.monthly_used;
179
+ const serverDailyUsed = Number(data.daily_used) || 0;
180
+ const serverMonthlyUsed = Number(data.monthly_used) || 0;
181
+ const serverDailyLimit = data.daily_limit != null ? Number(data.daily_limit) : null;
182
+ const serverMonthlyLimit = data.monthly_limit != null ? Number(data.monthly_limit) : null;
179
183
  this.budgetStatus = {
180
184
  ...data,
181
185
  // Use whichever spend is higher — server or local tracking
182
- daily_used: Math.max(data.daily_used ?? 0, localDailyUsed),
183
- monthly_used: Math.max(data.monthly_used ?? 0, localMonthlyUsed),
184
- // Preserve local limits if server doesn't provide them
185
- daily_limit: data.daily_limit ?? this.localDailyLimit,
186
- monthly_limit: data.monthly_limit ?? this.localMonthlyLimit
186
+ daily_used: Math.max(serverDailyUsed, localDailyUsed),
187
+ monthly_used: Math.max(serverMonthlyUsed, localMonthlyUsed),
188
+ // Use the stricter (lower) limit — local config takes priority if lower
189
+ daily_limit: this.pickStricterLimit(serverDailyLimit, this.localDailyLimit),
190
+ monthly_limit: this.pickStricterLimit(serverMonthlyLimit, this.localMonthlyLimit)
187
191
  };
188
192
  this.consecutiveFailures = 0;
189
193
  const newStatus = data.kill_switch_active ? "OFF" : data.status;
@@ -200,6 +204,22 @@ var Heartbeat = class {
200
204
  }
201
205
  }
202
206
  }
207
+ /**
208
+ * Pick the stricter (lower) of two limits.
209
+ * If one is null, use the other.
210
+ */
211
+ pickStricterLimit(a, b) {
212
+ if (a === null) return b;
213
+ if (b === null) return a;
214
+ return Math.min(a, b);
215
+ }
216
+ /**
217
+ * Force an immediate heartbeat poll (useful for kill switch checks).
218
+ * Returns a promise that resolves when the poll completes.
219
+ */
220
+ async forcePoll() {
221
+ await this.beat();
222
+ }
203
223
  /**
204
224
  * Update local budget tracking (called after each request).
205
225
  * This provides real-time budget awareness between heartbeats.
package/dist/index.mjs CHANGED
@@ -143,14 +143,18 @@ var Heartbeat = class {
143
143
  const data = await res.json();
144
144
  const localDailyUsed = this.budgetStatus.daily_used;
145
145
  const localMonthlyUsed = this.budgetStatus.monthly_used;
146
+ const serverDailyUsed = Number(data.daily_used) || 0;
147
+ const serverMonthlyUsed = Number(data.monthly_used) || 0;
148
+ const serverDailyLimit = data.daily_limit != null ? Number(data.daily_limit) : null;
149
+ const serverMonthlyLimit = data.monthly_limit != null ? Number(data.monthly_limit) : null;
146
150
  this.budgetStatus = {
147
151
  ...data,
148
152
  // Use whichever spend is higher — server or local tracking
149
- daily_used: Math.max(data.daily_used ?? 0, localDailyUsed),
150
- monthly_used: Math.max(data.monthly_used ?? 0, localMonthlyUsed),
151
- // Preserve local limits if server doesn't provide them
152
- daily_limit: data.daily_limit ?? this.localDailyLimit,
153
- monthly_limit: data.monthly_limit ?? this.localMonthlyLimit
153
+ daily_used: Math.max(serverDailyUsed, localDailyUsed),
154
+ monthly_used: Math.max(serverMonthlyUsed, localMonthlyUsed),
155
+ // Use the stricter (lower) limit — local config takes priority if lower
156
+ daily_limit: this.pickStricterLimit(serverDailyLimit, this.localDailyLimit),
157
+ monthly_limit: this.pickStricterLimit(serverMonthlyLimit, this.localMonthlyLimit)
154
158
  };
155
159
  this.consecutiveFailures = 0;
156
160
  const newStatus = data.kill_switch_active ? "OFF" : data.status;
@@ -167,6 +171,22 @@ var Heartbeat = class {
167
171
  }
168
172
  }
169
173
  }
174
+ /**
175
+ * Pick the stricter (lower) of two limits.
176
+ * If one is null, use the other.
177
+ */
178
+ pickStricterLimit(a, b) {
179
+ if (a === null) return b;
180
+ if (b === null) return a;
181
+ return Math.min(a, b);
182
+ }
183
+ /**
184
+ * Force an immediate heartbeat poll (useful for kill switch checks).
185
+ * Returns a promise that resolves when the poll completes.
186
+ */
187
+ async forcePoll() {
188
+ await this.beat();
189
+ }
170
190
  /**
171
191
  * Update local budget tracking (called after each request).
172
192
  * This provides real-time budget awareness between heartbeats.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "caplyr",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "AI Cost Control Plane — budget guardrails, auto-downgrade, and kill switch for AI API calls",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",