claude-token-saver 3.27.0 → 3.27.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/installer.js +20 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-token-saver",
3
- "version": "3.27.0",
3
+ "version": "3.27.1",
4
4
  "description": "Route the easy work your expensive Claude model keeps repeating down to haiku/sonnet — post-hoc session analysis, no realtime router, no extra LLM calls.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/installer.js CHANGED
@@ -378,23 +378,28 @@ export function installDoc2mdHook() {
378
378
  if (settings.hooks.PreToolUse !== undefined && !Array.isArray(settings.hooks.PreToolUse)) {
379
379
  return { path: file, action: 'skipped', reason: 'hooks.PreToolUse is not an array — fix settings.json manually' };
380
380
  }
381
+ // Each event is checked on its own. Returning early on "the Read hook is
382
+ // already there" would leave anyone upgrading from 3.26.x with the half that
383
+ // cannot see pptx and without the half that can — which is exactly what
384
+ // happened on the first machine to try it.
381
385
  const list = Array.isArray(settings.hooks.PreToolUse) ? settings.hooks.PreToolUse : [];
382
- const already = list.some((m) =>
383
- Array.isArray(m?.hooks) && m.hooks.some((h) => typeof h?.command === 'string' && h.command.includes('doc2md --hook')),
386
+ const hasReadHook = list.some((m) =>
387
+ Array.isArray(m?.hooks) && m.hooks.some((h) => typeof h?.command === 'string' && /doc2md --hook(?!-)/.test(h.command)),
384
388
  );
385
- if (already) return { path: file, action: 'exists' };
386
-
387
- list.push({
388
- matcher: 'Read',
389
- hooks: [{ type: 'command', command: DOC2MD_HOOK_COMMAND }],
390
- });
391
- settings.hooks.PreToolUse = list;
389
+ if (!hasReadHook) {
390
+ list.push({
391
+ matcher: 'Read',
392
+ hooks: [{ type: 'command', command: DOC2MD_HOOK_COMMAND }],
393
+ });
394
+ settings.hooks.PreToolUse = list;
395
+ }
392
396
 
393
397
  // The Read hook alone covers only PDFs. Claude Code refuses pptx/xlsx/docx
394
398
  // as binary before any PreToolUse hook runs, so for exactly the formats this
395
399
  // feature exists for, the tool call is dead before doc2md is consulted.
396
400
  // UserPromptSubmit runs earlier and sees the raw prompt text, which is where
397
401
  // a path the user typed can still be turned into Markdown.
402
+ let addedPrompt = false;
398
403
  if (settings.hooks.UserPromptSubmit === undefined || Array.isArray(settings.hooks.UserPromptSubmit)) {
399
404
  const prompts = Array.isArray(settings.hooks.UserPromptSubmit) ? settings.hooks.UserPromptSubmit : [];
400
405
  const hasPromptHook = prompts.some((m) =>
@@ -403,11 +408,15 @@ export function installDoc2mdHook() {
403
408
  if (!hasPromptHook) {
404
409
  prompts.push({ hooks: [{ type: 'command', command: DOC2MD_PROMPT_HOOK_COMMAND }] });
405
410
  settings.hooks.UserPromptSubmit = prompts;
411
+ addedPrompt = true;
406
412
  }
407
413
  }
408
414
 
409
- writeFileSync(file, JSON.stringify(settings, null, 2) + '\n');
410
- return { path: file, action: 'created' };
415
+ if (!hasReadHook || addedPrompt) {
416
+ writeFileSync(file, JSON.stringify(settings, null, 2) + '\n');
417
+ return { path: file, action: hasReadHook ? 'updated' : 'created' };
418
+ }
419
+ return { path: file, action: 'exists' };
411
420
  }
412
421
 
413
422
  export function removeDoc2mdHook() {