@botonic/plugin-ai-agents 0.49.0-alpha.3 → 0.49.0-alpha.5
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 +11 -8
- package/lib/cjs/llm-config.js +27 -43
- 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 +11 -8
- package/lib/esm/llm-config.js +27 -43
- 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 +49 -58
- 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/constants.ts
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
export const HUBTYPE_API_URL =
|
|
2
2
|
process.env.HUBTYPE_API_URL || 'https://api.hubtype.com'
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
export const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
// LLM Configuration (provider-agnostic; set LLM_PROVIDER=azure|openai)
|
|
5
|
+
export const LLM_PROVIDERS = {
|
|
6
|
+
AZURE: 'azure',
|
|
7
|
+
OPENAI: 'openai',
|
|
8
|
+
} as const
|
|
9
|
+
|
|
10
|
+
export type LLMProviderType = (typeof LLM_PROVIDERS)[keyof typeof LLM_PROVIDERS]
|
|
11
|
+
|
|
12
|
+
export const LLM_PROVIDER: LLMProviderType =
|
|
13
|
+
(process.env.LLM_PROVIDER as LLMProviderType) || LLM_PROVIDERS.AZURE
|
|
14
|
+
export const LLM_API_KEY = process.env.LLM_API_KEY // pragma: allowlist secret
|
|
15
|
+
export const LLM_API_URL = process.env.LLM_API_URL
|
|
16
|
+
export const LLM_AZURE_API_VERSION =
|
|
17
|
+
process.env.LLM_AZURE_API_VERSION || '2025-01-01-preview'
|
|
18
|
+
export const LLM_OPENAI_MODEL = process.env.LLM_OPENAI_MODEL || 'gpt-4.1-mini'
|
|
9
19
|
|
|
10
20
|
export const isProd = process.env.NODE_ENV === 'production'
|
|
11
21
|
|
|
@@ -13,14 +23,3 @@ export const MAX_MEMORY_LENGTH = 25
|
|
|
13
23
|
|
|
14
24
|
export const DEFAULT_TIMEOUT_16_SECONDS = 16000
|
|
15
25
|
export const DEFAULT_MAX_RETRIES = 2
|
|
16
|
-
|
|
17
|
-
export const LLM_PROVIDERS = {
|
|
18
|
-
LITELLM: 'litellm',
|
|
19
|
-
AZURE: 'azure',
|
|
20
|
-
} as const
|
|
21
|
-
|
|
22
|
-
export const LITELLM_TAG_KEYS = {
|
|
23
|
-
BOT_ID: 'bot_id',
|
|
24
|
-
ORG_ID: 'org_id',
|
|
25
|
-
SEPARATOR: ',',
|
|
26
|
-
} as const
|
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,32 @@ 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
|
-
return this.
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
private buildLiteLLMTags(): { 'x-litellm-tags': string } | undefined {
|
|
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
|
|
68
|
+
return this.getAzureOpenAiClient()
|
|
89
69
|
}
|
|
90
70
|
|
|
91
|
-
private
|
|
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
|
-
private
|
|
80
|
+
private getAzureOpenAiClient(): AzureOpenAI {
|
|
81
|
+
const baseURL = `${this.botContext.settings.AZURE_OPENAI_API_BASE || LLM_API_URL}openai/`
|
|
82
|
+
|
|
103
83
|
return new AzureOpenAI({
|
|
104
|
-
apiKey:
|
|
105
|
-
this.botContext.secrets.AZURE_OPENAI_API_KEY || AZURE_OPENAI_API_KEY,
|
|
84
|
+
apiKey: this.botContext.secrets.AZURE_OPENAI_API_KEY || LLM_API_KEY,
|
|
106
85
|
apiVersion:
|
|
107
86
|
this.botContext.settings.AZURE_OPENAI_API_VERSION ||
|
|
108
|
-
|
|
87
|
+
LLM_AZURE_API_VERSION,
|
|
109
88
|
deployment: this.modelName,
|
|
110
|
-
baseURL
|
|
111
|
-
this.botContext.settings.AZURE_OPENAI_API_BASE || AZURE_OPENAI_API_BASE,
|
|
89
|
+
baseURL,
|
|
112
90
|
timeout: this.timeout,
|
|
113
91
|
maxRetries: this.maxRetries,
|
|
114
92
|
dangerouslyAllowBrowser: !isProd,
|
|
@@ -119,6 +97,14 @@ export class LLMConfig {
|
|
|
119
97
|
model: string,
|
|
120
98
|
verbosity: VerbosityLevel
|
|
121
99
|
): ModelSettings {
|
|
100
|
+
if (model.includes('gpt-5')) {
|
|
101
|
+
return {
|
|
102
|
+
reasoning: { effort: 'none' },
|
|
103
|
+
temperature: 1,
|
|
104
|
+
text: { verbosity },
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
122
108
|
if (model.includes('gpt-4')) {
|
|
123
109
|
return {
|
|
124
110
|
temperature: 0,
|
|
@@ -126,10 +112,15 @@ export class LLMConfig {
|
|
|
126
112
|
}
|
|
127
113
|
}
|
|
128
114
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
115
|
+
throw new Error(`Unsupported model: ${model}`)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
getApiVersion(): string {
|
|
119
|
+
if (LLM_PROVIDER !== LLM_PROVIDERS.AZURE) {
|
|
120
|
+
return 'NOT_API_VERSION_FOR_OPENAI_PROVIDER'
|
|
133
121
|
}
|
|
122
|
+
return (
|
|
123
|
+
this.botContext.settings.AZURE_OPENAI_API_VERSION || LLM_AZURE_API_VERSION
|
|
124
|
+
)
|
|
134
125
|
}
|
|
135
126
|
}
|
|
@@ -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