@botonic/plugin-ai-agents 0.49.0-alpha.3 → 0.49.0-alpha.4
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/lib/cjs/agents/specialist-agent.js +2 -1
- package/lib/cjs/agents/specialist-agent.js.map +1 -1
- package/lib/cjs/constants.d.ts +10 -12
- package/lib/cjs/constants.js +11 -14
- package/lib/cjs/constants.js.map +1 -1
- package/lib/cjs/debug-logger.js +2 -8
- package/lib/cjs/debug-logger.js.map +1 -1
- package/lib/cjs/guardrails/input.js.map +1 -1
- package/lib/cjs/index.js +14 -2
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/llm-config.d.ts +10 -7
- package/lib/cjs/llm-config.js +24 -41
- package/lib/cjs/llm-config.js.map +1 -1
- package/lib/cjs/runners/base-runner.d.ts +1 -0
- package/lib/cjs/runners/base-runner.js +22 -16
- package/lib/cjs/runners/base-runner.js.map +1 -1
- package/lib/cjs/runners/router-runner.d.ts +2 -0
- package/lib/cjs/runners/router-runner.js +23 -8
- package/lib/cjs/runners/router-runner.js.map +1 -1
- package/lib/cjs/services/types.d.ts +1 -1
- package/lib/esm/agents/specialist-agent.js +2 -1
- package/lib/esm/agents/specialist-agent.js.map +1 -1
- package/lib/esm/constants.d.ts +10 -12
- package/lib/esm/constants.js +11 -14
- package/lib/esm/constants.js.map +1 -1
- package/lib/esm/debug-logger.js +2 -8
- package/lib/esm/debug-logger.js.map +1 -1
- package/lib/esm/guardrails/input.js.map +1 -1
- package/lib/esm/index.js +14 -2
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/llm-config.d.ts +10 -7
- package/lib/esm/llm-config.js +24 -41
- package/lib/esm/llm-config.js.map +1 -1
- package/lib/esm/runners/base-runner.d.ts +1 -0
- package/lib/esm/runners/base-runner.js +22 -16
- package/lib/esm/runners/base-runner.js.map +1 -1
- package/lib/esm/runners/router-runner.d.ts +2 -0
- package/lib/esm/runners/router-runner.js +23 -8
- package/lib/esm/runners/router-runner.js.map +1 -1
- package/lib/esm/services/types.d.ts +1 -1
- package/package.json +2 -2
- package/src/agents/specialist-agent.ts +2 -1
- package/src/constants.ts +15 -16
- package/src/debug-logger.ts +2 -8
- package/src/guardrails/input.ts +0 -1
- package/src/index.ts +14 -14
- package/src/llm-config.ts +45 -56
- package/src/runners/base-runner.ts +31 -19
- package/src/runners/router-runner.ts +35 -12
- package/src/services/types.ts +1 -1
package/src/debug-logger.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type ToolExecution,
|
|
5
5
|
} from '@botonic/core'
|
|
6
6
|
import type { ModelSettings } from '@openai/agents'
|
|
7
|
+
import { LLM_PROVIDER } from './constants'
|
|
7
8
|
import type { AgenticInputMessage, MemoryOptions, RunResult } from './types'
|
|
8
9
|
|
|
9
10
|
const PREFIX = '[BotonicPluginAiAgents]'
|
|
@@ -43,6 +44,7 @@ export interface DebugLogger {
|
|
|
43
44
|
class EnabledDebugLogger implements DebugLogger {
|
|
44
45
|
logInitialConfig(config: DebugLoggerConfig): void {
|
|
45
46
|
console.log(`${PREFIX} === Plugin Initialization ===`)
|
|
47
|
+
console.log(`${PREFIX} Provider: ${LLM_PROVIDER}`)
|
|
46
48
|
console.log(
|
|
47
49
|
`${PREFIX} Message History API Version: ${config.messageHistoryApiVersion}`
|
|
48
50
|
)
|
|
@@ -155,21 +157,13 @@ class EnabledDebugLogger implements DebugLogger {
|
|
|
155
157
|
}
|
|
156
158
|
|
|
157
159
|
class DisabledDebugLogger implements DebugLogger {
|
|
158
|
-
// biome-ignore lint/suspicious/noEmptyBlockStatements: intentional no-op implementation
|
|
159
160
|
logInitialConfig(): void {}
|
|
160
|
-
// biome-ignore lint/suspicious/noEmptyBlockStatements: intentional no-op implementation
|
|
161
161
|
logAgentDebugInfo(): void {}
|
|
162
|
-
// biome-ignore lint/suspicious/noEmptyBlockStatements: intentional no-op implementation
|
|
163
162
|
logModelSettings(): void {}
|
|
164
|
-
// biome-ignore lint/suspicious/noEmptyBlockStatements: intentional no-op implementation
|
|
165
163
|
logRunnerStart(_model: string, _modelSettings: ModelSettings): void {}
|
|
166
|
-
// biome-ignore lint/suspicious/noEmptyBlockStatements: intentional no-op implementation
|
|
167
164
|
logRunResult(): void {}
|
|
168
|
-
// biome-ignore lint/suspicious/noEmptyBlockStatements: intentional no-op implementation
|
|
169
165
|
logGuardrailTriggered(): void {}
|
|
170
|
-
// biome-ignore lint/suspicious/noEmptyBlockStatements: intentional no-op implementation
|
|
171
166
|
logRunnerError(): void {}
|
|
172
|
-
// biome-ignore lint/suspicious/noEmptyBlockStatements: intentional no-op implementation
|
|
173
167
|
logToolExecution(): void {}
|
|
174
168
|
}
|
|
175
169
|
|
package/src/guardrails/input.ts
CHANGED
|
@@ -123,7 +123,6 @@ async function sendGuardrailLlmRunTracking(
|
|
|
123
123
|
const durationPerCall = Math.round(totalDuration / rawResponses.length)
|
|
124
124
|
const temperature =
|
|
125
125
|
(llmConfig.modelSettings.temperature as number | undefined) ?? 0
|
|
126
|
-
|
|
127
126
|
const llmRuns = rawResponses.map(response => ({
|
|
128
127
|
inference_id: trackingContext.inferenceId,
|
|
129
128
|
is_test: trackingContext.isTest,
|
package/src/index.ts
CHANGED
|
@@ -132,13 +132,13 @@ export default class BotonicPluginAiAgents<
|
|
|
132
132
|
authToken: string,
|
|
133
133
|
inferenceId: string
|
|
134
134
|
) {
|
|
135
|
-
const llmConfig = new LLMConfig(
|
|
136
|
-
this.maxRetries,
|
|
137
|
-
this.timeout,
|
|
138
|
-
aiAgentArgs.model,
|
|
139
|
-
aiAgentArgs.verbosity,
|
|
140
|
-
botContext
|
|
141
|
-
)
|
|
135
|
+
const llmConfig = new LLMConfig({
|
|
136
|
+
maxRetries: this.maxRetries,
|
|
137
|
+
timeout: this.timeout,
|
|
138
|
+
modelName: aiAgentArgs.model,
|
|
139
|
+
verbosity: aiAgentArgs.verbosity,
|
|
140
|
+
botContext,
|
|
141
|
+
})
|
|
142
142
|
|
|
143
143
|
// Get LLM config, tools and agent
|
|
144
144
|
const { tools, agent } = await this.getSpecialistAgentAndTools(
|
|
@@ -194,13 +194,13 @@ export default class BotonicPluginAiAgents<
|
|
|
194
194
|
) {
|
|
195
195
|
const { specialists, name, instructions } = aiAgentArgs
|
|
196
196
|
|
|
197
|
-
const llmConfig = new LLMConfig(
|
|
198
|
-
this.maxRetries,
|
|
199
|
-
this.timeout,
|
|
200
|
-
aiAgentArgs.model,
|
|
201
|
-
aiAgentArgs.verbosity,
|
|
202
|
-
botContext
|
|
203
|
-
)
|
|
197
|
+
const llmConfig = new LLMConfig({
|
|
198
|
+
maxRetries: this.maxRetries,
|
|
199
|
+
timeout: this.timeout,
|
|
200
|
+
modelName: aiAgentArgs.model,
|
|
201
|
+
verbosity: aiAgentArgs.verbosity,
|
|
202
|
+
botContext,
|
|
203
|
+
})
|
|
204
204
|
|
|
205
205
|
const specialistsAgents = await Promise.all(
|
|
206
206
|
specialists.map(async specialistData => {
|
package/src/llm-config.ts
CHANGED
|
@@ -7,15 +7,22 @@ import {
|
|
|
7
7
|
} from '@openai/agents'
|
|
8
8
|
import OpenAI, { AzureOpenAI } from 'openai'
|
|
9
9
|
import {
|
|
10
|
-
AZURE_OPENAI_API_BASE,
|
|
11
|
-
AZURE_OPENAI_API_KEY,
|
|
12
|
-
AZURE_OPENAI_API_VERSION,
|
|
13
10
|
isProd,
|
|
14
|
-
|
|
11
|
+
LLM_API_KEY,
|
|
12
|
+
LLM_API_URL,
|
|
13
|
+
LLM_AZURE_API_VERSION,
|
|
14
|
+
LLM_OPENAI_MODEL,
|
|
15
|
+
LLM_PROVIDER,
|
|
15
16
|
LLM_PROVIDERS,
|
|
16
17
|
} from './constants'
|
|
17
18
|
|
|
18
|
-
export
|
|
19
|
+
export interface LLMConfigParams {
|
|
20
|
+
maxRetries: number
|
|
21
|
+
timeout: number
|
|
22
|
+
modelName: string
|
|
23
|
+
verbosity: VerbosityLevel
|
|
24
|
+
botContext: BotContext
|
|
25
|
+
}
|
|
19
26
|
|
|
20
27
|
export class LLMConfig {
|
|
21
28
|
private readonly maxRetries: number
|
|
@@ -25,17 +32,18 @@ export class LLMConfig {
|
|
|
25
32
|
public readonly modelSettings: ModelSettings
|
|
26
33
|
public readonly modelProvider: ModelProvider
|
|
27
34
|
|
|
28
|
-
constructor(
|
|
29
|
-
maxRetries
|
|
30
|
-
timeout
|
|
31
|
-
modelName
|
|
32
|
-
verbosity
|
|
33
|
-
botContext
|
|
34
|
-
) {
|
|
35
|
+
constructor({
|
|
36
|
+
maxRetries,
|
|
37
|
+
timeout,
|
|
38
|
+
modelName,
|
|
39
|
+
verbosity,
|
|
40
|
+
botContext,
|
|
41
|
+
}: LLMConfigParams) {
|
|
35
42
|
this.maxRetries = maxRetries
|
|
36
43
|
this.timeout = timeout
|
|
37
44
|
this.botContext = botContext
|
|
38
|
-
this.modelName =
|
|
45
|
+
this.modelName =
|
|
46
|
+
LLM_PROVIDER === LLM_PROVIDERS.OPENAI ? LLM_OPENAI_MODEL : modelName
|
|
39
47
|
this.modelProvider = this.getModelProvider()
|
|
40
48
|
this.modelSettings = this.getModelSettings(modelName, verbosity)
|
|
41
49
|
}
|
|
@@ -44,19 +52,6 @@ export class LLMConfig {
|
|
|
44
52
|
return await this.modelProvider.getModel(this.modelName)
|
|
45
53
|
}
|
|
46
54
|
|
|
47
|
-
getProviderName(): LLMProvider {
|
|
48
|
-
return this.botContext.settings.LITELLM_API_URL
|
|
49
|
-
? LLM_PROVIDERS.LITELLM
|
|
50
|
-
: LLM_PROVIDERS.AZURE
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
getApiVersion(): string | undefined {
|
|
54
|
-
return this.getProviderName() === LLM_PROVIDERS.AZURE
|
|
55
|
-
? this.botContext.settings.AZURE_OPENAI_API_VERSION ||
|
|
56
|
-
AZURE_OPENAI_API_VERSION
|
|
57
|
-
: undefined
|
|
58
|
-
}
|
|
59
|
-
|
|
60
55
|
private getModelProvider(): ModelProvider {
|
|
61
56
|
const client = this.getClient()
|
|
62
57
|
return new OpenAIProvider({
|
|
@@ -66,49 +61,30 @@ export class LLMConfig {
|
|
|
66
61
|
}
|
|
67
62
|
|
|
68
63
|
private getClient(): OpenAI | AzureOpenAI {
|
|
69
|
-
if (
|
|
70
|
-
return this.
|
|
64
|
+
if (LLM_PROVIDER === LLM_PROVIDERS.OPENAI) {
|
|
65
|
+
return this.getOpenAIClient()
|
|
71
66
|
}
|
|
72
67
|
|
|
73
68
|
return this.getAzureClient()
|
|
74
69
|
}
|
|
75
70
|
|
|
76
|
-
private
|
|
77
|
-
const botId = this.botContext.session.bot.id
|
|
78
|
-
const orgId = this.botContext.session.organization_id
|
|
79
|
-
const parts: string[] = []
|
|
80
|
-
if (botId) {
|
|
81
|
-
parts.push(`${LITELLM_TAG_KEYS.BOT_ID}:${botId}`)
|
|
82
|
-
}
|
|
83
|
-
if (orgId) {
|
|
84
|
-
parts.push(`${LITELLM_TAG_KEYS.ORG_ID}:${orgId}`)
|
|
85
|
-
}
|
|
86
|
-
return parts.length > 0
|
|
87
|
-
? { 'x-litellm-tags': parts.join(LITELLM_TAG_KEYS.SEPARATOR) }
|
|
88
|
-
: undefined
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
private getLiteLLMClient(): OpenAI {
|
|
71
|
+
private getOpenAIClient(): OpenAI {
|
|
92
72
|
return new OpenAI({
|
|
93
|
-
apiKey: this.botContext.secrets.
|
|
94
|
-
baseURL: this.botContext.settings.LITELLM_API_URL,
|
|
73
|
+
apiKey: this.botContext.secrets.AZURE_OPENAI_API_KEY || LLM_API_KEY,
|
|
95
74
|
timeout: this.timeout,
|
|
96
75
|
maxRetries: this.maxRetries,
|
|
97
76
|
dangerouslyAllowBrowser: !isProd,
|
|
98
|
-
defaultHeaders: this.buildLiteLLMTags(),
|
|
99
77
|
})
|
|
100
78
|
}
|
|
101
79
|
|
|
102
80
|
private getAzureClient(): AzureOpenAI {
|
|
103
81
|
return new AzureOpenAI({
|
|
104
|
-
apiKey:
|
|
105
|
-
this.botContext.secrets.AZURE_OPENAI_API_KEY || AZURE_OPENAI_API_KEY,
|
|
82
|
+
apiKey: this.botContext.secrets.AZURE_OPENAI_API_KEY || LLM_API_KEY,
|
|
106
83
|
apiVersion:
|
|
107
84
|
this.botContext.settings.AZURE_OPENAI_API_VERSION ||
|
|
108
|
-
|
|
85
|
+
LLM_AZURE_API_VERSION,
|
|
109
86
|
deployment: this.modelName,
|
|
110
|
-
baseURL:
|
|
111
|
-
this.botContext.settings.AZURE_OPENAI_API_BASE || AZURE_OPENAI_API_BASE,
|
|
87
|
+
baseURL: this.botContext.settings.AZURE_OPENAI_API_BASE || LLM_API_URL,
|
|
112
88
|
timeout: this.timeout,
|
|
113
89
|
maxRetries: this.maxRetries,
|
|
114
90
|
dangerouslyAllowBrowser: !isProd,
|
|
@@ -119,6 +95,14 @@ export class LLMConfig {
|
|
|
119
95
|
model: string,
|
|
120
96
|
verbosity: VerbosityLevel
|
|
121
97
|
): ModelSettings {
|
|
98
|
+
if (model.includes('gpt-5')) {
|
|
99
|
+
return {
|
|
100
|
+
reasoning: { effort: 'none' },
|
|
101
|
+
temperature: 1,
|
|
102
|
+
text: { verbosity },
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
122
106
|
if (model.includes('gpt-4')) {
|
|
123
107
|
return {
|
|
124
108
|
temperature: 0,
|
|
@@ -126,10 +110,15 @@ export class LLMConfig {
|
|
|
126
110
|
}
|
|
127
111
|
}
|
|
128
112
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
113
|
+
throw new Error(`Unsupported model: ${model}`)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
getApiVersion(): string {
|
|
117
|
+
if (LLM_PROVIDER !== LLM_PROVIDERS.AZURE) {
|
|
118
|
+
return 'NOT_API_VERSION_FOR_OPENAI_PROVIDER'
|
|
133
119
|
}
|
|
120
|
+
return (
|
|
121
|
+
this.botContext.settings.AZURE_OPENAI_API_VERSION || LLM_AZURE_API_VERSION
|
|
122
|
+
)
|
|
134
123
|
}
|
|
135
124
|
}
|
|
@@ -86,24 +86,11 @@ export abstract class BaseRunner<
|
|
|
86
86
|
|
|
87
87
|
return runResult
|
|
88
88
|
} catch (error) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
isTransferredToSpecialist: false,
|
|
95
|
-
messages: [],
|
|
96
|
-
memoryLength: 0,
|
|
97
|
-
toolsExecuted: [],
|
|
98
|
-
exit: true,
|
|
99
|
-
error: false,
|
|
100
|
-
inputGuardrailsTriggered: error.result.output.outputInfo,
|
|
101
|
-
outputGuardrailsTriggered: [],
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
this.logger.logGuardrailTriggered()
|
|
105
|
-
this.logger.logRunResult(runResult, startTime)
|
|
106
|
-
|
|
89
|
+
const runResult = this.handleInputGuardrailTripwireTriggered(
|
|
90
|
+
error,
|
|
91
|
+
startTime
|
|
92
|
+
)
|
|
93
|
+
if (runResult) {
|
|
107
94
|
return runResult
|
|
108
95
|
}
|
|
109
96
|
|
|
@@ -263,7 +250,6 @@ export abstract class BaseRunner<
|
|
|
263
250
|
const durationPerCall = Math.round(totalDuration / rawResponses.length)
|
|
264
251
|
const temperature =
|
|
265
252
|
(this.llmConfig.modelSettings.temperature as number | undefined) ?? 0
|
|
266
|
-
|
|
267
253
|
const llmRuns = rawResponses.map(response => ({
|
|
268
254
|
inference_id: this.inferenceId,
|
|
269
255
|
is_test: isTest,
|
|
@@ -286,4 +272,30 @@ export abstract class BaseRunner<
|
|
|
286
272
|
llm_runs: llmRuns,
|
|
287
273
|
})
|
|
288
274
|
}
|
|
275
|
+
|
|
276
|
+
protected handleInputGuardrailTripwireTriggered(
|
|
277
|
+
error: unknown,
|
|
278
|
+
startTime: number
|
|
279
|
+
): RunResult | undefined {
|
|
280
|
+
if (error instanceof InputGuardrailTripwireTriggered) {
|
|
281
|
+
const runResult: RunResult = {
|
|
282
|
+
startingAgentName: '',
|
|
283
|
+
lastAgentName: '',
|
|
284
|
+
availableSpecialists: [],
|
|
285
|
+
isTransferredToSpecialist: false,
|
|
286
|
+
messages: [],
|
|
287
|
+
memoryLength: 0,
|
|
288
|
+
toolsExecuted: [],
|
|
289
|
+
exit: true,
|
|
290
|
+
error: false,
|
|
291
|
+
inputGuardrailsTriggered: error.result.output.outputInfo,
|
|
292
|
+
outputGuardrailsTriggered: [],
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
this.logger.logGuardrailTriggered()
|
|
296
|
+
this.logger.logRunResult(runResult, startTime)
|
|
297
|
+
|
|
298
|
+
return runResult
|
|
299
|
+
}
|
|
300
|
+
}
|
|
289
301
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ResolvedPlugins } from '@botonic/core'
|
|
1
|
+
import type { AvailableSpecialist, ResolvedPlugins } from '@botonic/core'
|
|
2
2
|
import { Handoff } from '@openai/agents'
|
|
3
3
|
import type { Agent } from '@openai/agents-core'
|
|
4
4
|
|
|
@@ -16,17 +16,7 @@ export class RouterRunner<
|
|
|
16
16
|
): RunResult {
|
|
17
17
|
const base = super.buildRunResult(result, context, memoryLength)
|
|
18
18
|
|
|
19
|
-
const availableSpecialists =
|
|
20
|
-
(entry: Agent<any, any> | Handoff<any, any>) => {
|
|
21
|
-
const isHandoff = entry instanceof Handoff
|
|
22
|
-
const agent = isHandoff ? entry.agent : (entry as Agent<any, any>)
|
|
23
|
-
const description = isHandoff
|
|
24
|
-
? entry.toolDescription
|
|
25
|
-
: agent.handoffDescription
|
|
26
|
-
return { name: agent.name, description }
|
|
27
|
-
}
|
|
28
|
-
)
|
|
29
|
-
|
|
19
|
+
const availableSpecialists = this.getAvailableSpecialists()
|
|
30
20
|
const startingAgentName = this.agent.name ?? ''
|
|
31
21
|
const lastAgentName = result.lastAgent?.name ?? ''
|
|
32
22
|
|
|
@@ -38,4 +28,37 @@ export class RouterRunner<
|
|
|
38
28
|
isTransferredToSpecialist: startingAgentName !== lastAgentName,
|
|
39
29
|
}
|
|
40
30
|
}
|
|
31
|
+
|
|
32
|
+
protected override handleInputGuardrailTripwireTriggered(
|
|
33
|
+
error: unknown,
|
|
34
|
+
startTime: number
|
|
35
|
+
): RunResult | undefined {
|
|
36
|
+
const runResult = super.handleInputGuardrailTripwireTriggered(
|
|
37
|
+
error,
|
|
38
|
+
startTime
|
|
39
|
+
)
|
|
40
|
+
if (runResult) {
|
|
41
|
+
// Override attributes to match router agent
|
|
42
|
+
runResult.startingAgentName = this.agent.name
|
|
43
|
+
runResult.lastAgentName = this.agent.name
|
|
44
|
+
runResult.availableSpecialists = this.getAvailableSpecialists()
|
|
45
|
+
runResult.isTransferredToSpecialist = false
|
|
46
|
+
|
|
47
|
+
return runResult
|
|
48
|
+
}
|
|
49
|
+
return undefined
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private getAvailableSpecialists(): AvailableSpecialist[] {
|
|
53
|
+
return (this.agent.handoffs ?? []).map(
|
|
54
|
+
(entry: Agent<any, any> | Handoff<any, any>) => {
|
|
55
|
+
const isHandoff = entry instanceof Handoff
|
|
56
|
+
const agent = isHandoff ? entry.agent : (entry as Agent<any, any>)
|
|
57
|
+
const description = isHandoff
|
|
58
|
+
? entry.toolDescription
|
|
59
|
+
: agent.handoffDescription
|
|
60
|
+
return { name: agent.name, description }
|
|
61
|
+
}
|
|
62
|
+
)
|
|
63
|
+
}
|
|
41
64
|
}
|
package/src/services/types.ts
CHANGED