@agentica/core 0.12.0 → 0.12.2-dev.20250314

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.
Files changed (83) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +461 -461
  3. package/lib/Agentica.js +3 -1
  4. package/lib/Agentica.js.map +1 -1
  5. package/lib/context/internal/AgenticaTokenUsageAggregator.js +1 -1
  6. package/lib/context/internal/AgenticaTokenUsageAggregator.js.map +1 -1
  7. package/lib/index.mjs +5 -2
  8. package/lib/index.mjs.map +1 -1
  9. package/package.json +1 -1
  10. package/prompts/cancel.md +4 -4
  11. package/prompts/common.md +2 -2
  12. package/prompts/describe.md +6 -6
  13. package/prompts/execute.md +6 -6
  14. package/prompts/initialize.md +2 -2
  15. package/prompts/select.md +6 -6
  16. package/src/Agentica.ts +359 -356
  17. package/src/chatgpt/ChatGptAgent.ts +76 -76
  18. package/src/chatgpt/ChatGptCallFunctionAgent.ts +466 -466
  19. package/src/chatgpt/ChatGptCancelFunctionAgent.ts +280 -280
  20. package/src/chatgpt/ChatGptCompletionMessageUtil.ts +166 -166
  21. package/src/chatgpt/ChatGptDescribeFunctionAgent.ts +122 -122
  22. package/src/chatgpt/ChatGptHistoryDecoder.ts +88 -88
  23. package/src/chatgpt/ChatGptInitializeFunctionAgent.ts +96 -96
  24. package/src/chatgpt/ChatGptSelectFunctionAgent.ts +311 -311
  25. package/src/chatgpt/ChatGptUsageAggregator.ts +62 -62
  26. package/src/context/AgenticaCancelPrompt.ts +32 -32
  27. package/src/context/AgenticaClassOperation.ts +23 -23
  28. package/src/context/AgenticaContext.ts +130 -130
  29. package/src/context/AgenticaHttpOperation.ts +27 -27
  30. package/src/context/AgenticaOperation.ts +66 -66
  31. package/src/context/AgenticaOperationBase.ts +57 -57
  32. package/src/context/AgenticaOperationCollection.ts +52 -52
  33. package/src/context/AgenticaOperationSelection.ts +27 -27
  34. package/src/context/AgenticaTokenUsage.ts +170 -170
  35. package/src/context/internal/AgenticaTokenUsageAggregator.ts +66 -66
  36. package/src/context/internal/__IChatCancelFunctionsApplication.ts +23 -23
  37. package/src/context/internal/__IChatFunctionReference.ts +21 -21
  38. package/src/context/internal/__IChatInitialApplication.ts +15 -15
  39. package/src/context/internal/__IChatSelectFunctionsApplication.ts +24 -24
  40. package/src/events/AgenticaCallEvent.ts +36 -36
  41. package/src/events/AgenticaCancelEvent.ts +28 -28
  42. package/src/events/AgenticaDescribeEvent.ts +66 -66
  43. package/src/events/AgenticaEvent.ts +36 -36
  44. package/src/events/AgenticaEventBase.ts +7 -7
  45. package/src/events/AgenticaEventSource.ts +6 -6
  46. package/src/events/AgenticaExecuteEvent.ts +50 -50
  47. package/src/events/AgenticaInitializeEvent.ts +14 -14
  48. package/src/events/AgenticaRequestEvent.ts +45 -45
  49. package/src/events/AgenticaResponseEvent.ts +48 -48
  50. package/src/events/AgenticaSelectEvent.ts +37 -37
  51. package/src/events/AgenticaTextEvent.ts +62 -62
  52. package/src/functional/assertHttpLlmApplication.ts +55 -55
  53. package/src/functional/validateHttpLlmApplication.ts +66 -66
  54. package/src/index.ts +44 -44
  55. package/src/internal/AgenticaConstant.ts +4 -4
  56. package/src/internal/AgenticaDefaultPrompt.ts +43 -43
  57. package/src/internal/AgenticaOperationComposer.ts +96 -96
  58. package/src/internal/ByteArrayUtil.ts +5 -5
  59. package/src/internal/MPSCUtil.ts +111 -111
  60. package/src/internal/MathUtil.ts +3 -3
  61. package/src/internal/Singleton.ts +22 -22
  62. package/src/internal/StreamUtil.ts +64 -64
  63. package/src/internal/__map_take.ts +15 -15
  64. package/src/json/IAgenticaEventJson.ts +178 -178
  65. package/src/json/IAgenticaOperationJson.ts +36 -36
  66. package/src/json/IAgenticaOperationSelectionJson.ts +19 -19
  67. package/src/json/IAgenticaPromptJson.ts +130 -130
  68. package/src/json/IAgenticaTokenUsageJson.ts +107 -107
  69. package/src/prompts/AgenticaCancelPrompt.ts +32 -32
  70. package/src/prompts/AgenticaDescribePrompt.ts +41 -41
  71. package/src/prompts/AgenticaExecutePrompt.ts +52 -52
  72. package/src/prompts/AgenticaPrompt.ts +14 -14
  73. package/src/prompts/AgenticaPromptBase.ts +27 -27
  74. package/src/prompts/AgenticaSelectPrompt.ts +32 -32
  75. package/src/prompts/AgenticaTextPrompt.ts +31 -31
  76. package/src/structures/IAgenticaConfig.ts +123 -123
  77. package/src/structures/IAgenticaController.ts +133 -133
  78. package/src/structures/IAgenticaExecutor.ts +157 -157
  79. package/src/structures/IAgenticaProps.ts +69 -69
  80. package/src/structures/IAgenticaSystemPrompt.ts +125 -125
  81. package/src/structures/IAgenticaVendor.ts +39 -39
  82. package/src/transformers/AgenticaEventTransformer.ts +165 -165
  83. package/src/transformers/AgenticaPromptTransformer.ts +134 -134
package/src/Agentica.ts CHANGED
@@ -1,356 +1,359 @@
1
- import { ILlmSchema } from "@samchon/openapi";
2
-
3
- import { ChatGptAgent } from "./chatgpt/ChatGptAgent";
4
- import { ChatGptCompletionMessageUtil } from "./chatgpt/ChatGptCompletionMessageUtil";
5
- import { AgenticaContext } from "./context/AgenticaContext";
6
- import { AgenticaOperation } from "./context/AgenticaOperation";
7
- import { AgenticaOperationCollection } from "./context/AgenticaOperationCollection";
8
- import { AgenticaOperationSelection } from "./context/AgenticaOperationSelection";
9
- import { AgenticaTokenUsage } from "./context/AgenticaTokenUsage";
10
- import { AgenticaTokenUsageAggregator } from "./context/internal/AgenticaTokenUsageAggregator";
11
- import { AgenticaEvent } from "./events/AgenticaEvent";
12
- import { AgenticaInitializeEvent } from "./events/AgenticaInitializeEvent";
13
- import { AgenticaRequestEvent } from "./events/AgenticaRequestEvent";
14
- import { AgenticaTextEvent } from "./events/AgenticaTextEvent";
15
- import { AgenticaOperationComposer } from "./internal/AgenticaOperationComposer";
16
- import { StreamUtil } from "./internal/StreamUtil";
17
- import { __map_take } from "./internal/__map_take";
18
- import { AgenticaPrompt } from "./prompts/AgenticaPrompt";
19
- import { AgenticaTextPrompt } from "./prompts/AgenticaTextPrompt";
20
- import { IAgenticaConfig } from "./structures/IAgenticaConfig";
21
- import { IAgenticaController } from "./structures/IAgenticaController";
22
- import { IAgenticaProps } from "./structures/IAgenticaProps";
23
- import { IAgenticaVendor } from "./structures/IAgenticaVendor";
24
- import { AgenticaPromptTransformer } from "./transformers/AgenticaPromptTransformer";
25
-
26
- /**
27
- * Nestia A.I. chatbot agent.
28
- *
29
- * `Agentica` is a facade class for the super A.I. chatbot agent
30
- * which performs the {@link conversate user's conversation function}
31
- * with LLM (Large Language Model) function calling and manages the
32
- * {@link getPromptHistories prompt histories}.
33
- *
34
- * To understand and compose the `Agentica` class exactly, reference
35
- * below types concentrating on the documentation comments please.
36
- * Especially, you have to be careful about the {@link IAgenticaProps}
37
- * type which is used in the {@link constructor} function.
38
- *
39
- * - Constructors
40
- * - {@link IAgenticaProps}
41
- * - {@link IAgenticaVendor}
42
- * - {@link IAgenticaController}
43
- * - {@link IAgenticaConfig}
44
- * - {@link IAgenticaSystemPrompt}
45
- * - Accessors
46
- * - {@link IAgenticaOperation}
47
- * - {@link IAgenticaPromptJson}
48
- * - {@link IAgenticaEventJson}
49
- * - {@link IAgenticaTokenUsageJson}
50
- *
51
- * @author Samchon
52
- */
53
- export class Agentica<Model extends ILlmSchema.Model> {
54
- // THE OPERATIONS
55
- private readonly operations_: AgenticaOperationCollection<Model>;
56
-
57
- // STACK
58
- private readonly stack_: AgenticaOperationSelection<Model>[];
59
- private readonly prompt_histories_: AgenticaPrompt<Model>[];
60
- private readonly listeners_: Map<string, Set<Function>>;
61
-
62
- // STATUS
63
- private readonly token_usage_: AgenticaTokenUsage;
64
- private ready_: boolean;
65
- private readonly executor_: (
66
- ctx: AgenticaContext<Model>,
67
- ) => Promise<AgenticaPrompt<Model>[]>;
68
-
69
- /* -----------------------------------------------------------
70
- CONSTRUCTOR
71
- ----------------------------------------------------------- */
72
- /**
73
- * Initializer constructor.
74
- *
75
- * @param props Properties to construct the agent
76
- */
77
- public constructor(private readonly props: IAgenticaProps<Model>) {
78
- // OPERATIONS
79
- this.operations_ = AgenticaOperationComposer.compose({
80
- controllers: props.controllers,
81
- config: props.config,
82
- });
83
-
84
- // STATUS
85
- this.stack_ = [];
86
- this.listeners_ = new Map();
87
- this.prompt_histories_ = (props.histories ?? []).map((input) =>
88
- AgenticaPromptTransformer.transform({
89
- operations: this.operations_.group,
90
- prompt: input,
91
- }),
92
- );
93
-
94
- // STATUS
95
- this.token_usage_ = AgenticaTokenUsage.zero();
96
- this.ready_ = false;
97
- this.executor_ =
98
- typeof props.config?.executor === "function"
99
- ? props.config.executor
100
- : ChatGptAgent.execute(props.config?.executor ?? null);
101
- }
102
-
103
- /**
104
- * @internal
105
- */
106
- public clone(): Agentica<Model> {
107
- return new Agentica({
108
- ...this.props,
109
- histories: this.props.histories?.slice(),
110
- });
111
- }
112
-
113
- /* -----------------------------------------------------------
114
- ACCESSORS
115
- ----------------------------------------------------------- */
116
- /**
117
- * Conversate with the A.I. chatbot.
118
- *
119
- * User talks to the A.I. chatbot with the content.
120
- *
121
- * When the user's conversation implies the A.I. chatbot to execute a
122
- * function calling, the returned chat prompts will contain the
123
- * function calling information like {@link IAgenticaPromptJson.IExecute}.
124
- *
125
- * @param content The content to talk
126
- * @returns List of newly created chat prompts
127
- */
128
- public async conversate(content: string): Promise<AgenticaPrompt<Model>[]> {
129
- const prompt: AgenticaTextPrompt<"user"> = new AgenticaTextPrompt({
130
- role: "user",
131
- text: content,
132
- });
133
- await this.dispatch(
134
- new AgenticaTextEvent({
135
- role: "user",
136
- stream: StreamUtil.to(content),
137
- done: () => true,
138
- get: () => content,
139
- join: () => Promise.resolve(content),
140
- }),
141
- );
142
-
143
- const newbie: AgenticaPrompt<Model>[] = await this.executor_(
144
- this.getContext({
145
- prompt,
146
- usage: this.token_usage_,
147
- }),
148
- );
149
- this.prompt_histories_.push(prompt, ...newbie);
150
- return [prompt, ...newbie];
151
- }
152
-
153
- /**
154
- * Get configuration.
155
- */
156
- public getConfig(): IAgenticaConfig<Model> | undefined {
157
- return this.props.config;
158
- }
159
-
160
- /**
161
- * Get LLM vendor.
162
- */
163
- public getVendor(): IAgenticaVendor {
164
- return this.props.vendor;
165
- }
166
-
167
- /**
168
- * Get controllers.
169
- *
170
- * Get list of controllers, which are the collection of functions that
171
- * the "Super A.I. Chatbot" can execute.
172
- */
173
- public getControllers(): ReadonlyArray<IAgenticaController<Model>> {
174
- return this.props.controllers;
175
- }
176
-
177
- /**
178
- * Get operations.
179
- *
180
- * Get list of operations, which has capsuled the pair of controller
181
- * and function from the {@link getControllers controllers}.
182
- *
183
- * @returns
184
- */
185
- public getOperations(): ReadonlyArray<AgenticaOperation<Model>> {
186
- return this.operations_.array;
187
- }
188
-
189
- /**
190
- * Get the chatbot's prompt histories.
191
- *
192
- * Get list of chat prompts that the chatbot has been conversated.
193
- *
194
- * @returns List of chat prompts
195
- */
196
- public getPromptHistories(): AgenticaPrompt<Model>[] {
197
- return this.prompt_histories_;
198
- }
199
-
200
- /**
201
- * Get token usage of the A.I. chatbot.
202
- *
203
- * Entire token usage of the A.I. chatbot during the conversating
204
- * with the user by {@link conversate} method callings.
205
- *
206
- * @returns Cost of the A.I. chatbot
207
- */
208
- public getTokenUsage(): AgenticaTokenUsage {
209
- return this.token_usage_;
210
- }
211
-
212
- /**
213
- * @internal
214
- */
215
- public getContext(props: {
216
- prompt: AgenticaTextPrompt<"user">;
217
- usage: AgenticaTokenUsage;
218
- }): AgenticaContext<Model> {
219
- const dispatch = (event: AgenticaEvent<Model>) => this.dispatch(event);
220
- return {
221
- // APPLICATION
222
- operations: this.operations_,
223
- config: this.props.config,
224
-
225
- // STATES
226
- histories: this.prompt_histories_,
227
- stack: this.stack_,
228
- ready: () => this.ready_,
229
- prompt: props.prompt,
230
-
231
- // HANDLERS
232
- dispatch: (event) => this.dispatch(event),
233
- request: async (source, body) => {
234
- // request information
235
- const event: AgenticaRequestEvent = new AgenticaRequestEvent({
236
- source,
237
- body: {
238
- ...body,
239
- model: this.props.vendor.model,
240
- stream: true,
241
- },
242
- options: this.props.vendor.options,
243
- });
244
- await dispatch(event);
245
-
246
- // completion
247
- const completion = await this.props.vendor.api.chat.completions.create(
248
- event.body,
249
- event.options,
250
- );
251
-
252
- const [streamForEvent, temporaryStream] = StreamUtil.transform(
253
- completion.toReadableStream() as ReadableStream<Uint8Array>,
254
- (value) =>
255
- ChatGptCompletionMessageUtil.transformCompletionChunk(value),
256
- ).tee();
257
-
258
- const [streamForAggregate, streamForReturn] = temporaryStream.tee();
259
-
260
- void (async () => {
261
- const reader = streamForAggregate.getReader();
262
- while (true) {
263
- const chunk = await reader.read();
264
- if (chunk.done) break;
265
- if (chunk.value.usage) {
266
- AgenticaTokenUsageAggregator.aggregate({
267
- kind: source,
268
- completionUsage: chunk.value.usage,
269
- usage: props.usage,
270
- });
271
- }
272
- }
273
- })();
274
-
275
- await dispatch({
276
- type: "response",
277
- source: source,
278
- stream: streamForEvent,
279
- body: event.body,
280
- options: event.options,
281
- join: async () => {
282
- const chunks = await StreamUtil.readAll(streamForEvent);
283
- return ChatGptCompletionMessageUtil.merge(chunks);
284
- },
285
- });
286
-
287
- return streamForReturn;
288
- },
289
- initialize: async () => {
290
- this.ready_ = true;
291
- await dispatch(new AgenticaInitializeEvent());
292
- },
293
- };
294
- }
295
-
296
- /* -----------------------------------------------------------
297
- EVENT HANDLERS
298
- ----------------------------------------------------------- */
299
- /**
300
- * Add an event listener.
301
- *
302
- * Add an event listener to be called whenever the event is emitted.
303
- *
304
- * @param type Type of event
305
- * @param listener Callback function to be called whenever the event is emitted
306
- */
307
- public on<Type extends AgenticaEvent.Type>(
308
- type: Type,
309
- listener: (
310
- event: AgenticaEvent.Mapper<Model>[Type],
311
- ) => void | Promise<void>,
312
- ): this {
313
- __map_take(this.listeners_, type, () => new Set()).add(listener);
314
- return this;
315
- }
316
-
317
- /**
318
- * Erase an event listener.
319
- *
320
- * Erase an event listener to stop calling the callback function.
321
- *
322
- * @param type Type of event
323
- * @param listener Callback function to erase
324
- */
325
- public off<Type extends AgenticaEvent.Type>(
326
- type: Type,
327
- listener: (
328
- event: AgenticaEvent.Mapper<Model>[Type],
329
- ) => void | Promise<void>,
330
- ): this {
331
- const set = this.listeners_.get(type);
332
- if (set) {
333
- set.delete(listener);
334
- if (set.size === 0) this.listeners_.delete(type);
335
- }
336
- return this;
337
- }
338
-
339
- private async dispatch<Event extends AgenticaEvent<Model>>(
340
- event: Event,
341
- ): Promise<void> {
342
- const set = this.listeners_.get(event.type);
343
- if (set) {
344
- await Promise.all(
345
- Array.from(set).map(async (listener) => {
346
- try {
347
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call
348
- await listener(event);
349
- } catch {
350
- /* empty */
351
- }
352
- }),
353
- );
354
- }
355
- }
356
- }
1
+ import { ILlmSchema } from "@samchon/openapi";
2
+
3
+ import { ChatGptAgent } from "./chatgpt/ChatGptAgent";
4
+ import { ChatGptCompletionMessageUtil } from "./chatgpt/ChatGptCompletionMessageUtil";
5
+ import { AgenticaContext } from "./context/AgenticaContext";
6
+ import { AgenticaOperation } from "./context/AgenticaOperation";
7
+ import { AgenticaOperationCollection } from "./context/AgenticaOperationCollection";
8
+ import { AgenticaOperationSelection } from "./context/AgenticaOperationSelection";
9
+ import { AgenticaTokenUsage } from "./context/AgenticaTokenUsage";
10
+ import { AgenticaTokenUsageAggregator } from "./context/internal/AgenticaTokenUsageAggregator";
11
+ import { AgenticaEvent } from "./events/AgenticaEvent";
12
+ import { AgenticaInitializeEvent } from "./events/AgenticaInitializeEvent";
13
+ import { AgenticaRequestEvent } from "./events/AgenticaRequestEvent";
14
+ import { AgenticaTextEvent } from "./events/AgenticaTextEvent";
15
+ import { AgenticaOperationComposer } from "./internal/AgenticaOperationComposer";
16
+ import { StreamUtil } from "./internal/StreamUtil";
17
+ import { __map_take } from "./internal/__map_take";
18
+ import { AgenticaPrompt } from "./prompts/AgenticaPrompt";
19
+ import { AgenticaTextPrompt } from "./prompts/AgenticaTextPrompt";
20
+ import { IAgenticaConfig } from "./structures/IAgenticaConfig";
21
+ import { IAgenticaController } from "./structures/IAgenticaController";
22
+ import { IAgenticaProps } from "./structures/IAgenticaProps";
23
+ import { IAgenticaVendor } from "./structures/IAgenticaVendor";
24
+ import { AgenticaPromptTransformer } from "./transformers/AgenticaPromptTransformer";
25
+
26
+ /**
27
+ * Nestia A.I. chatbot agent.
28
+ *
29
+ * `Agentica` is a facade class for the super A.I. chatbot agent
30
+ * which performs the {@link conversate user's conversation function}
31
+ * with LLM (Large Language Model) function calling and manages the
32
+ * {@link getPromptHistories prompt histories}.
33
+ *
34
+ * To understand and compose the `Agentica` class exactly, reference
35
+ * below types concentrating on the documentation comments please.
36
+ * Especially, you have to be careful about the {@link IAgenticaProps}
37
+ * type which is used in the {@link constructor} function.
38
+ *
39
+ * - Constructors
40
+ * - {@link IAgenticaProps}
41
+ * - {@link IAgenticaVendor}
42
+ * - {@link IAgenticaController}
43
+ * - {@link IAgenticaConfig}
44
+ * - {@link IAgenticaSystemPrompt}
45
+ * - Accessors
46
+ * - {@link IAgenticaOperation}
47
+ * - {@link IAgenticaPromptJson}
48
+ * - {@link IAgenticaEventJson}
49
+ * - {@link IAgenticaTokenUsageJson}
50
+ *
51
+ * @author Samchon
52
+ */
53
+ export class Agentica<Model extends ILlmSchema.Model> {
54
+ // THE OPERATIONS
55
+ private readonly operations_: AgenticaOperationCollection<Model>;
56
+
57
+ // STACK
58
+ private readonly stack_: AgenticaOperationSelection<Model>[];
59
+ private readonly prompt_histories_: AgenticaPrompt<Model>[];
60
+ private readonly listeners_: Map<string, Set<Function>>;
61
+
62
+ // STATUS
63
+ private readonly token_usage_: AgenticaTokenUsage;
64
+ private ready_: boolean;
65
+ private readonly executor_: (
66
+ ctx: AgenticaContext<Model>,
67
+ ) => Promise<AgenticaPrompt<Model>[]>;
68
+
69
+ /* -----------------------------------------------------------
70
+ CONSTRUCTOR
71
+ ----------------------------------------------------------- */
72
+ /**
73
+ * Initializer constructor.
74
+ *
75
+ * @param props Properties to construct the agent
76
+ */
77
+ public constructor(private readonly props: IAgenticaProps<Model>) {
78
+ // OPERATIONS
79
+ this.operations_ = AgenticaOperationComposer.compose({
80
+ controllers: props.controllers,
81
+ config: props.config,
82
+ });
83
+
84
+ // STATUS
85
+ this.stack_ = [];
86
+ this.listeners_ = new Map();
87
+ this.prompt_histories_ = (props.histories ?? []).map((input) =>
88
+ AgenticaPromptTransformer.transform({
89
+ operations: this.operations_.group,
90
+ prompt: input,
91
+ }),
92
+ );
93
+
94
+ // STATUS
95
+ this.token_usage_ = AgenticaTokenUsage.zero();
96
+ this.ready_ = false;
97
+ this.executor_ =
98
+ typeof props.config?.executor === "function"
99
+ ? props.config.executor
100
+ : ChatGptAgent.execute(props.config?.executor ?? null);
101
+ }
102
+
103
+ /**
104
+ * @internal
105
+ */
106
+ public clone(): Agentica<Model> {
107
+ return new Agentica({
108
+ ...this.props,
109
+ histories: this.props.histories?.slice(),
110
+ });
111
+ }
112
+
113
+ /* -----------------------------------------------------------
114
+ ACCESSORS
115
+ ----------------------------------------------------------- */
116
+ /**
117
+ * Conversate with the A.I. chatbot.
118
+ *
119
+ * User talks to the A.I. chatbot with the content.
120
+ *
121
+ * When the user's conversation implies the A.I. chatbot to execute a
122
+ * function calling, the returned chat prompts will contain the
123
+ * function calling information like {@link IAgenticaPromptJson.IExecute}.
124
+ *
125
+ * @param content The content to talk
126
+ * @returns List of newly created chat prompts
127
+ */
128
+ public async conversate(content: string): Promise<AgenticaPrompt<Model>[]> {
129
+ const prompt: AgenticaTextPrompt<"user"> = new AgenticaTextPrompt({
130
+ role: "user",
131
+ text: content,
132
+ });
133
+ await this.dispatch(
134
+ new AgenticaTextEvent({
135
+ role: "user",
136
+ stream: StreamUtil.to(content),
137
+ done: () => true,
138
+ get: () => content,
139
+ join: () => Promise.resolve(content),
140
+ }),
141
+ );
142
+
143
+ const newbie: AgenticaPrompt<Model>[] = await this.executor_(
144
+ this.getContext({
145
+ prompt,
146
+ usage: this.token_usage_,
147
+ }),
148
+ );
149
+ this.prompt_histories_.push(prompt, ...newbie);
150
+ return [prompt, ...newbie];
151
+ }
152
+
153
+ /**
154
+ * Get configuration.
155
+ */
156
+ public getConfig(): IAgenticaConfig<Model> | undefined {
157
+ return this.props.config;
158
+ }
159
+
160
+ /**
161
+ * Get LLM vendor.
162
+ */
163
+ public getVendor(): IAgenticaVendor {
164
+ return this.props.vendor;
165
+ }
166
+
167
+ /**
168
+ * Get controllers.
169
+ *
170
+ * Get list of controllers, which are the collection of functions that
171
+ * the "Super A.I. Chatbot" can execute.
172
+ */
173
+ public getControllers(): ReadonlyArray<IAgenticaController<Model>> {
174
+ return this.props.controllers;
175
+ }
176
+
177
+ /**
178
+ * Get operations.
179
+ *
180
+ * Get list of operations, which has capsuled the pair of controller
181
+ * and function from the {@link getControllers controllers}.
182
+ *
183
+ * @returns
184
+ */
185
+ public getOperations(): ReadonlyArray<AgenticaOperation<Model>> {
186
+ return this.operations_.array;
187
+ }
188
+
189
+ /**
190
+ * Get the chatbot's prompt histories.
191
+ *
192
+ * Get list of chat prompts that the chatbot has been conversated.
193
+ *
194
+ * @returns List of chat prompts
195
+ */
196
+ public getPromptHistories(): AgenticaPrompt<Model>[] {
197
+ return this.prompt_histories_;
198
+ }
199
+
200
+ /**
201
+ * Get token usage of the A.I. chatbot.
202
+ *
203
+ * Entire token usage of the A.I. chatbot during the conversating
204
+ * with the user by {@link conversate} method callings.
205
+ *
206
+ * @returns Cost of the A.I. chatbot
207
+ */
208
+ public getTokenUsage(): AgenticaTokenUsage {
209
+ return this.token_usage_;
210
+ }
211
+
212
+ /**
213
+ * @internal
214
+ */
215
+ public getContext(props: {
216
+ prompt: AgenticaTextPrompt<"user">;
217
+ usage: AgenticaTokenUsage;
218
+ }): AgenticaContext<Model> {
219
+ const dispatch = (event: AgenticaEvent<Model>) => this.dispatch(event);
220
+ return {
221
+ // APPLICATION
222
+ operations: this.operations_,
223
+ config: this.props.config,
224
+
225
+ // STATES
226
+ histories: this.prompt_histories_,
227
+ stack: this.stack_,
228
+ ready: () => this.ready_,
229
+ prompt: props.prompt,
230
+
231
+ // HANDLERS
232
+ dispatch: (event) => this.dispatch(event),
233
+ request: async (source, body) => {
234
+ // request information
235
+ const event: AgenticaRequestEvent = new AgenticaRequestEvent({
236
+ source,
237
+ body: {
238
+ ...body,
239
+ model: this.props.vendor.model,
240
+ stream: true,
241
+ stream_options: {
242
+ include_usage: true,
243
+ },
244
+ },
245
+ options: this.props.vendor.options,
246
+ });
247
+ await dispatch(event);
248
+
249
+ // completion
250
+ const completion = await this.props.vendor.api.chat.completions.create(
251
+ event.body,
252
+ event.options,
253
+ );
254
+
255
+ const [streamForEvent, temporaryStream] = StreamUtil.transform(
256
+ completion.toReadableStream() as ReadableStream<Uint8Array>,
257
+ (value) =>
258
+ ChatGptCompletionMessageUtil.transformCompletionChunk(value),
259
+ ).tee();
260
+
261
+ const [streamForAggregate, streamForReturn] = temporaryStream.tee();
262
+
263
+ void (async () => {
264
+ const reader = streamForAggregate.getReader();
265
+ while (true) {
266
+ const chunk = await reader.read();
267
+ if (chunk.done) break;
268
+ if (chunk.value.usage) {
269
+ AgenticaTokenUsageAggregator.aggregate({
270
+ kind: source,
271
+ completionUsage: chunk.value.usage,
272
+ usage: props.usage,
273
+ });
274
+ }
275
+ }
276
+ })();
277
+
278
+ await dispatch({
279
+ type: "response",
280
+ source: source,
281
+ stream: streamForEvent,
282
+ body: event.body,
283
+ options: event.options,
284
+ join: async () => {
285
+ const chunks = await StreamUtil.readAll(streamForEvent);
286
+ return ChatGptCompletionMessageUtil.merge(chunks);
287
+ },
288
+ });
289
+
290
+ return streamForReturn;
291
+ },
292
+ initialize: async () => {
293
+ this.ready_ = true;
294
+ await dispatch(new AgenticaInitializeEvent());
295
+ },
296
+ };
297
+ }
298
+
299
+ /* -----------------------------------------------------------
300
+ EVENT HANDLERS
301
+ ----------------------------------------------------------- */
302
+ /**
303
+ * Add an event listener.
304
+ *
305
+ * Add an event listener to be called whenever the event is emitted.
306
+ *
307
+ * @param type Type of event
308
+ * @param listener Callback function to be called whenever the event is emitted
309
+ */
310
+ public on<Type extends AgenticaEvent.Type>(
311
+ type: Type,
312
+ listener: (
313
+ event: AgenticaEvent.Mapper<Model>[Type],
314
+ ) => void | Promise<void>,
315
+ ): this {
316
+ __map_take(this.listeners_, type, () => new Set()).add(listener);
317
+ return this;
318
+ }
319
+
320
+ /**
321
+ * Erase an event listener.
322
+ *
323
+ * Erase an event listener to stop calling the callback function.
324
+ *
325
+ * @param type Type of event
326
+ * @param listener Callback function to erase
327
+ */
328
+ public off<Type extends AgenticaEvent.Type>(
329
+ type: Type,
330
+ listener: (
331
+ event: AgenticaEvent.Mapper<Model>[Type],
332
+ ) => void | Promise<void>,
333
+ ): this {
334
+ const set = this.listeners_.get(type);
335
+ if (set) {
336
+ set.delete(listener);
337
+ if (set.size === 0) this.listeners_.delete(type);
338
+ }
339
+ return this;
340
+ }
341
+
342
+ private async dispatch<Event extends AgenticaEvent<Model>>(
343
+ event: Event,
344
+ ): Promise<void> {
345
+ const set = this.listeners_.get(event.type);
346
+ if (set) {
347
+ await Promise.all(
348
+ Array.from(set).map(async (listener) => {
349
+ try {
350
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
351
+ await listener(event);
352
+ } catch {
353
+ /* empty */
354
+ }
355
+ }),
356
+ );
357
+ }
358
+ }
359
+ }