@goodandready/dsh-context-lens 0.1.15 → 0.1.17

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/lib/index.js CHANGED
@@ -13,6 +13,7 @@ export const Config = z.object({
13
13
  tokenSavingsTracking: z.boolean().default(true).description('Track and display token budget savings'),
14
14
  autoCompressThreshold: z.number().default(4000).description('Auto-compress threshold in chars (0 to disable)'),
15
15
  budgetLimit: z.number().default(100000).description('Session token budget; compressions stop counting after this limit'),
16
+ budgetAlertPercent: z.number().default(90).description('Budget percentage threshold (50-99%) for warning alert'),
16
17
  autoCollapse: z.boolean().default(true).description('Warn in UI when budget is nearly exhausted (does not force-close the settings card)')
17
18
  });
18
19
 
@@ -37,6 +38,14 @@ function getFocus(key) {
37
38
  return focusBySession.get(key);
38
39
  }
39
40
 
41
+ function clearFocus(key) {
42
+ if (key) {
43
+ focusBySession.set(key, { paths: [], updatedAt: new Date().toISOString() });
44
+ } else {
45
+ focusBySession.clear();
46
+ }
47
+ }
48
+
40
49
  const OUTPUT_SCHEMA = { type: 'object', properties: { success: { type: 'boolean' } }, additionalProperties: true };
41
50
  const renderOutput = (_args, result) => JSON.stringify(result, null, 2);
42
51
 
@@ -53,6 +62,7 @@ export function apply(ctx, config) {
53
62
  const cfg = getConfig();
54
63
  if (cfg && cfg.tokenSavingsTracking === false) return null;
55
64
  if (cfg && typeof cfg.budgetLimit === 'number') tracker.setBudgetLimit(cfg.budgetLimit);
65
+ if (cfg && typeof cfg.budgetAlertPercent === 'number') tracker.setBudgetAlertPercent(cfg.budgetAlertPercent);
56
66
  return tracker.record(original, compressed);
57
67
  } catch {
58
68
  // #39: never record on config/read errors
@@ -114,12 +124,12 @@ export function apply(ctx, config) {
114
124
 
115
125
  ctx.tools.register({
116
126
  name: 'context_lens_compress_code',
117
- description: 'Generate AST skeleton for a large source file (JS/TS/Python/Go/Rust/Java) to save context',
127
+ description: 'Generate AST skeleton for a large source file (JS/TS/Python/Go/Rust/Java/C/C++/SQL) to save context',
118
128
  parameters: {
119
129
  type: 'object',
120
130
  properties: {
121
131
  code: { type: 'string', description: 'Source code to skeletonize' },
122
- language: { type: 'string', enum: ['js', 'ts', 'py', 'python', 'go', 'rust', 'java'], description: 'Language hint' },
132
+ language: { type: 'string', enum: ['js', 'ts', 'py', 'python', 'go', 'rust', 'java', 'c', 'cpp', 'sql'], description: 'Language hint' },
123
133
  maxDepth: { type: 'number', description: 'Max depth' },
124
134
  filePath: { type: 'string', description: 'File path to check focus (if in focus, returns full code)' },
125
135
  sessionId: { type: 'string', description: 'Session id for focus lookup' }
@@ -178,7 +188,8 @@ export function apply(ctx, config) {
178
188
  execute: async (params, meta) => {
179
189
  const cfg = getConfig();
180
190
  if (typeof cfg.budgetLimit === 'number') tracker.setBudgetLimit(cfg.budgetLimit);
181
- const stats = tracker.getStats(cfg.budgetLimit);
191
+ if (typeof cfg.budgetAlertPercent === 'number') tracker.setBudgetAlertPercent(cfg.budgetAlertPercent);
192
+ const stats = tracker.getStats(cfg.budgetLimit, cfg.budgetAlertPercent);
182
193
  const history = tracker.getHistory();
183
194
  const key = sessionKey(params || {}, meta);
184
195
  return {
@@ -189,7 +200,8 @@ export function apply(ctx, config) {
189
200
  autoCollapse: cfg.autoCollapse !== false,
190
201
  focus: getFocus(key),
191
202
  sessionId: key,
192
- autoCompressThreshold: cfg.autoCompressThreshold
203
+ autoCompressThreshold: cfg.autoCompressThreshold,
204
+ budgetAlertPercent: cfg.budgetAlertPercent ?? 90
193
205
  };
194
206
  }
195
207
  });
@@ -202,6 +214,7 @@ export function apply(ctx, config) {
202
214
  handler: (req, res) => {
203
215
  const cfg = getConfig();
204
216
  if (typeof cfg.budgetLimit === 'number') tracker.setBudgetLimit(cfg.budgetLimit);
217
+ if (typeof cfg.budgetAlertPercent === 'number') tracker.setBudgetAlertPercent(cfg.budgetAlertPercent);
205
218
  let sId = '__default__';
206
219
  try {
207
220
  const u = new URL(req.url, 'http://127.0.0.1');
@@ -211,7 +224,7 @@ export function apply(ctx, config) {
211
224
  res.end(JSON.stringify({
212
225
  ok: true,
213
226
  plugin: 'dsh-context-lens',
214
- stats: tracker.getStats(cfg.budgetLimit),
227
+ stats: tracker.getStats(cfg.budgetLimit, cfg.budgetAlertPercent),
215
228
  history: tracker.getHistory(),
216
229
  focus: getFocus(sId),
217
230
  sessionId: sId
@@ -219,6 +232,23 @@ export function apply(ctx, config) {
219
232
  }
220
233
  }), 'dsh-context-lens status route');
221
234
 
235
+ // Quick clear-focus API route
236
+ ctx.effect(() => ctx.webServer.register({
237
+ kind: 'exact',
238
+ path: '/dsh-context-lens/clear-focus',
239
+ handler: async (req, res) => {
240
+ let sId = lastActiveSession || '__default__';
241
+ try {
242
+ const u = new URL(req.url, 'http://127.0.0.1');
243
+ const qId = u.searchParams.get('sessionId') || u.searchParams.get('session_id');
244
+ if (qId) sId = qId;
245
+ } catch {}
246
+ clearFocus(sId);
247
+ res.setHeader('content-type', 'application/json');
248
+ res.end(JSON.stringify({ ok: true, sessionId: sId, focus: getFocus(sId) }));
249
+ }
250
+ }), 'dsh-context-lens clear-focus route');
251
+
222
252
  // #45: server-backed preview (same compressor as tools)
223
253
  ctx.effect(() => ctx.webServer.register({
224
254
  kind: 'exact',
@@ -242,6 +272,4 @@ export function apply(ctx, config) {
242
272
  }
243
273
  }), 'dsh-context-lens compress-preview route');
244
274
  }
245
- }
246
-
247
- export { compressLog, skeletonize, shouldAutoCompress };
275
+ }
@@ -7,6 +7,7 @@ let calls = 0;
7
7
  const history = []; // last 10
8
8
  const MAX_HISTORY = 10;
9
9
  let defaultBudgetLimit = 100000; // tokens
10
+ let defaultBudgetAlertPercent = 90; // threshold percent for low budget warning
10
11
 
11
12
  export { estimateTokens };
12
13
 
@@ -16,6 +17,12 @@ export function setBudgetLimit(limit) {
16
17
  }
17
18
  }
18
19
 
20
+ export function setBudgetAlertPercent(percent) {
21
+ if (typeof percent === 'number' && percent >= 50 && percent <= 99) {
22
+ defaultBudgetAlertPercent = percent;
23
+ }
24
+ }
25
+
19
26
  export function record(originalText, compressedText) {
20
27
  const o = estimateTokens(originalText);
21
28
  const c = estimateTokens(compressedText);
@@ -41,16 +48,19 @@ export function record(originalText, compressedText) {
41
48
  return { originalTokens: o, compressedTokens: c, savedTokens: saved };
42
49
  }
43
50
 
44
- export function getStats(budgetLimitOverride) {
51
+ export function getStats(budgetLimitOverride, budgetAlertPercentOverride) {
45
52
  const limit = (typeof budgetLimitOverride === 'number' && budgetLimitOverride > 0)
46
53
  ? budgetLimitOverride
47
54
  : defaultBudgetLimit;
55
+ const alertPercent = (typeof budgetAlertPercentOverride === 'number' && budgetAlertPercentOverride >= 50 && budgetAlertPercentOverride <= 99)
56
+ ? budgetAlertPercentOverride
57
+ : defaultBudgetAlertPercent;
48
58
  const saved = Math.max(0, totalOriginal - totalCompressed);
49
59
  const pct = totalOriginal ? Math.round((1 - totalCompressed / totalOriginal) * 100) : 0;
50
60
  const budgetUsed = totalCompressed;
51
61
  const budgetRemaining = Math.max(0, limit - budgetUsed);
52
62
  const budgetPercent = Math.min(100, Math.round((budgetUsed / limit) * 100));
53
- const lowBudget = budgetPercent > 90;
63
+ const lowBudget = budgetPercent >= alertPercent;
54
64
  return {
55
65
  totalOriginal,
56
66
  totalCompressed,
@@ -62,6 +72,7 @@ export function getStats(budgetLimitOverride) {
62
72
  budgetPercent,
63
73
  lowBudget,
64
74
  budgetLimit: limit,
75
+ budgetAlertPercent: alertPercent,
65
76
  countingStopped: budgetUsed >= limit
66
77
  };
67
78
  }
@@ -79,7 +90,4 @@ export function reset() {
79
90
  totalCompressed = 0;
80
91
  calls = 0;
81
92
  history.length = 0;
82
- defaultBudgetLimit = 100000;
83
- }
84
-
85
- export default { estimateTokens, setBudgetLimit, record, getStats, getHistory, clearHistory, reset };
93
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-context-lens",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "DSH plugin for AST context compression, test log filtering, and token budget guard",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -14,6 +14,8 @@
14
14
  "lib/",
15
15
  "cordis.patch.yml",
16
16
  "README.md",
17
+ "README.zh.md",
18
+ "README.ru.md",
17
19
  "LICENSE"
18
20
  ],
19
21
  "scripts": {