@falai/agent 1.2.0 → 1.2.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.
- package/dist/cjs/core/ResponseEngine.d.ts +0 -2
- package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
- package/dist/cjs/core/ResponseEngine.js +2 -6
- package/dist/cjs/core/ResponseEngine.js.map +1 -1
- package/dist/cjs/core/ResponseModal.d.ts.map +1 -1
- package/dist/cjs/core/ResponseModal.js +45 -54
- package/dist/cjs/core/ResponseModal.js.map +1 -1
- package/dist/cjs/core/ResponsePipeline.d.ts +2 -1
- package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/cjs/core/ResponsePipeline.js +17 -19
- package/dist/cjs/core/ResponsePipeline.js.map +1 -1
- package/dist/cjs/core/RoutingEngine.js +2 -2
- package/dist/cjs/core/RoutingEngine.js.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.d.ts +7 -0
- package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.js +101 -12
- package/dist/cjs/providers/AnthropicProvider.js.map +1 -1
- package/dist/cjs/providers/GeminiProvider.d.ts +7 -0
- package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/cjs/providers/GeminiProvider.js +81 -2
- package/dist/cjs/providers/GeminiProvider.js.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.d.ts +5 -0
- package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.js +51 -12
- package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.d.ts +5 -0
- package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.js +50 -12
- package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
- package/dist/cjs/types/ai.d.ts +2 -2
- package/dist/cjs/types/ai.d.ts.map +1 -1
- package/dist/core/ResponseEngine.d.ts +0 -2
- package/dist/core/ResponseEngine.d.ts.map +1 -1
- package/dist/core/ResponseEngine.js +2 -6
- package/dist/core/ResponseEngine.js.map +1 -1
- package/dist/core/ResponseModal.d.ts.map +1 -1
- package/dist/core/ResponseModal.js +46 -55
- package/dist/core/ResponseModal.js.map +1 -1
- package/dist/core/ResponsePipeline.d.ts +2 -1
- package/dist/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/core/ResponsePipeline.js +18 -20
- package/dist/core/ResponsePipeline.js.map +1 -1
- package/dist/core/RoutingEngine.js +3 -3
- package/dist/core/RoutingEngine.js.map +1 -1
- package/dist/providers/AnthropicProvider.d.ts +7 -0
- package/dist/providers/AnthropicProvider.d.ts.map +1 -1
- package/dist/providers/AnthropicProvider.js +101 -12
- package/dist/providers/AnthropicProvider.js.map +1 -1
- package/dist/providers/GeminiProvider.d.ts +7 -0
- package/dist/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/providers/GeminiProvider.js +81 -2
- package/dist/providers/GeminiProvider.js.map +1 -1
- package/dist/providers/OpenAIProvider.d.ts +5 -0
- package/dist/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/providers/OpenAIProvider.js +51 -12
- package/dist/providers/OpenAIProvider.js.map +1 -1
- package/dist/providers/OpenRouterProvider.d.ts +5 -0
- package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/providers/OpenRouterProvider.js +50 -12
- package/dist/providers/OpenRouterProvider.js.map +1 -1
- package/dist/types/ai.d.ts +2 -2
- package/dist/types/ai.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/ResponseEngine.ts +2 -9
- package/src/core/ResponseModal.ts +56 -67
- package/src/core/ResponsePipeline.ts +22 -22
- package/src/core/RoutingEngine.ts +3 -3
- package/src/providers/AnthropicProvider.ts +110 -12
- package/src/providers/GeminiProvider.ts +91 -2
- package/src/providers/OpenAIProvider.ts +56 -12
- package/src/providers/OpenRouterProvider.ts +55 -12
- package/src/types/ai.ts +2 -2
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
AgentStructuredResponse,
|
|
20
20
|
StructuredSchema,
|
|
21
21
|
} from "../types";
|
|
22
|
+
import type { HistoryItem } from "../types/history";
|
|
22
23
|
import { withTimeoutAndRetry } from "../utils/retry";
|
|
23
24
|
import { tryParseJSONResponse } from "../utils/json";
|
|
24
25
|
import { logger } from "../utils/logger";
|
|
@@ -152,6 +153,62 @@ export class GeminiProvider implements AiProvider {
|
|
|
152
153
|
};
|
|
153
154
|
}
|
|
154
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Build Gemini-formatted contents from HistoryItem[] array.
|
|
158
|
+
* Gemini uses "user"/"model" roles (not "assistant").
|
|
159
|
+
* System messages are extracted separately for systemInstruction.
|
|
160
|
+
* Tool results map to functionResponse parts, tool calls to functionCall parts.
|
|
161
|
+
*/
|
|
162
|
+
private buildGeminiContents(history: HistoryItem[]): {
|
|
163
|
+
contents: Array<{ role: string; parts: Array<Record<string, unknown>> }>;
|
|
164
|
+
systemInstructions: string[];
|
|
165
|
+
} {
|
|
166
|
+
const contents: Array<{ role: string; parts: Array<Record<string, unknown>> }> = [];
|
|
167
|
+
const systemInstructions: string[] = [];
|
|
168
|
+
|
|
169
|
+
for (const item of history) {
|
|
170
|
+
switch (item.role) {
|
|
171
|
+
case "system":
|
|
172
|
+
systemInstructions.push(item.content);
|
|
173
|
+
break;
|
|
174
|
+
case "user":
|
|
175
|
+
contents.push({ role: "user", parts: [{ text: item.content }] });
|
|
176
|
+
break;
|
|
177
|
+
case "assistant":
|
|
178
|
+
if (item.tool_calls && item.tool_calls.length > 0) {
|
|
179
|
+
const parts: Array<Record<string, unknown>> = [];
|
|
180
|
+
if (item.content) {
|
|
181
|
+
parts.push({ text: item.content });
|
|
182
|
+
}
|
|
183
|
+
for (const tc of item.tool_calls) {
|
|
184
|
+
parts.push({
|
|
185
|
+
functionCall: { name: tc.name, args: tc.arguments },
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
contents.push({ role: "model", parts });
|
|
189
|
+
} else {
|
|
190
|
+
contents.push({ role: "model", parts: [{ text: item.content || "" }] });
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
193
|
+
case "tool":
|
|
194
|
+
contents.push({
|
|
195
|
+
role: "user",
|
|
196
|
+
parts: [
|
|
197
|
+
{
|
|
198
|
+
functionResponse: {
|
|
199
|
+
name: item.name,
|
|
200
|
+
response: typeof item.content === "object" ? item.content : { result: item.content },
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
],
|
|
204
|
+
});
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return { contents, systemInstructions };
|
|
210
|
+
}
|
|
211
|
+
|
|
155
212
|
/**
|
|
156
213
|
* Convert tool parameter schemas (JSON Schema) to Gemini's Schema format.
|
|
157
214
|
* Gemini's FunctionDeclaration.parameters expects its own Schema type,
|
|
@@ -430,9 +487,25 @@ export class GeminiProvider implements AiProvider {
|
|
|
430
487
|
|
|
431
488
|
let response: GenerateContentResponse;
|
|
432
489
|
try {
|
|
490
|
+
// Build contents from history
|
|
491
|
+
const { contents: historyContents, systemInstructions } = this.buildGeminiContents(input.history);
|
|
492
|
+
|
|
493
|
+
// Append the current prompt as the final user content
|
|
494
|
+
historyContents.push({ role: "user", parts: [{ text: input.prompt }] });
|
|
495
|
+
|
|
496
|
+
// Set system instruction from history if present
|
|
497
|
+
if (systemInstructions.length > 0) {
|
|
498
|
+
const existingSystem = configOverride.systemInstruction;
|
|
499
|
+
if (typeof existingSystem === "string") {
|
|
500
|
+
configOverride.systemInstruction = `${existingSystem}\n\n${systemInstructions.join("\n\n")}`;
|
|
501
|
+
} else {
|
|
502
|
+
configOverride.systemInstruction = systemInstructions.join("\n\n");
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
433
506
|
response = await this.genAI.models.generateContent({
|
|
434
507
|
model,
|
|
435
|
-
contents:
|
|
508
|
+
contents: historyContents,
|
|
436
509
|
config: {
|
|
437
510
|
...configOverride,
|
|
438
511
|
...(input.signal ? { abortSignal: input.signal } : {}),
|
|
@@ -620,9 +693,25 @@ export class GeminiProvider implements AiProvider {
|
|
|
620
693
|
|
|
621
694
|
let stream;
|
|
622
695
|
try {
|
|
696
|
+
// Build contents from history
|
|
697
|
+
const { contents: historyContents, systemInstructions } = this.buildGeminiContents(input.history);
|
|
698
|
+
|
|
699
|
+
// Append the current prompt as the final user content
|
|
700
|
+
historyContents.push({ role: "user", parts: [{ text: input.prompt }] });
|
|
701
|
+
|
|
702
|
+
// Set system instruction from history if present
|
|
703
|
+
if (systemInstructions.length > 0) {
|
|
704
|
+
const existingSystem = configOverride.systemInstruction;
|
|
705
|
+
if (typeof existingSystem === "string") {
|
|
706
|
+
configOverride.systemInstruction = `${existingSystem}\n\n${systemInstructions.join("\n\n")}`;
|
|
707
|
+
} else {
|
|
708
|
+
configOverride.systemInstruction = systemInstructions.join("\n\n");
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
623
712
|
stream = await this.genAI.models.generateContentStream({
|
|
624
713
|
model,
|
|
625
|
-
contents:
|
|
714
|
+
contents: historyContents,
|
|
626
715
|
config: {
|
|
627
716
|
...configOverride,
|
|
628
717
|
...(input.signal ? { abortSignal: input.signal } : {}),
|
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
AgentStructuredResponse,
|
|
14
14
|
StructuredSchema,
|
|
15
15
|
} from "../types";
|
|
16
|
+
import type { HistoryItem } from "../types/history";
|
|
16
17
|
import { withTimeoutAndRetry, logger } from "../utils";
|
|
17
18
|
import { FunctionParameters } from "openai/resources/shared.mjs";
|
|
18
19
|
|
|
@@ -161,6 +162,52 @@ export class OpenAIProvider implements AiProvider {
|
|
|
161
162
|
};
|
|
162
163
|
}
|
|
163
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Build OpenAI-formatted messages from HistoryItem[] array.
|
|
167
|
+
* Maps directly to ChatCompletionMessageParam format.
|
|
168
|
+
*/
|
|
169
|
+
private buildOpenAIMessages(history: HistoryItem[]): Array<unknown> {
|
|
170
|
+
const messages: Array<unknown> = [];
|
|
171
|
+
|
|
172
|
+
for (const item of history) {
|
|
173
|
+
switch (item.role) {
|
|
174
|
+
case "system":
|
|
175
|
+
messages.push({ role: "system", content: item.content });
|
|
176
|
+
break;
|
|
177
|
+
case "user":
|
|
178
|
+
messages.push({ role: "user", content: item.content });
|
|
179
|
+
break;
|
|
180
|
+
case "assistant":
|
|
181
|
+
if (item.tool_calls && item.tool_calls.length > 0) {
|
|
182
|
+
messages.push({
|
|
183
|
+
role: "assistant",
|
|
184
|
+
content: item.content || null,
|
|
185
|
+
tool_calls: item.tool_calls.map(tc => ({
|
|
186
|
+
id: tc.id,
|
|
187
|
+
type: "function",
|
|
188
|
+
function: {
|
|
189
|
+
name: tc.name,
|
|
190
|
+
arguments: JSON.stringify(tc.arguments),
|
|
191
|
+
},
|
|
192
|
+
})),
|
|
193
|
+
});
|
|
194
|
+
} else {
|
|
195
|
+
messages.push({ role: "assistant", content: item.content || "" });
|
|
196
|
+
}
|
|
197
|
+
break;
|
|
198
|
+
case "tool":
|
|
199
|
+
messages.push({
|
|
200
|
+
role: "tool",
|
|
201
|
+
tool_call_id: item.tool_call_id,
|
|
202
|
+
content: typeof item.content === "string" ? item.content : JSON.stringify(item.content),
|
|
203
|
+
});
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return messages;
|
|
209
|
+
}
|
|
210
|
+
|
|
164
211
|
/**
|
|
165
212
|
* Adapt common schema format to OpenAI's format.
|
|
166
213
|
* OpenAI uses standard JSON Schema, so this is mostly a passthrough.
|
|
@@ -265,14 +312,12 @@ export class OpenAIProvider implements AiProvider {
|
|
|
265
312
|
input: GenerateMessageInput<TContext>
|
|
266
313
|
): Promise<GenerateMessageOutput<TStructured>> {
|
|
267
314
|
const operation = async (): Promise<GenerateMessageOutput> => {
|
|
315
|
+
const historyMessages = this.buildOpenAIMessages(input.history);
|
|
316
|
+
historyMessages.push({ role: "user", content: input.prompt });
|
|
317
|
+
|
|
268
318
|
const params: ChatCompletionCreateParamsNonStreaming = {
|
|
269
319
|
model,
|
|
270
|
-
messages: [
|
|
271
|
-
{
|
|
272
|
-
role: "user",
|
|
273
|
-
content: input.prompt,
|
|
274
|
-
},
|
|
275
|
-
],
|
|
320
|
+
messages: historyMessages as ChatCompletionCreateParamsNonStreaming["messages"],
|
|
276
321
|
...this.config,
|
|
277
322
|
};
|
|
278
323
|
|
|
@@ -468,15 +513,14 @@ export class OpenAIProvider implements AiProvider {
|
|
|
468
513
|
model: string,
|
|
469
514
|
input: GenerateMessageInput<TContext>
|
|
470
515
|
): AsyncGenerator<GenerateMessageStreamChunk<TStructured>> {
|
|
516
|
+
// Build messages from history and append prompt as final user message
|
|
517
|
+
const historyMessages = this.buildOpenAIMessages(input.history);
|
|
518
|
+
historyMessages.push({ role: "user" as const, content: input.prompt });
|
|
519
|
+
|
|
471
520
|
const params = {
|
|
472
521
|
...this.config,
|
|
473
522
|
model,
|
|
474
|
-
messages: [
|
|
475
|
-
{
|
|
476
|
-
role: "user" as const,
|
|
477
|
-
content: input.prompt,
|
|
478
|
-
},
|
|
479
|
-
],
|
|
523
|
+
messages: historyMessages as ChatCompletionCreateParamsNonStreaming["messages"],
|
|
480
524
|
stream: true as const,
|
|
481
525
|
};
|
|
482
526
|
|
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
GenerateMessageStreamChunk,
|
|
16
16
|
StructuredSchema,
|
|
17
17
|
} from "../types";
|
|
18
|
+
import type { HistoryItem } from "../types/history";
|
|
18
19
|
import { withTimeoutAndRetry, logger } from "../utils";
|
|
19
20
|
|
|
20
21
|
const DEFAULT_RETRY_CONFIG = {
|
|
@@ -171,6 +172,52 @@ export class OpenRouterProvider implements AiProvider {
|
|
|
171
172
|
};
|
|
172
173
|
}
|
|
173
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Build OpenRouter-formatted messages from HistoryItem[] array.
|
|
177
|
+
* OpenRouter uses OpenAI-compatible format.
|
|
178
|
+
*/
|
|
179
|
+
private buildOpenRouterMessages(history: HistoryItem[]): Array<unknown> {
|
|
180
|
+
const messages: Array<unknown> = [];
|
|
181
|
+
|
|
182
|
+
for (const item of history) {
|
|
183
|
+
switch (item.role) {
|
|
184
|
+
case "system":
|
|
185
|
+
messages.push({ role: "system", content: item.content });
|
|
186
|
+
break;
|
|
187
|
+
case "user":
|
|
188
|
+
messages.push({ role: "user", content: item.content });
|
|
189
|
+
break;
|
|
190
|
+
case "assistant":
|
|
191
|
+
if (item.tool_calls && item.tool_calls.length > 0) {
|
|
192
|
+
messages.push({
|
|
193
|
+
role: "assistant",
|
|
194
|
+
content: item.content || null,
|
|
195
|
+
tool_calls: item.tool_calls.map(tc => ({
|
|
196
|
+
id: tc.id,
|
|
197
|
+
type: "function",
|
|
198
|
+
function: {
|
|
199
|
+
name: tc.name,
|
|
200
|
+
arguments: JSON.stringify(tc.arguments),
|
|
201
|
+
},
|
|
202
|
+
})),
|
|
203
|
+
});
|
|
204
|
+
} else {
|
|
205
|
+
messages.push({ role: "assistant", content: item.content || "" });
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
case "tool":
|
|
209
|
+
messages.push({
|
|
210
|
+
role: "tool",
|
|
211
|
+
tool_call_id: item.tool_call_id,
|
|
212
|
+
content: typeof item.content === "string" ? item.content : JSON.stringify(item.content),
|
|
213
|
+
});
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return messages;
|
|
219
|
+
}
|
|
220
|
+
|
|
174
221
|
/**
|
|
175
222
|
* Adapt common schema format to OpenRouter's format.
|
|
176
223
|
* OpenRouter is OpenAI-compatible and uses standard JSON Schema.
|
|
@@ -272,14 +319,12 @@ export class OpenRouterProvider implements AiProvider {
|
|
|
272
319
|
input: GenerateMessageInput<TContext>
|
|
273
320
|
): Promise<GenerateMessageOutput<TStructured>> {
|
|
274
321
|
const operation = async (): Promise<GenerateMessageOutput> => {
|
|
322
|
+
const historyMessages = this.buildOpenRouterMessages(input.history);
|
|
323
|
+
historyMessages.push({ role: "user", content: input.prompt });
|
|
324
|
+
|
|
275
325
|
const params: ChatCompletionCreateParamsNonStreaming = {
|
|
276
326
|
model,
|
|
277
|
-
messages: [
|
|
278
|
-
{
|
|
279
|
-
role: "user",
|
|
280
|
-
content: input.prompt,
|
|
281
|
-
},
|
|
282
|
-
],
|
|
327
|
+
messages: historyMessages as ChatCompletionCreateParamsNonStreaming["messages"],
|
|
283
328
|
...this.config,
|
|
284
329
|
};
|
|
285
330
|
|
|
@@ -471,15 +516,13 @@ export class OpenRouterProvider implements AiProvider {
|
|
|
471
516
|
model: string,
|
|
472
517
|
input: GenerateMessageInput<TContext>
|
|
473
518
|
): AsyncGenerator<GenerateMessageStreamChunk<TStructured>> {
|
|
519
|
+
const historyMessages = this.buildOpenRouterMessages(input.history);
|
|
520
|
+
historyMessages.push({ role: "user" as const, content: input.prompt });
|
|
521
|
+
|
|
474
522
|
const params = {
|
|
475
523
|
...this.config,
|
|
476
524
|
model,
|
|
477
|
-
messages: [
|
|
478
|
-
{
|
|
479
|
-
role: "user" as const,
|
|
480
|
-
content: input.prompt,
|
|
481
|
-
},
|
|
482
|
-
],
|
|
525
|
+
messages: historyMessages as ChatCompletionCreateParamsNonStreaming["messages"],
|
|
483
526
|
stream: true as const,
|
|
484
527
|
};
|
|
485
528
|
|
package/src/types/ai.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* AI provider strategy types
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type { HistoryItem } from "./history";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Reasoning/thinking configuration for AI models
|
|
@@ -36,7 +36,7 @@ export interface GenerateMessageInput<TContext = unknown> {
|
|
|
36
36
|
/** The constructed prompt */
|
|
37
37
|
prompt: string;
|
|
38
38
|
/** Interaction history */
|
|
39
|
-
history:
|
|
39
|
+
history: HistoryItem[];
|
|
40
40
|
/** Context data */
|
|
41
41
|
context: TContext;
|
|
42
42
|
/** Tools available for AI to call during this interaction */
|