claude-usage-limits 1.40.2 → 1.40.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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "usage-limits",
3
3
  "displayName": "Usage Limits",
4
- "version": "1.40.2",
4
+ "version": "1.40.3",
5
5
  "description": "Puts your remaining Claude Code usage limit into Claude's context before every prompt, so it opens with what fits in the budget instead of starting work that gets cut off. Reports headroom as turns rather than percentages, prices a job before you start it, and detects your plan tier.",
6
6
  "author": {
7
7
  "name": "Ridelink",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usage-limits",
3
- "version": "1.40.2",
3
+ "version": "1.40.3",
4
4
  "description": "Reports how much of your Codex usage limit is left as turns of work rather than a percentage, prices a job before you start it, and counts the other agents sharing the same budget.",
5
5
  "author": {
6
6
  "name": "Ridelink",
package/README.md CHANGED
@@ -418,6 +418,13 @@ would fire into a session that never stopped. A weekly wall still arms. The
418
418
  acknowledgement lapses by itself when the 5-hour window it was made against
419
419
  resets.
420
420
 
421
+ A deferral is different from a wake, and is treated differently. `defer` is a
422
+ time **you** named, so it is always scheduled — but if you defer to `reset` while
423
+ low-priority is acknowledged, the confirmation says that this session carries
424
+ past the 5-hour reset and waiting for it buys nothing. The mid-turn pulse follows
425
+ the brief onto the weekly too, out of the same function, so the two can never
426
+ report different windows.
427
+
421
428
  **The graceful wrap-up note.** Claude Code can inject its own "finish up"
422
429
  instruction at the wall. The mechanism is real, and the gate is
423
430
  `tengu_lantern_wick_mode` — the bundle's own normalizer keeps only `"wrap-up"`
@@ -1295,7 +1302,7 @@ test/ node --test, no dependencies
1295
1302
  node --test
1296
1303
  ```
1297
1304
 
1298
- 895 tests over the pricing, the window arithmetic, plan and credit detection,
1305
+ 901 tests over the pricing, the window arithmetic, plan and credit detection,
1299
1306
  the status line, the before-prompt line, the mid-turn pulse, the after-reply tally and the session history, job forecasting,
1300
1307
  per-project attribution, the Codex reader and its installer, the CLI,
1301
1308
  packaging, the settings save/restore, and what Claude Code's own wall-time
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-usage-limits",
3
- "version": "1.40.2",
3
+ "version": "1.40.3",
4
4
  "description": "Puts your remaining Claude Code usage limit into Claude's context before every prompt, so it opens with what fits in the budget instead of starting work that gets cut off. Reports headroom as turns rather than percentages, prices a job before you start it, and detects your plan tier.",
5
5
  "keywords": [
6
6
  "claude",
@@ -140,7 +140,10 @@ function confirmation(parts) {
140
140
  const tail = [];
141
141
  tail.push('Nothing has been started');
142
142
  if (parts.items) tail.push(parts.items + ' saved');
143
- if (parts.resetNote) tail.push(parts.resetNote);
143
+ // Every note, not only the first: two can apply at once.
144
+ for (const note of parts.notes && parts.notes.length ? parts.notes : [parts.resetNote]) {
145
+ if (note) tail.push(note);
146
+ }
144
147
  return line + tail.join('; ') + '. Run "defer cancel" to call it off.';
145
148
  }
146
149
 
@@ -154,7 +157,7 @@ function bindingReset(now) {
154
157
  usage.setHost(host.detect(process.argv.slice(2), process.env));
155
158
  const collected = usage.collect(now);
156
159
  const utilization = collected && collected.utilization;
157
- if (!utilization) return { resetsAt: null, percent: null };
160
+ if (!utilization) return { resetsAt: null, percent: null, windowKey: null };
158
161
  let worst = null;
159
162
  for (const key of Object.keys(utilization)) {
160
163
  const window = utilization[key];
@@ -163,12 +166,24 @@ function bindingReset(now) {
163
166
  if (!Number.isFinite(percent)) continue;
164
167
  const resets = Date.parse(window.resets_at);
165
168
  if (!worst || percent > worst.percent) {
166
- worst = { percent, resetsAt: Number.isFinite(resets) ? resets : null };
169
+ worst = { percent, resetsAt: Number.isFinite(resets) ? resets : null, windowKey: key };
167
170
  }
168
171
  }
169
172
  return worst || { resetsAt: null, percent: null };
170
173
  } catch (err) {
171
- return { resetsAt: null, percent: null };
174
+ return { resetsAt: null, percent: null, windowKey: null };
175
+ }
176
+ }
177
+
178
+ // Claude Code only, like every other reader of this fact: /low-priority is its
179
+ // slash command against its account, and Codex files a five-hour window under the
180
+ // same key.
181
+ function lowPriorityAcknowledged(now) {
182
+ try {
183
+ if (host.detect(process.argv.slice(2), process.env) !== host.CLAUDE) return false;
184
+ return Boolean(require('./lowpri.js').readAck(now));
185
+ } catch (err) {
186
+ return false;
172
187
  }
173
188
  }
174
189
 
@@ -198,13 +213,29 @@ function plan(options) {
198
213
  notes.push('note: that is before the window resets at ' + formatClock(binding.resetsAt));
199
214
  }
200
215
  }
216
+ // A deferral is a time the user named, so it is honoured whatever else is
217
+ // true - unlike an automatic relay wake, which the acknowledgement refuses.
218
+ // But waiting for a 5-hour reset this session carries straight past is
219
+ // waiting for nothing, and that is worth one line before the task is
220
+ // registered rather than after it fires.
221
+ if (options.lowPriorityAck && binding.windowKey === 'five_hour') {
222
+ notes.push(
223
+ 'note: you have said /low-priority is on, so this session carries past the 5-hour reset ' +
224
+ 'and waiting for it buys nothing - the weekly is the window that still stops work'
225
+ );
226
+ }
201
227
  return {
202
228
  ok: true,
203
229
  at: when.at,
204
230
  label: when.label,
205
231
  clock: formatClock(when.at),
206
232
  in: when.at - now,
233
+ // resetNote is the first of them, kept because the confirmation and the
234
+ // tests have always read that field. `notes` is all of them, because there
235
+ // can now be two and dropping the second would have hidden the one fact
236
+ // worth printing: that waiting for this reset buys nothing.
207
237
  resetNote: notes[0] || null,
238
+ notes,
208
239
  };
209
240
  }
210
241
 
@@ -256,7 +287,7 @@ function main(argv, now) {
256
287
  }
257
288
 
258
289
  const binding = bindingReset(at);
259
- const decided = plan({ now: at, when: first, binding });
290
+ const decided = plan({ now: at, when: first, binding, lowPriorityAck: lowPriorityAcknowledged(at) });
260
291
  if (!decided.ok) return decided.error;
261
292
 
262
293
  const id = sessionId(args, process.env);
@@ -304,6 +335,7 @@ function main(argv, now) {
304
335
  in: decided.in,
305
336
  items,
306
337
  resetNote: decided.resetNote,
338
+ notes: decided.notes,
307
339
  });
308
340
  }
309
341
 
@@ -317,4 +349,4 @@ if (require.main === module) {
317
349
  }
318
350
  }
319
351
 
320
- module.exports = { parseWhen, formatClock, formatSpan, confirmation, plan, status, cancel, main, MINUTE, HOUR };
352
+ module.exports = { lowPriorityAcknowledged, parseWhen, formatClock, formatSpan, confirmation, plan, status, cancel, main, MINUTE, HOUR };