booths 0.0.6 → 0.1.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/README.md +144 -98
- package/dist/index.d.ts +26 -7
- package/dist/index.js +330 -221
- package/package.json +12 -5
package/README.md
CHANGED
|
@@ -1,146 +1,192 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Booths
|
|
2
|
+
|
|
3
|
+
Booths is a modular and extensible framework for building and managing conversational AI agents. It provides a structured way to define the capabilities, context, and tools for different AI-powered conversational flows.
|
|
4
|
+
|
|
5
|
+
The system is designed around a central `CoreBooth` class that orchestrates interactions between users and a Large Language Model (LLM), leveraging a system of registries and plugins to manage the conversational state and capabilities.
|
|
6
|
+
|
|
7
|
+
## Architecture Overview
|
|
8
|
+
|
|
9
|
+
The Booths framework is built around a few key concepts that work together to create a powerful and flexible conversational AI system.
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
graph TD
|
|
13
|
+
subgraph User Interface
|
|
14
|
+
A[Vue.js Component]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
subgraph Booth Service Layer
|
|
18
|
+
B(useLLMService)
|
|
19
|
+
C(CoreBooth)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
subgraph Core Components
|
|
23
|
+
D[Interaction Processor]
|
|
24
|
+
E[LLM Adapter]
|
|
25
|
+
F[Registries]
|
|
26
|
+
G[Plugins]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
A -- "sends user input" --> B
|
|
30
|
+
B -- "initializes and calls" --> C
|
|
31
|
+
C -- "delegates to" --> D
|
|
32
|
+
D -- "uses" --> E
|
|
33
|
+
D -- "uses" --> F
|
|
34
|
+
D -- "executes" --> G
|
|
35
|
+
E -- "communicates with" --> H((LLM))
|
|
36
|
+
F -- "manages" --> I{Booths}
|
|
37
|
+
F -- "manages" --> J{Tools}
|
|
38
|
+
F -- "manages" --> K{Plugins}
|
|
39
|
+
G -- "hook into" --> D
|
|
40
|
+
|
|
41
|
+
style B fill:#f9f,stroke:#333,stroke-width:2px
|
|
42
|
+
style C fill:#f9f,stroke:#333,stroke-width:2px
|
|
43
|
+
```
|
|
2
44
|
|
|
3
|
-
|
|
45
|
+
1. **User Interface**: A frontend application (e.g., a Vue component) captures user input and displays the conversation.
|
|
46
|
+
2. **Service Layer (`useLLMService.ts`)**: This layer acts as a bridge between the UI and the Booths engine. It initializes the `CoreBooth`, manages the conversational state, and exposes methods for sending messages.
|
|
47
|
+
3. **`CoreBooth`**: The central orchestrator of the system. It is configured with an `LLMAdapter`, and a set of registries for booths, tools, and plugins.
|
|
48
|
+
4. **`InteractionProcessor`**: The engine that drives the conversation. It takes user input, runs it through the plugin lifecycle, sends it to the LLM (via the adapter), and processes the response.
|
|
49
|
+
5. **`LLMAdapter`**: A component that handles communication with the specific LLM provider (e.g., OpenAI). It translates requests and responses between the Booths system and the LLM's API.
|
|
50
|
+
6. **Registries**: These are responsible for managing the different components of the system:
|
|
51
|
+
* `BoothRegistry`: Manages `BoothConfig` objects that define the behavior of different AI agents.
|
|
52
|
+
* `ToolRegistry`: Manages the tools (functions) that booths can use.
|
|
53
|
+
* `BoothPluginRegistry`: Manages the plugins that hook into the conversational lifecycle.
|
|
54
|
+
7. **Plugins**: These are modules that add functionality to the system by hooking into the `InteractionProcessor`'s lifecycle (e.g., managing conversation history, providing context to the LLM, executing tools).
|
|
4
55
|
|
|
5
|
-
|
|
56
|
+
## Running the Examples
|
|
6
57
|
|
|
7
|
-
|
|
58
|
+
The best way to understand the Booths framework is to run the example application provided in the `src/examples` directory.
|
|
8
59
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
60
|
+
### Prerequisites
|
|
61
|
+
|
|
62
|
+
- Node.js and npm installed.
|
|
63
|
+
- An OpenAI API key.
|
|
64
|
+
|
|
65
|
+
### Setup
|
|
66
|
+
|
|
67
|
+
1. **Clone the repository:**
|
|
68
|
+
```bash
|
|
69
|
+
git clone <repository-url>
|
|
70
|
+
cd booths
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
2. **Install dependencies:**
|
|
74
|
+
```bash
|
|
75
|
+
npm install
|
|
76
|
+
```
|
|
12
77
|
|
|
13
|
-
|
|
78
|
+
3. **Set up your environment variables:**
|
|
79
|
+
Create a `.env.local` file in the root of the project and add your OpenAI API key:
|
|
80
|
+
```
|
|
81
|
+
VITE_OPENAI_API_KEY=your-openai-api-key
|
|
82
|
+
```
|
|
14
83
|
|
|
15
|
-
|
|
84
|
+
4. **Run the application:**
|
|
85
|
+
```bash
|
|
86
|
+
npm run dev
|
|
87
|
+
```
|
|
16
88
|
|
|
17
|
-
|
|
89
|
+
This will start a local development server. Open your browser to the specified address (usually `http://localhost:5173`) to see the chat application in action.
|
|
18
90
|
|
|
19
|
-
|
|
91
|
+
The example application features a collection of pirate-themed booths that demonstrate how to create and manage different conversational agents. You can interact with a "Sea Lore" booth, a "Shipwright" booth, and even a "Duel" booth.
|
|
92
|
+
|
|
93
|
+
## Quick Start Guide
|
|
94
|
+
|
|
95
|
+
Here is a lightweight example of how to set up and use the Core Booth system manually.
|
|
96
|
+
|
|
97
|
+
### 1. Define a Booth
|
|
98
|
+
|
|
99
|
+
First, define a booth configuration. This object specifies the booth's identity, role, and the tools it can use.
|
|
20
100
|
|
|
21
101
|
```typescript
|
|
22
102
|
// in my-booths.ts
|
|
23
103
|
import type { BoothConfig } from 'booths';
|
|
24
104
|
|
|
25
|
-
export const
|
|
26
|
-
id: '
|
|
27
|
-
role: '
|
|
28
|
-
description: 'You
|
|
29
|
-
tools: ['
|
|
30
|
-
examples: ["
|
|
105
|
+
export const pirateBooth: BoothConfig = {
|
|
106
|
+
id: 'pirate-booth',
|
|
107
|
+
role: 'You are a salty pirate captain.',
|
|
108
|
+
description: 'You speak like a pirate and can tell pirate jokes.',
|
|
109
|
+
tools: ['tell_pirate_joke'],
|
|
110
|
+
examples: ["Tell me a joke.", "Why are pirates called pirates?"],
|
|
31
111
|
};
|
|
32
112
|
```
|
|
33
113
|
|
|
114
|
+
### 2. Define a Tool
|
|
115
|
+
|
|
116
|
+
Next, create a tool that the booth can use. A tool is a function that the LLM can decide to call.
|
|
117
|
+
|
|
34
118
|
```typescript
|
|
35
119
|
// in my-tools.ts
|
|
36
120
|
import type { ToolModule } from 'booths';
|
|
37
121
|
|
|
38
|
-
export const
|
|
122
|
+
export const tellPirateJokeTool: ToolModule = {
|
|
39
123
|
type: 'function',
|
|
40
|
-
name: '
|
|
41
|
-
description: '
|
|
124
|
+
name: 'tell_pirate_joke',
|
|
125
|
+
description: 'Tells a classic pirate joke.',
|
|
42
126
|
parameters: { type: 'object', properties: {} },
|
|
43
127
|
execute: async () => {
|
|
44
|
-
|
|
45
|
-
return { accountId: '123', plan: 'Pro' };
|
|
128
|
+
return { joke: "Why are pirates called pirates? Because they arrrr!" };
|
|
46
129
|
},
|
|
47
130
|
};
|
|
48
131
|
```
|
|
49
132
|
|
|
50
|
-
###
|
|
133
|
+
### 3. Implement the LLM Adapter
|
|
51
134
|
|
|
52
|
-
The `CoreBooth` requires an `LLMAdapter` to communicate with your chosen language model. Here is a minimal example
|
|
135
|
+
The `CoreBooth` requires an `LLMAdapter` to communicate with your chosen language model. Here is a minimal example for OpenAI.
|
|
53
136
|
|
|
54
137
|
```typescript
|
|
55
|
-
// in
|
|
56
|
-
import type { LLMAdapter, ResponseCreateParamsNonStreaming } from 'booths';
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// In a real application, you would make a call to an LLM API (e.g., OpenAI, Anthropic).
|
|
62
|
-
console.log('Sending to LLM:', params.messages);
|
|
63
|
-
|
|
64
|
-
const lastMessage = params.messages[params.messages.length - 1];
|
|
65
|
-
|
|
66
|
-
if (lastMessage.content?.includes("check my account plan")) {
|
|
67
|
-
return {
|
|
68
|
-
id: 'fake-response-id',
|
|
69
|
-
choices: [{
|
|
70
|
-
message: {
|
|
71
|
-
role: 'assistant',
|
|
72
|
-
content: null,
|
|
73
|
-
tool_calls: [{
|
|
74
|
-
id: 'tool-call-1',
|
|
75
|
-
type: 'function',
|
|
76
|
-
function: {
|
|
77
|
-
name: 'get_user_account_details',
|
|
78
|
-
arguments: '{}'
|
|
79
|
-
}
|
|
80
|
-
}]
|
|
81
|
-
}
|
|
82
|
-
}]
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return {
|
|
87
|
-
id: 'fake-response-id',
|
|
88
|
-
choices: [{
|
|
89
|
-
message: {
|
|
90
|
-
role: 'assistant',
|
|
91
|
-
content: "I am on the Pro plan.",
|
|
92
|
-
}
|
|
93
|
-
}]
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
}
|
|
138
|
+
// in openAIAdapter.ts
|
|
139
|
+
import type { LLMAdapter, ResponseCreateParamsNonStreaming, Response } from 'booths';
|
|
140
|
+
import openai from 'openai';
|
|
141
|
+
|
|
142
|
+
export class OpenAIAdapter implements LLMAdapter<any> {
|
|
143
|
+
openai: openai;
|
|
97
144
|
|
|
98
|
-
|
|
145
|
+
constructor(apiKey: string) {
|
|
146
|
+
this.openai = new openai({ apiKey, dangerouslyAllowBrowser: true });
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
invoke(params: ResponseCreateParamsNonStreaming) {
|
|
150
|
+
return this.openai.responses.create({ ...params, model: 'gpt-4o' });
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async interpret(response: Response): Promise<Response> {
|
|
154
|
+
return response;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
99
157
|
```
|
|
100
158
|
|
|
101
|
-
###
|
|
159
|
+
### 4. Initialize the CoreBooth
|
|
102
160
|
|
|
103
|
-
|
|
161
|
+
Finally, use the `createCoreBooth` factory to instantiate the system.
|
|
104
162
|
|
|
105
163
|
```typescript
|
|
106
164
|
// in main.ts
|
|
107
|
-
import {
|
|
108
|
-
import {
|
|
109
|
-
import {
|
|
110
|
-
import
|
|
111
|
-
|
|
112
|
-
// 1. Create
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
toolRegistry.registerTools([
|
|
120
|
-
|
|
121
|
-
//
|
|
122
|
-
boothRegistry.setCurrentContextId('customer-support');
|
|
123
|
-
|
|
124
|
-
// 4. Create the CoreBooth instance with the adapter
|
|
125
|
-
const coreBooth = new CoreBooth({
|
|
126
|
-
booths: boothRegistry,
|
|
127
|
-
tools: toolRegistry,
|
|
128
|
-
boothPlugins: boothPluginRegistry,
|
|
129
|
-
llmAdapter: new MyLLMAdapter(),
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
// 5. Send a message and get a response
|
|
165
|
+
import { createCoreBooth } from 'booths';
|
|
166
|
+
import { pirateBooth } from './my-booths';
|
|
167
|
+
import { tellPirateJokeTool } from './my-tools';
|
|
168
|
+
import { OpenAIAdapter } from './openAIAdapter';
|
|
169
|
+
|
|
170
|
+
// 1. Create the LLM adapter
|
|
171
|
+
const llmAdapter = new OpenAIAdapter('your-openai-api-key');
|
|
172
|
+
|
|
173
|
+
// 2. Create the CoreBooth instance
|
|
174
|
+
const coreBooth = createCoreBooth(llmAdapter, pirateBooth);
|
|
175
|
+
|
|
176
|
+
// 3. Register the tool (this step will be improved in future versions)
|
|
177
|
+
coreBooth.toolRegistry.registerTools([tellPirateJokeTool]);
|
|
178
|
+
|
|
179
|
+
// 4. Send a message and get a response
|
|
133
180
|
async function haveConversation() {
|
|
134
|
-
const userInput = '
|
|
181
|
+
const userInput = 'Tell me a pirate joke.';
|
|
135
182
|
const response = await coreBooth.callProcessor.send(userInput);
|
|
136
183
|
|
|
137
184
|
console.log(response.output_text);
|
|
138
|
-
// Expected output
|
|
185
|
+
// Expected output: "Why are pirates called pirates? Because they arrrr!"
|
|
139
186
|
}
|
|
140
187
|
|
|
141
188
|
haveConversation();
|
|
142
189
|
```
|
|
143
|
-
|
|
144
190
|
## How It Works
|
|
145
191
|
|
|
146
192
|
The Core Booth system is comprised of several key components that work together to process user input and generate contextual responses.
|
package/dist/index.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export declare interface BoothConfig {
|
|
|
37
37
|
/** The developer or team responsible for the booth. */
|
|
38
38
|
developer?: string;
|
|
39
39
|
/** A list of tool names that this booth is authorized to use. */
|
|
40
|
-
tools
|
|
40
|
+
tools?: string[];
|
|
41
41
|
/**
|
|
42
42
|
* A list of tools in the format expected by the Multi-Category Peppercorn (MCP) system.
|
|
43
43
|
* This is likely for more complex tool definitions.
|
|
@@ -51,7 +51,7 @@ export declare interface BoothConfig {
|
|
|
51
51
|
*/
|
|
52
52
|
responseFormat?: string;
|
|
53
53
|
/** A list of example queries or inputs that the booth is designed to handle. */
|
|
54
|
-
examples
|
|
54
|
+
examples?: string[];
|
|
55
55
|
/**
|
|
56
56
|
* Defines fallback behavior for when the booth receives a query that is out of scope.
|
|
57
57
|
*/
|
|
@@ -121,7 +121,7 @@ export declare interface BoothPlugin {
|
|
|
121
121
|
* @param context - Context information about the tool call execution.
|
|
122
122
|
* @returns The potentially modified tool call result.
|
|
123
123
|
*/
|
|
124
|
-
onAfterToolCall?: (utilities: RepositoryUtilities, toolCall: ResponseFunctionToolCall, result:
|
|
124
|
+
onAfterToolCall?: (utilities: RepositoryUtilities, toolCall: ResponseFunctionToolCall, result: unknown, context: ToolCallContext) => Promise<unknown>;
|
|
125
125
|
/**
|
|
126
126
|
* Called when an individual tool call encounters an error during execution.
|
|
127
127
|
* This allows for custom error handling or recovery.
|
|
@@ -131,7 +131,7 @@ export declare interface BoothPlugin {
|
|
|
131
131
|
* @param context - Context information about the tool call execution.
|
|
132
132
|
* @returns The error result or a recovery value to use instead.
|
|
133
133
|
*/
|
|
134
|
-
onToolCallError?: (utilities: RepositoryUtilities, toolCall: ResponseFunctionToolCall, error: Error, context: ToolCallContext) => Promise<
|
|
134
|
+
onToolCallError?: (utilities: RepositoryUtilities, toolCall: ResponseFunctionToolCall, error: Error, context: ToolCallContext) => Promise<unknown>;
|
|
135
135
|
/**
|
|
136
136
|
* Determines whether the interaction loop should end. This is a mandatory method
|
|
137
137
|
* for all plugins.
|
|
@@ -372,6 +372,11 @@ export declare class BoothRegistry {
|
|
|
372
372
|
* @returns Record of all booth configurations indexed by their IDs
|
|
373
373
|
*/
|
|
374
374
|
getAllBooths(): Record<string, BoothConfig>;
|
|
375
|
+
/**
|
|
376
|
+
* Checks if the registry is operating in a multi-booth configuration.
|
|
377
|
+
* @returns {boolean} `true` if there is more than one booth registered, otherwise `false`.
|
|
378
|
+
*/
|
|
379
|
+
get isMultiBoothMode(): boolean;
|
|
375
380
|
/**
|
|
376
381
|
* Removes a booth configuration from the registry by its ID.
|
|
377
382
|
* Throws an error if the booth doesn't exist.
|
|
@@ -457,6 +462,7 @@ export declare class ConversationHistoryPlugin implements BoothPlugin {
|
|
|
457
462
|
* @private
|
|
458
463
|
*/
|
|
459
464
|
private readonly plugin_description;
|
|
465
|
+
private responseContainsBoothChange;
|
|
460
466
|
/**
|
|
461
467
|
* Returns the plugin's unique identifier.
|
|
462
468
|
*/
|
|
@@ -487,7 +493,7 @@ export declare class ConversationHistoryPlugin implements BoothPlugin {
|
|
|
487
493
|
* @param response
|
|
488
494
|
* @returns Unmodified response parameters
|
|
489
495
|
*/
|
|
490
|
-
onResponseReceived(
|
|
496
|
+
onResponseReceived(utilities: RepositoryUtilities, responseParams: ResponseCreateParamsNonStreaming, response: Response_2): Promise<{
|
|
491
497
|
input: ( ResponseFunctionToolCall | EasyInputMessage | ResponseOutputMessage | ResponseFileSearchToolCall | ResponseComputerToolCall | ResponseInputItem.ComputerCallOutput | ResponseFunctionWebSearch | ResponseInputItem.FunctionCallOutput | ResponseReasoningItem | ResponseInputItem.ImageGenerationCall | ResponseCodeInterpreterToolCall | ResponseInputItem.LocalShellCall | ResponseInputItem.LocalShellCallOutput | ResponseInputItem.McpListTools | ResponseInputItem.McpApprovalRequest | ResponseInputItem.McpApprovalResponse | ResponseInputItem.McpCall | ResponseInputItem.ItemReference)[];
|
|
492
498
|
stream?: false | null;
|
|
493
499
|
background?: boolean | null;
|
|
@@ -586,6 +592,17 @@ export declare class CoreBooth<T> {
|
|
|
586
592
|
});
|
|
587
593
|
}
|
|
588
594
|
|
|
595
|
+
/**
|
|
596
|
+
* Creates a new instance of CoreBooth configured for a single booth.
|
|
597
|
+
* This factory simplifies the setup of a CoreBooth by managing the
|
|
598
|
+
* instantiation of the necessary registries.
|
|
599
|
+
*
|
|
600
|
+
* @param llmAdapter - The LLM adapter for communication with the language model.
|
|
601
|
+
* @param boothConfig - The configuration for the single booth to be used.
|
|
602
|
+
* @returns A fully configured CoreBooth instance.
|
|
603
|
+
*/
|
|
604
|
+
export declare function createCoreBooth<T>(llmAdapter: LLMAdapter<T>, boothConfig: BoothConfig): CoreBooth<T>;
|
|
605
|
+
|
|
589
606
|
/**
|
|
590
607
|
* Creates a `route_to_booth` tool module that can be used by the LLM to switch the conversation
|
|
591
608
|
* context to a different booth. The tool's definition is dynamically generated based on the
|
|
@@ -691,7 +708,7 @@ export declare class InteractionProcessor<T> {
|
|
|
691
708
|
* @param boothRegistry - The registry for booth configurations.
|
|
692
709
|
* @param boothPlugins - The registry for booth plugins.
|
|
693
710
|
* @param toolRegistry - The registry for available tools.
|
|
694
|
-
* @param
|
|
711
|
+
* @param llmAdapter - The adapter for interacting with the LLM.
|
|
695
712
|
*/
|
|
696
713
|
constructor(boothRegistry: BoothRegistry, boothPlugins: BoothPluginRegistry, toolRegistry: ToolRegistry, llmAdapter: LLMAdapter<T>);
|
|
697
714
|
/**
|
|
@@ -725,6 +742,8 @@ export declare type RepositoryUtilities = {
|
|
|
725
742
|
toolRegistry: ToolRegistry;
|
|
726
743
|
/** An instance of the BoothPluginRegistry for managing and coordinating plugins. */
|
|
727
744
|
pluginRegistry: BoothPluginRegistry;
|
|
745
|
+
/** An instance of the LLMAdapter for direct interaction with the Language Model. */
|
|
746
|
+
llmAdapter: LLMAdapter<unknown>;
|
|
728
747
|
};
|
|
729
748
|
|
|
730
749
|
export { ResponseCreateParamsNonStreaming }
|
|
@@ -776,7 +795,7 @@ export declare class ToolExecutorPlugin implements BoothPlugin {
|
|
|
776
795
|
* @param utilities - Repository utilities for accessing registries.
|
|
777
796
|
* @param toolCall - The tool call to execute.
|
|
778
797
|
* @param context - Context information about the tool call execution.
|
|
779
|
-
* @returns The function
|
|
798
|
+
* @returns The function calls output item for the response.
|
|
780
799
|
* @private
|
|
781
800
|
*/
|
|
782
801
|
private executeToolCall;
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
var _ = Object.defineProperty;
|
|
2
|
+
var B = (i, t, o) => t in i ? _(i, t, { enumerable: !0, configurable: !0, writable: !0, value: o }) : i[t] = o;
|
|
3
|
+
var s = (i, t, o) => B(i, typeof t != "symbol" ? t + "" : t, o);
|
|
4
|
+
class R {
|
|
5
|
+
constructor() {
|
|
6
|
+
/**
|
|
7
|
+
* Collection of registered plugins.
|
|
8
|
+
* @private
|
|
9
|
+
*/
|
|
10
|
+
s(this, "plugins", []);
|
|
11
|
+
}
|
|
7
12
|
/**
|
|
8
13
|
* Registers a single plugin in the registry.
|
|
9
14
|
* Throws an error if a plugin with the same ID already exists.
|
|
@@ -111,7 +116,11 @@ class g {
|
|
|
111
116
|
*/
|
|
112
117
|
async runShouldEndInteractionLoop(t, o, e) {
|
|
113
118
|
for (const r of this.plugins)
|
|
114
|
-
if (await r.shouldEndInteractionLoop(
|
|
119
|
+
if (await r.shouldEndInteractionLoop(
|
|
120
|
+
t,
|
|
121
|
+
o,
|
|
122
|
+
e
|
|
123
|
+
))
|
|
115
124
|
return !0;
|
|
116
125
|
return !1;
|
|
117
126
|
}
|
|
@@ -158,8 +167,8 @@ class g {
|
|
|
158
167
|
*/
|
|
159
168
|
async runAfterToolCall(t, o, e, r) {
|
|
160
169
|
let n = e;
|
|
161
|
-
for (const
|
|
162
|
-
|
|
170
|
+
for (const l of this.plugins)
|
|
171
|
+
l.onAfterToolCall && (n = await l.onAfterToolCall(t, o, n, r));
|
|
163
172
|
return n;
|
|
164
173
|
}
|
|
165
174
|
/**
|
|
@@ -175,31 +184,31 @@ class g {
|
|
|
175
184
|
*/
|
|
176
185
|
async runToolCallError(t, o, e, r) {
|
|
177
186
|
let n = `Error: ${e.message}`;
|
|
178
|
-
for (const
|
|
179
|
-
|
|
187
|
+
for (const l of this.plugins)
|
|
188
|
+
l.onToolCallError && (n = await l.onToolCallError(t, o, e, r));
|
|
180
189
|
return n;
|
|
181
190
|
}
|
|
182
191
|
}
|
|
183
|
-
class
|
|
192
|
+
class T {
|
|
184
193
|
/**
|
|
185
194
|
* Creates a new booth registry with a specified base booth configuration.
|
|
186
195
|
*
|
|
187
196
|
* @param baseBooth - The base booth configuration that all other booths extend from
|
|
188
197
|
* @param currentContextId - The initial current context booth ID (default is 'orchestrator')
|
|
189
198
|
*/
|
|
190
|
-
constructor(t, o
|
|
191
|
-
|
|
199
|
+
constructor(t, o) {
|
|
200
|
+
/**
|
|
201
|
+
* Collection of registered booth configurations, indexed by their IDs.
|
|
202
|
+
* @private
|
|
203
|
+
*/
|
|
204
|
+
s(this, "booths", {});
|
|
205
|
+
/**
|
|
206
|
+
* The current context booth ID, defaulting to the orchestrator context.
|
|
207
|
+
* @private
|
|
208
|
+
*/
|
|
209
|
+
s(this, "currentContextId");
|
|
210
|
+
this.baseBooth = t, this.registerBooth(t), this.currentContextId = o || t.id;
|
|
192
211
|
}
|
|
193
|
-
/**
|
|
194
|
-
* Collection of registered booth configurations, indexed by their IDs.
|
|
195
|
-
* @private
|
|
196
|
-
*/
|
|
197
|
-
booths = {};
|
|
198
|
-
/**
|
|
199
|
-
* The current context booth ID, defaulting to the orchestrator context.
|
|
200
|
-
* @private
|
|
201
|
-
*/
|
|
202
|
-
currentContextId;
|
|
203
212
|
/**
|
|
204
213
|
* Gets the current context booth ID.
|
|
205
214
|
*
|
|
@@ -238,9 +247,7 @@ class b {
|
|
|
238
247
|
* @param boothConfig - The booth configuration to register
|
|
239
248
|
*/
|
|
240
249
|
registerBooth(t) {
|
|
241
|
-
|
|
242
|
-
throw new Error(`Booth with ID ${t.id} is already registered.`);
|
|
243
|
-
this.booths[t.id] = t;
|
|
250
|
+
this.booths[t.id] || (this.booths[t.id] = t);
|
|
244
251
|
}
|
|
245
252
|
/**
|
|
246
253
|
* Returns the base booth configuration that was provided during initialization.
|
|
@@ -290,6 +297,13 @@ class b {
|
|
|
290
297
|
getAllBooths() {
|
|
291
298
|
return this.booths;
|
|
292
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Checks if the registry is operating in a multi-booth configuration.
|
|
302
|
+
* @returns {boolean} `true` if there is more than one booth registered, otherwise `false`.
|
|
303
|
+
*/
|
|
304
|
+
get isMultiBoothMode() {
|
|
305
|
+
return Object.keys(this.booths).length > 1;
|
|
306
|
+
}
|
|
293
307
|
/**
|
|
294
308
|
* Removes a booth configuration from the registry by its ID.
|
|
295
309
|
* Throws an error if the booth doesn't exist.
|
|
@@ -302,18 +316,18 @@ class b {
|
|
|
302
316
|
delete this.booths[t];
|
|
303
317
|
}
|
|
304
318
|
}
|
|
305
|
-
class
|
|
319
|
+
class E {
|
|
306
320
|
/**
|
|
307
321
|
* Creates an instance of InteractionProcessor.
|
|
308
322
|
* @param boothRegistry - The registry for booth configurations.
|
|
309
323
|
* @param boothPlugins - The registry for booth plugins.
|
|
310
324
|
* @param toolRegistry - The registry for available tools.
|
|
311
|
-
* @param
|
|
325
|
+
* @param llmAdapter - The adapter for interacting with the LLM.
|
|
312
326
|
*/
|
|
313
327
|
constructor(t, o, e, r) {
|
|
328
|
+
s(this, "loopLimit", 10);
|
|
314
329
|
this.boothRegistry = t, this.boothPlugins = o, this.toolRegistry = e, this.llmAdapter = r;
|
|
315
330
|
}
|
|
316
|
-
loopLimit = 10;
|
|
317
331
|
/**
|
|
318
332
|
* Creates a synthetic error response with proper structure and error details.
|
|
319
333
|
* @param error - The error that occurred
|
|
@@ -389,14 +403,16 @@ class d {
|
|
|
389
403
|
{
|
|
390
404
|
toolRegistry: this.toolRegistry,
|
|
391
405
|
boothRegistry: this.boothRegistry,
|
|
392
|
-
pluginRegistry: this.boothPlugins
|
|
406
|
+
pluginRegistry: this.boothPlugins,
|
|
407
|
+
llmAdapter: this.llmAdapter
|
|
393
408
|
},
|
|
394
409
|
e
|
|
395
410
|
), r = await this.callLLM(e), e = await this.boothPlugins.runResponseReceived(
|
|
396
411
|
{
|
|
397
412
|
toolRegistry: this.toolRegistry,
|
|
398
413
|
boothRegistry: this.boothRegistry,
|
|
399
|
-
pluginRegistry: this.boothPlugins
|
|
414
|
+
pluginRegistry: this.boothPlugins,
|
|
415
|
+
llmAdapter: this.llmAdapter
|
|
400
416
|
},
|
|
401
417
|
e,
|
|
402
418
|
r
|
|
@@ -404,7 +420,8 @@ class d {
|
|
|
404
420
|
{
|
|
405
421
|
toolRegistry: this.toolRegistry,
|
|
406
422
|
boothRegistry: this.boothRegistry,
|
|
407
|
-
pluginRegistry: this.boothPlugins
|
|
423
|
+
pluginRegistry: this.boothPlugins,
|
|
424
|
+
llmAdapter: this.llmAdapter
|
|
408
425
|
},
|
|
409
426
|
e,
|
|
410
427
|
r
|
|
@@ -433,7 +450,8 @@ class d {
|
|
|
433
450
|
{
|
|
434
451
|
toolRegistry: this.toolRegistry,
|
|
435
452
|
boothRegistry: this.boothRegistry,
|
|
436
|
-
pluginRegistry: this.boothPlugins
|
|
453
|
+
pluginRegistry: this.boothPlugins,
|
|
454
|
+
llmAdapter: this.llmAdapter
|
|
437
455
|
},
|
|
438
456
|
o,
|
|
439
457
|
t
|
|
@@ -443,29 +461,87 @@ class d {
|
|
|
443
461
|
{
|
|
444
462
|
toolRegistry: this.toolRegistry,
|
|
445
463
|
boothRegistry: this.boothRegistry,
|
|
446
|
-
pluginRegistry: this.boothPlugins
|
|
464
|
+
pluginRegistry: this.boothPlugins,
|
|
465
|
+
llmAdapter: this.llmAdapter
|
|
447
466
|
},
|
|
448
467
|
e
|
|
449
468
|
), e;
|
|
450
469
|
}
|
|
451
470
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
471
|
+
const C = {
|
|
472
|
+
id: "summarizer",
|
|
473
|
+
role: 'You are a highly skilled summarization AI. Your task is to read a conversation history and provide a concise, neutral, and objective summary. The summary should capture the key points, decisions made, and any unresolved questions. It must be written from a third-person perspective and should be clear enough for another AI assistant to understand the full context and continue the conversation seamlessly without needing the original transcript. Do not add any conversational fluff or introductory phrases like "Here is the summary:".',
|
|
474
|
+
description: "A specialized booth for summarizing conversation histories."
|
|
475
|
+
}, d = "route_to_booth";
|
|
476
|
+
function w(i) {
|
|
477
|
+
const t = i.getAllBooths(), o = Object.values(t).map(
|
|
478
|
+
(r) => `- ${r.id}: ${r.role}
|
|
479
|
+
Examples:
|
|
480
|
+
${(r.examples || []).map((n) => ` - "${n}"`).join(`
|
|
481
|
+
`)}`
|
|
482
|
+
).join(`
|
|
483
|
+
`), e = Object.keys(t);
|
|
484
|
+
return {
|
|
485
|
+
type: "function",
|
|
486
|
+
name: d,
|
|
487
|
+
description: "Routes the conversation to a specialized booth based on the user's needs. Each booth has a specific role and set of capabilities.",
|
|
488
|
+
parameters: {
|
|
489
|
+
type: "object",
|
|
490
|
+
properties: {
|
|
491
|
+
targetBooth: {
|
|
492
|
+
type: "string",
|
|
493
|
+
description: `The ID of the booth to route the conversation to. Must be one of the following available booths:
|
|
494
|
+
${o}`,
|
|
495
|
+
enum: e
|
|
496
|
+
}
|
|
497
|
+
},
|
|
498
|
+
required: ["targetBooth"],
|
|
499
|
+
additionalProperties: !1
|
|
500
|
+
},
|
|
501
|
+
strict: !0,
|
|
502
|
+
/**
|
|
503
|
+
* Executes the tool's logic, which sets the current context in the `boothRegistry`
|
|
504
|
+
* to the specified `targetBooth`.
|
|
505
|
+
* @param targetBooth - The ID of the booth to switch to.
|
|
506
|
+
* @returns An object with a `content` property indicating the result of the operation.
|
|
507
|
+
*/
|
|
508
|
+
execute: async function({ targetBooth: r }) {
|
|
509
|
+
try {
|
|
510
|
+
return i.setCurrentContextId(r), {
|
|
511
|
+
content: `Routed to booth ${r}`
|
|
512
|
+
};
|
|
513
|
+
} catch (n) {
|
|
514
|
+
return console.error("[routeToBoothTool] Error routing to booth:", n), {
|
|
515
|
+
content: `Error: Unable to route to booth ${r}.`
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
let c = [];
|
|
522
|
+
class I {
|
|
523
|
+
constructor() {
|
|
524
|
+
/**
|
|
525
|
+
* Unique identifier for this plugin instance.
|
|
526
|
+
* @private
|
|
527
|
+
*/
|
|
528
|
+
s(this, "plugin_id", "conversation-history");
|
|
529
|
+
/**
|
|
530
|
+
* Display name for this plugin.
|
|
531
|
+
* @private
|
|
532
|
+
*/
|
|
533
|
+
s(this, "plugin_name", "Conversation History Plugin");
|
|
534
|
+
/**
|
|
535
|
+
* Brief description of the plugin's purpose and functionality.
|
|
536
|
+
* @private
|
|
537
|
+
*/
|
|
538
|
+
s(this, "plugin_description", "A plugin to manage conversation history in booths.");
|
|
539
|
+
}
|
|
540
|
+
responseContainsBoothChange(t) {
|
|
541
|
+
return t.output ? t.output.some((o) => o.type === "function_call" ? o.name === d : o.type === "message" && "tool_calls" in o && Array.isArray(o.tool_calls) ? o.tool_calls.some(
|
|
542
|
+
(e) => e.type === "function" && e.function.name === d
|
|
543
|
+
) : !1) : !1;
|
|
544
|
+
}
|
|
469
545
|
/**
|
|
470
546
|
* Returns the plugin's unique identifier.
|
|
471
547
|
*/
|
|
@@ -494,9 +570,9 @@ class p {
|
|
|
494
570
|
*/
|
|
495
571
|
async onBeforeInteractionLoopStart(t, o) {
|
|
496
572
|
const { input: e } = o, r = typeof e == "string" ? [{ role: "user", content: e }] : e || [];
|
|
497
|
-
return
|
|
573
|
+
return c.push(...r), {
|
|
498
574
|
...o,
|
|
499
|
-
input:
|
|
575
|
+
input: c
|
|
500
576
|
};
|
|
501
577
|
}
|
|
502
578
|
/**
|
|
@@ -509,8 +585,20 @@ class p {
|
|
|
509
585
|
* @returns Unmodified response parameters
|
|
510
586
|
*/
|
|
511
587
|
async onResponseReceived(t, o, e) {
|
|
512
|
-
|
|
513
|
-
|
|
588
|
+
let n = [...o.input, ...(e == null ? void 0 : e.output) ?? []];
|
|
589
|
+
if (this.responseContainsBoothChange(e)) {
|
|
590
|
+
const a = `Please summarize the following conversation history:
|
|
591
|
+
|
|
592
|
+
${JSON.stringify(c)}`, g = (await S(t.llmAdapter, C).callProcessor.send(a)).output_text, f = n.filter((h) => "role" in h && h.role === "user").pop(), y = {
|
|
593
|
+
role: "developer",
|
|
594
|
+
content: `A conversation summary up to this point: ${g}`
|
|
595
|
+
}, m = n.filter(
|
|
596
|
+
(h) => "type" in h && h.type === "function_call" || h.type === "function_call_output"
|
|
597
|
+
);
|
|
598
|
+
c = f ? [...m, y, f] : [...m, y], n = c;
|
|
599
|
+
} else
|
|
600
|
+
c = n;
|
|
601
|
+
return {
|
|
514
602
|
...o,
|
|
515
603
|
input: n
|
|
516
604
|
};
|
|
@@ -525,22 +613,24 @@ class p {
|
|
|
525
613
|
return !1;
|
|
526
614
|
}
|
|
527
615
|
}
|
|
528
|
-
class
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
616
|
+
class v {
|
|
617
|
+
constructor() {
|
|
618
|
+
/**
|
|
619
|
+
* Unique identifier for this plugin instance.
|
|
620
|
+
* @private
|
|
621
|
+
*/
|
|
622
|
+
s(this, "plugin_id", "context-provider");
|
|
623
|
+
/**
|
|
624
|
+
* Display the name for this plugin.
|
|
625
|
+
* @private
|
|
626
|
+
*/
|
|
627
|
+
s(this, "plugin_name", "Context Provider Plugin");
|
|
628
|
+
/**
|
|
629
|
+
* Brief description of the plugin's purpose and functionality.
|
|
630
|
+
* @private
|
|
631
|
+
*/
|
|
632
|
+
s(this, "plugin_description", "A plugin to provide context to booths.");
|
|
633
|
+
}
|
|
544
634
|
/**
|
|
545
635
|
* Returns the plugin's unique identifier.
|
|
546
636
|
*/
|
|
@@ -568,11 +658,17 @@ class f {
|
|
|
568
658
|
* @returns Updated response parameters with added instructions containing booth context
|
|
569
659
|
*/
|
|
570
660
|
async onBeforeMessageSend(t, o) {
|
|
571
|
-
const e = t.boothRegistry
|
|
572
|
-
let n = e.description;
|
|
573
|
-
|
|
661
|
+
const e = t.boothRegistry;
|
|
662
|
+
let n = e.baseBoothConfig.description;
|
|
663
|
+
if (e.isMultiBoothMode) {
|
|
664
|
+
const l = e.orchestratorBoothConfig, a = e.currentContextBoothConfig;
|
|
665
|
+
n += `
|
|
666
|
+
|
|
667
|
+
${l.description}`, a.id !== l.id && (n += `
|
|
574
668
|
|
|
575
|
-
${
|
|
669
|
+
${a.description}`);
|
|
670
|
+
}
|
|
671
|
+
return { ...o, instructions: n };
|
|
576
672
|
}
|
|
577
673
|
/**
|
|
578
674
|
* Determines whether the interaction loop should end.
|
|
@@ -584,12 +680,12 @@ class f {
|
|
|
584
680
|
return !1;
|
|
585
681
|
}
|
|
586
682
|
}
|
|
587
|
-
class
|
|
588
|
-
tools;
|
|
683
|
+
class A {
|
|
589
684
|
/**
|
|
590
685
|
* Initializes an empty Map to store tools.
|
|
591
686
|
*/
|
|
592
687
|
constructor() {
|
|
688
|
+
s(this, "tools");
|
|
593
689
|
this.tools = /* @__PURE__ */ new Map();
|
|
594
690
|
}
|
|
595
691
|
registerTools(t) {
|
|
@@ -640,10 +736,12 @@ class m {
|
|
|
640
736
|
this.tools.delete(t);
|
|
641
737
|
}
|
|
642
738
|
}
|
|
643
|
-
class
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
739
|
+
class P {
|
|
740
|
+
constructor() {
|
|
741
|
+
s(this, "description", "A plugin to aggregate and provide tools from base and context booths.");
|
|
742
|
+
s(this, "id", "tool-provider");
|
|
743
|
+
s(this, "name", "Tool Provider Plugin");
|
|
744
|
+
}
|
|
647
745
|
/**
|
|
648
746
|
* Before a message is sent, this hook gathers the tool keys from both the base and context booths,
|
|
649
747
|
* retrieves the corresponding tool definitions from the `toolRegistry`, and adds them to the
|
|
@@ -653,18 +751,22 @@ class y {
|
|
|
653
751
|
* @returns The updated response parameters with the aggregated list of tools.
|
|
654
752
|
*/
|
|
655
753
|
async onBeforeMessageSend(t, o) {
|
|
656
|
-
const e = t.boothRegistry.baseBoothConfig, r = t.boothRegistry.currentContextBoothConfig, n = [...e.tools || [], ...r
|
|
754
|
+
const e = t.boothRegistry.baseBoothConfig, r = t.boothRegistry.currentContextBoothConfig, n = [...e.tools || [], ...(r == null ? void 0 : r.tools) || []], l = /* @__PURE__ */ new Set();
|
|
657
755
|
for (const u of n) {
|
|
658
|
-
if (
|
|
756
|
+
if (l.has(u))
|
|
659
757
|
throw new Error(`Duplicate tool key detected: ${u}`);
|
|
660
|
-
|
|
758
|
+
l.add(u);
|
|
661
759
|
}
|
|
662
|
-
const
|
|
760
|
+
const a = n.map(
|
|
663
761
|
(u) => t.toolRegistry.getTool(u)
|
|
664
762
|
);
|
|
665
|
-
|
|
763
|
+
if (e.mcp && a.push(...e.mcp), r != null && r.mcp && a.push(...r.mcp), t.boothRegistry.isMultiBoothMode) {
|
|
764
|
+
const u = w(t.boothRegistry);
|
|
765
|
+
a.push(u);
|
|
766
|
+
}
|
|
767
|
+
return {
|
|
666
768
|
...o,
|
|
667
|
-
tools:
|
|
769
|
+
tools: a
|
|
668
770
|
};
|
|
669
771
|
}
|
|
670
772
|
/**
|
|
@@ -676,16 +778,18 @@ class y {
|
|
|
676
778
|
return !1;
|
|
677
779
|
}
|
|
678
780
|
}
|
|
679
|
-
class
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
781
|
+
class x {
|
|
782
|
+
constructor() {
|
|
783
|
+
s(this, "id", "tool-executor");
|
|
784
|
+
s(this, "name", "Tool Executor");
|
|
785
|
+
s(this, "description", "Checks for tool calls in the response, executes them, and adds the results to the message history.");
|
|
786
|
+
}
|
|
683
787
|
/**
|
|
684
788
|
* Executes a single tool call with proper hook integration.
|
|
685
789
|
* @param utilities - Repository utilities for accessing registries.
|
|
686
790
|
* @param toolCall - The tool call to execute.
|
|
687
791
|
* @param context - Context information about the tool call execution.
|
|
688
|
-
* @returns The function
|
|
792
|
+
* @returns The function calls output item for the response.
|
|
689
793
|
* @private
|
|
690
794
|
*/
|
|
691
795
|
async executeToolCall(t, o, e) {
|
|
@@ -701,16 +805,16 @@ class w {
|
|
|
701
805
|
call_id: r.call_id,
|
|
702
806
|
output: `Error: Tool '${r.name}' not found.`
|
|
703
807
|
};
|
|
704
|
-
const
|
|
808
|
+
const l = await n.execute(JSON.parse(r.arguments)), a = await t.pluginRegistry.runAfterToolCall(
|
|
705
809
|
t,
|
|
706
810
|
r,
|
|
707
|
-
|
|
811
|
+
l,
|
|
708
812
|
e
|
|
709
813
|
);
|
|
710
814
|
return {
|
|
711
815
|
type: "function_call_output",
|
|
712
816
|
call_id: r.call_id,
|
|
713
|
-
output: JSON.stringify(
|
|
817
|
+
output: JSON.stringify(a)
|
|
714
818
|
};
|
|
715
819
|
} catch (r) {
|
|
716
820
|
console.error(`Error executing tool ${o.name}:`, r);
|
|
@@ -737,24 +841,24 @@ class w {
|
|
|
737
841
|
* @returns The updated response parameters, potentially with tool call outputs added to the input.
|
|
738
842
|
*/
|
|
739
843
|
async onResponseReceived(t, o, e) {
|
|
740
|
-
const
|
|
741
|
-
(
|
|
742
|
-
) ?? [];
|
|
844
|
+
const r = (e == null ? void 0 : e.output) ?? [], n = (r == null ? void 0 : r.filter(
|
|
845
|
+
(a) => a.type === "function_call"
|
|
846
|
+
)) ?? [];
|
|
743
847
|
if (!n.length)
|
|
744
848
|
return o;
|
|
745
|
-
const
|
|
746
|
-
for (let
|
|
747
|
-
const u = n[
|
|
849
|
+
const l = [];
|
|
850
|
+
for (let a = 0; a < n.length; a++) {
|
|
851
|
+
const u = n[a], p = {
|
|
748
852
|
responseParams: o,
|
|
749
853
|
response: e,
|
|
750
|
-
toolCallIndex:
|
|
854
|
+
toolCallIndex: a,
|
|
751
855
|
totalToolCalls: n.length
|
|
752
|
-
},
|
|
753
|
-
|
|
856
|
+
}, g = await this.executeToolCall(t, u, p);
|
|
857
|
+
l.push(g);
|
|
754
858
|
}
|
|
755
859
|
return {
|
|
756
860
|
...o,
|
|
757
|
-
input: [...o.input, ...
|
|
861
|
+
input: [...o.input, ...l]
|
|
758
862
|
};
|
|
759
863
|
}
|
|
760
864
|
/**
|
|
@@ -766,55 +870,12 @@ class w {
|
|
|
766
870
|
return !1;
|
|
767
871
|
}
|
|
768
872
|
}
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
(
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
).join(`
|
|
776
|
-
`), e = Object.keys(t);
|
|
777
|
-
return {
|
|
778
|
-
type: "function",
|
|
779
|
-
name: "route_to_booth",
|
|
780
|
-
description: "Routes the conversation to a specialized booth based on the user's needs. Each booth has a specific role and set of capabilities.",
|
|
781
|
-
parameters: {
|
|
782
|
-
type: "object",
|
|
783
|
-
properties: {
|
|
784
|
-
targetBooth: {
|
|
785
|
-
type: "string",
|
|
786
|
-
description: `The ID of the booth to route the conversation to. Must be one of the following available booths:
|
|
787
|
-
${o}`,
|
|
788
|
-
enum: e
|
|
789
|
-
}
|
|
790
|
-
},
|
|
791
|
-
required: ["targetBooth"],
|
|
792
|
-
additionalProperties: !1
|
|
793
|
-
},
|
|
794
|
-
strict: !0,
|
|
795
|
-
/**
|
|
796
|
-
* Executes the tool's logic, which sets the current context in the `boothRegistry`
|
|
797
|
-
* to the specified `targetBooth`.
|
|
798
|
-
* @param targetBooth - The ID of the booth to switch to.
|
|
799
|
-
* @returns An object with a `content` property indicating the result of the operation.
|
|
800
|
-
*/
|
|
801
|
-
execute: async function({ targetBooth: r }) {
|
|
802
|
-
try {
|
|
803
|
-
return i.setCurrentContextId(r), {
|
|
804
|
-
content: `Routed to booth ${r}`
|
|
805
|
-
};
|
|
806
|
-
} catch (n) {
|
|
807
|
-
return console.error("[routeToBoothTool] Error routing to booth:", n), {
|
|
808
|
-
content: `Error: Unable to route to booth ${r}.`
|
|
809
|
-
};
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
};
|
|
813
|
-
}
|
|
814
|
-
class R {
|
|
815
|
-
description = "A plugin to ensure the interaction loop can be finished.";
|
|
816
|
-
id = "finish-turn-plugin";
|
|
817
|
-
name = "Finish Turn Plugin";
|
|
873
|
+
class L {
|
|
874
|
+
constructor() {
|
|
875
|
+
s(this, "description", "A plugin to ensure the interaction loop can be finished.");
|
|
876
|
+
s(this, "id", "finish-turn-plugin");
|
|
877
|
+
s(this, "name", "Finish Turn Plugin");
|
|
878
|
+
}
|
|
818
879
|
/**
|
|
819
880
|
* Before sending a message, this hook adds an instruction to the LLM to include a
|
|
820
881
|
* specific marker (`__awaiting_user_response__`) when it expects a user response.
|
|
@@ -830,7 +891,7 @@ class R {
|
|
|
830
891
|
|
|
831
892
|
[MUST]
|
|
832
893
|
- Add the marker "__awaiting_user_response__" to the end of your response when you expect a user response.
|
|
833
|
-
- This marker indicates that the interaction loop should end and the system should wait for user input
|
|
894
|
+
- This marker indicates that the interaction loop should end and the system should wait for user input.
|
|
834
895
|
- If the marker is not present, the system will continue to process the response as usual.
|
|
835
896
|
`, {
|
|
836
897
|
...o,
|
|
@@ -867,51 +928,51 @@ class R {
|
|
|
867
928
|
return o;
|
|
868
929
|
}
|
|
869
930
|
}
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
931
|
+
const b = {
|
|
932
|
+
id: "orchestrator",
|
|
933
|
+
role: `
|
|
934
|
+
This booth serves as the orchestration layer that analyzes user intent and routes
|
|
935
|
+
conversations to the most appropriate specialized booth configuration.
|
|
936
|
+
`,
|
|
937
|
+
description: `
|
|
938
|
+
You are the orchestration layer responsible for determining which booth configuration
|
|
939
|
+
should be active based on user needs. Focus exclusively on routing - do not answer
|
|
940
|
+
questions or provide information directly to users.
|
|
941
|
+
|
|
942
|
+
[ROUTING STRATEGY]
|
|
943
|
+
- Analyze user request and route to the most appropriate specialized booth immediately
|
|
944
|
+
- This booth is only active for initial routing or when explicitly routed back to
|
|
945
|
+
- Once routed, the target booth handles the conversation until completion or re-routing
|
|
946
|
+
|
|
947
|
+
[ROUTING TARGETS]
|
|
948
|
+
- Ambiguous requests → Ask for clarification, then route appropriately
|
|
949
|
+
|
|
950
|
+
[CORE PRINCIPLES]
|
|
951
|
+
- Maintain illusion of single, continuous assistant
|
|
952
|
+
- Never reference booths, tools, or system mechanics to users
|
|
953
|
+
- Silent routing is preferred when intent is clear
|
|
954
|
+
- Only speak to users when clarification is absolutely necessary
|
|
955
|
+
|
|
956
|
+
[ROUTING BEHAVIOR]
|
|
957
|
+
- Clear intent: Route silently using route_to_booth() - do NOT respond to user
|
|
958
|
+
- Ambiguous intent: Ask user for clarification, then route once clarified
|
|
959
|
+
- Never respond to user AND route - it's either respond OR route, not both
|
|
960
|
+
|
|
961
|
+
[BEHAVIOR EXAMPLES]
|
|
962
|
+
- User: "How do I test my number?" → route_to_booth({ targetBooth: 'page-router-booth' })
|
|
963
|
+
- User: "I need help" → "What specifically would you like help with?" → then route based on response
|
|
964
|
+
`
|
|
965
|
+
};
|
|
966
|
+
function S(i, t) {
|
|
967
|
+
const o = new T(t), e = new A(), r = new R();
|
|
968
|
+
return new M({
|
|
969
|
+
llmAdapter: i,
|
|
970
|
+
booths: o,
|
|
971
|
+
tools: e,
|
|
972
|
+
boothPlugins: r
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
class M {
|
|
915
976
|
/**
|
|
916
977
|
* Initializes a new instance of the CoreBooth class.
|
|
917
978
|
* Sets up the plugin registries, system plugins, and interaction processor.
|
|
@@ -922,15 +983,62 @@ class B {
|
|
|
922
983
|
* @param {ToolRegistry} options.tools - Registry containing tool configurations
|
|
923
984
|
*/
|
|
924
985
|
constructor(t) {
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
986
|
+
/**
|
|
987
|
+
* Represents a registry that maintains a collection of plugins for a booth system.
|
|
988
|
+
* The boothPluginRegistry is used to manage and access plugins that enhance
|
|
989
|
+
* or extend the booth's behavior or features.
|
|
990
|
+
*
|
|
991
|
+
* This variable is intended to provide a central location for plugin registration,
|
|
992
|
+
* retrieval, and management.
|
|
993
|
+
*
|
|
994
|
+
* @type {BoothPluginRegistry}
|
|
995
|
+
*/
|
|
996
|
+
s(this, "boothPluginRegistry");
|
|
997
|
+
/**
|
|
998
|
+
* Registry for managing booth configurations across the system.
|
|
999
|
+
* This registry maintains a collection of booth definitions that can be
|
|
1000
|
+
* accessed by their unique identifiers.
|
|
1001
|
+
*
|
|
1002
|
+
* @type {BoothRegistry}
|
|
1003
|
+
*/
|
|
1004
|
+
s(this, "boothRegistry");
|
|
1005
|
+
/**
|
|
1006
|
+
* Primary processor for handling interactions between users and the booth system.
|
|
1007
|
+
* Responsible for sending messages to the LLM, processing responses, and managing
|
|
1008
|
+
* the interaction loop through plugins.
|
|
1009
|
+
*
|
|
1010
|
+
* @type {InteractionProcessor}
|
|
1011
|
+
*/
|
|
1012
|
+
s(this, "callProcessor");
|
|
1013
|
+
/**
|
|
1014
|
+
* Registry dedicated to system-level plugins that are always available.
|
|
1015
|
+
* This includes core functionality plugins like conversation history and context providers,
|
|
1016
|
+
* as well as any user-defined plugins from the boothPluginRegistry.
|
|
1017
|
+
*
|
|
1018
|
+
* @type {BoothPluginRegistry}
|
|
1019
|
+
*/
|
|
1020
|
+
s(this, "systemPluginsRegistry");
|
|
1021
|
+
/**
|
|
1022
|
+
* A variable that represents a registry for managing and maintaining a collection of tools.
|
|
1023
|
+
* `toolRegistry` is an instance of the `ToolRegistry` class, which provides functionalities
|
|
1024
|
+
* for adding, removing, and retrieving tools.
|
|
1025
|
+
*
|
|
1026
|
+
* The `ToolRegistry` class typically serves as a centralized storage or management
|
|
1027
|
+
* solution for tools that are used in a specific context or application.
|
|
1028
|
+
*/
|
|
1029
|
+
s(this, "toolRegistry");
|
|
1030
|
+
if (this.boothPluginRegistry = t.boothPlugins, this.boothRegistry = t.booths, this.toolRegistry = t.tools, this.boothRegistry.isMultiBoothMode) {
|
|
1031
|
+
this.boothRegistry.registerBooth(b), this.boothRegistry.setCurrentContextId(b.id);
|
|
1032
|
+
const o = w(this.boothRegistry);
|
|
1033
|
+
this.toolRegistry.registerTools([o]);
|
|
1034
|
+
}
|
|
1035
|
+
this.systemPluginsRegistry = new R(), this.systemPluginsRegistry.registerPlugins([
|
|
1036
|
+
new I(),
|
|
1037
|
+
new v(),
|
|
1038
|
+
new P(),
|
|
1039
|
+
new x(),
|
|
1040
|
+
new L()
|
|
1041
|
+
]), this.systemPluginsRegistry.registerPlugins(this.boothPluginRegistry.getPlugins()), this.callProcessor = new E(
|
|
934
1042
|
this.boothRegistry,
|
|
935
1043
|
this.systemPluginsRegistry,
|
|
936
1044
|
this.toolRegistry,
|
|
@@ -939,15 +1047,16 @@ class B {
|
|
|
939
1047
|
}
|
|
940
1048
|
}
|
|
941
1049
|
export {
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1050
|
+
R as BoothPluginRegistry,
|
|
1051
|
+
T as BoothRegistry,
|
|
1052
|
+
v as ContextProviderPlugin,
|
|
1053
|
+
I as ConversationHistoryPlugin,
|
|
1054
|
+
M as CoreBooth,
|
|
1055
|
+
L as FinishTurnPlugin,
|
|
1056
|
+
E as InteractionProcessor,
|
|
1057
|
+
x as ToolExecutorPlugin,
|
|
1058
|
+
P as ToolProviderPlugin,
|
|
1059
|
+
A as ToolRegistry,
|
|
1060
|
+
S as createCoreBooth,
|
|
1061
|
+
w as createRouteToBoothTool
|
|
953
1062
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "booths",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.0
|
|
4
|
+
"version": "0.1.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -18,18 +18,25 @@
|
|
|
18
18
|
"scripts": {
|
|
19
19
|
"dev": "vite",
|
|
20
20
|
"build": "tsc && vite build",
|
|
21
|
-
"preview": "vite preview"
|
|
21
|
+
"preview": "vite preview",
|
|
22
|
+
"format": "prettier --write \"src/**/*.{js,ts,vue,json,css,scss,md}\""
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"@eslint/js": "^9.30.1",
|
|
25
26
|
"@types/node": "^24.0.11",
|
|
27
|
+
"@vitejs/plugin-vue": "^5.2.4",
|
|
28
|
+
"@vue/eslint-config-prettier": "^10.2.0",
|
|
29
|
+
"dotenv": "^17.2.0",
|
|
26
30
|
"eslint": "^9.30.1",
|
|
27
|
-
"
|
|
31
|
+
"eslint-config-prettier": "^10.1.5",
|
|
32
|
+
"openai": "^5.9.0",
|
|
33
|
+
"prettier": "^3.6.2",
|
|
28
34
|
"typescript": "~5.8.3",
|
|
29
35
|
"typescript-eslint": "^8.36.0",
|
|
30
|
-
"vite": "^
|
|
36
|
+
"vite": "^6.3.5",
|
|
31
37
|
"vite-plugin-dts": "^4.5.4",
|
|
32
|
-
"vite-tsconfig-paths": "^5.1.4"
|
|
38
|
+
"vite-tsconfig-paths": "^5.1.4",
|
|
39
|
+
"vue": "^3.5.17"
|
|
33
40
|
},
|
|
34
41
|
"peerDependencies": {
|
|
35
42
|
"openai": "^5.8.2"
|