@yanzc/claude-pro 0.5.6 → 0.5.8

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/src/cache.js CHANGED
@@ -80,6 +80,7 @@ export class CacheStats {
80
80
  this.ttl = '5m';
81
81
  this.model = null; // the model that answered the last request
82
82
  this.effort = null;
83
+ this.clockUntil = null; // the footer's prompt cache clock (see clock): null shows none
83
84
  }
84
85
 
85
86
  // The history was cut or replaced (compaction, /rewind, /resume): the next request will not find the old
@@ -88,6 +89,21 @@ export class CacheStats {
88
89
  this.expected = null;
89
90
  }
90
91
 
92
+ // A compaction replaced the conversation: none of it is in the cache until the next response.
93
+ noteCompacted() {
94
+ this.noteRewrite();
95
+ if (this.clockUntil != null) this.clockUntil = 0;
96
+ }
97
+
98
+ // The prompt cache clock of the footer, as in Claude Code's VS Code extension: the minutes left before what
99
+ // the last request left in the cache runs out (each response that used the cache starts it again), or cold
100
+ // once it has run out and right after a compaction, until the next response. null before any response
101
+ // reported cache use. A resumed conversation starts from the clockUntil its session file kept.
102
+ clock(now = Date.now()) {
103
+ if (this.clockUntil == null) return null;
104
+ return now < this.clockUntil ? { minutes: Math.ceil((this.clockUntil - now) / 60_000) } : { cold: true };
105
+ }
106
+
91
107
  // One finished request. `at` is when it started: the TTL counts from there, not from the end of the reply.
92
108
  record({ usage, fingerprint: fp = null, ttl = '5m', caching = true, at = Date.now() }) {
93
109
  const u = usage || {};
@@ -107,6 +123,7 @@ export class CacheStats {
107
123
  this.expected = caching ? read + write : null;
108
124
  this.expiresAt = at + TTL_MS[ttl];
109
125
  this.ttl = ttl;
126
+ if (caching && (read || write)) this.clockUntil = this.expiresAt;
110
127
  if (fp) {
111
128
  this.prev = fp;
112
129
  this.model = fp.model;
package/src/commands.js CHANGED
@@ -624,7 +624,7 @@ export function buildCommands(app) {
624
624
  reloadConfig();
625
625
  app.screen.setFull(want === 'fullscreen');
626
626
  out(want === 'fullscreen'
627
- ? `Fullscreen: the input box stays at the bottom; scroll with the wheel, PgUp/PgDn, ctrl+Home/End. To select text, hold Shift while dragging. (Saved in ${file})`
627
+ ? `Fullscreen: the input box stays at the bottom; scroll with the wheel, PgUp/PgDn, ctrl+Home/End; drag to select and copy; ctrl+f to find in the conversation. (Saved in ${file})`
628
628
  : `Default renderer: the conversation scrolls in the terminal. (Saved in ${file})`);
629
629
  },
630
630
  });
package/src/session.js CHANGED
@@ -79,6 +79,13 @@ export class SessionStore {
79
79
  reset(messages) { this.append({ type: 'reset', messages, at: Date.now() }); }
80
80
  // What the conversation's requests have cost so far (USD, see pricing.js), written after each one; the newest wins.
81
81
  setCost(usd) { this.append({ type: 'meta', cost: usd, at: Date.now() }); }
82
+ // Until when the conversation's prompt cache lasts (ms since epoch; 0: cold), for the footer's clock of a
83
+ // resumed conversation (see CacheStats.clock). Written after each of its requests and compactions.
84
+ setCacheUntil(until) {
85
+ if (until == null || until === this.cacheUntil) return;
86
+ this.cacheUntil = until;
87
+ this.append({ type: 'meta', cacheUntil: until, at: Date.now() });
88
+ }
82
89
  // The system prompt this conversation runs behind, kept so that a resumed one continues behind the same prompt
83
90
  // and so with the prompt cache it already has (see runtime.resumeSystemPrompt). Written when it first appears
84
91
  // and whenever it changes (after a compaction); the newest one wins when the session is loaded.
@@ -117,6 +124,7 @@ export class SessionStore {
117
124
  name: typeof meta.name === 'string' && meta.name.trim() ? meta.name : null,
118
125
  systemPrompt: typeof meta.systemPrompt === 'string' && meta.systemPrompt.trim() ? meta.systemPrompt : null,
119
126
  cost: Number(meta.cost) > 0 ? Number(meta.cost) : 0,
127
+ cacheUntil: Number.isFinite(meta.cacheUntil) && meta.cacheUntil >= 0 ? meta.cacheUntil : null,
120
128
  };
121
129
  }
122
130
 
package/src/ui/ansi.js CHANGED
@@ -51,6 +51,8 @@ export const c = {
51
51
  plan: hex('#48968c'),
52
52
  edits: hex('#af87ff'),
53
53
  code: hex('#b1b9f9'),
54
+ userBg: hex('#373737', true), // the band behind the user's messages (see renderUserMessage)
55
+ userText: hex('#e4e4e4'),
54
56
  diffAdd: hex('#225c2b', true),
55
57
  diffDel: hex('#7a2936', true),
56
58
  diffAddWord: hex('#38a660', true),
package/src/ui/render.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // Formatting of transcript items: user prompts, tool calls and results, diffs, todos.
2
2
 
3
- import { c, stringWidth, truncate, padEnd, wordWrap, wrapLine } from './ansi.js';
3
+ import { c, colorEnabled, stringWidth, truncate, padEnd, wordWrap, wrapLine } from './ansi.js';
4
4
  import { displayPath } from '../utils/paths.js';
5
5
  import { renderMarkdown } from './markdown.js';
6
6
 
@@ -129,14 +129,19 @@ export function renderToolResult(entry, { verbose = false, width = 100, cwd }) {
129
129
  return resultLines(shown);
130
130
  }
131
131
 
132
+ // What the user wrote, on a band of background colour across the window, so that it stands apart from the replies
133
+ // (as in Claude Code). The band is the rest of each row erased in that colour (\x1b[K), which needs no padding and
134
+ // so fits any width the window is given later.
135
+ const userRow = (s) => (colorEnabled ? c.userBg(s + '\x1b[K') : s);
136
+
132
137
  export function renderUserMessage(text, width) {
133
138
  const lines = text.replace(/\r\n/g, '\n').split('\n');
134
139
  const out = [];
135
140
  lines.forEach((l, i) => {
136
141
  const wrapped = wordWrap(l, Math.max(10, width - 3));
137
- wrapped.forEach((wl, j) => out.push((i === 0 && j === 0 ? c.gray('> ') : ' ') + c.gray(wl)));
142
+ wrapped.forEach((wl, j) => out.push(userRow((i === 0 && j === 0 ? c.gray('> ') : ' ') + c.userText(wl))));
138
143
  });
139
- if (out.length > 30) return [...out.slice(0, 25), c.dim(` … +${out.length - 25} lines`)];
144
+ if (out.length > 30) return [...out.slice(0, 25), userRow(c.gray(` … +${out.length - 25} lines`))];
140
145
  return out;
141
146
  }
142
147