goblin-agents 2.5.0 → 3.0.1

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.
@@ -150,6 +150,11 @@ class AiAgentShape {
150
150
  role = string; //agent role
151
151
  prompt = string; //default system prompt
152
152
  contexts = record(string, string); //additionnal system prompt context
153
+ reasonings = record(
154
+ string,
155
+ enumeration(false, true, 'low', 'medium', 'high')
156
+ ); //contextuals reasonings levels
157
+ models = record(string, string); //contextuals models
153
158
  provider = enumeration('ollama', 'open-ai');
154
159
  model = string;
155
160
  otherModels = array(string);
@@ -161,7 +166,7 @@ class AiAgentShape {
161
166
  tools = option(array(object));
162
167
  toolServiceId = option(string);
163
168
  usability = enumeration('disabled', 'experimental', 'stable', 'deprecated');
164
- reasoning = option(boolean);
169
+ reasoning = option(enumeration(false, true, 'low', 'medium', 'high'));
165
170
  vectorQuality = option(enumeration('f32', 'int8'));
166
171
  meta = MetaShape;
167
172
  }
@@ -201,6 +206,8 @@ class AiAgentLogic extends Elf.Archetype {
201
206
  otherModels: defaultValues.otherModels,
202
207
  messages: {},
203
208
  contexts: {},
209
+ reasonings: {},
210
+ models: {},
204
211
  options: defaultValues.options,
205
212
  host: defaultValues.host,
206
213
  headers: defaultValues.headers,
@@ -239,6 +246,12 @@ class AiAgentLogic extends Elf.Archetype {
239
246
  if (state.contexts[contextId]) {
240
247
  delete state.contexts[contextId];
241
248
  }
249
+ if (state.models[contextId]) {
250
+ delete state.models[contextId];
251
+ }
252
+ if (state.reasonings[contextId]) {
253
+ delete state.reasonings[contextId];
254
+ }
242
255
  }
243
256
 
244
257
  set(contextId, messages) {
@@ -246,9 +259,11 @@ class AiAgentLogic extends Elf.Archetype {
246
259
  state.messages[contextId] = messages;
247
260
  }
248
261
 
249
- setContext(contextId, context) {
262
+ setContext(contextId, context, model, reasoning) {
250
263
  const {state} = this;
251
264
  state.contexts[contextId] = context;
265
+ state.models[contextId] = model || this.state.model;
266
+ state.reasonings[contextId] = reasoning || this.state.reasoning;
252
267
  }
253
268
 
254
269
  chat(contextId, role, content) {
@@ -579,8 +594,15 @@ class AiAgent extends Elf {
579
594
  this.logic.set(contextId, messages);
580
595
  }
581
596
 
582
- async setContext(contextId, context) {
583
- this.logic.setContext(contextId, context);
597
+ /**
598
+ * Set chat session context, model and level of reasoning
599
+ * @param {*} contextId
600
+ * @param {string} context
601
+ * @param {string} model
602
+ * @param {string} reasoning
603
+ */
604
+ async setContext(contextId, context, model, reasoning) {
605
+ this.logic.setContext(contextId, context, model, reasoning);
584
606
  }
585
607
 
586
608
  async chat(contextId, question, userDesktopId) {
@@ -591,7 +613,9 @@ class AiAgent extends Elf {
591
613
 
592
614
  await this._loadProvider();
593
615
  const contextMessages = this.state.messages[contextId] || [];
594
- const context = this.state.contexts[contextId];
616
+ const context = this.state.contexts[contextId] || null;
617
+ const reasoning = this.state.reasonings[contextId] || this.state.reasoning;
618
+ const model = this.state.models[contextId] || this.state.model;
595
619
 
596
620
  let systemPrompt = this.state.prompt || '';
597
621
  if (context) {
@@ -623,12 +647,12 @@ ${context}
623
647
  this.log.dbg(`🐈 Chat session started : ${contextId}`);
624
648
 
625
649
  const chatCompletionRequest = {
626
- model: this.state.model,
650
+ model,
651
+ reasoning,
627
652
  messages,
628
653
  options,
629
654
  format: this.state.format?.toJS(),
630
655
  tools: this.state.tools?.toJS(),
631
- reasoning: this.state.reasoning,
632
656
  };
633
657
 
634
658
  const result = await this._provider.chat(chatCompletionRequest);
@@ -716,47 +740,6 @@ ${context}
716
740
  this.logic.addToolMessage(contextId, toolId, toolName, answer);
717
741
  }
718
742
 
719
- async ask(contextId, question, questionId) {
720
- if (this.state.provider !== 'ollama') {
721
- throw new Error('Streaming API not impl.');
722
- }
723
-
724
- await this._mutex.lock(this.id);
725
- this.quest.defer(() => this._mutex.unlock(this.id));
726
-
727
- await this._loadProvider();
728
-
729
- const contextMessages = this.state.messages[contextId] || [];
730
- const messages = [
731
- {role: 'system', content: this.state.prompt},
732
- ...Array.from(contextMessages).map((m) => m._state.toJS()), //history
733
- ];
734
- //add new question
735
- messages.push({role: 'user', content: question});
736
-
737
- let options;
738
- if (this.state.options) {
739
- const pState = this.state._state.toJS();
740
- options = pState?.options;
741
- }
742
- const response = await this._provider.chat({
743
- model: this.state.model,
744
- messages,
745
- reasoning: this.state.reasoning,
746
- options,
747
- stream: true,
748
- });
749
-
750
- let agentResponse = '';
751
- for await (const part of response) {
752
- agentResponse += part.message.content;
753
- this.quest.evt(`<${questionId}>`, {part: part.message.content});
754
- }
755
-
756
- //keep agent response
757
- this.logic.ask(contextId, question, agentResponse);
758
- }
759
-
760
743
  async resumeExchange(resumePrompt, contextId) {
761
744
  await this._mutex.lock(this.id);
762
745
  this.quest.defer(() => this._mutex.unlock(this.id));
@@ -778,7 +761,7 @@ ${context}
778
761
  model: this.state.model,
779
762
  prompt,
780
763
  system: resumePrompt,
781
- reasoning: this.state.reasoning,
764
+ reasoning: 'low',
782
765
  options,
783
766
  stream: false,
784
767
  });
@@ -814,7 +797,7 @@ ${context}
814
797
  model: this.state.model,
815
798
  prompt,
816
799
  system: CONVERSATION_TITLE_PROMPT,
817
- reasoning: this.state.reasoning,
800
+ reasoning: 'low',
818
801
  options,
819
802
  stream: false,
820
803
  });
@@ -822,68 +805,6 @@ ${context}
822
805
  return cleanText(title).trim();
823
806
  }
824
807
 
825
- async react(reactPrompt, contextId, question) {
826
- await this._mutex.lock(this.id);
827
- this.quest.defer(() => this._mutex.unlock(this.id));
828
-
829
- await this._loadProvider();
830
- const feedId = await this.newQuestFeed();
831
- const contextMessages = this.state.messages[contextId] || [];
832
- const messages = [
833
- {role: 'system', content: reactPrompt},
834
- ...Array.from(contextMessages).map((m) => m._state.toJS()), //history
835
- {role: 'user', content: question},
836
- ];
837
- this.log.dbg('ReAct Question:', question);
838
-
839
- let options;
840
- if (this.state.options) {
841
- options = this.state.options.toJS();
842
- }
843
-
844
- const answer = await this._provider.chat({
845
- model: this.state.model,
846
- messages,
847
- options,
848
- reasoning: this.state.reasoning,
849
- format: {
850
- type: 'object',
851
- properties: {
852
- observation: {type: 'string'},
853
- thought: {type: 'string'},
854
- action: {type: 'string'},
855
- agentId: {type: 'string'},
856
- result: {type: 'string'},
857
- },
858
- required: ['observation', 'thought', 'action', 'agentId', 'result'],
859
- },
860
- });
861
- if (!answer.message.content) {
862
- await this.addAssistantMessage(
863
- contextId,
864
- 'Génération stoppée. Impossible de répondre.'
865
- );
866
- return;
867
- }
868
- const {agentId, action, result, observation} = answer.message.content;
869
- this.log.dbg('ReAct Observation:', observation);
870
- this.log.dbg('ReAct Action:', action);
871
- // Ajoute l'observation
872
- await this.addAssistantMessage(contextId, observation);
873
- // Si un agent est nécessaire, appel de l'agent externe
874
- if (agentId) {
875
- const result = await this.callAgent(
876
- contextId,
877
- agentId,
878
- `${observation} -> ${action}`,
879
- feedId
880
- );
881
- return {agentId, action, result, observation};
882
- }
883
-
884
- return {agentId, action, result, observation};
885
- }
886
-
887
808
  async callAgent(contextId, agentId, action, feedId) {
888
809
  this.log.dbg(`🥸 calling "${agentId}" with action: "${action}"`);
889
810
  const exist = await this.cryo.isPersisted(AiAgentLogic.db, agentId);
@@ -13,7 +13,6 @@ class OpenAIProvider extends LLMProvider {
13
13
  }
14
14
 
15
15
  async chat(chatRequest) {
16
- delete chatRequest.reasoning; //not yet supported
17
16
  if (chatRequest.options) {
18
17
  chatRequest = {...chatRequest, ...chatRequest.options};
19
18
  delete chatRequest.options;
@@ -24,6 +23,12 @@ class OpenAIProvider extends LLMProvider {
24
23
  if (!chatRequest.format) {
25
24
  delete chatRequest.format;
26
25
  }
26
+ if (chatRequest.reasoning !== undefined) {
27
+ if (chatRequest.reasoning) {
28
+ chatRequest.reasoning_effort = chatRequest.reasoning;
29
+ }
30
+ delete chatRequest.reasoning;
31
+ }
27
32
  const useFormat = chatRequest?.format !== undefined;
28
33
  if (useFormat) {
29
34
  chatRequest.response_format = {
@@ -69,7 +74,16 @@ class OpenAIProvider extends LLMProvider {
69
74
  }
70
75
 
71
76
  async gen(genRequest) {
72
- const {model, system, prompt, format, tools, options, stream} = genRequest;
77
+ const {
78
+ model,
79
+ system,
80
+ prompt,
81
+ format,
82
+ tools,
83
+ options,
84
+ stream,
85
+ reasoning,
86
+ } = genRequest;
73
87
  const chatRequest = {
74
88
  model,
75
89
  messages: [
@@ -80,6 +94,7 @@ class OpenAIProvider extends LLMProvider {
80
94
  format,
81
95
  tools,
82
96
  stream,
97
+ reasoning,
83
98
  };
84
99
  const chat = await this.chat(chatRequest);
85
100
  return chat.message.content;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goblin-agents",
3
- "version": "2.5.0",
3
+ "version": "3.0.1",
4
4
  "description": "AI Agents framework",
5
5
  "author": "Epsitec SA",
6
6
  "contributors": [