ctxjev-cli 0.1.5 → 0.1.6

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/dist/index.js CHANGED
@@ -7,6 +7,7 @@ import { parseArgs } from 'node:util';
7
7
  import pc from 'picocolors';
8
8
  import { DEFAULT_POLICY, createUsageAccumulator, pruneContext, summarizeSavings } from 'ctxjev-core';
9
9
  import { formatReport } from './report.js';
10
+ import { DEFAULT_CACHE_PATH, loadFileScoreCache } from './scoreCache.js';
10
11
  import { parseTranscript } from './transcript.js';
11
12
  // Read from this package's own package.json rather than a hardcoded constant, so --version
12
13
  // can't silently go stale after the next release the way a literal string would.
@@ -25,9 +26,13 @@ ${pc.bold('Options')}
25
26
  --drop-below <0-1> Relevance floor below which an entry is dropped. (default ${DEFAULT_POLICY.dropBelow})
26
27
  --summarize-below <0-1> Relevance floor below which an entry is summarized. (default ${DEFAULT_POLICY.summarizeBelow})
27
28
  --json Print machine-readable JSON instead of the report.
29
+ --no-cache Don't read or write the score cache (${DEFAULT_CACHE_PATH}).
28
30
  --help Show this help.
29
31
  --version Print the installed version.
30
32
 
33
+ Scores are cached by goal + entry content (not by transcript or entry id), so re-running the same
34
+ analysis, or reusing a tool result across transcripts, costs nothing the second time.
35
+
31
36
  ${pc.bold('Transcript formats (auto-detected)')}
32
37
  ctxjev's own: { "goal": "...", "entries": [{ "id", "role", "toolName"?, "content", "timestamp" }] }
33
38
  Claude Code: a real session .jsonl (transcript_path, or ~/.claude/projects/*/*.jsonl) — the
@@ -43,6 +48,14 @@ function failAll(messages) {
43
48
  console.error(`${pc.red('✖')} ${message}`);
44
49
  process.exit(1);
45
50
  }
51
+ /** Rejects anything that isn't a real number in [0, 1] instead of silently becoming NaN — a NaN
52
+ * threshold compares false against every score, so `decideAction` would quietly never "drop". */
53
+ function parseThreshold(raw) {
54
+ const n = Number(raw);
55
+ if (Number.isNaN(n) || n < 0 || n > 1)
56
+ return undefined;
57
+ return n;
58
+ }
46
59
  async function runAnalyze(argv) {
47
60
  const { positionals, values } = parseArgs({
48
61
  args: argv,
@@ -52,13 +65,15 @@ async function runAnalyze(argv) {
52
65
  'drop-below': { type: 'string' },
53
66
  'summarize-below': { type: 'string' },
54
67
  json: { type: 'boolean', default: false },
68
+ 'no-cache': { type: 'boolean', default: false },
55
69
  },
56
70
  });
57
71
  const [file] = positionals;
58
72
  if (!file)
59
73
  fail('missing <transcript.json> — see `ctxjev --help`');
60
- // Both checked up front, independently a user missing the key AND pointing at a bad path
61
- // should hear about both in one run, not fix one only to discover the other on the next try.
74
+ // Every problem checked up front, independently, and all of them reported together a user
75
+ // missing the key, pointing at a bad path, AND passing a bad threshold should hear about all
76
+ // three in one run, not fix one only to discover the next on the following try.
62
77
  const problems = [];
63
78
  if (!process.env.TYPESAFE_API_KEY) {
64
79
  problems.push('TYPESAFE_API_KEY is not set — get one at console.typesafe.ai/settings/keys');
@@ -70,19 +85,33 @@ async function runAnalyze(argv) {
70
85
  catch {
71
86
  problems.push(`couldn't read ${file}`);
72
87
  }
88
+ let dropBelow = DEFAULT_POLICY.dropBelow;
89
+ if (values['drop-below'] !== undefined) {
90
+ const parsed = parseThreshold(values['drop-below']);
91
+ if (parsed === undefined)
92
+ problems.push(`--drop-below must be a number between 0 and 1, got "${values['drop-below']}"`);
93
+ else
94
+ dropBelow = parsed;
95
+ }
96
+ let summarizeBelow = DEFAULT_POLICY.summarizeBelow;
97
+ if (values['summarize-below'] !== undefined) {
98
+ const parsed = parseThreshold(values['summarize-below']);
99
+ if (parsed === undefined)
100
+ problems.push(`--summarize-below must be a number between 0 and 1, got "${values['summarize-below']}"`);
101
+ else
102
+ summarizeBelow = parsed;
103
+ }
73
104
  if (problems.length > 0)
74
105
  failAll(problems);
75
106
  const transcript = parseTranscript(raw);
76
107
  const goal = values.goal ?? transcript.goal;
77
108
  if (!goal)
78
109
  fail('no goal — pass --goal or set "goal" in the transcript file');
79
- const policy = {
80
- dropBelow: values['drop-below'] ? Number(values['drop-below']) : DEFAULT_POLICY.dropBelow,
81
- summarizeBelow: values['summarize-below'] ? Number(values['summarize-below']) : DEFAULT_POLICY.summarizeBelow,
82
- recencyWeight: DEFAULT_POLICY.recencyWeight,
83
- };
110
+ const policy = { dropBelow, summarizeBelow, recencyWeight: DEFAULT_POLICY.recencyWeight };
111
+ const { cache, save } = values['no-cache'] ? { cache: undefined, save: async () => { } } : await loadFileScoreCache();
84
112
  const { usage, onUsage } = createUsageAccumulator();
85
- const decisions = await pruneContext(transcript.entries, goal, policy, { onUsage });
113
+ const decisions = await pruneContext(transcript.entries, goal, policy, { onUsage, cache });
114
+ await save();
86
115
  const savings = summarizeSavings(transcript.entries, decisions);
87
116
  if (values.json) {
88
117
  console.log(JSON.stringify({ decisions, savings, usage }, null, 2));
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { ScoreCache } from 'ctxjev-core';
2
+ export declare const DEFAULT_CACHE_PATH: string;
3
+ /**
4
+ * A `ScoreCache` backed by a single JSON file (`~/.cache/ctxjev/score-cache.json` by default),
5
+ * shared across every `ctxjev analyze` run. Jev is probabilistic — re-scoring the exact same
6
+ * content against the exact same goal costs real money for an answer that's already been seen,
7
+ * which is exactly what happened repeatedly while demoing this CLI against the same sample
8
+ * transcripts. Grows unbounded (no eviction) — fine for a personal cache of judgments, not meant
9
+ * as a general key-value store.
10
+ */
11
+ export declare function loadFileScoreCache(path?: string): Promise<{
12
+ cache: ScoreCache;
13
+ save: () => Promise<void>;
14
+ }>;
@@ -0,0 +1,40 @@
1
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { dirname, join } from 'node:path';
4
+ export const DEFAULT_CACHE_PATH = join(homedir(), '.cache', 'ctxjev', 'score-cache.json');
5
+ /**
6
+ * A `ScoreCache` backed by a single JSON file (`~/.cache/ctxjev/score-cache.json` by default),
7
+ * shared across every `ctxjev analyze` run. Jev is probabilistic — re-scoring the exact same
8
+ * content against the exact same goal costs real money for an answer that's already been seen,
9
+ * which is exactly what happened repeatedly while demoing this CLI against the same sample
10
+ * transcripts. Grows unbounded (no eviction) — fine for a personal cache of judgments, not meant
11
+ * as a general key-value store.
12
+ */
13
+ export async function loadFileScoreCache(path = DEFAULT_CACHE_PATH) {
14
+ const store = new Map(await readCacheFile(path));
15
+ let dirty = false;
16
+ const cache = {
17
+ get: (key) => store.get(key),
18
+ set: (key, value) => {
19
+ store.set(key, value);
20
+ dirty = true;
21
+ },
22
+ };
23
+ const save = async () => {
24
+ if (!dirty)
25
+ return;
26
+ await mkdir(dirname(path), { recursive: true });
27
+ await writeFile(path, JSON.stringify(Object.fromEntries(store)), 'utf8');
28
+ };
29
+ return { cache, save };
30
+ }
31
+ async function readCacheFile(path) {
32
+ try {
33
+ const raw = JSON.parse(await readFile(path, 'utf8'));
34
+ return Object.entries(raw);
35
+ }
36
+ catch {
37
+ return [];
38
+ }
39
+ }
40
+ //# sourceMappingURL=scoreCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoreCache.js","sourceRoot":"","sources":["../src/scoreCache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAGzC,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAA;AAEzF;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAe,kBAAkB;IACxE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAiB,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC,CAAA;IAChE,IAAI,KAAK,GAAG,KAAK,CAAA;IAEjB,MAAM,KAAK,GAAe;QACxB,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;QAC5B,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YAClB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YACrB,KAAK,GAAG,IAAI,CAAA;QACd,CAAC;KACF,CAAA;IAED,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;QACtB,IAAI,CAAC,KAAK;YAAE,OAAM;QAClB,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC/C,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;IAC1E,CAAC,CAAA;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;AACxB,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,IAAY;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;QACpD,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ctxjev-cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "CLI for ctxjev — analyze an agent transcript and report what Jev would keep, drop, or summarize.",
5
5
  "keywords": [
6
6
  "cli",
@@ -38,7 +38,7 @@
38
38
  ],
39
39
  "dependencies": {
40
40
  "picocolors": "^1.1.1",
41
- "ctxjev-core": "0.1.5"
41
+ "ctxjev-core": "0.1.6"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^22",