@botonic/plugin-ai-agents 0.43.0-alpha.0 → 0.43.0-beta.0
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/agent-builder.d.ts +2 -13
- package/lib/cjs/agent-builder.js +10 -34
- package/lib/cjs/agent-builder.js.map +1 -1
- package/lib/cjs/constants.d.ts +0 -3
- package/lib/cjs/constants.js +1 -6
- package/lib/cjs/constants.js.map +1 -1
- package/lib/cjs/guardrails/input.js.map +1 -1
- package/lib/cjs/hubtype-api-client.d.ts +13 -0
- package/lib/cjs/hubtype-api-client.js +103 -0
- package/lib/cjs/hubtype-api-client.js.map +1 -1
- package/lib/cjs/index.d.ts +2 -0
- package/lib/cjs/index.js +23 -14
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/openai.js +3 -18
- package/lib/cjs/openai.js.map +1 -1
- package/lib/cjs/runner.js +2 -5
- package/lib/cjs/runner.js.map +1 -1
- package/lib/cjs/tools/retrieve-knowledge.d.ts +1 -8
- package/lib/cjs/tools/retrieve-knowledge.js +1 -2
- package/lib/cjs/tools/retrieve-knowledge.js.map +1 -1
- package/lib/cjs/types.d.ts +13 -2
- package/lib/esm/agent-builder.d.ts +2 -13
- package/lib/esm/agent-builder.js +11 -35
- package/lib/esm/agent-builder.js.map +1 -1
- package/lib/esm/constants.d.ts +0 -3
- package/lib/esm/constants.js +0 -5
- package/lib/esm/constants.js.map +1 -1
- package/lib/esm/guardrails/input.js.map +1 -1
- package/lib/esm/hubtype-api-client.d.ts +13 -0
- package/lib/esm/hubtype-api-client.js +103 -0
- package/lib/esm/hubtype-api-client.js.map +1 -1
- package/lib/esm/index.d.ts +2 -0
- package/lib/esm/index.js +23 -14
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/openai.js +4 -18
- package/lib/esm/openai.js.map +1 -1
- package/lib/esm/runner.js +2 -5
- package/lib/esm/runner.js.map +1 -1
- package/lib/esm/tools/retrieve-knowledge.d.ts +1 -8
- package/lib/esm/tools/retrieve-knowledge.js +1 -2
- package/lib/esm/tools/retrieve-knowledge.js.map +1 -1
- package/lib/esm/types.d.ts +13 -2
- package/package.json +3 -3
- package/src/agent-builder.ts +22 -64
- package/src/constants.ts +0 -7
- package/src/guardrails/input.ts +1 -1
- package/src/hubtype-api-client.ts +169 -0
- package/src/index.ts +38 -13
- package/src/openai.ts +3 -19
- package/src/runner.ts +6 -15
- package/src/tools/retrieve-knowledge.ts +2 -3
- package/src/types.ts +14 -2
package/src/agent-builder.ts
CHANGED
|
@@ -1,29 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
Agent,
|
|
4
|
-
AgentOutputType,
|
|
5
|
-
InputGuardrail,
|
|
6
|
-
ModelSettings,
|
|
7
|
-
} from '@openai/agents'
|
|
1
|
+
import { ResolvedPlugins } from '@botonic/core'
|
|
2
|
+
import { Agent, InputGuardrail, ModelSettings } from '@openai/agents'
|
|
8
3
|
|
|
9
|
-
import { OPENAI_MODEL, OPENAI_PROVIDER } from './constants'
|
|
10
4
|
import { createInputGuardrail } from './guardrails'
|
|
11
5
|
import { OutputSchema } from './structured-output'
|
|
12
6
|
import { mandatoryTools, retrieveKnowledge } from './tools'
|
|
13
|
-
import { AIAgent, ContactInfo,
|
|
14
|
-
|
|
15
|
-
interface AIAgentBuilderOptions<
|
|
16
|
-
TPlugins extends ResolvedPlugins = ResolvedPlugins,
|
|
17
|
-
TExtraData = any,
|
|
18
|
-
> {
|
|
19
|
-
name: string
|
|
20
|
-
instructions: string
|
|
21
|
-
tools: Tool<TPlugins, TExtraData>[]
|
|
22
|
-
campaignContext?: CampaignV2
|
|
23
|
-
contactInfo: ContactInfo
|
|
24
|
-
inputGuardrailRules: GuardrailRule[]
|
|
25
|
-
sourceIds: string[]
|
|
26
|
-
}
|
|
7
|
+
import { AIAgent, ContactInfo, GuardrailRule, Tool } from './types'
|
|
27
8
|
|
|
28
9
|
export class AIAgentBuilder<
|
|
29
10
|
TPlugins extends ResolvedPlugins = ResolvedPlugins,
|
|
@@ -34,47 +15,33 @@ export class AIAgentBuilder<
|
|
|
34
15
|
private tools: Tool<TPlugins, TExtraData>[]
|
|
35
16
|
private inputGuardrails: InputGuardrail[]
|
|
36
17
|
|
|
37
|
-
constructor(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
18
|
+
constructor(
|
|
19
|
+
name: string,
|
|
20
|
+
instructions: string,
|
|
21
|
+
tools: Tool<TPlugins, TExtraData>[],
|
|
22
|
+
contactInfo: ContactInfo,
|
|
23
|
+
inputGuardrailRules: GuardrailRule[],
|
|
24
|
+
sourceIds: string[]
|
|
25
|
+
) {
|
|
26
|
+
this.name = name
|
|
27
|
+
this.instructions = this.addExtraInstructions(instructions, contactInfo)
|
|
28
|
+
this.tools = this.addHubtypeTools(tools, sourceIds)
|
|
45
29
|
this.inputGuardrails = []
|
|
46
|
-
if (
|
|
47
|
-
const inputGuardrail = createInputGuardrail(
|
|
30
|
+
if (inputGuardrailRules.length > 0) {
|
|
31
|
+
const inputGuardrail = createInputGuardrail(inputGuardrailRules)
|
|
48
32
|
this.inputGuardrails.push(inputGuardrail)
|
|
49
33
|
}
|
|
50
34
|
}
|
|
51
35
|
|
|
52
36
|
build(): AIAgent<TPlugins, TExtraData> {
|
|
53
|
-
const modelSettings: ModelSettings = {}
|
|
54
|
-
if (OPENAI_PROVIDER === 'openai') {
|
|
55
|
-
// @ts-expect-error - reasoning.effort is valid but we need to update openai and typescript dependencies
|
|
56
|
-
modelSettings.reasoning = { effort: 'none' }
|
|
57
|
-
modelSettings.text = { verbosity: 'medium' }
|
|
58
|
-
}
|
|
37
|
+
const modelSettings: ModelSettings = {}
|
|
59
38
|
|
|
60
|
-
if (this.tools.includes(retrieveKnowledge)
|
|
39
|
+
if (this.tools.includes(retrieveKnowledge)) {
|
|
61
40
|
modelSettings.toolChoice = retrieveKnowledge.name
|
|
62
41
|
}
|
|
63
42
|
|
|
64
|
-
|
|
65
|
-
// Azure OpenAI uses deployment name instead
|
|
66
|
-
const model = OPENAI_PROVIDER === 'openai' ? OPENAI_MODEL : undefined
|
|
67
|
-
|
|
68
|
-
// TODO: Improve type safety - replace AgentOutputType<any> with AgentOutputType<typeof OutputSchema>
|
|
69
|
-
// Currently using explicit type parameters to avoid type inference issues where Agent constructor
|
|
70
|
-
// infers ZodObject instead of AgentOutputType<typeof OutputSchema>. The explicit type parameters
|
|
71
|
-
// ensure compatibility with AIAgent type definition. Future improvements:
|
|
72
|
-
// 1. Update @openai/agents package to properly infer AgentOutputType from outputType parameter
|
|
73
|
-
// 2. Replace AgentOutputType<any> with AgentOutputType<typeof OutputSchema> once type system allows
|
|
74
|
-
// 3. Consider updating AIAgent type definition if @openai/agents types change significantly
|
|
75
|
-
return new Agent<Context<TPlugins, TExtraData>, AgentOutputType<any>>({
|
|
43
|
+
return new Agent({
|
|
76
44
|
name: this.name,
|
|
77
|
-
model,
|
|
78
45
|
instructions: this.instructions,
|
|
79
46
|
tools: this.tools,
|
|
80
47
|
outputType: OutputSchema,
|
|
@@ -86,15 +53,13 @@ export class AIAgentBuilder<
|
|
|
86
53
|
|
|
87
54
|
private addExtraInstructions(
|
|
88
55
|
initialInstructions: string,
|
|
89
|
-
contactInfo: ContactInfo
|
|
90
|
-
campaignContext?: CampaignV2
|
|
56
|
+
contactInfo: ContactInfo
|
|
91
57
|
): string {
|
|
92
|
-
const instructions = `<instructions>\n${initialInstructions
|
|
58
|
+
const instructions = `<instructions>\n${initialInstructions}\n</instructions>`
|
|
93
59
|
const metadataInstructions = this.getMetadataInstructions()
|
|
94
60
|
const contactInfoInstructions = this.getContactInfoInstructions(contactInfo)
|
|
95
|
-
const campaignInstructions = this.getCampaignInstructions(campaignContext)
|
|
96
61
|
const outputInstructions = this.getOutputInstructions()
|
|
97
|
-
return `${instructions}\n\n${metadataInstructions}\n\n${contactInfoInstructions}\n\n${
|
|
62
|
+
return `${instructions}\n\n${metadataInstructions}\n\n${contactInfoInstructions}\n\n${outputInstructions}`
|
|
98
63
|
}
|
|
99
64
|
|
|
100
65
|
private getContactInfoInstructions(contactInfo: ContactInfo): string {
|
|
@@ -109,13 +74,6 @@ export class AIAgentBuilder<
|
|
|
109
74
|
return `<metadata>\n${metadata}\n</metadata>`
|
|
110
75
|
}
|
|
111
76
|
|
|
112
|
-
private getCampaignInstructions(campaignContext?: CampaignV2): string {
|
|
113
|
-
if (!campaignContext || !campaignContext.agent_context) {
|
|
114
|
-
return ''
|
|
115
|
-
}
|
|
116
|
-
return `<campaign_context>\n${campaignContext.agent_context}\n</campaign_context>`
|
|
117
|
-
}
|
|
118
|
-
|
|
119
77
|
private getOutputInstructions(): string {
|
|
120
78
|
const example = {
|
|
121
79
|
messages: [
|
package/src/constants.ts
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
export const HUBTYPE_API_URL =
|
|
2
2
|
process.env.HUBTYPE_API_URL || 'https://api.hubtype.com'
|
|
3
3
|
|
|
4
|
-
// OpenAI Provider Configuration
|
|
5
|
-
export const OPENAI_API_KEY = process.env.OPENAI_API_KEY // pragma: allowlist secret
|
|
6
|
-
export const OPENAI_MODEL = process.env.OPENAI_MODEL || 'gpt-4.1-mini'
|
|
7
|
-
export const OPENAI_PROVIDER: 'openai' | 'azure' =
|
|
8
|
-
(process.env.OPENAI_PROVIDER as 'openai' | 'azure') || 'azure'
|
|
9
|
-
|
|
10
|
-
// Azure OpenAI Configuration
|
|
11
4
|
export const AZURE_OPENAI_API_KEY = process.env.AZURE_OPENAI_API_KEY // pragma: allowlist secret
|
|
12
5
|
export const AZURE_OPENAI_API_BASE = process.env.AZURE_OPENAI_API_BASE
|
|
13
6
|
export const AZURE_OPENAI_API_DEPLOYMENT_NAME =
|
package/src/guardrails/input.ts
CHANGED
|
@@ -22,7 +22,7 @@ export function createInputGuardrail(rules: GuardrailRule[]): InputGuardrail {
|
|
|
22
22
|
execute: async ({ input, context }) => {
|
|
23
23
|
const lastMessage = input[input.length - 1] as UserMessageItem
|
|
24
24
|
const result = await run(agent, [lastMessage], { context })
|
|
25
|
-
const finalOutput = result.finalOutput
|
|
25
|
+
const finalOutput = result.finalOutput
|
|
26
26
|
if (finalOutput === undefined) {
|
|
27
27
|
throw new Error('Guardrail agent failed to produce output')
|
|
28
28
|
}
|
|
@@ -17,6 +17,63 @@ interface HubtypeUserMessage {
|
|
|
17
17
|
|
|
18
18
|
type HubtypeMessage = HubtypeAssistantMessage | HubtypeUserMessage
|
|
19
19
|
|
|
20
|
+
// V2 API Types
|
|
21
|
+
interface HubtypeToolCall {
|
|
22
|
+
id: string
|
|
23
|
+
type: 'function'
|
|
24
|
+
function: {
|
|
25
|
+
name: string
|
|
26
|
+
arguments: string
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface HubtypeUserMessageV2 {
|
|
31
|
+
role: 'user'
|
|
32
|
+
content: string | null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface HubtypeAssistantMessageV2 {
|
|
36
|
+
role: 'assistant'
|
|
37
|
+
content: string | null
|
|
38
|
+
tool_calls?: HubtypeToolCall[] | null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface HubtypeToolMessageV2 {
|
|
42
|
+
role: 'tool'
|
|
43
|
+
content: string | null
|
|
44
|
+
tool_call_id: string
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface HubtypeSystemMessageV2 {
|
|
48
|
+
role: 'system'
|
|
49
|
+
content: string | null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type HubtypeMessageV2 =
|
|
53
|
+
| HubtypeUserMessageV2
|
|
54
|
+
| HubtypeAssistantMessageV2
|
|
55
|
+
| HubtypeToolMessageV2
|
|
56
|
+
| HubtypeSystemMessageV2
|
|
57
|
+
|
|
58
|
+
interface MessageHistoryResponseV2 {
|
|
59
|
+
messages: HubtypeMessageV2[]
|
|
60
|
+
conversation_id: string | null
|
|
61
|
+
truncated: boolean
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface GetMessagesV2Options {
|
|
65
|
+
maxMessages?: number
|
|
66
|
+
includeToolCalls?: boolean
|
|
67
|
+
maxFullToolResults?: number
|
|
68
|
+
debugMode?: boolean
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface GetMessagesV2Result {
|
|
72
|
+
messages: AgenticInputMessage[]
|
|
73
|
+
conversationId: string | null
|
|
74
|
+
truncated: boolean
|
|
75
|
+
}
|
|
76
|
+
|
|
20
77
|
export class HubtypeApiClient {
|
|
21
78
|
private readonly authToken: string
|
|
22
79
|
|
|
@@ -92,6 +149,118 @@ export class HubtypeApiClient {
|
|
|
92
149
|
}
|
|
93
150
|
}
|
|
94
151
|
|
|
152
|
+
async getMessagesV2(
|
|
153
|
+
request: BotContext,
|
|
154
|
+
options: GetMessagesV2Options = {}
|
|
155
|
+
): Promise<GetMessagesV2Result> {
|
|
156
|
+
const url = `${HUBTYPE_API_URL}/external/v2/ai/agent/message_history/`
|
|
157
|
+
const headers = {
|
|
158
|
+
'Content-Type': 'application/json',
|
|
159
|
+
Authorization: `Bearer ${this.authToken}`,
|
|
160
|
+
}
|
|
161
|
+
const params: Record<string, string | number | boolean> = {
|
|
162
|
+
last_message_id: request.input.message_id,
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (options.maxMessages !== undefined) {
|
|
166
|
+
params.max_messages = options.maxMessages
|
|
167
|
+
}
|
|
168
|
+
if (options.includeToolCalls !== undefined) {
|
|
169
|
+
params.include_tool_calls = options.includeToolCalls
|
|
170
|
+
}
|
|
171
|
+
if (options.maxFullToolResults !== undefined) {
|
|
172
|
+
params.max_full_tool_results = options.maxFullToolResults
|
|
173
|
+
}
|
|
174
|
+
if (options.debugMode !== undefined) {
|
|
175
|
+
params.debug_mode = options.debugMode
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
const response = await axios.get<MessageHistoryResponseV2>(url, {
|
|
180
|
+
headers,
|
|
181
|
+
params,
|
|
182
|
+
})
|
|
183
|
+
const { messages, conversation_id, truncated } = response.data
|
|
184
|
+
const formattedMessages = messages
|
|
185
|
+
.map(message => this.formatMessageV2(message))
|
|
186
|
+
.filter((message): message is AgenticInputMessage => message !== null)
|
|
187
|
+
return {
|
|
188
|
+
messages: formattedMessages,
|
|
189
|
+
conversationId: conversation_id,
|
|
190
|
+
truncated,
|
|
191
|
+
}
|
|
192
|
+
} catch (error) {
|
|
193
|
+
console.error(error)
|
|
194
|
+
throw new Error('Failed to get messages from Hubtype V2 API')
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private formatMessageV2(
|
|
199
|
+
message: HubtypeMessageV2
|
|
200
|
+
): AgenticInputMessage | null {
|
|
201
|
+
switch (message.role) {
|
|
202
|
+
case 'user':
|
|
203
|
+
return {
|
|
204
|
+
role: 'user',
|
|
205
|
+
content: message.content ?? '',
|
|
206
|
+
}
|
|
207
|
+
case 'assistant': {
|
|
208
|
+
const assistantMessage = message as HubtypeAssistantMessageV2
|
|
209
|
+
// If assistant message has tool_calls, include them for context
|
|
210
|
+
// Using double assertion as the OpenAI API supports this format,
|
|
211
|
+
// but the agents SDK types are more restrictive
|
|
212
|
+
if (
|
|
213
|
+
assistantMessage.tool_calls &&
|
|
214
|
+
assistantMessage.tool_calls.length > 0
|
|
215
|
+
) {
|
|
216
|
+
return {
|
|
217
|
+
role: 'assistant',
|
|
218
|
+
content: assistantMessage.content ?? '',
|
|
219
|
+
tool_calls: assistantMessage.tool_calls.map(tc => ({
|
|
220
|
+
id: tc.id,
|
|
221
|
+
type: tc.type,
|
|
222
|
+
function: {
|
|
223
|
+
name: tc.function.name,
|
|
224
|
+
arguments: tc.function.arguments,
|
|
225
|
+
},
|
|
226
|
+
})),
|
|
227
|
+
} as unknown as AgenticInputMessage
|
|
228
|
+
}
|
|
229
|
+
// Regular assistant message without tool_calls
|
|
230
|
+
return {
|
|
231
|
+
role: 'assistant',
|
|
232
|
+
content: [
|
|
233
|
+
{
|
|
234
|
+
type: 'output_text',
|
|
235
|
+
text: assistantMessage.content ?? '',
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
status: 'completed',
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
case 'tool': {
|
|
242
|
+
// Tool messages provide context about previous tool executions
|
|
243
|
+
// Using double assertion as the OpenAI API supports this format,
|
|
244
|
+
// but the agents SDK types are more restrictive
|
|
245
|
+
const toolMessage = message as HubtypeToolMessageV2
|
|
246
|
+
return {
|
|
247
|
+
role: 'tool',
|
|
248
|
+
tool_call_id: toolMessage.tool_call_id,
|
|
249
|
+
content: toolMessage.content ?? '',
|
|
250
|
+
} as unknown as AgenticInputMessage
|
|
251
|
+
}
|
|
252
|
+
case 'system':
|
|
253
|
+
return {
|
|
254
|
+
role: 'system',
|
|
255
|
+
content: message.content ?? '',
|
|
256
|
+
}
|
|
257
|
+
default:
|
|
258
|
+
throw new Error(
|
|
259
|
+
`Invalid message role: ${(message as HubtypeMessageV2).role}`
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
95
264
|
private formatMessage(message: HubtypeMessage): AgenticInputMessage {
|
|
96
265
|
if (message.role === 'user') {
|
|
97
266
|
return {
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
Context,
|
|
12
12
|
CustomTool,
|
|
13
13
|
InferenceResponse,
|
|
14
|
+
MemoryOptions,
|
|
15
|
+
MessageHistoryApiVersion,
|
|
14
16
|
PluginAiAgentOptions,
|
|
15
17
|
Tool,
|
|
16
18
|
} from './types'
|
|
@@ -21,12 +23,24 @@ export default class BotonicPluginAiAgents<
|
|
|
21
23
|
> implements Plugin
|
|
22
24
|
{
|
|
23
25
|
private readonly authToken?: string
|
|
26
|
+
private readonly messageHistoryApiVersion: MessageHistoryApiVersion
|
|
27
|
+
private readonly memory: MemoryOptions
|
|
24
28
|
public toolDefinitions: CustomTool<TPlugins, TExtraData>[] = []
|
|
25
29
|
|
|
26
30
|
constructor(options?: PluginAiAgentOptions<TPlugins, TExtraData>) {
|
|
27
31
|
setUpOpenAI(options?.maxRetries, options?.timeout)
|
|
32
|
+
|
|
33
|
+
if (options?.messageHistoryApiVersion === 'v1' && options?.memory) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
'Cannot use memory when messageHistoryApiVersion is "v1". ' +
|
|
36
|
+
'Either set messageHistoryApiVersion to "v2" or remove memory.'
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
28
40
|
this.authToken = options?.authToken
|
|
29
41
|
this.toolDefinitions = options?.customTools || []
|
|
42
|
+
this.messageHistoryApiVersion = options?.messageHistoryApiVersion ?? 'v2'
|
|
43
|
+
this.memory = options?.memory ?? {}
|
|
30
44
|
}
|
|
31
45
|
|
|
32
46
|
pre(): void {
|
|
@@ -46,15 +60,14 @@ export default class BotonicPluginAiAgents<
|
|
|
46
60
|
const tools = this.buildTools(
|
|
47
61
|
aiAgentArgs.activeTools?.map(tool => tool.name) || []
|
|
48
62
|
)
|
|
49
|
-
const agent = new AIAgentBuilder<TPlugins, TExtraData>(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
tools
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}).build()
|
|
63
|
+
const agent = new AIAgentBuilder<TPlugins, TExtraData>(
|
|
64
|
+
aiAgentArgs.name,
|
|
65
|
+
aiAgentArgs.instructions,
|
|
66
|
+
tools,
|
|
67
|
+
request.session.user.contact_info || {},
|
|
68
|
+
aiAgentArgs.inputGuardrailRules || [],
|
|
69
|
+
aiAgentArgs.sourceIds || []
|
|
70
|
+
).build()
|
|
58
71
|
|
|
59
72
|
const messages = await this.getMessages(
|
|
60
73
|
request,
|
|
@@ -94,12 +107,24 @@ export default class BotonicPluginAiAgents<
|
|
|
94
107
|
authToken: string,
|
|
95
108
|
memoryLength: number
|
|
96
109
|
): Promise<AgenticInputMessage[]> {
|
|
97
|
-
|
|
98
|
-
|
|
110
|
+
const hubtypeClient = new HubtypeApiClient(authToken)
|
|
111
|
+
|
|
112
|
+
if (!isProd) {
|
|
113
|
+
return await hubtypeClient.getLocalMessages(memoryLength)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (this.messageHistoryApiVersion === 'v1') {
|
|
99
117
|
return await hubtypeClient.getMessages(request, memoryLength)
|
|
100
118
|
}
|
|
101
|
-
|
|
102
|
-
|
|
119
|
+
|
|
120
|
+
// Default to V2
|
|
121
|
+
const result = await hubtypeClient.getMessagesV2(request, {
|
|
122
|
+
maxMessages: this.memory.maxMessages ?? memoryLength,
|
|
123
|
+
includeToolCalls: this.memory.includeToolCalls ?? true,
|
|
124
|
+
maxFullToolResults: this.memory.maxFullToolResults ?? 1,
|
|
125
|
+
debugMode: this.memory.debugMode ?? false,
|
|
126
|
+
})
|
|
127
|
+
return result.messages
|
|
103
128
|
}
|
|
104
129
|
|
|
105
130
|
private buildTools(activeToolNames: string[]): Tool<TPlugins, TExtraData>[] {
|
package/src/openai.ts
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
setOpenAIAPI,
|
|
4
4
|
setTracingDisabled,
|
|
5
5
|
} from '@openai/agents'
|
|
6
|
-
import
|
|
6
|
+
import { AzureOpenAI } from 'openai'
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
AZURE_OPENAI_API_BASE,
|
|
@@ -11,37 +11,21 @@ import {
|
|
|
11
11
|
AZURE_OPENAI_API_KEY,
|
|
12
12
|
AZURE_OPENAI_API_VERSION,
|
|
13
13
|
isProd,
|
|
14
|
-
OPENAI_API_KEY,
|
|
15
|
-
OPENAI_PROVIDER,
|
|
16
14
|
} from './constants'
|
|
17
15
|
|
|
18
16
|
export function setUpOpenAI(maxRetries?: number, timeout?: number) {
|
|
19
|
-
|
|
20
|
-
setAzureOpenAIClient(maxRetries, timeout)
|
|
21
|
-
} else {
|
|
22
|
-
setOpenAIClient(maxRetries, timeout)
|
|
23
|
-
}
|
|
17
|
+
setAzureOpenAIClient(maxRetries, timeout)
|
|
24
18
|
setOpenAIAPI('chat_completions')
|
|
25
19
|
setTracingDisabled(true)
|
|
26
20
|
}
|
|
27
21
|
|
|
28
|
-
function setOpenAIClient(maxRetries?: number, timeout?: number) {
|
|
29
|
-
const client = new OpenAI({
|
|
30
|
-
apiKey: OPENAI_API_KEY,
|
|
31
|
-
timeout: timeout || 16000, // 16 seconds
|
|
32
|
-
maxRetries: maxRetries || 2,
|
|
33
|
-
dangerouslyAllowBrowser: !isProd,
|
|
34
|
-
})
|
|
35
|
-
setDefaultOpenAIClient(client)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
22
|
function setAzureOpenAIClient(maxRetries?: number, timeout?: number) {
|
|
39
23
|
const client = new AzureOpenAI({
|
|
40
24
|
apiKey: AZURE_OPENAI_API_KEY,
|
|
41
25
|
apiVersion: AZURE_OPENAI_API_VERSION,
|
|
42
26
|
deployment: AZURE_OPENAI_API_DEPLOYMENT_NAME,
|
|
43
27
|
baseURL: AZURE_OPENAI_API_BASE,
|
|
44
|
-
timeout: timeout ||
|
|
28
|
+
timeout: timeout || 8000, // 8 seconds
|
|
45
29
|
maxRetries: maxRetries || 2,
|
|
46
30
|
dangerouslyAllowBrowser: !isProd,
|
|
47
31
|
})
|
package/src/runner.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ResolvedPlugins, ToolExecution } from '@botonic/core'
|
|
2
2
|
import {
|
|
3
3
|
InputGuardrailTripwireTriggered,
|
|
4
4
|
Runner,
|
|
@@ -14,15 +14,6 @@ import {
|
|
|
14
14
|
RunResult,
|
|
15
15
|
} from './types'
|
|
16
16
|
|
|
17
|
-
// Minimal interface matching the properties we actually use from Runner.run() result
|
|
18
|
-
// This bypasses strict type checking while maintaining type safety for accessed properties
|
|
19
|
-
interface AIAgentRunnerResult {
|
|
20
|
-
finalOutput?: {
|
|
21
|
-
messages?: OutputMessage[]
|
|
22
|
-
}
|
|
23
|
-
newItems?: RunToolCallItem[]
|
|
24
|
-
}
|
|
25
|
-
|
|
26
17
|
export class AIAgentRunner<
|
|
27
18
|
TPlugins extends ResolvedPlugins = ResolvedPlugins,
|
|
28
19
|
TExtraData = any,
|
|
@@ -37,15 +28,15 @@ export class AIAgentRunner<
|
|
|
37
28
|
messages: AgenticInputMessage[],
|
|
38
29
|
context: Context<TPlugins, TExtraData>
|
|
39
30
|
): Promise<RunResult> {
|
|
31
|
+
console.log(
|
|
32
|
+
'Running agent with messages',
|
|
33
|
+
JSON.stringify(messages, null, 2)
|
|
34
|
+
)
|
|
40
35
|
try {
|
|
41
36
|
const runner = new Runner({
|
|
42
37
|
modelSettings: { temperature: 0 },
|
|
43
38
|
})
|
|
44
|
-
|
|
45
|
-
// doesn't perfectly match our interface, but the properties we access are compatible
|
|
46
|
-
const result = (await runner.run(this.agent, messages, {
|
|
47
|
-
context,
|
|
48
|
-
})) as AIAgentRunnerResult
|
|
39
|
+
const result = await runner.run(this.agent, messages, { context })
|
|
49
40
|
|
|
50
41
|
const outputMessages = result.finalOutput?.messages || []
|
|
51
42
|
const hasExit =
|
|
@@ -4,7 +4,7 @@ import { z } from 'zod'
|
|
|
4
4
|
import { HubtypeApiClient } from '../hubtype-api-client'
|
|
5
5
|
import { Context } from '../types'
|
|
6
6
|
|
|
7
|
-
export const retrieveKnowledge = tool({
|
|
7
|
+
export const retrieveKnowledge = tool<any, Context, any>({
|
|
8
8
|
name: 'retrieve_knowledge',
|
|
9
9
|
description:
|
|
10
10
|
'Consult the knowledge base for information before answering. Use this tool to make sure the information you provide is faithful.',
|
|
@@ -12,11 +12,10 @@ export const retrieveKnowledge = tool({
|
|
|
12
12
|
query: z.string().describe('The query to search the knowledge base for'),
|
|
13
13
|
}),
|
|
14
14
|
execute: async (
|
|
15
|
-
|
|
15
|
+
{ query }: { query: string },
|
|
16
16
|
runContext?: RunContext<Context>
|
|
17
17
|
): Promise<string[]> => {
|
|
18
18
|
const context = runContext?.context
|
|
19
|
-
const query = input.query
|
|
20
19
|
if (!context) {
|
|
21
20
|
throw new Error('Context is required')
|
|
22
21
|
}
|
package/src/types.ts
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
Agent,
|
|
12
12
|
AgentInputItem,
|
|
13
|
-
AgentOutputType,
|
|
14
13
|
RunContext as OpenAIRunContext,
|
|
15
14
|
Tool as OpenAITool,
|
|
16
15
|
} from '@openai/agents'
|
|
@@ -65,7 +64,16 @@ export type Tool<
|
|
|
65
64
|
export type AIAgent<
|
|
66
65
|
TPlugins extends ResolvedPlugins = ResolvedPlugins,
|
|
67
66
|
TExtraData = any,
|
|
68
|
-
> = Agent<Context<TPlugins, TExtraData>,
|
|
67
|
+
> = Agent<Context<TPlugins, TExtraData>, typeof OutputSchema>
|
|
68
|
+
export type MessageHistoryApiVersion = 'v1' | 'v2'
|
|
69
|
+
|
|
70
|
+
export interface MemoryOptions {
|
|
71
|
+
maxMessages?: number
|
|
72
|
+
includeToolCalls?: boolean
|
|
73
|
+
maxFullToolResults?: number
|
|
74
|
+
debugMode?: boolean
|
|
75
|
+
}
|
|
76
|
+
|
|
69
77
|
export interface PluginAiAgentOptions<
|
|
70
78
|
TPlugins extends ResolvedPlugins = ResolvedPlugins,
|
|
71
79
|
TExtraData = any,
|
|
@@ -74,6 +82,10 @@ export interface PluginAiAgentOptions<
|
|
|
74
82
|
customTools?: CustomTool<TPlugins, TExtraData>[]
|
|
75
83
|
maxRetries?: number
|
|
76
84
|
timeout?: number
|
|
85
|
+
/** API version for message history endpoint. Defaults to 'v2'. */
|
|
86
|
+
messageHistoryApiVersion?: MessageHistoryApiVersion
|
|
87
|
+
/** Options for V2 message history API. Only used when messageHistoryApiVersion is 'v2'. */
|
|
88
|
+
memory?: MemoryOptions
|
|
77
89
|
}
|
|
78
90
|
|
|
79
91
|
export type AgenticInputMessage = AgentInputItem
|