@askalf/deepdive 0.15.0 → 0.17.0

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 (43) hide show
  1. package/README.md +11 -1
  2. package/dist/agent.d.ts +3 -1
  3. package/dist/agent.d.ts.map +1 -1
  4. package/dist/agent.js +23 -0
  5. package/dist/agent.js.map +1 -1
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +133 -11
  8. package/dist/cli.js.map +1 -1
  9. package/dist/config-file.d.ts.map +1 -1
  10. package/dist/config-file.js +3 -0
  11. package/dist/config-file.js.map +1 -1
  12. package/dist/config.d.ts +6 -0
  13. package/dist/config.d.ts.map +1 -1
  14. package/dist/config.js +13 -1
  15. package/dist/config.js.map +1 -1
  16. package/dist/index.d.ts +3 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +3 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/search/openalex.d.ts +24 -0
  21. package/dist/search/openalex.d.ts.map +1 -0
  22. package/dist/search/openalex.js +71 -0
  23. package/dist/search/openalex.js.map +1 -0
  24. package/dist/search/semanticscholar.d.ts +21 -0
  25. package/dist/search/semanticscholar.d.ts.map +1 -0
  26. package/dist/search/semanticscholar.js +58 -0
  27. package/dist/search/semanticscholar.js.map +1 -0
  28. package/dist/search.d.ts.map +1 -1
  29. package/dist/search.js +9 -0
  30. package/dist/search.js.map +1 -1
  31. package/dist/sessions.d.ts +9 -0
  32. package/dist/sessions.d.ts.map +1 -1
  33. package/dist/sessions.js +72 -1
  34. package/dist/sessions.js.map +1 -1
  35. package/dist/similarity.d.ts +5 -0
  36. package/dist/similarity.d.ts.map +1 -0
  37. package/dist/similarity.js +53 -0
  38. package/dist/similarity.js.map +1 -0
  39. package/dist/stats.d.ts +20 -0
  40. package/dist/stats.d.ts.map +1 -0
  41. package/dist/stats.js +73 -0
  42. package/dist/stats.js.map +1 -0
  43. package/package.json +1 -1
@@ -0,0 +1,58 @@
1
+ // Semantic Scholar search adapter. No API key (keyless requests are
2
+ // rate-limited but fine interactively; set DEEPDIVE_S2_KEY to use an API key).
3
+ // Uses the Graph API paper-search endpoint. Strong for CS / general academic
4
+ // questions — the kept source is the paper's landing page.
5
+ import { searchTimeoutSignal } from "../search.js";
6
+ export class SemanticScholarSearch {
7
+ key;
8
+ name = "semanticscholar";
9
+ constructor(key) {
10
+ this.key = key;
11
+ }
12
+ async search(query, limit, signal) {
13
+ const url = new URL("https://api.semanticscholar.org/graph/v1/paper/search");
14
+ url.searchParams.set("query", query);
15
+ url.searchParams.set("limit", String(Math.min(Math.max(limit, 1), 100)));
16
+ url.searchParams.set("fields", "title,url,abstract,year,citationCount,authors");
17
+ const headers = {
18
+ accept: "application/json",
19
+ "user-agent": "deepdive (+https://github.com/askalf/deepdive)",
20
+ };
21
+ if (this.key)
22
+ headers["x-api-key"] = this.key;
23
+ const res = await fetch(url, { headers, signal: searchTimeoutSignal(signal) });
24
+ if (!res.ok)
25
+ throw new Error(`semanticscholar ${res.status} ${res.statusText}`);
26
+ const json = (await res.json());
27
+ return mapS2Papers(json.data ?? [], limit);
28
+ }
29
+ }
30
+ // Exported for unit tests. Pure mapper. Falls back to the S2 paper page when a
31
+ // paper has no canonical `url`. Snippet leads with citation count + year.
32
+ export function mapS2Papers(papers, limit) {
33
+ return papers
34
+ .filter((p) => (p.title ?? "").length > 0 && (p.url || p.paperId))
35
+ .slice(0, limit)
36
+ .map((p, i) => ({
37
+ url: p.url || `https://www.semanticscholar.org/paper/${p.paperId}`,
38
+ title: p.title,
39
+ snippet: s2Snippet(p),
40
+ rank: i + 1,
41
+ }));
42
+ }
43
+ function s2Snippet(p) {
44
+ const parts = [];
45
+ if (typeof p.citationCount === "number") {
46
+ parts.push(`${p.citationCount} citation${p.citationCount === 1 ? "" : "s"}`);
47
+ }
48
+ if (typeof p.year === "number")
49
+ parts.push(String(p.year));
50
+ const authors = (p.authors ?? []).map((a) => a.name).filter(Boolean);
51
+ if (authors.length > 0) {
52
+ parts.push(authors.length > 3 ? `${authors.slice(0, 3).join(", ")}, et al.` : authors.join(", "));
53
+ }
54
+ if (p.abstract)
55
+ parts.push(p.abstract.slice(0, 160).trim());
56
+ return parts.join(" · ");
57
+ }
58
+ //# sourceMappingURL=semanticscholar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semanticscholar.js","sourceRoot":"","sources":["../../src/search/semanticscholar.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CACrF;AAOD,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,WAAW,CAIrE;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACtC,OAAO,CAAC,aAAa,CAAC,CAmFxB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAUnE"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CACrF;AAOD,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,WAAW,CAIrE;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACtC,OAAO,CAAC,aAAa,CAAC,CA4FxB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAUnE"}
package/dist/search.js CHANGED
@@ -79,6 +79,15 @@ export async function resolveSearchAdapter(name, env) {
79
79
  const { PubMedSearch } = await import("./search/pubmed.js");
80
80
  return new PubMedSearch();
81
81
  }
82
+ case "semanticscholar":
83
+ case "s2": {
84
+ const { SemanticScholarSearch } = await import("./search/semanticscholar.js");
85
+ return new SemanticScholarSearch(env.DEEPDIVE_S2_KEY);
86
+ }
87
+ case "openalex": {
88
+ const { OpenAlexSearch } = await import("./search/openalex.js");
89
+ return new OpenAlexSearch(env.DEEPDIVE_OPENALEX_MAILTO);
90
+ }
82
91
  case "auto": {
83
92
  // DDG primary, Brave fallback. Brave is optional — if no key is set,
84
93
  // `auto` degrades to DDG-only (the pre-auto default behavior) rather
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ export interface SessionRecord {
19
19
  model: string;
20
20
  };
21
21
  parentId?: string;
22
+ tags?: string[];
22
23
  }
23
24
  export interface SessionMeta {
24
25
  id: string;
@@ -27,6 +28,7 @@ export interface SessionMeta {
27
28
  sourceCount: number;
28
29
  rounds: number;
29
30
  model: string;
31
+ tags?: string[];
30
32
  }
31
33
  export interface SessionStorageOptions {
32
34
  dir: string;
@@ -39,8 +41,15 @@ export declare function listSessions(opts: SessionStorageOptions): Promise<{
39
41
  sessions: SessionMeta[];
40
42
  bad: string[];
41
43
  }>;
44
+ export declare function loadAllSessions(opts: SessionStorageOptions): Promise<{
45
+ records: SessionRecord[];
46
+ bad: string[];
47
+ }>;
42
48
  export declare function resolveSessionId(prefix: string, opts: SessionStorageOptions): Promise<string>;
43
49
  export declare function renderSessionsList(metas: SessionMeta[]): string;
50
+ export declare function normalizeTags(raw: string[]): string[];
51
+ export declare function tagSession(id: string, tags: string[], opts: SessionStorageOptions): Promise<string[]>;
52
+ export declare function untagSession(id: string, tags: string[], opts: SessionStorageOptions): Promise<string[]>;
44
53
  export declare function humanDuration(ms: number): string;
45
54
  export declare function deleteSession(id: string, opts: SessionStorageOptions): Promise<void>;
46
55
  export interface PruneCriteria {
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"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"}
package/dist/sessions.js CHANGED
@@ -90,6 +90,7 @@ export async function listSessions(opts) {
90
90
  sourceCount: r.sources.length,
91
91
  rounds: r.rounds.length,
92
92
  model: r.llm?.model ?? "(unknown)",
93
+ ...(Array.isArray(r.tags) && r.tags.length > 0 ? { tags: r.tags } : {}),
93
94
  });
94
95
  }
95
96
  catch {
@@ -99,6 +100,38 @@ export async function listSessions(opts) {
99
100
  sessions.sort((a, b) => b.createdAt - a.createdAt);
100
101
  return { sessions, bad };
101
102
  }
103
+ // Loads every parseable session record (full content, not just metadata) for
104
+ // aggregate analysis (`deepdive stats`). Unparseable files are collected in
105
+ // `bad` and skipped. Newest first.
106
+ export async function loadAllSessions(opts) {
107
+ let entries = [];
108
+ try {
109
+ entries = await fs.readdir(opts.dir);
110
+ }
111
+ catch {
112
+ return { records: [], bad: [] };
113
+ }
114
+ const records = [];
115
+ const bad = [];
116
+ for (const f of entries) {
117
+ if (!f.endsWith(".json") || f.endsWith(".tmp"))
118
+ continue;
119
+ try {
120
+ const raw = await fs.readFile(join(opts.dir, f), "utf-8");
121
+ const r = JSON.parse(raw);
122
+ if (r.schema !== 1) {
123
+ bad.push(f);
124
+ continue;
125
+ }
126
+ records.push(r);
127
+ }
128
+ catch {
129
+ bad.push(f);
130
+ }
131
+ }
132
+ records.sort((a, b) => b.createdAt - a.createdAt);
133
+ return { records, bad };
134
+ }
102
135
  // Resolves a partial id (timestamp-prefix shorthand) against the
103
136
  // directory. Exported for tests and reuse from the resume path.
104
137
  //
@@ -142,10 +175,48 @@ export function renderSessionsList(metas) {
142
175
  for (const m of metas) {
143
176
  const ago = humanDuration(Date.now() - m.createdAt);
144
177
  const q = m.question.length > 60 ? m.question.slice(0, 59) + "…" : m.question;
145
- lines.push(` ${m.id} ${ago.padStart(8)} ${m.sourceCount} src · ${m.rounds} round ${q}`);
178
+ const tags = m.tags && m.tags.length > 0 ? " " + m.tags.map((t) => `#${t}`).join(" ") : "";
179
+ lines.push(` ${m.id} ${ago.padStart(8)} ${m.sourceCount} src · ${m.rounds} round ${q}${tags}`);
146
180
  }
147
181
  return lines.join("\n");
148
182
  }
183
+ // ── Tags ─────────────────────────────────────────────────────────────────────
184
+ // Exported for unit tests. Normalize a raw tag list: trim, lowercase, drop
185
+ // empties and the leading '#' people will inevitably type, dedupe, preserve
186
+ // first-seen order. Tags are labels — lowercase keeps filtering predictable.
187
+ export function normalizeTags(raw) {
188
+ const out = [];
189
+ const seen = new Set();
190
+ for (const r of raw) {
191
+ const t = r.trim().replace(/^#/, "").toLowerCase();
192
+ if (t.length === 0 || seen.has(t))
193
+ continue;
194
+ seen.add(t);
195
+ out.push(t);
196
+ }
197
+ return out;
198
+ }
199
+ // Adds tags to a saved session (load → merge → atomic save). Returns the
200
+ // updated tag list.
201
+ export async function tagSession(id, tags, opts) {
202
+ const record = await loadSession(id, opts);
203
+ const merged = normalizeTags([...(record.tags ?? []), ...tags]);
204
+ record.tags = merged;
205
+ await saveSession(record, opts);
206
+ return merged;
207
+ }
208
+ // Removes tags from a saved session. Returns the remaining tag list.
209
+ export async function untagSession(id, tags, opts) {
210
+ const record = await loadSession(id, opts);
211
+ const remove = new Set(normalizeTags(tags));
212
+ const remaining = (record.tags ?? []).filter((t) => !remove.has(t));
213
+ if (remaining.length > 0)
214
+ record.tags = remaining;
215
+ else
216
+ delete record.tags;
217
+ await saveSession(record, opts);
218
+ return remaining;
219
+ }
149
220
  // Exported for tests.
150
221
  export function humanDuration(ms) {
151
222
  if (ms < 0)
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare const DEFAULT_NEAR_DUPE_THRESHOLD = 0.9;
2
+ export declare function contentShingles(text: string, n?: number): Set<string>;
3
+ export declare function jaccard(a: Set<string>, b: Set<string>): number;
4
+ export declare function findNearDuplicate(candidate: Set<string>, kept: Set<string>[], threshold?: number): number;
5
+ //# sourceMappingURL=similarity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"similarity.d.ts","sourceRoot":"","sources":["../src/similarity.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAM/C,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,GAAE,MAAqB,GAAG,GAAG,CAAC,MAAM,CAAC,CAYnF;AAKD,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAQ9D;AAID,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EACtB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,EACnB,SAAS,GAAE,MAAoC,GAC9C,MAAM,CAKR"}
@@ -0,0 +1,53 @@
1
+ // Near-duplicate detection over extracted source content. The same article
2
+ // syndicated across several sites (wire stories, scraped mirrors, canonical +
3
+ // AMP copies on different hosts) survives URL-level dedupe but wastes a
4
+ // source slot and pads the synth context with repeated text. A cheap shingle
5
+ // Jaccard check catches it: two documents sharing ≳90% of their word 5-grams
6
+ // are the same article, not two perspectives.
7
+ //
8
+ // Pure over strings and sets; hand-rolled, no deps. Content is already capped
9
+ // at maxWordsPerSource (2000 default) so a shingle set is ≤ ~2000 entries and
10
+ // the pairwise compare against ≤ maxSources kept docs is trivial.
11
+ export const DEFAULT_NEAR_DUPE_THRESHOLD = 0.9;
12
+ const SHINGLE_SIZE = 5;
13
+ // Word n-gram shingle set for a document. Lowercased, whitespace-tokenized.
14
+ // A document shorter than the shingle size contributes its whole token
15
+ // sequence as a single shingle so two identical short docs still match.
16
+ export function contentShingles(text, n = SHINGLE_SIZE) {
17
+ const tokens = text.toLowerCase().split(/\s+/).filter(Boolean);
18
+ const out = new Set();
19
+ if (tokens.length === 0)
20
+ return out;
21
+ if (tokens.length < n) {
22
+ out.add(tokens.join(" "));
23
+ return out;
24
+ }
25
+ for (let i = 0; i + n <= tokens.length; i++) {
26
+ out.add(tokens.slice(i, i + n).join(" "));
27
+ }
28
+ return out;
29
+ }
30
+ // Jaccard similarity |A∩B| / |A∪B| over two shingle sets. 0 when either set
31
+ // is empty (an empty doc is "similar" to nothing — it gets dropped by the
32
+ // min-words gate upstream anyway, never by dedupe).
33
+ export function jaccard(a, b) {
34
+ if (a.size === 0 || b.size === 0)
35
+ return 0;
36
+ const [small, large] = a.size <= b.size ? [a, b] : [b, a];
37
+ let intersection = 0;
38
+ for (const s of small) {
39
+ if (large.has(s))
40
+ intersection++;
41
+ }
42
+ return intersection / (a.size + b.size - intersection);
43
+ }
44
+ // Returns the index of the first kept document whose similarity to
45
+ // `candidate` meets the threshold, or -1 when the candidate is genuinely new.
46
+ export function findNearDuplicate(candidate, kept, threshold = DEFAULT_NEAR_DUPE_THRESHOLD) {
47
+ for (let i = 0; i < kept.length; i++) {
48
+ if (jaccard(candidate, kept[i]) >= threshold)
49
+ return i;
50
+ }
51
+ return -1;
52
+ }
53
+ //# sourceMappingURL=similarity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"similarity.js","sourceRoot":"","sources":["../src/similarity.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,8EAA8E;AAC9E,wEAAwE;AACxE,6EAA6E;AAC7E,6EAA6E;AAC7E,8CAA8C;AAC9C,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAC9E,kEAAkE;AAElE,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAC/C,MAAM,YAAY,GAAG,CAAC,CAAC;AAEvB,4EAA4E;AAC5E,uEAAuE;AACvE,wEAAwE;AACxE,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,IAAY,YAAY;IACpE,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC/D,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IACpC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1B,OAAO,GAAG,CAAC;IACb,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,4EAA4E;AAC5E,0EAA0E;AAC1E,oDAAoD;AACpD,MAAM,UAAU,OAAO,CAAC,CAAc,EAAE,CAAc;IACpD,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1D,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,YAAY,EAAE,CAAC;IACnC,CAAC;IACD,OAAO,YAAY,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,YAAY,CAAC,CAAC;AACzD,CAAC;AAED,mEAAmE;AACnE,8EAA8E;AAC9E,MAAM,UAAU,iBAAiB,CAC/B,SAAsB,EACtB,IAAmB,EACnB,YAAoB,2BAA2B;IAE/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS;YAAE,OAAO,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { SessionRecord } from "./sessions.js";
2
+ export interface ModelStat {
3
+ model: string;
4
+ count: number;
5
+ costUsd: number;
6
+ }
7
+ export interface SessionStats {
8
+ count: number;
9
+ totalCostUsd: number;
10
+ totalSources: number;
11
+ totalRounds: number;
12
+ deepRuns: number;
13
+ avgSourcesPerSession: number;
14
+ byModel: ModelStat[];
15
+ oldest?: number;
16
+ newest?: number;
17
+ }
18
+ export declare function aggregateSessionStats(records: SessionRecord[]): SessionStats;
19
+ export declare function renderStats(stats: SessionStats): string;
20
+ //# sourceMappingURL=stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../src/stats.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,YAAY,CA+C5E;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CA2BvD"}
package/dist/stats.js ADDED
@@ -0,0 +1,73 @@
1
+ // Aggregate insights across saved sessions — what have I researched, how much
2
+ // has it cost, which models did the work. Pure over a list of SessionRecords
3
+ // (the CLI reads them); rendering is separate so it's unit-testable.
4
+ export function aggregateSessionStats(records) {
5
+ const byModel = new Map();
6
+ let totalCostUsd = 0;
7
+ let totalSources = 0;
8
+ let totalRounds = 0;
9
+ let deepRuns = 0;
10
+ let oldest;
11
+ let newest;
12
+ for (const r of records) {
13
+ const cost = typeof r.cost?.amountUsd === "number" ? r.cost.amountUsd : 0;
14
+ totalCostUsd += cost;
15
+ totalSources += r.sources?.length ?? 0;
16
+ const rounds = r.rounds?.length ?? 0;
17
+ totalRounds += rounds;
18
+ if (rounds > 1)
19
+ deepRuns++;
20
+ const model = r.llm?.model ?? "(unknown)";
21
+ let bucket = byModel.get(model);
22
+ if (!bucket) {
23
+ bucket = { model, count: 0, costUsd: 0 };
24
+ byModel.set(model, bucket);
25
+ }
26
+ bucket.count++;
27
+ bucket.costUsd += cost;
28
+ if (typeof r.createdAt === "number") {
29
+ if (oldest === undefined || r.createdAt < oldest)
30
+ oldest = r.createdAt;
31
+ if (newest === undefined || r.createdAt > newest)
32
+ newest = r.createdAt;
33
+ }
34
+ }
35
+ const models = Array.from(byModel.values()).sort((a, b) => b.count - a.count || b.costUsd - a.costUsd);
36
+ return {
37
+ count: records.length,
38
+ totalCostUsd,
39
+ totalSources,
40
+ totalRounds,
41
+ deepRuns,
42
+ avgSourcesPerSession: records.length > 0 ? totalSources / records.length : 0,
43
+ byModel: models,
44
+ oldest,
45
+ newest,
46
+ };
47
+ }
48
+ // Exported for unit tests. Human-readable summary block.
49
+ export function renderStats(stats) {
50
+ if (stats.count === 0) {
51
+ return "(no sessions yet — run `deepdive \"<question>\"` to create one)";
52
+ }
53
+ const lines = [];
54
+ lines.push(`sessions ${stats.count}`);
55
+ lines.push(`cost ~$${stats.totalCostUsd.toFixed(stats.totalCostUsd < 0.01 ? 4 : 2)} total (calculated at list price)`);
56
+ lines.push(`sources ${stats.totalSources} fetched · ${stats.avgSourcesPerSession.toFixed(1)} avg/session`);
57
+ lines.push(`rounds ${stats.totalRounds} total · ${stats.deepRuns} deep run${stats.deepRuns === 1 ? "" : "s"}`);
58
+ if (stats.oldest !== undefined && stats.newest !== undefined) {
59
+ lines.push(`span ${isoDay(stats.oldest)} → ${isoDay(stats.newest)}`);
60
+ }
61
+ if (stats.byModel.length > 0) {
62
+ lines.push("models");
63
+ for (const m of stats.byModel) {
64
+ lines.push(` ${m.model.padEnd(22)} ${String(m.count).padStart(4)} run${m.count === 1 ? " " : "s"} · ~$${m.costUsd.toFixed(m.costUsd < 0.01 ? 4 : 2)}`);
65
+ }
66
+ }
67
+ return lines.join("\n");
68
+ }
69
+ function isoDay(ms) {
70
+ const d = new Date(ms);
71
+ return Number.isNaN(d.getTime()) ? "?" : d.toISOString().slice(0, 10);
72
+ }
73
+ //# sourceMappingURL=stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../src/stats.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,6EAA6E;AAC7E,qEAAqE;AAsBrE,MAAM,UAAU,qBAAqB,CAAC,OAAwB;IAC5D,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC7C,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,MAA0B,CAAC;IAC/B,IAAI,MAA0B,CAAC;IAE/B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1E,YAAY,IAAI,IAAI,CAAC;QACrB,YAAY,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC;QACrC,WAAW,IAAI,MAAM,CAAC;QACtB,IAAI,MAAM,GAAG,CAAC;YAAE,QAAQ,EAAE,CAAC;QAE3B,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,IAAI,WAAW,CAAC;QAC1C,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC7B,CAAC;QACD,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC;QAEvB,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YACpC,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,GAAG,MAAM;gBAAE,MAAM,GAAG,CAAC,CAAC,SAAS,CAAC;YACvE,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,GAAG,MAAM;gBAAE,MAAM,GAAG,CAAC,CAAC,SAAS,CAAC;QACzE,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAC9C,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CACrD,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,MAAM;QACrB,YAAY;QACZ,YAAY;QACZ,WAAW;QACX,QAAQ;QACR,oBAAoB,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC5E,OAAO,EAAE,MAAM;QACf,MAAM;QACN,MAAM;KACP,CAAC;AACJ,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,WAAW,CAAC,KAAmB;IAC7C,IAAI,KAAK,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,iEAAiE,CAAC;IAC3E,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACxC,KAAK,CAAC,IAAI,CACR,gBAAgB,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,mCAAmC,CACjH,CAAC;IACF,KAAK,CAAC,IAAI,CACR,cAAc,KAAK,CAAC,YAAY,cAAc,KAAK,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAClG,CAAC;IACF,KAAK,CAAC,IAAI,CACR,cAAc,KAAK,CAAC,WAAW,YAAY,KAAK,CAAC,QAAQ,YAAY,KAAK,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CACvG,CAAC;IACF,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC7D,KAAK,CAAC,IAAI,CAAC,cAAc,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrB,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAC5I,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,MAAM,CAAC,EAAU;IACxB,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askalf/deepdive",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "description": "A local research agent. One command, cited answer. Routes every LLM call through your own proxy (dario, Anthropic-compat, OpenAI-compat). Headless browser + pluggable search + multi-provider LLM — zero hosted dependencies.",
5
5
  "type": "module",
6
6
  "bin": {