@botonic/plugin-ai-agents 0.36.0-alpha.1 → 0.36.0-alpha.10
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/README.md +14 -0
- package/lib/cjs/agent-builder.d.ts +10 -0
- package/lib/cjs/agent-builder.js +43 -0
- package/lib/cjs/agent-builder.js.map +1 -0
- package/lib/cjs/constants.d.ts +3 -2
- package/lib/cjs/constants.js +5 -4
- package/lib/cjs/constants.js.map +1 -1
- package/lib/{esm/hubtype-client.d.ts → cjs/hubtype-api-client.d.ts} +3 -1
- package/lib/cjs/hubtype-api-client.js +76 -0
- package/lib/cjs/hubtype-api-client.js.map +1 -0
- package/lib/cjs/index.d.ts +5 -2
- package/lib/cjs/index.js +40 -17
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/openai.d.ts +1 -0
- package/lib/cjs/openai.js +23 -0
- package/lib/cjs/openai.js.map +1 -0
- package/lib/cjs/runner.d.ts +7 -0
- package/lib/cjs/runner.js +35 -0
- package/lib/cjs/runner.js.map +1 -0
- package/lib/cjs/structured-output/carousel.d.ts +100 -0
- package/lib/cjs/structured-output/carousel.js +21 -0
- package/lib/cjs/structured-output/carousel.js.map +1 -0
- package/lib/cjs/structured-output/exit.d.ts +12 -0
- package/lib/cjs/structured-output/exit.js +11 -0
- package/lib/cjs/structured-output/exit.js.map +1 -0
- package/lib/cjs/structured-output/index.d.ts +198 -0
- package/lib/cjs/structured-output/index.js +14 -0
- package/lib/cjs/structured-output/index.js.map +1 -0
- package/lib/cjs/structured-output/shared.d.ts +3 -0
- package/lib/cjs/structured-output/shared.js +3 -0
- package/lib/cjs/structured-output/shared.js.map +1 -0
- package/lib/cjs/structured-output/text-with-buttons.d.ts +34 -0
- package/lib/cjs/structured-output/text-with-buttons.js +15 -0
- package/lib/cjs/structured-output/text-with-buttons.js.map +1 -0
- package/lib/cjs/structured-output/text.d.ts +28 -0
- package/lib/cjs/structured-output/text.js +13 -0
- package/lib/cjs/structured-output/text.js.map +1 -0
- package/lib/cjs/tools/index.d.ts +2 -0
- package/lib/cjs/tools/index.js +5 -0
- package/lib/cjs/tools/index.js.map +1 -0
- package/lib/cjs/types.d.ts +20 -22
- package/lib/esm/agent-builder.d.ts +10 -0
- package/lib/esm/agent-builder.js +39 -0
- package/lib/esm/agent-builder.js.map +1 -0
- package/lib/esm/constants.d.ts +3 -2
- package/lib/esm/constants.js +4 -3
- package/lib/esm/constants.js.map +1 -1
- package/lib/{cjs/hubtype-client.d.ts → esm/hubtype-api-client.d.ts} +3 -1
- package/lib/esm/hubtype-api-client.js +72 -0
- package/lib/esm/hubtype-api-client.js.map +1 -0
- package/lib/esm/index.d.ts +5 -2
- package/lib/esm/index.js +39 -16
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/openai.d.ts +1 -0
- package/lib/esm/openai.js +19 -0
- package/lib/esm/openai.js.map +1 -0
- package/lib/esm/runner.d.ts +7 -0
- package/lib/esm/runner.js +31 -0
- package/lib/esm/runner.js.map +1 -0
- package/lib/esm/structured-output/carousel.d.ts +100 -0
- package/lib/esm/structured-output/carousel.js +18 -0
- package/lib/esm/structured-output/carousel.js.map +1 -0
- package/lib/esm/structured-output/exit.d.ts +12 -0
- package/lib/esm/structured-output/exit.js +7 -0
- package/lib/esm/structured-output/exit.js.map +1 -0
- package/lib/esm/structured-output/index.d.ts +198 -0
- package/lib/esm/structured-output/index.js +11 -0
- package/lib/esm/structured-output/index.js.map +1 -0
- package/lib/esm/structured-output/shared.d.ts +3 -0
- package/lib/esm/structured-output/shared.js +2 -0
- package/lib/esm/structured-output/shared.js.map +1 -0
- package/lib/esm/structured-output/text-with-buttons.d.ts +34 -0
- package/lib/esm/structured-output/text-with-buttons.js +11 -0
- package/lib/esm/structured-output/text-with-buttons.js.map +1 -0
- package/lib/esm/structured-output/text.d.ts +28 -0
- package/lib/esm/structured-output/text.js +10 -0
- package/lib/esm/structured-output/text.js.map +1 -0
- package/lib/esm/tools/index.d.ts +2 -0
- package/lib/esm/tools/index.js +2 -0
- package/lib/esm/tools/index.js.map +1 -0
- package/lib/esm/types.d.ts +20 -22
- package/package.json +7 -7
- package/src/agent-builder.ts +48 -0
- package/src/constants.ts +7 -4
- package/src/hubtype-api-client.ts +89 -0
- package/src/index.ts +56 -19
- package/src/openai.ts +30 -0
- package/src/runner.ts +43 -0
- package/src/structured-output/carousel.ts +36 -0
- package/src/structured-output/exit.ts +15 -0
- package/src/structured-output/index.ts +27 -0
- package/src/structured-output/shared.ts +3 -0
- package/src/structured-output/text-with-buttons.ts +23 -0
- package/src/structured-output/text.ts +19 -0
- package/src/tools/index.ts +3 -0
- package/src/types.ts +27 -29
- package/lib/cjs/ai-agent-client.d.ts +0 -11
- package/lib/cjs/ai-agent-client.js +0 -50
- package/lib/cjs/ai-agent-client.js.map +0 -1
- package/lib/cjs/errors.d.ts +0 -3
- package/lib/cjs/errors.js +0 -11
- package/lib/cjs/errors.js.map +0 -1
- package/lib/cjs/hubtype-client.js +0 -36
- package/lib/cjs/hubtype-client.js.map +0 -1
- package/lib/cjs/tools.d.ts +0 -6
- package/lib/cjs/tools.js +0 -41
- package/lib/cjs/tools.js.map +0 -1
- package/lib/cjs/utils.d.ts +0 -2
- package/lib/cjs/utils.js +0 -22
- package/lib/cjs/utils.js.map +0 -1
- package/lib/esm/ai-agent-client.d.ts +0 -11
- package/lib/esm/ai-agent-client.js +0 -46
- package/lib/esm/ai-agent-client.js.map +0 -1
- package/lib/esm/errors.d.ts +0 -3
- package/lib/esm/errors.js +0 -7
- package/lib/esm/errors.js.map +0 -1
- package/lib/esm/hubtype-client.js +0 -32
- package/lib/esm/hubtype-client.js.map +0 -1
- package/lib/esm/tools.d.ts +0 -6
- package/lib/esm/tools.js +0 -38
- package/lib/esm/tools.js.map +0 -1
- package/lib/esm/utils.d.ts +0 -2
- package/lib/esm/utils.js +0 -18
- package/lib/esm/utils.js.map +0 -1
- package/src/ai-agent-client.ts +0 -73
- package/src/errors.ts +0 -6
- package/src/hubtype-client.ts +0 -43
- package/src/tools.ts +0 -51
- package/src/utils.ts +0 -24
package/lib/esm/types.d.ts
CHANGED
|
@@ -1,29 +1,27 @@
|
|
|
1
|
+
import { Agent, AgentInputItem, RunContext, Tool as OpenAITool } from '@openai/agents';
|
|
2
|
+
import { ZodSchema } from 'zod';
|
|
3
|
+
import { OutputMessage, OutputSchema } from './structured-output';
|
|
4
|
+
export interface Context {
|
|
5
|
+
authToken: string;
|
|
6
|
+
}
|
|
7
|
+
export interface CustomTool {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
schema: ZodSchema;
|
|
11
|
+
func: (input?: any, runContext?: RunContext<Context>) => Promise<any>;
|
|
12
|
+
}
|
|
13
|
+
export type Tool = OpenAITool<Context>;
|
|
14
|
+
export type AIAgent = Agent<Context, typeof OutputSchema>;
|
|
1
15
|
export interface PluginAiAgentOptions {
|
|
2
16
|
authToken?: string;
|
|
17
|
+
customTools?: CustomTool[];
|
|
3
18
|
}
|
|
4
19
|
export interface AiAgentArgs {
|
|
5
20
|
name: string;
|
|
6
21
|
instructions: string;
|
|
22
|
+
activeTools?: {
|
|
23
|
+
name: string;
|
|
24
|
+
}[];
|
|
7
25
|
}
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
export interface AssistantMessage extends AgenticBaseMessage {
|
|
12
|
-
role: 'assistant';
|
|
13
|
-
content: string;
|
|
14
|
-
}
|
|
15
|
-
export interface UserMessage extends AgenticBaseMessage {
|
|
16
|
-
role: 'user';
|
|
17
|
-
content: string;
|
|
18
|
-
}
|
|
19
|
-
export interface ToolMessage extends AgenticBaseMessage {
|
|
20
|
-
role: 'tool';
|
|
21
|
-
toolName: string;
|
|
22
|
-
toolOutput: string | null;
|
|
23
|
-
}
|
|
24
|
-
export interface ExitMessage extends AgenticBaseMessage {
|
|
25
|
-
role: 'exit';
|
|
26
|
-
}
|
|
27
|
-
export type AgenticInputMessage = AssistantMessage | UserMessage;
|
|
28
|
-
export type AgenticOutputMessage = AssistantMessage | ToolMessage | ExitMessage;
|
|
29
|
-
export type AgenticMessage = AssistantMessage | UserMessage | ToolMessage | ExitMessage;
|
|
26
|
+
export type AgenticInputMessage = AgentInputItem;
|
|
27
|
+
export type AgenticOutputMessage = OutputMessage;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botonic/plugin-ai-agents",
|
|
3
|
-
"version": "0.36.0-alpha.
|
|
3
|
+
"version": "0.36.0-alpha.10",
|
|
4
4
|
"main": "./lib/cjs/index.js",
|
|
5
5
|
"module": "./lib/esm/index.js",
|
|
6
6
|
"description": "Use AI Agents to generate your contents",
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
"lint_core": "../../node_modules/.bin/eslint_d --cache --quiet 'src/**/*.ts*'"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@botonic/core": "^0.36.0
|
|
17
|
-
"@
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
16
|
+
"@botonic/core": "^0.36.0",
|
|
17
|
+
"@openai/agents": "^0.0.10",
|
|
18
|
+
"axios": "^1.10.0",
|
|
19
|
+
"openai": "^5.8.3",
|
|
20
|
+
"uuid": "^10.0.0",
|
|
21
|
+
"zod": "^3.25.57"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@types/uuid": "^10.0.0"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Agent } from '@openai/agents'
|
|
2
|
+
|
|
3
|
+
import { OutputSchema } from './structured-output'
|
|
4
|
+
import { mandatoryTools } from './tools'
|
|
5
|
+
import { AIAgent, Tool } from './types'
|
|
6
|
+
|
|
7
|
+
export class AIAgentBuilder {
|
|
8
|
+
private name: string
|
|
9
|
+
private instructions: string
|
|
10
|
+
private tools: Tool[]
|
|
11
|
+
|
|
12
|
+
constructor(name: string, instructions: string, tools: Tool[]) {
|
|
13
|
+
this.name = name
|
|
14
|
+
this.instructions = this.addExtraInstructions(instructions)
|
|
15
|
+
this.tools = this.addHubtypeTools(tools)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
build(): AIAgent {
|
|
19
|
+
return new Agent({
|
|
20
|
+
name: this.name,
|
|
21
|
+
instructions: this.instructions,
|
|
22
|
+
tools: this.tools,
|
|
23
|
+
outputType: OutputSchema,
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private addExtraInstructions(instructions: string): string {
|
|
28
|
+
const metadata = `Current Date: ${new Date().toISOString()}`
|
|
29
|
+
const example = {
|
|
30
|
+
messages: [
|
|
31
|
+
{
|
|
32
|
+
type: 'text',
|
|
33
|
+
content: {
|
|
34
|
+
text: 'Hello, how can I help you today?',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
numMessages: 1,
|
|
39
|
+
}
|
|
40
|
+
const output = `Return a JSON that follows the output schema provided. Never return multiple output schemas concatenated by a line break.\n<example>\n${JSON.stringify(example)}\n</example>`
|
|
41
|
+
return `<instructions>\n${instructions}\n</instructions>\n\n<metadata>\n${metadata}\n</metadata>\n\n<output>\n${output}\n</output>`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private addHubtypeTools(tools: Tool[]): Tool[] {
|
|
45
|
+
const hubtypeTools: Tool[] = [...mandatoryTools]
|
|
46
|
+
return [...hubtypeTools, ...tools]
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/constants.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export const HUBTYPE_API_URL =
|
|
2
2
|
process.env.HUBTYPE_API_URL || 'https://api.hubtype.com'
|
|
3
3
|
|
|
4
|
-
export const AZURE_OPENAI_API_KEY = process.env.AZURE_OPENAI_API_KEY
|
|
5
|
-
export const AZURE_OPENAI_API_DEPLOYMENT_NAME =
|
|
6
|
-
process.env.AZURE_OPENAI_API_DEPLOYMENT_NAME
|
|
7
|
-
export const AZURE_OPENAI_API_VERSION = process.env.AZURE_OPENAI_API_VERSION
|
|
4
|
+
export const AZURE_OPENAI_API_KEY = process.env.AZURE_OPENAI_API_KEY // pragma: allowlist secret
|
|
8
5
|
export const AZURE_OPENAI_API_BASE = process.env.AZURE_OPENAI_API_BASE
|
|
6
|
+
export const AZURE_OPENAI_API_DEPLOYMENT_NAME =
|
|
7
|
+
process.env.AZURE_OPENAI_API_DEPLOYMENT_NAME || 'gpt-4o-mini_p1'
|
|
8
|
+
export const AZURE_OPENAI_API_VERSION =
|
|
9
|
+
process.env.AZURE_OPENAI_API_VERSION || '2024-12-01-preview'
|
|
10
|
+
|
|
11
|
+
export const isProd = process.env.NODE_ENV === 'production'
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
2
|
+
import { BotContext } from '@botonic/core'
|
|
3
|
+
import axios from 'axios'
|
|
4
|
+
|
|
5
|
+
import { HUBTYPE_API_URL } from './constants'
|
|
6
|
+
import { AgenticInputMessage } from './types'
|
|
7
|
+
|
|
8
|
+
interface HubtypeAssistantMessage {
|
|
9
|
+
role: 'assistant'
|
|
10
|
+
content: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface HubtypeUserMessage {
|
|
14
|
+
role: 'user'
|
|
15
|
+
content: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type HubtypeMessage = HubtypeAssistantMessage | HubtypeUserMessage
|
|
19
|
+
|
|
20
|
+
export class HubtypeApiClient {
|
|
21
|
+
private readonly authToken: string
|
|
22
|
+
|
|
23
|
+
constructor(authToken: string) {
|
|
24
|
+
this.authToken = authToken
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async getLocalMessages(memoryLength: number): Promise<AgenticInputMessage[]> {
|
|
28
|
+
const localBotonicState = localStorage.getItem('botonicState')
|
|
29
|
+
const botonicState = JSON.parse(localBotonicState || '{}')
|
|
30
|
+
const messages = botonicState.messages
|
|
31
|
+
const filteredMessages = messages
|
|
32
|
+
.filter(message => message.data.text)
|
|
33
|
+
.map(message => ({
|
|
34
|
+
role: message.sentBy === 'user' ? 'user' : 'assistant',
|
|
35
|
+
content: message.data.text,
|
|
36
|
+
}))
|
|
37
|
+
.map(message => this.formatMessage(message))
|
|
38
|
+
return filteredMessages.slice(-memoryLength)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async getMessages(
|
|
42
|
+
request: BotContext,
|
|
43
|
+
memoryLength: number
|
|
44
|
+
): Promise<AgenticInputMessage[]> {
|
|
45
|
+
const url = `${HUBTYPE_API_URL}/external/v1/ai/agent/message_history/`
|
|
46
|
+
const headers = {
|
|
47
|
+
'Content-Type': 'application/json',
|
|
48
|
+
Authorization: `Bearer ${this.authToken}`,
|
|
49
|
+
}
|
|
50
|
+
const params = {
|
|
51
|
+
last_message_id: request.input.message_id,
|
|
52
|
+
num_messages: memoryLength,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const response = await axios.get<{ messages: HubtypeMessage[] }>(url, {
|
|
57
|
+
headers,
|
|
58
|
+
params,
|
|
59
|
+
})
|
|
60
|
+
const messages = response.data.messages
|
|
61
|
+
return messages.map(message => this.formatMessage(message))
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error(error)
|
|
64
|
+
throw new Error('Failed to get messages from Hubtype')
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private formatMessage(message: HubtypeMessage): AgenticInputMessage {
|
|
69
|
+
if (message.role === 'user') {
|
|
70
|
+
return {
|
|
71
|
+
content: message.content,
|
|
72
|
+
role: 'user',
|
|
73
|
+
}
|
|
74
|
+
} else if (message.role === 'assistant') {
|
|
75
|
+
return {
|
|
76
|
+
role: 'assistant',
|
|
77
|
+
content: [
|
|
78
|
+
{
|
|
79
|
+
type: 'output_text',
|
|
80
|
+
text: message.content,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
status: 'completed',
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
throw new Error('Invalid message role')
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
import { BotContext, Plugin } from '@botonic/core'
|
|
2
|
+
import { tool } from '@openai/agents'
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { AIAgentBuilder } from './agent-builder'
|
|
5
|
+
import { isProd } from './constants'
|
|
6
|
+
import { HubtypeApiClient } from './hubtype-api-client'
|
|
7
|
+
import { setUpOpenAI } from './openai'
|
|
8
|
+
import { AIAgentRunner } from './runner'
|
|
6
9
|
import {
|
|
10
|
+
AgenticInputMessage,
|
|
7
11
|
AgenticOutputMessage,
|
|
8
12
|
AiAgentArgs,
|
|
13
|
+
Context,
|
|
14
|
+
CustomTool,
|
|
9
15
|
PluginAiAgentOptions,
|
|
10
|
-
|
|
16
|
+
Tool,
|
|
11
17
|
} from './types'
|
|
12
|
-
import { loadChatModel } from './utils'
|
|
13
|
-
|
|
14
|
-
const isProd = process.env.NODE_ENV === 'production'
|
|
15
18
|
|
|
16
19
|
export default class BotonicPluginAiAgents implements Plugin {
|
|
17
20
|
private readonly authToken?: string
|
|
21
|
+
public toolDefinitions: CustomTool[] = []
|
|
22
|
+
|
|
18
23
|
constructor(options?: PluginAiAgentOptions) {
|
|
24
|
+
setUpOpenAI()
|
|
19
25
|
this.authToken = options?.authToken
|
|
26
|
+
this.toolDefinitions = options?.customTools || []
|
|
20
27
|
}
|
|
21
28
|
|
|
22
29
|
pre(): void {
|
|
@@ -26,31 +33,61 @@ export default class BotonicPluginAiAgents implements Plugin {
|
|
|
26
33
|
async getInference(
|
|
27
34
|
request: BotContext,
|
|
28
35
|
aiAgentArgs: AiAgentArgs
|
|
29
|
-
): Promise<AgenticOutputMessage | undefined> {
|
|
36
|
+
): Promise<AgenticOutputMessage[] | undefined> {
|
|
30
37
|
try {
|
|
31
38
|
const authToken = isProd ? request.session._access_token : this.authToken
|
|
32
39
|
if (!authToken) {
|
|
33
40
|
throw new Error('Auth token is required')
|
|
34
41
|
}
|
|
35
42
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
const tools = this.buildTools(
|
|
44
|
+
aiAgentArgs.activeTools?.map(tool => tool.name) || []
|
|
45
|
+
)
|
|
46
|
+
const agent = new AIAgentBuilder(
|
|
47
|
+
aiAgentArgs.name,
|
|
48
|
+
aiAgentArgs.instructions,
|
|
49
|
+
tools
|
|
50
|
+
).build()
|
|
40
51
|
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
...MANDATORY_TOOLS,
|
|
46
|
-
])
|
|
52
|
+
const messages = await this.getMessages(request, authToken, 25)
|
|
53
|
+
const context: Context = {
|
|
54
|
+
authToken,
|
|
55
|
+
}
|
|
47
56
|
|
|
48
|
-
|
|
57
|
+
const runner = new AIAgentRunner(agent)
|
|
58
|
+
return await runner.run(messages, context)
|
|
49
59
|
} catch (error) {
|
|
50
60
|
console.error('error plugin returns undefined', error)
|
|
51
61
|
return undefined
|
|
52
62
|
}
|
|
53
63
|
}
|
|
64
|
+
|
|
65
|
+
private async getMessages(
|
|
66
|
+
request: BotContext,
|
|
67
|
+
authToken: string,
|
|
68
|
+
memoryLength: number
|
|
69
|
+
): Promise<AgenticInputMessage[]> {
|
|
70
|
+
if (isProd) {
|
|
71
|
+
const hubtypeClient = new HubtypeApiClient(authToken)
|
|
72
|
+
return await hubtypeClient.getMessages(request, memoryLength)
|
|
73
|
+
}
|
|
74
|
+
const hubtypeClient = new HubtypeApiClient(authToken)
|
|
75
|
+
return await hubtypeClient.getLocalMessages(memoryLength)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private buildTools(activeToolNames: string[]): Tool[] {
|
|
79
|
+
const availableTools = this.toolDefinitions.filter(tool =>
|
|
80
|
+
activeToolNames.includes(tool.name)
|
|
81
|
+
)
|
|
82
|
+
return availableTools.map(toolDefinition => {
|
|
83
|
+
return tool<any, Context, any>({
|
|
84
|
+
name: toolDefinition.name,
|
|
85
|
+
description: toolDefinition.description,
|
|
86
|
+
parameters: toolDefinition.schema,
|
|
87
|
+
execute: toolDefinition.func,
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
}
|
|
54
91
|
}
|
|
55
92
|
|
|
56
93
|
export * from './types'
|
package/src/openai.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {
|
|
2
|
+
setDefaultOpenAIClient,
|
|
3
|
+
setOpenAIAPI,
|
|
4
|
+
setTracingDisabled,
|
|
5
|
+
} from '@openai/agents'
|
|
6
|
+
import { AzureOpenAI } from 'openai'
|
|
7
|
+
import {
|
|
8
|
+
AZURE_OPENAI_API_BASE,
|
|
9
|
+
AZURE_OPENAI_API_DEPLOYMENT_NAME,
|
|
10
|
+
AZURE_OPENAI_API_KEY,
|
|
11
|
+
AZURE_OPENAI_API_VERSION,
|
|
12
|
+
isProd,
|
|
13
|
+
} from './constants'
|
|
14
|
+
|
|
15
|
+
export function setUpOpenAI() {
|
|
16
|
+
setAzureOpenAIClient()
|
|
17
|
+
setOpenAIAPI('chat_completions')
|
|
18
|
+
setTracingDisabled(true)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function setAzureOpenAIClient() {
|
|
22
|
+
const client = new AzureOpenAI({
|
|
23
|
+
apiKey: AZURE_OPENAI_API_KEY,
|
|
24
|
+
apiVersion: AZURE_OPENAI_API_VERSION,
|
|
25
|
+
deployment: AZURE_OPENAI_API_DEPLOYMENT_NAME,
|
|
26
|
+
baseURL: AZURE_OPENAI_API_BASE,
|
|
27
|
+
dangerouslyAllowBrowser: !isProd,
|
|
28
|
+
})
|
|
29
|
+
setDefaultOpenAIClient(client)
|
|
30
|
+
}
|
package/src/runner.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Runner } from '@openai/agents'
|
|
2
|
+
import {
|
|
3
|
+
AIAgent,
|
|
4
|
+
AgenticInputMessage,
|
|
5
|
+
AgenticOutputMessage,
|
|
6
|
+
Context,
|
|
7
|
+
} from './types'
|
|
8
|
+
|
|
9
|
+
export class AIAgentRunner {
|
|
10
|
+
private agent: AIAgent
|
|
11
|
+
|
|
12
|
+
constructor(agent: AIAgent) {
|
|
13
|
+
this.agent = agent
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async run(
|
|
17
|
+
messages: AgenticInputMessage[],
|
|
18
|
+
context: Context,
|
|
19
|
+
maxRetries: number = 1
|
|
20
|
+
): Promise<AgenticOutputMessage[]> {
|
|
21
|
+
return this.runWithRetry(messages, context, maxRetries, 1)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private async runWithRetry(
|
|
25
|
+
messages: AgenticInputMessage[],
|
|
26
|
+
context: Context,
|
|
27
|
+
maxRetries: number,
|
|
28
|
+
attempt: number
|
|
29
|
+
): Promise<AgenticOutputMessage[]> {
|
|
30
|
+
try {
|
|
31
|
+
const runner = new Runner({
|
|
32
|
+
modelSettings: { temperature: 0 },
|
|
33
|
+
})
|
|
34
|
+
const result = await runner.run(this.agent, messages, { context })
|
|
35
|
+
return result.finalOutput?.messages || []
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (attempt > maxRetries) {
|
|
38
|
+
throw error
|
|
39
|
+
}
|
|
40
|
+
return this.runWithRetry(messages, context, maxRetries, attempt + 1)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { BaseMessage } from './shared'
|
|
4
|
+
|
|
5
|
+
interface CarouselElement {
|
|
6
|
+
title: string
|
|
7
|
+
subtitle: string
|
|
8
|
+
image: string
|
|
9
|
+
button: { text: string; url: string }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface CarouselMessage extends BaseMessage {
|
|
13
|
+
type: 'carousel'
|
|
14
|
+
content: {
|
|
15
|
+
elements: CarouselElement[]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const CarouselSchema = z
|
|
20
|
+
.object({
|
|
21
|
+
type: z.enum(['carousel']),
|
|
22
|
+
content: z.object({
|
|
23
|
+
elements: z.array(
|
|
24
|
+
z.object({
|
|
25
|
+
title: z.string(),
|
|
26
|
+
subtitle: z.string(),
|
|
27
|
+
image: z.string(),
|
|
28
|
+
button: z.object({
|
|
29
|
+
text: z.string(),
|
|
30
|
+
url: z.string(),
|
|
31
|
+
}),
|
|
32
|
+
})
|
|
33
|
+
),
|
|
34
|
+
}),
|
|
35
|
+
})
|
|
36
|
+
.describe('A carousel message containing a list of elements')
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import z from 'zod'
|
|
2
|
+
|
|
3
|
+
import { BaseMessage } from './shared'
|
|
4
|
+
|
|
5
|
+
export interface ExitMessage extends BaseMessage {
|
|
6
|
+
type: 'exit'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const ExitSchema = z
|
|
10
|
+
.object({
|
|
11
|
+
type: z.enum(['exit']),
|
|
12
|
+
})
|
|
13
|
+
.describe(
|
|
14
|
+
'An exit message. This message should only be used to exit the agent due to out of context or the user asking to exit the conversation'
|
|
15
|
+
)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { CarouselMessage, CarouselSchema } from './carousel'
|
|
4
|
+
import { ExitMessage, ExitSchema } from './exit'
|
|
5
|
+
import { TextMessage, TextSchema } from './text'
|
|
6
|
+
import {
|
|
7
|
+
TextWithButtonsMessage,
|
|
8
|
+
TextWithButtonsSchema,
|
|
9
|
+
} from './text-with-buttons'
|
|
10
|
+
|
|
11
|
+
export type OutputMessage =
|
|
12
|
+
| TextMessage
|
|
13
|
+
| TextWithButtonsMessage
|
|
14
|
+
| CarouselMessage
|
|
15
|
+
| ExitMessage
|
|
16
|
+
|
|
17
|
+
export interface Output {
|
|
18
|
+
messages: OutputMessage[]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const OutputSchema = z
|
|
22
|
+
.object({
|
|
23
|
+
messages: z.array(
|
|
24
|
+
z.union([TextSchema, TextWithButtonsSchema, CarouselSchema, ExitSchema])
|
|
25
|
+
),
|
|
26
|
+
})
|
|
27
|
+
.describe('The messages to be sent to the user')
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import z from 'zod'
|
|
2
|
+
|
|
3
|
+
import { BaseMessage } from './shared'
|
|
4
|
+
|
|
5
|
+
export interface TextWithButtonsMessage extends BaseMessage {
|
|
6
|
+
type: 'textWithButtons'
|
|
7
|
+
content: {
|
|
8
|
+
text: string
|
|
9
|
+
buttons: string[]
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const TextWithButtonsSchema = z
|
|
14
|
+
.object({
|
|
15
|
+
type: z.enum(['textWithButtons']),
|
|
16
|
+
content: z.object({
|
|
17
|
+
text: z.string(),
|
|
18
|
+
buttons: z.array(z.string()),
|
|
19
|
+
}),
|
|
20
|
+
})
|
|
21
|
+
.describe(
|
|
22
|
+
'A text message with buttons to allow the user to use quick replies'
|
|
23
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { BaseMessage } from './shared'
|
|
4
|
+
|
|
5
|
+
export interface TextMessage extends BaseMessage {
|
|
6
|
+
type: 'text'
|
|
7
|
+
content: {
|
|
8
|
+
text: string
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const TextSchema = z
|
|
13
|
+
.object({
|
|
14
|
+
type: z.enum(['text']),
|
|
15
|
+
content: z.object({
|
|
16
|
+
text: z.string(),
|
|
17
|
+
}),
|
|
18
|
+
})
|
|
19
|
+
.describe('A text message')
|
package/src/types.ts
CHANGED
|
@@ -1,39 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
Agent,
|
|
3
|
+
AgentInputItem,
|
|
4
|
+
RunContext,
|
|
5
|
+
Tool as OpenAITool,
|
|
6
|
+
} from '@openai/agents'
|
|
7
|
+
import { ZodSchema } from 'zod'
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
role: 'assistant' | 'user' | 'tool' | 'exit'
|
|
11
|
-
}
|
|
9
|
+
import { OutputMessage, OutputSchema } from './structured-output'
|
|
12
10
|
|
|
13
|
-
export interface
|
|
14
|
-
|
|
15
|
-
content: string
|
|
11
|
+
export interface Context {
|
|
12
|
+
authToken: string
|
|
16
13
|
}
|
|
17
14
|
|
|
18
|
-
export interface
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
export interface CustomTool {
|
|
16
|
+
name: string
|
|
17
|
+
description: string
|
|
18
|
+
schema: ZodSchema
|
|
19
|
+
func: (input?: any, runContext?: RunContext<Context>) => Promise<any>
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
export type Tool = OpenAITool<Context>
|
|
23
|
+
export type AIAgent = Agent<Context, typeof OutputSchema>
|
|
24
|
+
|
|
25
|
+
export interface PluginAiAgentOptions {
|
|
26
|
+
authToken?: string
|
|
27
|
+
customTools?: CustomTool[]
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
export interface
|
|
30
|
-
|
|
30
|
+
export interface AiAgentArgs {
|
|
31
|
+
name: string
|
|
32
|
+
instructions: string
|
|
33
|
+
activeTools?: { name: string }[]
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
export type AgenticInputMessage =
|
|
34
|
-
export type AgenticOutputMessage =
|
|
35
|
-
export type AgenticMessage =
|
|
36
|
-
| AssistantMessage
|
|
37
|
-
| UserMessage
|
|
38
|
-
| ToolMessage
|
|
39
|
-
| ExitMessage
|
|
36
|
+
export type AgenticInputMessage = AgentInputItem
|
|
37
|
+
export type AgenticOutputMessage = OutputMessage
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
2
|
-
import { StructuredTool } from '@langchain/core/tools';
|
|
3
|
-
import { CompiledStateGraph } from '@langchain/langgraph';
|
|
4
|
-
import { AgenticInputMessage, AgenticOutputMessage, AiAgentArgs } from './types';
|
|
5
|
-
export declare class AiAgentClient {
|
|
6
|
-
name: string;
|
|
7
|
-
instructions: string;
|
|
8
|
-
agent: CompiledStateGraph<any, any>;
|
|
9
|
-
constructor(aiAgentArgs: AiAgentArgs, chatModel: BaseChatModel, tools?: StructuredTool[]);
|
|
10
|
-
runAgent(_messages: AgenticInputMessage[]): Promise<AgenticOutputMessage>;
|
|
11
|
-
}
|