viho-llm 1.0.7 → 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/README.md CHANGED
@@ -111,13 +111,13 @@ await runAgents([
111
111
  {
112
112
  agentStartCallback: () => console.log('Agent 1 starting'),
113
113
  agentRequestOptions: { llm: openai, modelName: 'gpt-4o', messages: [...], isJson: false, thinking: null },
114
- agentEndCallback: (response) => { console.log(response); return false; },
114
+ agentEndCallback: (response, allResponses) => { console.log(response); return false; },
115
115
  agentBreakCallback: () => console.log('Breaking'), // optional
116
116
  },
117
117
  ]);
118
118
  ```
119
119
 
120
- - `agentEndCallback` returns truthy to break the sequence
120
+ - `agentEndCallback(response, allResponses)` — receives current response and all previous responses; returns truthy to break
121
121
  - `agentBreakCallback` (optional) is called before breaking
122
122
 
123
123
  ## License
package/index.js CHANGED
@@ -538,37 +538,50 @@ 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
576
+
567
577
  /**
568
578
  * runAgents
569
579
  * @param {*} agents
570
580
  */
571
581
  const runAgents = async (agents) => {
582
+ // const
583
+ const agentResponses = [];
584
+
572
585
  // for
573
586
  for (let i = 0; i < agents.length; i++) {
574
587
  const agent = agents[i];
@@ -582,9 +595,10 @@ const runAgents = async (agents) => {
582
595
  // go
583
596
  agentStartCallback();
584
597
  const agentResponse = await callLLM(agentRequestOptions);
598
+ agentResponses.push(agentResponse);
585
599
 
586
600
  // check
587
- const breakAgent = agentEndCallback(agentResponse);
601
+ const breakAgent = agentEndCallback(agentResponse, agentResponses);
588
602
  if (breakAgent) {
589
603
  if (agentBreakCallback) agentBreakCallback();
590
604
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viho-llm",
3
- "version": "1.0.7",
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": "e19813c5650c9966fac687b8e3940a34a8481deb"
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
  };
@@ -1,10 +1,14 @@
1
1
  // util
2
2
  import { callLLM } from './agent-util.js';
3
+
3
4
  /**
4
5
  * runAgents
5
6
  * @param {*} agents
6
7
  */
7
8
  export const runAgents = async (agents) => {
9
+ // const
10
+ const agentResponses = [];
11
+
8
12
  // for
9
13
  for (let i = 0; i < agents.length; i++) {
10
14
  const agent = agents[i];
@@ -18,9 +22,10 @@ export const runAgents = async (agents) => {
18
22
  // go
19
23
  agentStartCallback();
20
24
  const agentResponse = await callLLM(agentRequestOptions);
25
+ agentResponses.push(agentResponse);
21
26
 
22
27
  // check
23
- const breakAgent = agentEndCallback(agentResponse);
28
+ const breakAgent = agentEndCallback(agentResponse, agentResponses);
24
29
  if (breakAgent) {
25
30
  if (agentBreakCallback) agentBreakCallback();
26
31
  break;