viho-llm 1.0.8 → 1.0.9

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/index.js CHANGED
@@ -538,29 +538,38 @@ const callLLM = async (options) => {
538
538
  * @returns
539
539
  */
540
540
  const extractJSON = (text) => {
541
- const cleaned = text.replace(/\{\{/g, '{').replace(/\}\}/g, '}');
541
+ if (typeof text === 'object' && text !== null) return text;
542
+ const str = String(text).trim();
543
+
544
+ // 1. 尝试直接解析
542
545
  try {
543
- return JSON.parse(cleaned);
544
- } catch (e) {
545
- // try next
546
+ return JSON.parse(str);
547
+ } catch (_) {
548
+ /* ignore */
546
549
  }
547
- const codeBlock = cleaned.match(/```(?:json)?\s*([\s\S]*?)```/);
548
- if (codeBlock) {
550
+
551
+ // 2. 尝试从 markdown 代码块提取
552
+ const codeBlockMatch = str.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
553
+ if (codeBlockMatch) {
549
554
  try {
550
- return JSON.parse(codeBlock[1].trim());
551
- } catch (e) {
552
- // try next
555
+ return JSON.parse(codeBlockMatch[1].trim());
556
+ } catch (_) {
557
+ /* ignore */
553
558
  }
554
559
  }
555
- const match = cleaned.match(/(\{[\s\S]*\}|\[[\s\S]*\])/);
556
- if (match) {
560
+
561
+ // 3. 尝试提取第一个 {...} 块
562
+ const firstBrace = str.indexOf('{');
563
+ const lastBrace = str.lastIndexOf('}');
564
+ if (firstBrace !== -1 && lastBrace > firstBrace) {
557
565
  try {
558
- return JSON.parse(match[1]);
559
- } catch (e) {
560
- // try next
566
+ return JSON.parse(str.slice(firstBrace, lastBrace + 1));
567
+ } catch (_) {
568
+ /* ignore */
561
569
  }
562
570
  }
563
- throw new Error(`Cannot extract JSON from: ${text.slice(0, 200)}`);
571
+
572
+ throw new Error(`Cannot parse JSON from LLM response: ${str.slice(0, 200)}`);
564
573
  };
565
574
 
566
575
  // util
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viho-llm",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Utility library for working with multiple LLM providers (Google Gemini and OpenAI), providing common tools and helpers for AI interactions",
5
5
  "keywords": [
6
6
  "llm",
@@ -68,5 +68,5 @@
68
68
  }
69
69
  }
70
70
  },
71
- "gitHead": "46a9940278370dfe84caa47adcb4ebcd1f5c1393"
71
+ "gitHead": "24672073850eae9daef6781b1eec972b899381ad"
72
72
  }
@@ -22,27 +22,36 @@ export const callLLM = async (options) => {
22
22
  * @returns
23
23
  */
24
24
  export const extractJSON = (text) => {
25
- const cleaned = text.replace(/\{\{/g, '{').replace(/\}\}/g, '}');
25
+ if (typeof text === 'object' && text !== null) return text;
26
+ const str = String(text).trim();
27
+
28
+ // 1. 尝试直接解析
26
29
  try {
27
- return JSON.parse(cleaned);
28
- } catch (e) {
29
- // try next
30
+ return JSON.parse(str);
31
+ } catch (_) {
32
+ /* ignore */
30
33
  }
31
- const codeBlock = cleaned.match(/```(?:json)?\s*([\s\S]*?)```/);
32
- if (codeBlock) {
34
+
35
+ // 2. 尝试从 markdown 代码块提取
36
+ const codeBlockMatch = str.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
37
+ if (codeBlockMatch) {
33
38
  try {
34
- return JSON.parse(codeBlock[1].trim());
35
- } catch (e) {
36
- // try next
39
+ return JSON.parse(codeBlockMatch[1].trim());
40
+ } catch (_) {
41
+ /* ignore */
37
42
  }
38
43
  }
39
- const match = cleaned.match(/(\{[\s\S]*\}|\[[\s\S]*\])/);
40
- if (match) {
44
+
45
+ // 3. 尝试提取第一个 {...} 块
46
+ const firstBrace = str.indexOf('{');
47
+ const lastBrace = str.lastIndexOf('}');
48
+ if (firstBrace !== -1 && lastBrace > firstBrace) {
41
49
  try {
42
- return JSON.parse(match[1]);
43
- } catch (e) {
44
- // try next
50
+ return JSON.parse(str.slice(firstBrace, lastBrace + 1));
51
+ } catch (_) {
52
+ /* ignore */
45
53
  }
46
54
  }
47
- throw new Error(`Cannot extract JSON from: ${text.slice(0, 200)}`);
55
+
56
+ throw new Error(`Cannot parse JSON from LLM response: ${str.slice(0, 200)}`);
48
57
  };