@agentica/core 0.31.2 → 0.31.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.mjs CHANGED
@@ -1095,6 +1095,138 @@ function cancelFunctionFromContext(ctx, reference) {
1095
1095
  ctx.dispatch(event);
1096
1096
  }
1097
1097
 
1098
+ class AsyncQueueClosedError extends Error {
1099
+ constructor(message) {
1100
+ super(message);
1101
+ this.name = "AsyncQueueClosedError";
1102
+ }
1103
+ }
1104
+
1105
+ class AsyncQueue {
1106
+ constructor() {
1107
+ this.queue = [];
1108
+ this.resolvers = [];
1109
+ this.closeResolvers = [];
1110
+ this.emptyResolvers = [];
1111
+ this.closed = false;
1112
+ }
1113
+ enqueue(item) {
1114
+ if (this.closed) {
1115
+ console.error(new AsyncQueueClosedError("Cannot enqueue item: queue is closed."));
1116
+ return;
1117
+ }
1118
+ this.queue.push(item);
1119
+ if (this.resolvers.length > 0) {
1120
+ this.resolvers.shift()?.({
1121
+ value: this.queue.shift(),
1122
+ done: false
1123
+ });
1124
+ }
1125
+ }
1126
+ async dequeue() {
1127
+ const item = (() => {
1128
+ if (!this.isEmpty()) {
1129
+ return {
1130
+ value: this.queue.shift(),
1131
+ done: false
1132
+ };
1133
+ }
1134
+ if (this.isClosed()) {
1135
+ return {
1136
+ value: undefined,
1137
+ done: true
1138
+ };
1139
+ }
1140
+ return null;
1141
+ })();
1142
+ if (this.isEmpty() && this.emptyResolvers.length !== 0) {
1143
+ this.emptyResolvers.forEach((resolve => resolve()));
1144
+ this.emptyResolvers = [];
1145
+ }
1146
+ if (item !== null) {
1147
+ return item;
1148
+ }
1149
+ return new Promise((resolve => this.resolvers.push(resolve)));
1150
+ }
1151
+ isEmpty() {
1152
+ return this.queue.length === 0;
1153
+ }
1154
+ isClosed() {
1155
+ return this.closed;
1156
+ }
1157
+ done() {
1158
+ return this.isClosed() && this.isEmpty();
1159
+ }
1160
+ close() {
1161
+ this.closed = true;
1162
+ while (this.resolvers.length > 0) {
1163
+ this.resolvers.shift()?.({
1164
+ value: undefined,
1165
+ done: true
1166
+ });
1167
+ }
1168
+ this.closeResolvers.forEach((resolve => resolve()));
1169
+ }
1170
+ async waitUntilEmpty() {
1171
+ if (this.isEmpty()) {
1172
+ return Promise.resolve();
1173
+ }
1174
+ return new Promise((resolve => {
1175
+ this.emptyResolvers.push(resolve);
1176
+ }));
1177
+ }
1178
+ async waitClosed() {
1179
+ if (this.isClosed()) {
1180
+ return Promise.resolve();
1181
+ }
1182
+ return new Promise((resolve => {
1183
+ this.closeResolvers.push(resolve);
1184
+ }));
1185
+ }
1186
+ }
1187
+
1188
+ class MPSC {
1189
+ constructor() {
1190
+ this.queue = new AsyncQueue;
1191
+ this.consumer = new ReadableStream({
1192
+ pull: async controller => {
1193
+ const {value, done} = await this.queue.dequeue();
1194
+ if (done === true) {
1195
+ controller.close();
1196
+ return;
1197
+ }
1198
+ controller.enqueue(value);
1199
+ }
1200
+ });
1201
+ }
1202
+ produce(chunk) {
1203
+ this.queue.enqueue(chunk);
1204
+ }
1205
+ close() {
1206
+ this.queue.close();
1207
+ }
1208
+ done() {
1209
+ return this.queue.done();
1210
+ }
1211
+ async waitClosed() {
1212
+ await this.queue.waitClosed();
1213
+ }
1214
+ async waitUntilEmpty() {
1215
+ await this.queue.waitUntilEmpty();
1216
+ }
1217
+ }
1218
+
1219
+ var index$2 = Object.freeze({
1220
+ __proto__: null,
1221
+ AsyncQueue,
1222
+ AsyncQueueClosedError,
1223
+ ChatGptCompletionMessageUtil,
1224
+ MPSC,
1225
+ StreamUtil,
1226
+ streamDefaultReaderToAsyncGenerator,
1227
+ toAsyncGenerator
1228
+ });
1229
+
1098
1230
  async function call(ctx, operations) {
1099
1231
  const stream = await ctx.request("call", {
1100
1232
  messages: [ {
@@ -1123,8 +1255,49 @@ async function call(ctx, operations) {
1123
1255
  }))),
1124
1256
  tool_choice: "auto"
1125
1257
  });
1126
- const chunks = await StreamUtil.readAll(stream);
1127
- const completion = ChatGptCompletionMessageUtil.merge(chunks);
1258
+ const selectContext = [];
1259
+ const nullableCompletion = await StreamUtil.reduce(stream, (async (accPromise, chunk) => {
1260
+ const acc = await accPromise;
1261
+ const registerContext = choices => {
1262
+ for (const choice of choices) {
1263
+ if (choice.finish_reason != null) {
1264
+ selectContext[choice.index]?.mpsc.close();
1265
+ continue;
1266
+ }
1267
+ if (choice.delta.content == null) {
1268
+ continue;
1269
+ }
1270
+ if (selectContext[choice.index] != null) {
1271
+ selectContext[choice.index].content += choice.delta.content;
1272
+ selectContext[choice.index].mpsc.produce(choice.delta.content);
1273
+ continue;
1274
+ }
1275
+ const mpsc = new MPSC;
1276
+ selectContext[choice.index] = {
1277
+ content: choice.delta.content,
1278
+ mpsc
1279
+ };
1280
+ mpsc.produce(choice.delta.content);
1281
+ const event = createAssistantMessageEvent({
1282
+ stream: streamDefaultReaderToAsyncGenerator(mpsc.consumer.getReader()),
1283
+ done: () => mpsc.done(),
1284
+ get: () => selectContext[choice.index]?.content ?? "",
1285
+ join: async () => {
1286
+ await mpsc.waitClosed();
1287
+ return selectContext[choice.index].content;
1288
+ }
1289
+ });
1290
+ ctx.dispatch(event);
1291
+ }
1292
+ };
1293
+ if (acc.object === "chat.completion.chunk") {
1294
+ registerContext([ acc, chunk ].flatMap((v => v.choices)));
1295
+ return ChatGptCompletionMessageUtil.merge([ acc, chunk ]);
1296
+ }
1297
+ registerContext(chunk.choices);
1298
+ return ChatGptCompletionMessageUtil.accumulate(acc, chunk);
1299
+ }));
1300
+ const completion = nullableCompletion;
1128
1301
  const executes = [];
1129
1302
  const retry = ctx.config?.retry ?? AgenticaConstant.RETRY;
1130
1303
  for (const choice of completion.choices) {
@@ -1145,16 +1318,6 @@ async function call(ctx, operations) {
1145
1318
  }
1146
1319
  }
1147
1320
  }
1148
- if (choice.message.role === "assistant" && choice.message.content != null && choice.message.content.length !== 0) {
1149
- const text = choice.message.content;
1150
- const event = createAssistantMessageEvent({
1151
- get: () => text,
1152
- done: () => true,
1153
- stream: toAsyncGenerator(text),
1154
- join: async () => Promise.resolve(text)
1155
- });
1156
- ctx.dispatch(event);
1157
- }
1158
1321
  }
1159
1322
  return executes;
1160
1323
  }
@@ -1665,127 +1828,6 @@ function emendMessages$1(failures) {
1665
1828
  } ])).flat();
1666
1829
  }
1667
1830
 
1668
- class AsyncQueueClosedError extends Error {
1669
- constructor(message) {
1670
- super(message);
1671
- this.name = "AsyncQueueClosedError";
1672
- }
1673
- }
1674
-
1675
- class AsyncQueue {
1676
- constructor() {
1677
- this.queue = [];
1678
- this.resolvers = [];
1679
- this.closeResolvers = [];
1680
- this.emptyResolvers = [];
1681
- this.closed = false;
1682
- }
1683
- enqueue(item) {
1684
- if (this.closed) {
1685
- console.error(new AsyncQueueClosedError("Cannot enqueue item: queue is closed."));
1686
- return;
1687
- }
1688
- this.queue.push(item);
1689
- if (this.resolvers.length > 0) {
1690
- this.resolvers.shift()?.({
1691
- value: this.queue.shift(),
1692
- done: false
1693
- });
1694
- }
1695
- }
1696
- async dequeue() {
1697
- const item = (() => {
1698
- if (!this.isEmpty()) {
1699
- return {
1700
- value: this.queue.shift(),
1701
- done: false
1702
- };
1703
- }
1704
- if (this.isClosed()) {
1705
- return {
1706
- value: undefined,
1707
- done: true
1708
- };
1709
- }
1710
- return null;
1711
- })();
1712
- if (this.isEmpty() && this.emptyResolvers.length !== 0) {
1713
- this.emptyResolvers.forEach((resolve => resolve()));
1714
- this.emptyResolvers = [];
1715
- }
1716
- if (item !== null) {
1717
- return item;
1718
- }
1719
- return new Promise((resolve => this.resolvers.push(resolve)));
1720
- }
1721
- isEmpty() {
1722
- return this.queue.length === 0;
1723
- }
1724
- isClosed() {
1725
- return this.closed;
1726
- }
1727
- done() {
1728
- return this.isClosed() && this.isEmpty();
1729
- }
1730
- close() {
1731
- this.closed = true;
1732
- while (this.resolvers.length > 0) {
1733
- this.resolvers.shift()?.({
1734
- value: undefined,
1735
- done: true
1736
- });
1737
- }
1738
- this.closeResolvers.forEach((resolve => resolve()));
1739
- }
1740
- async waitUntilEmpty() {
1741
- if (this.isEmpty()) {
1742
- return Promise.resolve();
1743
- }
1744
- return new Promise((resolve => {
1745
- this.emptyResolvers.push(resolve);
1746
- }));
1747
- }
1748
- async waitClosed() {
1749
- if (this.isClosed()) {
1750
- return Promise.resolve();
1751
- }
1752
- return new Promise((resolve => {
1753
- this.closeResolvers.push(resolve);
1754
- }));
1755
- }
1756
- }
1757
-
1758
- class MPSC {
1759
- constructor() {
1760
- this.queue = new AsyncQueue;
1761
- this.consumer = new ReadableStream({
1762
- pull: async controller => {
1763
- const {value, done} = await this.queue.dequeue();
1764
- if (done === true) {
1765
- controller.close();
1766
- return;
1767
- }
1768
- controller.enqueue(value);
1769
- }
1770
- });
1771
- }
1772
- produce(chunk) {
1773
- this.queue.enqueue(chunk);
1774
- }
1775
- close() {
1776
- this.queue.close();
1777
- }
1778
- done() {
1779
- return this.queue.done();
1780
- }
1781
- async waitClosed() {
1782
- await this.queue.waitClosed();
1783
- }
1784
- async waitUntilEmpty() {
1785
- await this.queue.waitUntilEmpty();
1786
- }
1787
- }
1788
-
1789
1831
  async function describe(ctx, histories) {
1790
1832
  if (histories.length === 0) {
1791
1833
  return;
@@ -2736,8 +2778,49 @@ async function step(ctx, operations, retry, failures) {
2736
2778
  } ],
2737
2779
  tool_choice: retry === 0 ? "auto" : "required"
2738
2780
  });
2739
- const chunks = await StreamUtil.readAll(completionStream);
2740
- const completion = ChatGptCompletionMessageUtil.merge(chunks);
2781
+ const selectContext = [];
2782
+ const nullableCompletion = await StreamUtil.reduce(completionStream, (async (accPromise, chunk) => {
2783
+ const acc = await accPromise;
2784
+ const registerContext = choices => {
2785
+ for (const choice of choices) {
2786
+ if (choice.finish_reason != null) {
2787
+ selectContext[choice.index]?.mpsc.close();
2788
+ continue;
2789
+ }
2790
+ if (choice.delta.content == null) {
2791
+ continue;
2792
+ }
2793
+ if (selectContext[choice.index] != null) {
2794
+ selectContext[choice.index].content += choice.delta.content;
2795
+ selectContext[choice.index].mpsc.produce(choice.delta.content);
2796
+ continue;
2797
+ }
2798
+ const mpsc = new MPSC;
2799
+ selectContext[choice.index] = {
2800
+ content: choice.delta.content,
2801
+ mpsc
2802
+ };
2803
+ mpsc.produce(choice.delta.content);
2804
+ const event = createAssistantMessageEvent({
2805
+ stream: streamDefaultReaderToAsyncGenerator(mpsc.consumer.getReader()),
2806
+ done: () => mpsc.done(),
2807
+ get: () => selectContext[choice.index]?.content ?? "",
2808
+ join: async () => {
2809
+ await mpsc.waitClosed();
2810
+ return selectContext[choice.index].content;
2811
+ }
2812
+ });
2813
+ ctx.dispatch(event);
2814
+ }
2815
+ };
2816
+ if (acc.object === "chat.completion.chunk") {
2817
+ registerContext([ acc, chunk ].flatMap((v => v.choices)));
2818
+ return ChatGptCompletionMessageUtil.merge([ acc, chunk ]);
2819
+ }
2820
+ registerContext(chunk.choices);
2821
+ return ChatGptCompletionMessageUtil.accumulate(acc, chunk);
2822
+ }));
2823
+ const completion = nullableCompletion;
2741
2824
  if (retry++ < (ctx.config?.retry ?? AgenticaConstant.RETRY)) {
2742
2825
  const failures = [];
2743
2826
  for (const choice of completion.choices) {
@@ -2845,15 +2928,6 @@ async function step(ctx, operations, retry, failures) {
2845
2928
  }
2846
2929
  }
2847
2930
  }
2848
- if (choice.message.role === "assistant" && choice.message.content != null && choice.message.content.length !== 0) {
2849
- const event = createAssistantMessageEvent({
2850
- stream: toAsyncGenerator(choice.message.content),
2851
- join: async () => Promise.resolve(choice.message.content),
2852
- done: () => true,
2853
- get: () => choice.message.content
2854
- });
2855
- ctx.dispatch(event);
2856
- }
2857
2931
  }
2858
2932
  }
2859
2933
 
@@ -3210,7 +3284,7 @@ class Agentica {
3210
3284
  }
3211
3285
  }
3212
3286
 
3213
- var index$2 = Object.freeze({
3287
+ var index$1 = Object.freeze({
3214
3288
  __proto__: null,
3215
3289
  createAssistantMessageEvent,
3216
3290
  createAssistantMessageHistory,
@@ -41888,7 +41962,7 @@ async function validateMcpController(props) {
41888
41962
  };
41889
41963
  }
41890
41964
 
41891
- var index$1 = Object.freeze({
41965
+ var index = Object.freeze({
41892
41966
  __proto__: null,
41893
41967
  ChatGptDescribeFunctionAgent,
41894
41968
  call,
@@ -42082,16 +42156,5 @@ class MicroAgentica {
42082
42156
  }
42083
42157
  }
42084
42158
 
42085
- var index = Object.freeze({
42086
- __proto__: null,
42087
- AsyncQueue,
42088
- AsyncQueueClosedError,
42089
- ChatGptCompletionMessageUtil,
42090
- MPSC,
42091
- StreamUtil,
42092
- streamDefaultReaderToAsyncGenerator,
42093
- toAsyncGenerator
42094
- });
42095
-
42096
- export { Agentica, AgenticaDefaultPrompt, AgenticaSystemPrompt, AgenticaTokenUsage, MicroAgentica, assertHttpController, assertHttpLlmApplication, assertMcpController, index$2 as factory, index$1 as orchestrate, index as utils, validateHttpController, validateHttpLlmApplication, validateMcpController, write };
42159
+ export { Agentica, AgenticaDefaultPrompt, AgenticaSystemPrompt, AgenticaTokenUsage, MicroAgentica, assertHttpController, assertHttpLlmApplication, assertMcpController, index$1 as factory, index as orchestrate, index$2 as utils, validateHttpController, validateHttpLlmApplication, validateMcpController, write };
42097
42160
  //# sourceMappingURL=index.mjs.map