studylens 0.1.1 → 0.1.3
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/README.md +25 -97
- package/bin/studylens.js +7 -7
- package/config/llm-config.template.json +9 -9
- package/config/prompts.json +7 -7
- package/core/extractor.js +70 -70
- package/core/llm-provider.js +2 -2
- package/core/wiki-storage.js +414 -414
- package/package.json +67 -62
- package/portal/dist/assets/{index-C94Qe946.js → index-C1LyiykQ.js} +22 -22
- package/portal/dist/index.html +12 -12
- package/portal/package.json +28 -28
- package/server/index.js +558 -555
- package/core/llm-provider.test.js +0 -92
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
const { extractJSON } = require('./llm-provider');
|
|
2
|
-
|
|
3
|
-
describe('extractJSON', () => {
|
|
4
|
-
// Regression: double-escaped regex bug (commit adc4ff5)
|
|
5
|
-
// Previously \s was written as \\s in source, causing regex to look for literal \s chars
|
|
6
|
-
it('strips markdown code fences with whitespace', () => {
|
|
7
|
-
const input = '```json\n[{"title": "Test"}]\n```';
|
|
8
|
-
const result = extractJSON(input, { isArray: true });
|
|
9
|
-
expect(result).toEqual([{ title: 'Test' }]);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('strips code fences with varying whitespace', () => {
|
|
13
|
-
const input = '```json \n{"answer": "hello"}\n``` ';
|
|
14
|
-
const result = extractJSON(input);
|
|
15
|
-
expect(result).toEqual({ answer: 'hello' });
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('returns null when no JSON found', () => {
|
|
19
|
-
expect(extractJSON('no json here', { isArray: true })).toBeNull();
|
|
20
|
-
expect(extractJSON('just some text')).toBeNull();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('parses clean JSON array', () => {
|
|
24
|
-
const result = extractJSON('[{"a": 1}, {"a": 2}]', { isArray: true });
|
|
25
|
-
expect(result).toEqual([{ a: 1 }, { a: 2 }]);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('parses clean JSON object', () => {
|
|
29
|
-
const result = extractJSON('{"answer": "hello", "cards": []}');
|
|
30
|
-
expect(result).toEqual({ answer: 'hello', cards: [] });
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('repairs trailing commas', () => {
|
|
34
|
-
const result = extractJSON('{"a": 1, "b": 2,}');
|
|
35
|
-
expect(result).toEqual({ a: 1, b: 2 });
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('repairs unescaped newlines in string values', () => {
|
|
39
|
-
const input = '{"answer": "line1\nline2", "cards": []}';
|
|
40
|
-
const result = extractJSON(input);
|
|
41
|
-
expect(result).toEqual({ answer: 'line1\nline2', cards: [] });
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// Regression: AI decomposition returning empty (expandEntry)
|
|
45
|
-
it('uses repairKeys fallback when JSON has curly/smart quotes', () => {
|
|
46
|
-
const input = '[{“title”: “Foo”, “content”: “Bar”, “category”: “Baz”}]';
|
|
47
|
-
const result = extractJSON(input, { isArray: true, repairKeys: ['title', 'content', 'category'] });
|
|
48
|
-
expect(result).toEqual([{ title: 'Foo', content: 'Bar', category: 'Baz' }]);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('uses repairKeys for question/category pairs', () => {
|
|
52
|
-
const input = '[{“question”: “What is X?”, “category”: “概念”}]';
|
|
53
|
-
const result = extractJSON(input, { isArray: true, repairKeys: ['question', 'category'] });
|
|
54
|
-
expect(result).toEqual([{ question: 'What is X?', category: '概念' }]);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('repairs unescaped double quotes inside string values', () => {
|
|
58
|
-
const input = '[{"title": "形成\\"树瘤\\"的原因", "content": "正常"}]';
|
|
59
|
-
const raw = input.replace(/\\"/g, '"').replace(',"', '", "');
|
|
60
|
-
const mangled = '[{"title": "形成"树瘤"的原因", "content": "正常"}]';
|
|
61
|
-
const result = extractJSON(mangled, { isArray: true });
|
|
62
|
-
expect(result).not.toBeNull();
|
|
63
|
-
expect(result[0].title).toContain('树瘤');
|
|
64
|
-
expect(result[0].content).toBe('正常');
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('repairs multiple unescaped quotes in one string', () => {
|
|
68
|
-
const input = '{"answer": "He said "hello" and she said "bye"", "ok": true}';
|
|
69
|
-
const result = extractJSON(input);
|
|
70
|
-
expect(result).not.toBeNull();
|
|
71
|
-
expect(result.answer).toContain('hello');
|
|
72
|
-
expect(result.ok).toBe(true);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('handles already-escaped quotes without double-escaping', () => {
|
|
76
|
-
const input = '{"answer": "He said \\"hello\\"", "ok": true}';
|
|
77
|
-
const result = extractJSON(input);
|
|
78
|
-
expect(result).toEqual({ answer: 'He said "hello"', ok: true });
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('extracts JSON embedded in surrounding text', () => {
|
|
82
|
-
const input = 'Here is the result:\n[{"id": 1}]\nDone.';
|
|
83
|
-
const result = extractJSON(input, { isArray: true });
|
|
84
|
-
expect(result).toEqual([{ id: 1 }]);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('prefers array match when isArray is true', () => {
|
|
88
|
-
const input = '{"wrapper": [{"a": 1}]}';
|
|
89
|
-
const result = extractJSON(input, { isArray: true });
|
|
90
|
-
expect(result).toEqual([{ a: 1 }]);
|
|
91
|
-
});
|
|
92
|
-
});
|