notoken-core 1.4.0 → 1.4.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.
@@ -25,6 +25,15 @@ export interface LLMState {
25
25
  tokensSaved: number;
26
26
  commandsHandledOffline: number;
27
27
  lastSaved: string;
28
+ sessions: SessionStats[];
29
+ }
30
+ export interface SessionStats {
31
+ id: string;
32
+ folder: string;
33
+ startedAt: string;
34
+ endedAt?: string;
35
+ tokensSaved: number;
36
+ commandsHandled: number;
28
37
  }
29
38
  export declare function detectProviders(): LLMProvider[];
30
39
  export declare function formatStatus(): string;
@@ -36,9 +45,16 @@ export declare function isOfflineMode(): boolean;
36
45
  export declare function isLLMDisabled(name: string): boolean;
37
46
  export declare function recordOfflineCommand(): void;
38
47
  export declare function getTokensSaved(): {
39
- tokens: number;
40
- commands: number;
48
+ session: {
49
+ tokens: number;
50
+ commands: number;
51
+ };
52
+ total: {
53
+ tokens: number;
54
+ commands: number;
55
+ };
41
56
  };
42
57
  export declare function formatTokensSaved(): string;
43
58
  export declare function formatTokensSavedBrief(): string;
59
+ export declare function getSessionId(): string;
44
60
  export declare function saveOnExit(): void;
@@ -21,6 +21,12 @@ const c = {
21
21
  green: "\x1b[32m", yellow: "\x1b[33m", red: "\x1b[31m", cyan: "\x1b[36m",
22
22
  };
23
23
  // ─── State Persistence ──────────────────────────────────────────────────────
24
+ // Per-session counters (reset each launch)
25
+ let sessionTokens = 0;
26
+ let sessionCommands = 0;
27
+ const sessionId = `session_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
28
+ const sessionStartedAt = new Date().toISOString();
29
+ const sessionFolder = process.cwd();
24
30
  function loadState() {
25
31
  try {
26
32
  if (existsSync(STATE_FILE)) {
@@ -28,13 +34,16 @@ function loadState() {
28
34
  }
29
35
  }
30
36
  catch { }
31
- return { offlineMode: false, disabled: [], tokensSaved: 0, commandsHandledOffline: 0, lastSaved: new Date().toISOString() };
37
+ return { offlineMode: false, disabled: [], tokensSaved: 0, commandsHandledOffline: 0, lastSaved: new Date().toISOString(), sessions: [] };
32
38
  }
33
- function saveState(state) {
39
+ function saveState(s) {
34
40
  try {
35
41
  mkdirSync(USER_HOME, { recursive: true });
36
- state.lastSaved = new Date().toISOString();
37
- writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
42
+ s.lastSaved = new Date().toISOString();
43
+ // Keep last 50 sessions
44
+ if (s.sessions.length > 50)
45
+ s.sessions = s.sessions.slice(-50);
46
+ writeFileSync(STATE_FILE, JSON.stringify(s, null, 2));
38
47
  }
39
48
  catch { }
40
49
  }
@@ -111,7 +120,9 @@ export function formatStatus() {
111
120
  }
112
121
  // Token savings
113
122
  lines.push("");
114
- lines.push(` ${c.cyan}Tokens saved:${c.reset} ~${formatTokens(state.tokensSaved)} (${state.commandsHandledOffline} commands handled offline)`);
123
+ lines.push(` ${c.bold}This session:${c.reset} ~${formatTokens(sessionTokens)} tokens saved (${sessionCommands} commands)`);
124
+ lines.push(` ${c.bold}All time:${c.reset} ~${formatTokens(state.tokensSaved)} tokens saved (${state.commandsHandledOffline} commands)`);
125
+ lines.push(` ${c.dim}Session: ${sessionId} | Folder: ${sessionFolder}${c.reset}`);
115
126
  return lines.join("\n");
116
127
  }
117
128
  // ─── Controls ───────────────────────────────────────────────────────────────
@@ -150,27 +161,47 @@ const AVG_TOKENS_PER_CALL = 700;
150
161
  export function recordOfflineCommand() {
151
162
  state.commandsHandledOffline++;
152
163
  state.tokensSaved += AVG_TOKENS_PER_CALL;
153
- // Save periodically (every 10 commands)
164
+ sessionCommands++;
165
+ sessionTokens += AVG_TOKENS_PER_CALL;
154
166
  if (state.commandsHandledOffline % 10 === 0)
155
167
  saveState(state);
156
168
  }
157
169
  export function getTokensSaved() {
158
- return { tokens: state.tokensSaved, commands: state.commandsHandledOffline };
170
+ return {
171
+ session: { tokens: sessionTokens, commands: sessionCommands },
172
+ total: { tokens: state.tokensSaved, commands: state.commandsHandledOffline },
173
+ };
159
174
  }
160
175
  export function formatTokensSaved() {
161
- const { tokens, commands } = getTokensSaved();
162
- if (commands === 0)
176
+ if (sessionCommands === 0 && state.commandsHandledOffline === 0)
163
177
  return "";
164
- return `${c.dim}~${formatTokens(tokens)} tokens saved (${commands} commands handled offline)${c.reset}`;
178
+ const lines = [];
179
+ if (sessionCommands > 0) {
180
+ lines.push(`${c.dim}This session: ~${formatTokens(sessionTokens)} tokens saved (${sessionCommands} commands)${c.reset}`);
181
+ }
182
+ lines.push(`${c.dim}All time: ~${formatTokens(state.tokensSaved)} tokens saved (${state.commandsHandledOffline} commands)${c.reset}`);
183
+ return lines.join("\n");
165
184
  }
166
185
  export function formatTokensSavedBrief() {
167
- const { tokens, commands } = getTokensSaved();
168
- if (commands === 0)
186
+ if (sessionCommands === 0)
169
187
  return "";
170
- return `${c.dim}Tokens saved: ~${formatTokens(tokens)}${c.reset}`;
188
+ return `${c.dim}Session: ~${formatTokens(sessionTokens)} saved | Total: ~${formatTokens(state.tokensSaved)}${c.reset}`;
171
189
  }
172
- // Save state on exit
190
+ export function getSessionId() {
191
+ return sessionId;
192
+ }
193
+ // Save state on exit — record session stats
173
194
  export function saveOnExit() {
195
+ if (sessionCommands > 0) {
196
+ state.sessions.push({
197
+ id: sessionId,
198
+ folder: sessionFolder,
199
+ startedAt: sessionStartedAt,
200
+ endedAt: new Date().toISOString(),
201
+ tokensSaved: sessionTokens,
202
+ commandsHandled: sessionCommands,
203
+ });
204
+ }
174
205
  saveState(state);
175
206
  }
176
207
  // ─── Helpers ────────────────────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "notoken-core",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "Shared engine for notoken — NLP parsing, execution, detection, analysis",
5
5
  "type": "module",
6
6
  "license": "MIT",