@corbat-tech/coco 2.23.1 → 2.24.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/dist/cli/index.js +533 -213
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +548 -204
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -13072,6 +13072,147 @@ function createKimiCodeProvider(config) {
|
|
|
13072
13072
|
|
|
13073
13073
|
// src/providers/openai.ts
|
|
13074
13074
|
init_errors();
|
|
13075
|
+
function getSingleBuilderKey(builders) {
|
|
13076
|
+
return builders.size === 1 ? Array.from(builders.keys())[0] ?? null : null;
|
|
13077
|
+
}
|
|
13078
|
+
function parseToolCallArguments(args, providerName) {
|
|
13079
|
+
try {
|
|
13080
|
+
return args ? JSON.parse(args) : {};
|
|
13081
|
+
} catch {
|
|
13082
|
+
try {
|
|
13083
|
+
if (args) {
|
|
13084
|
+
const repaired = jsonrepair(args);
|
|
13085
|
+
return JSON.parse(repaired);
|
|
13086
|
+
}
|
|
13087
|
+
} catch {
|
|
13088
|
+
console.error(`[${providerName}] Cannot parse tool arguments: ${args.slice(0, 200)}`);
|
|
13089
|
+
}
|
|
13090
|
+
return {};
|
|
13091
|
+
}
|
|
13092
|
+
}
|
|
13093
|
+
var ChatToolCallAssembler = class {
|
|
13094
|
+
builders = /* @__PURE__ */ new Map();
|
|
13095
|
+
lastBuilderKey = null;
|
|
13096
|
+
consume(delta) {
|
|
13097
|
+
const key = typeof delta.index === "number" ? `index:${delta.index}` : typeof delta.id === "string" && delta.id.length > 0 ? `id:${delta.id}` : getSingleBuilderKey(this.builders) ?? this.lastBuilderKey ?? `fallback:${this.builders.size}`;
|
|
13098
|
+
let started;
|
|
13099
|
+
if (!this.builders.has(key)) {
|
|
13100
|
+
const initialId = delta.id ?? "";
|
|
13101
|
+
const initialName = delta.function?.name ?? "";
|
|
13102
|
+
this.builders.set(key, { id: initialId, name: initialName, arguments: "" });
|
|
13103
|
+
started = {
|
|
13104
|
+
id: initialId || void 0,
|
|
13105
|
+
name: initialName || void 0
|
|
13106
|
+
};
|
|
13107
|
+
}
|
|
13108
|
+
const builder = this.builders.get(key);
|
|
13109
|
+
this.lastBuilderKey = key;
|
|
13110
|
+
if (delta.id) {
|
|
13111
|
+
builder.id = delta.id;
|
|
13112
|
+
}
|
|
13113
|
+
if (delta.function?.name) {
|
|
13114
|
+
builder.name = delta.function.name;
|
|
13115
|
+
}
|
|
13116
|
+
const text = delta.function?.arguments ?? "";
|
|
13117
|
+
if (!text) return { started };
|
|
13118
|
+
builder.arguments += text;
|
|
13119
|
+
return {
|
|
13120
|
+
started,
|
|
13121
|
+
argumentDelta: {
|
|
13122
|
+
id: builder.id,
|
|
13123
|
+
name: builder.name,
|
|
13124
|
+
text
|
|
13125
|
+
}
|
|
13126
|
+
};
|
|
13127
|
+
}
|
|
13128
|
+
finalizeAll(providerName) {
|
|
13129
|
+
const result = [];
|
|
13130
|
+
for (const builder of this.builders.values()) {
|
|
13131
|
+
result.push({
|
|
13132
|
+
id: builder.id,
|
|
13133
|
+
name: builder.name,
|
|
13134
|
+
input: parseToolCallArguments(builder.arguments, providerName)
|
|
13135
|
+
});
|
|
13136
|
+
}
|
|
13137
|
+
this.builders.clear();
|
|
13138
|
+
this.lastBuilderKey = null;
|
|
13139
|
+
return result;
|
|
13140
|
+
}
|
|
13141
|
+
};
|
|
13142
|
+
var ResponsesToolCallAssembler = class {
|
|
13143
|
+
builders = /* @__PURE__ */ new Map();
|
|
13144
|
+
outputIndexToBuilderKey = /* @__PURE__ */ new Map();
|
|
13145
|
+
onOutputItemAdded(event) {
|
|
13146
|
+
const item = event.item;
|
|
13147
|
+
if (!item || item.type !== "function_call") return null;
|
|
13148
|
+
const callId = item.call_id ?? "";
|
|
13149
|
+
const itemKey = item.id ?? callId;
|
|
13150
|
+
this.builders.set(itemKey, {
|
|
13151
|
+
callId,
|
|
13152
|
+
name: item.name ?? "",
|
|
13153
|
+
arguments: item.arguments ?? ""
|
|
13154
|
+
});
|
|
13155
|
+
if (typeof event.output_index === "number") {
|
|
13156
|
+
this.outputIndexToBuilderKey.set(event.output_index, itemKey);
|
|
13157
|
+
}
|
|
13158
|
+
return {
|
|
13159
|
+
id: callId,
|
|
13160
|
+
name: item.name ?? ""
|
|
13161
|
+
};
|
|
13162
|
+
}
|
|
13163
|
+
onArgumentsDelta(event) {
|
|
13164
|
+
const builderKey = this.resolveBuilderKey(event.item_id, event.output_index);
|
|
13165
|
+
if (!builderKey) return;
|
|
13166
|
+
const builder = this.builders.get(builderKey);
|
|
13167
|
+
if (!builder) return;
|
|
13168
|
+
builder.arguments += event.delta ?? "";
|
|
13169
|
+
}
|
|
13170
|
+
onArgumentsDone(event, providerName) {
|
|
13171
|
+
const builderKey = this.resolveBuilderKey(event.item_id, event.output_index);
|
|
13172
|
+
if (!builderKey) return null;
|
|
13173
|
+
const builder = this.builders.get(builderKey);
|
|
13174
|
+
if (!builder) return null;
|
|
13175
|
+
const toolCall = {
|
|
13176
|
+
id: builder.callId,
|
|
13177
|
+
name: builder.name,
|
|
13178
|
+
input: parseToolCallArguments(event.arguments ?? builder.arguments, providerName)
|
|
13179
|
+
};
|
|
13180
|
+
this.deleteBuilder(builderKey);
|
|
13181
|
+
return toolCall;
|
|
13182
|
+
}
|
|
13183
|
+
finalizeAll(providerName) {
|
|
13184
|
+
const calls = [];
|
|
13185
|
+
for (const builder of this.builders.values()) {
|
|
13186
|
+
calls.push({
|
|
13187
|
+
id: builder.callId,
|
|
13188
|
+
name: builder.name,
|
|
13189
|
+
input: parseToolCallArguments(builder.arguments, providerName)
|
|
13190
|
+
});
|
|
13191
|
+
}
|
|
13192
|
+
this.builders.clear();
|
|
13193
|
+
this.outputIndexToBuilderKey.clear();
|
|
13194
|
+
return calls;
|
|
13195
|
+
}
|
|
13196
|
+
resolveBuilderKey(itemId, outputIndex) {
|
|
13197
|
+
if (itemId && this.builders.has(itemId)) {
|
|
13198
|
+
return itemId;
|
|
13199
|
+
}
|
|
13200
|
+
if (typeof outputIndex === "number") {
|
|
13201
|
+
return this.outputIndexToBuilderKey.get(outputIndex) ?? null;
|
|
13202
|
+
}
|
|
13203
|
+
return getSingleBuilderKey(this.builders);
|
|
13204
|
+
}
|
|
13205
|
+
deleteBuilder(builderKey) {
|
|
13206
|
+
this.builders.delete(builderKey);
|
|
13207
|
+
for (const [idx, key] of this.outputIndexToBuilderKey.entries()) {
|
|
13208
|
+
if (key === builderKey) {
|
|
13209
|
+
this.outputIndexToBuilderKey.delete(idx);
|
|
13210
|
+
}
|
|
13211
|
+
}
|
|
13212
|
+
}
|
|
13213
|
+
};
|
|
13214
|
+
|
|
13215
|
+
// src/providers/openai.ts
|
|
13075
13216
|
var DEFAULT_MODEL2 = "gpt-5.4-codex";
|
|
13076
13217
|
var CONTEXT_WINDOWS2 = {
|
|
13077
13218
|
// OpenAI models
|
|
@@ -13411,8 +13552,7 @@ var OpenAIProvider = class {
|
|
|
13411
13552
|
const stream = await this.client.chat.completions.create(
|
|
13412
13553
|
requestParams
|
|
13413
13554
|
);
|
|
13414
|
-
const
|
|
13415
|
-
let lastToolCallKey = null;
|
|
13555
|
+
const toolCallAssembler = new ChatToolCallAssembler();
|
|
13416
13556
|
const streamTimeout = this.config.timeout ?? 12e4;
|
|
13417
13557
|
let lastActivityTime = Date.now();
|
|
13418
13558
|
const timeoutController = new AbortController();
|
|
@@ -13426,30 +13566,6 @@ var OpenAIProvider = class {
|
|
|
13426
13566
|
timeoutController.signal.addEventListener("abort", () => stream.controller.abort(), {
|
|
13427
13567
|
once: true
|
|
13428
13568
|
});
|
|
13429
|
-
const providerName = this.name;
|
|
13430
|
-
const parseArguments2 = (builder) => {
|
|
13431
|
-
let input = {};
|
|
13432
|
-
try {
|
|
13433
|
-
input = builder.arguments ? JSON.parse(builder.arguments) : {};
|
|
13434
|
-
} catch (error) {
|
|
13435
|
-
console.warn(
|
|
13436
|
-
`[${providerName}] Failed to parse tool call arguments for ${builder.name}: ${builder.arguments?.slice(0, 300)}`
|
|
13437
|
-
);
|
|
13438
|
-
try {
|
|
13439
|
-
if (builder.arguments) {
|
|
13440
|
-
const repaired = jsonrepair(builder.arguments);
|
|
13441
|
-
input = JSON.parse(repaired);
|
|
13442
|
-
console.log(`[${providerName}] \u2713 Successfully repaired JSON for ${builder.name}`);
|
|
13443
|
-
}
|
|
13444
|
-
} catch {
|
|
13445
|
-
console.error(
|
|
13446
|
-
`[${providerName}] Cannot repair JSON for ${builder.name}, using empty object`
|
|
13447
|
-
);
|
|
13448
|
-
console.error(`[${providerName}] Original error:`, error);
|
|
13449
|
-
}
|
|
13450
|
-
}
|
|
13451
|
-
return input;
|
|
13452
|
-
};
|
|
13453
13569
|
try {
|
|
13454
13570
|
let streamStopReason;
|
|
13455
13571
|
for await (const chunk of stream) {
|
|
@@ -13462,38 +13578,31 @@ var OpenAIProvider = class {
|
|
|
13462
13578
|
}
|
|
13463
13579
|
if (delta?.tool_calls) {
|
|
13464
13580
|
for (const toolCallDelta of delta.tool_calls) {
|
|
13465
|
-
const
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
name: toolCallDelta.function?.name ??
|
|
13470
|
-
arguments:
|
|
13471
|
-
}
|
|
13581
|
+
const consumed = toolCallAssembler.consume({
|
|
13582
|
+
index: toolCallDelta.index,
|
|
13583
|
+
id: toolCallDelta.id ?? void 0,
|
|
13584
|
+
function: {
|
|
13585
|
+
name: toolCallDelta.function?.name ?? void 0,
|
|
13586
|
+
arguments: toolCallDelta.function?.arguments ?? void 0
|
|
13587
|
+
}
|
|
13588
|
+
});
|
|
13589
|
+
if (consumed.started) {
|
|
13472
13590
|
yield {
|
|
13473
13591
|
type: "tool_use_start",
|
|
13474
13592
|
toolCall: {
|
|
13475
|
-
id:
|
|
13476
|
-
name:
|
|
13593
|
+
id: consumed.started.id,
|
|
13594
|
+
name: consumed.started.name
|
|
13477
13595
|
}
|
|
13478
13596
|
};
|
|
13479
13597
|
}
|
|
13480
|
-
|
|
13481
|
-
lastToolCallKey = key;
|
|
13482
|
-
if (toolCallDelta.id) {
|
|
13483
|
-
builder.id = toolCallDelta.id;
|
|
13484
|
-
}
|
|
13485
|
-
if (toolCallDelta.function?.name) {
|
|
13486
|
-
builder.name = toolCallDelta.function.name;
|
|
13487
|
-
}
|
|
13488
|
-
if (toolCallDelta.function?.arguments) {
|
|
13489
|
-
builder.arguments += toolCallDelta.function.arguments;
|
|
13598
|
+
if (consumed.argumentDelta) {
|
|
13490
13599
|
yield {
|
|
13491
13600
|
type: "tool_use_delta",
|
|
13492
13601
|
toolCall: {
|
|
13493
|
-
id:
|
|
13494
|
-
name:
|
|
13602
|
+
id: consumed.argumentDelta.id,
|
|
13603
|
+
name: consumed.argumentDelta.name
|
|
13495
13604
|
},
|
|
13496
|
-
text:
|
|
13605
|
+
text: consumed.argumentDelta.text
|
|
13497
13606
|
};
|
|
13498
13607
|
}
|
|
13499
13608
|
}
|
|
@@ -13502,27 +13611,26 @@ var OpenAIProvider = class {
|
|
|
13502
13611
|
if (finishReason) {
|
|
13503
13612
|
streamStopReason = this.mapFinishReason(finishReason);
|
|
13504
13613
|
}
|
|
13505
|
-
if (finishReason
|
|
13506
|
-
for (const
|
|
13614
|
+
if (finishReason) {
|
|
13615
|
+
for (const toolCall of toolCallAssembler.finalizeAll(this.name)) {
|
|
13507
13616
|
yield {
|
|
13508
13617
|
type: "tool_use_end",
|
|
13509
13618
|
toolCall: {
|
|
13510
|
-
id:
|
|
13511
|
-
name:
|
|
13512
|
-
input:
|
|
13619
|
+
id: toolCall.id,
|
|
13620
|
+
name: toolCall.name,
|
|
13621
|
+
input: toolCall.input
|
|
13513
13622
|
}
|
|
13514
13623
|
};
|
|
13515
13624
|
}
|
|
13516
|
-
toolCallBuilders.clear();
|
|
13517
13625
|
}
|
|
13518
13626
|
}
|
|
13519
|
-
for (const
|
|
13627
|
+
for (const toolCall of toolCallAssembler.finalizeAll(this.name)) {
|
|
13520
13628
|
yield {
|
|
13521
13629
|
type: "tool_use_end",
|
|
13522
13630
|
toolCall: {
|
|
13523
|
-
id:
|
|
13524
|
-
name:
|
|
13525
|
-
input:
|
|
13631
|
+
id: toolCall.id,
|
|
13632
|
+
name: toolCall.name,
|
|
13633
|
+
input: toolCall.input
|
|
13526
13634
|
}
|
|
13527
13635
|
};
|
|
13528
13636
|
}
|
|
@@ -13959,7 +14067,7 @@ var OpenAIProvider = class {
|
|
|
13959
14067
|
toolCalls.push({
|
|
13960
14068
|
id: item.call_id,
|
|
13961
14069
|
name: item.name,
|
|
13962
|
-
input:
|
|
14070
|
+
input: parseToolCallArguments(item.arguments, this.name)
|
|
13963
14071
|
});
|
|
13964
14072
|
}
|
|
13965
14073
|
}
|
|
@@ -14065,8 +14173,7 @@ var OpenAIProvider = class {
|
|
|
14065
14173
|
const stream = await this.client.responses.create(
|
|
14066
14174
|
requestParams
|
|
14067
14175
|
);
|
|
14068
|
-
const
|
|
14069
|
-
const outputIndexToBuilderKey = /* @__PURE__ */ new Map();
|
|
14176
|
+
const toolCallAssembler = new ResponsesToolCallAssembler();
|
|
14070
14177
|
const streamTimeout = this.config.timeout ?? 12e4;
|
|
14071
14178
|
let lastActivityTime = Date.now();
|
|
14072
14179
|
const timeoutController = new AbortController();
|
|
@@ -14090,67 +14197,66 @@ var OpenAIProvider = class {
|
|
|
14090
14197
|
yield { type: "text", text: event.delta };
|
|
14091
14198
|
break;
|
|
14092
14199
|
case "response.output_item.added":
|
|
14093
|
-
|
|
14094
|
-
const
|
|
14095
|
-
const
|
|
14096
|
-
|
|
14097
|
-
|
|
14098
|
-
|
|
14099
|
-
|
|
14200
|
+
{
|
|
14201
|
+
const item = event.item;
|
|
14202
|
+
const start = toolCallAssembler.onOutputItemAdded({
|
|
14203
|
+
output_index: event.output_index,
|
|
14204
|
+
item: {
|
|
14205
|
+
type: item.type,
|
|
14206
|
+
id: item.id,
|
|
14207
|
+
call_id: item.call_id,
|
|
14208
|
+
name: item.name,
|
|
14209
|
+
arguments: item.arguments
|
|
14210
|
+
}
|
|
14100
14211
|
});
|
|
14101
|
-
if (
|
|
14102
|
-
outputIndexToBuilderKey.set(event.output_index, itemKey);
|
|
14103
|
-
}
|
|
14212
|
+
if (!start) break;
|
|
14104
14213
|
yield {
|
|
14105
14214
|
type: "tool_use_start",
|
|
14106
|
-
toolCall: { id:
|
|
14215
|
+
toolCall: { id: start.id, name: start.name }
|
|
14107
14216
|
};
|
|
14108
14217
|
}
|
|
14109
14218
|
break;
|
|
14110
14219
|
case "response.function_call_arguments.delta":
|
|
14111
|
-
{
|
|
14112
|
-
|
|
14113
|
-
|
|
14114
|
-
|
|
14115
|
-
|
|
14116
|
-
builder.arguments += event.delta;
|
|
14117
|
-
}
|
|
14118
|
-
}
|
|
14220
|
+
toolCallAssembler.onArgumentsDelta({
|
|
14221
|
+
item_id: event.item_id,
|
|
14222
|
+
output_index: event.output_index,
|
|
14223
|
+
delta: event.delta
|
|
14224
|
+
});
|
|
14119
14225
|
break;
|
|
14120
14226
|
case "response.function_call_arguments.done":
|
|
14121
14227
|
{
|
|
14122
|
-
const
|
|
14123
|
-
|
|
14124
|
-
|
|
14125
|
-
|
|
14228
|
+
const toolCall = toolCallAssembler.onArgumentsDone(
|
|
14229
|
+
{
|
|
14230
|
+
item_id: event.item_id,
|
|
14231
|
+
output_index: event.output_index,
|
|
14232
|
+
arguments: event.arguments
|
|
14233
|
+
},
|
|
14234
|
+
this.name
|
|
14235
|
+
);
|
|
14236
|
+
if (toolCall) {
|
|
14126
14237
|
yield {
|
|
14127
14238
|
type: "tool_use_end",
|
|
14128
14239
|
toolCall: {
|
|
14129
|
-
id:
|
|
14130
|
-
name:
|
|
14131
|
-
input:
|
|
14240
|
+
id: toolCall.id,
|
|
14241
|
+
name: toolCall.name,
|
|
14242
|
+
input: toolCall.input
|
|
14132
14243
|
}
|
|
14133
14244
|
};
|
|
14134
|
-
fnCallBuilders.delete(builderKey);
|
|
14135
|
-
for (const [idx, key] of outputIndexToBuilderKey.entries()) {
|
|
14136
|
-
if (key === builderKey) outputIndexToBuilderKey.delete(idx);
|
|
14137
|
-
}
|
|
14138
14245
|
}
|
|
14139
14246
|
}
|
|
14140
14247
|
break;
|
|
14141
14248
|
case "response.completed":
|
|
14142
14249
|
{
|
|
14143
|
-
for (const
|
|
14250
|
+
for (const toolCall of toolCallAssembler.finalizeAll(this.name)) {
|
|
14144
14251
|
yield {
|
|
14145
14252
|
type: "tool_use_end",
|
|
14146
14253
|
toolCall: {
|
|
14147
|
-
id:
|
|
14148
|
-
name:
|
|
14149
|
-
input:
|
|
14254
|
+
id: toolCall.id,
|
|
14255
|
+
name: toolCall.name,
|
|
14256
|
+
input: toolCall.input
|
|
14150
14257
|
}
|
|
14151
14258
|
};
|
|
14152
14259
|
}
|
|
14153
|
-
fnCallBuilders.clear();
|
|
14154
14260
|
const hasToolCalls = event.response.output.some(
|
|
14155
14261
|
(i) => i.type === "function_call"
|
|
14156
14262
|
);
|
|
@@ -14270,24 +14376,6 @@ var OpenAIProvider = class {
|
|
|
14270
14376
|
strict: false
|
|
14271
14377
|
}));
|
|
14272
14378
|
}
|
|
14273
|
-
/**
|
|
14274
|
-
* Parse tool call arguments with jsonrepair fallback (Responses API)
|
|
14275
|
-
*/
|
|
14276
|
-
parseResponsesArguments(args) {
|
|
14277
|
-
try {
|
|
14278
|
-
return args ? JSON.parse(args) : {};
|
|
14279
|
-
} catch {
|
|
14280
|
-
try {
|
|
14281
|
-
if (args) {
|
|
14282
|
-
const repaired = jsonrepair(args);
|
|
14283
|
-
return JSON.parse(repaired);
|
|
14284
|
-
}
|
|
14285
|
-
} catch {
|
|
14286
|
-
console.error(`[${this.name}] Cannot parse tool arguments: ${args.slice(0, 200)}`);
|
|
14287
|
-
}
|
|
14288
|
-
return {};
|
|
14289
|
-
}
|
|
14290
|
-
}
|
|
14291
14379
|
};
|
|
14292
14380
|
function createKimiProvider(config) {
|
|
14293
14381
|
const provider = new OpenAIProvider("kimi", "Kimi (Moonshot)");
|
|
@@ -14335,21 +14423,6 @@ function extractAccountId(accessToken) {
|
|
|
14335
14423
|
const auth = claims["https://api.openai.com/auth"];
|
|
14336
14424
|
return claims["chatgpt_account_id"] || auth?.["chatgpt_account_id"] || claims["organizations"]?.[0]?.id;
|
|
14337
14425
|
}
|
|
14338
|
-
function parseArguments(args) {
|
|
14339
|
-
try {
|
|
14340
|
-
return args ? JSON.parse(args) : {};
|
|
14341
|
-
} catch {
|
|
14342
|
-
try {
|
|
14343
|
-
if (args) {
|
|
14344
|
-
const repaired = jsonrepair(args);
|
|
14345
|
-
return JSON.parse(repaired);
|
|
14346
|
-
}
|
|
14347
|
-
} catch {
|
|
14348
|
-
console.error(`[Codex] Cannot parse tool arguments: ${args.slice(0, 200)}`);
|
|
14349
|
-
}
|
|
14350
|
-
return {};
|
|
14351
|
-
}
|
|
14352
|
-
}
|
|
14353
14426
|
var CodexProvider = class {
|
|
14354
14427
|
id = "codex";
|
|
14355
14428
|
name = "OpenAI Codex (ChatGPT Plus/Pro)";
|
|
@@ -14649,8 +14722,7 @@ var CodexProvider = class {
|
|
|
14649
14722
|
let inputTokens = 0;
|
|
14650
14723
|
let outputTokens = 0;
|
|
14651
14724
|
const toolCalls = [];
|
|
14652
|
-
const
|
|
14653
|
-
const outputIndexToBuilderKey = /* @__PURE__ */ new Map();
|
|
14725
|
+
const toolCallAssembler = new ResponsesToolCallAssembler();
|
|
14654
14726
|
await this.readSSEStream(response, (event) => {
|
|
14655
14727
|
if (event.id) responseId = event.id;
|
|
14656
14728
|
switch (event.type) {
|
|
@@ -14661,41 +14733,35 @@ var CodexProvider = class {
|
|
|
14661
14733
|
content = event.text ?? content;
|
|
14662
14734
|
break;
|
|
14663
14735
|
case "response.output_item.added": {
|
|
14664
|
-
|
|
14665
|
-
|
|
14666
|
-
|
|
14667
|
-
|
|
14668
|
-
callId: item.call_id,
|
|
14669
|
-
name: item.name,
|
|
14670
|
-
arguments: item.arguments ?? ""
|
|
14671
|
-
});
|
|
14672
|
-
if (typeof event.output_index === "number") {
|
|
14673
|
-
outputIndexToBuilderKey.set(event.output_index, itemKey);
|
|
14674
|
-
}
|
|
14675
|
-
}
|
|
14736
|
+
toolCallAssembler.onOutputItemAdded({
|
|
14737
|
+
output_index: event.output_index,
|
|
14738
|
+
item: event.item
|
|
14739
|
+
});
|
|
14676
14740
|
break;
|
|
14677
14741
|
}
|
|
14678
14742
|
case "response.function_call_arguments.delta": {
|
|
14679
|
-
|
|
14680
|
-
|
|
14681
|
-
|
|
14682
|
-
|
|
14743
|
+
toolCallAssembler.onArgumentsDelta({
|
|
14744
|
+
item_id: event.item_id,
|
|
14745
|
+
output_index: event.output_index,
|
|
14746
|
+
delta: event.delta
|
|
14747
|
+
});
|
|
14683
14748
|
break;
|
|
14684
14749
|
}
|
|
14685
14750
|
case "response.function_call_arguments.done": {
|
|
14686
|
-
const
|
|
14687
|
-
|
|
14688
|
-
|
|
14689
|
-
|
|
14751
|
+
const toolCall = toolCallAssembler.onArgumentsDone(
|
|
14752
|
+
{
|
|
14753
|
+
item_id: event.item_id,
|
|
14754
|
+
output_index: event.output_index,
|
|
14755
|
+
arguments: event.arguments
|
|
14756
|
+
},
|
|
14757
|
+
this.name
|
|
14758
|
+
);
|
|
14759
|
+
if (toolCall) {
|
|
14690
14760
|
toolCalls.push({
|
|
14691
|
-
id:
|
|
14692
|
-
name:
|
|
14693
|
-
input:
|
|
14761
|
+
id: toolCall.id,
|
|
14762
|
+
name: toolCall.name,
|
|
14763
|
+
input: toolCall.input
|
|
14694
14764
|
});
|
|
14695
|
-
fnCallBuilders.delete(builderKey);
|
|
14696
|
-
for (const [idx, key] of outputIndexToBuilderKey.entries()) {
|
|
14697
|
-
if (key === builderKey) outputIndexToBuilderKey.delete(idx);
|
|
14698
|
-
}
|
|
14699
14765
|
}
|
|
14700
14766
|
break;
|
|
14701
14767
|
}
|
|
@@ -14706,14 +14772,13 @@ var CodexProvider = class {
|
|
|
14706
14772
|
inputTokens = usage.input_tokens ?? 0;
|
|
14707
14773
|
outputTokens = usage.output_tokens ?? 0;
|
|
14708
14774
|
}
|
|
14709
|
-
for (const
|
|
14775
|
+
for (const toolCall of toolCallAssembler.finalizeAll(this.name)) {
|
|
14710
14776
|
toolCalls.push({
|
|
14711
|
-
id:
|
|
14712
|
-
name:
|
|
14713
|
-
input:
|
|
14777
|
+
id: toolCall.id,
|
|
14778
|
+
name: toolCall.name,
|
|
14779
|
+
input: toolCall.input
|
|
14714
14780
|
});
|
|
14715
14781
|
}
|
|
14716
|
-
fnCallBuilders.clear();
|
|
14717
14782
|
break;
|
|
14718
14783
|
}
|
|
14719
14784
|
}
|
|
@@ -14807,8 +14872,7 @@ var CodexProvider = class {
|
|
|
14807
14872
|
const reader = response.body.getReader();
|
|
14808
14873
|
const decoder = new TextDecoder();
|
|
14809
14874
|
let buffer = "";
|
|
14810
|
-
const
|
|
14811
|
-
const outputIndexToBuilderKey = /* @__PURE__ */ new Map();
|
|
14875
|
+
const toolCallAssembler = new ResponsesToolCallAssembler();
|
|
14812
14876
|
let lastActivityTime = Date.now();
|
|
14813
14877
|
const timeoutController = new AbortController();
|
|
14814
14878
|
const timeoutInterval = setInterval(() => {
|
|
@@ -14841,65 +14905,58 @@ var CodexProvider = class {
|
|
|
14841
14905
|
yield { type: "text", text: event.delta ?? "" };
|
|
14842
14906
|
break;
|
|
14843
14907
|
case "response.output_item.added": {
|
|
14844
|
-
const
|
|
14845
|
-
|
|
14846
|
-
|
|
14847
|
-
|
|
14848
|
-
|
|
14849
|
-
name: item.name,
|
|
14850
|
-
arguments: item.arguments ?? ""
|
|
14851
|
-
});
|
|
14852
|
-
if (typeof event.output_index === "number") {
|
|
14853
|
-
outputIndexToBuilderKey.set(event.output_index, itemKey);
|
|
14854
|
-
}
|
|
14908
|
+
const start = toolCallAssembler.onOutputItemAdded({
|
|
14909
|
+
output_index: event.output_index,
|
|
14910
|
+
item: event.item
|
|
14911
|
+
});
|
|
14912
|
+
if (start) {
|
|
14855
14913
|
yield {
|
|
14856
14914
|
type: "tool_use_start",
|
|
14857
|
-
toolCall: { id:
|
|
14915
|
+
toolCall: { id: start.id, name: start.name }
|
|
14858
14916
|
};
|
|
14859
14917
|
}
|
|
14860
14918
|
break;
|
|
14861
14919
|
}
|
|
14862
14920
|
case "response.function_call_arguments.delta": {
|
|
14863
|
-
|
|
14864
|
-
|
|
14865
|
-
|
|
14866
|
-
|
|
14867
|
-
|
|
14868
|
-
}
|
|
14921
|
+
toolCallAssembler.onArgumentsDelta({
|
|
14922
|
+
item_id: event.item_id,
|
|
14923
|
+
output_index: event.output_index,
|
|
14924
|
+
delta: event.delta
|
|
14925
|
+
});
|
|
14869
14926
|
break;
|
|
14870
14927
|
}
|
|
14871
14928
|
case "response.function_call_arguments.done": {
|
|
14872
|
-
const
|
|
14873
|
-
|
|
14874
|
-
|
|
14875
|
-
|
|
14929
|
+
const toolCall = toolCallAssembler.onArgumentsDone(
|
|
14930
|
+
{
|
|
14931
|
+
item_id: event.item_id,
|
|
14932
|
+
output_index: event.output_index,
|
|
14933
|
+
arguments: event.arguments
|
|
14934
|
+
},
|
|
14935
|
+
this.name
|
|
14936
|
+
);
|
|
14937
|
+
if (toolCall) {
|
|
14876
14938
|
yield {
|
|
14877
14939
|
type: "tool_use_end",
|
|
14878
14940
|
toolCall: {
|
|
14879
|
-
id:
|
|
14880
|
-
name:
|
|
14881
|
-
input:
|
|
14941
|
+
id: toolCall.id,
|
|
14942
|
+
name: toolCall.name,
|
|
14943
|
+
input: toolCall.input
|
|
14882
14944
|
}
|
|
14883
14945
|
};
|
|
14884
|
-
fnCallBuilders.delete(builderKey);
|
|
14885
|
-
for (const [idx, key] of outputIndexToBuilderKey.entries()) {
|
|
14886
|
-
if (key === builderKey) outputIndexToBuilderKey.delete(idx);
|
|
14887
|
-
}
|
|
14888
14946
|
}
|
|
14889
14947
|
break;
|
|
14890
14948
|
}
|
|
14891
14949
|
case "response.completed": {
|
|
14892
|
-
for (const
|
|
14950
|
+
for (const toolCall of toolCallAssembler.finalizeAll(this.name)) {
|
|
14893
14951
|
yield {
|
|
14894
14952
|
type: "tool_use_end",
|
|
14895
14953
|
toolCall: {
|
|
14896
|
-
id:
|
|
14897
|
-
name:
|
|
14898
|
-
input:
|
|
14954
|
+
id: toolCall.id,
|
|
14955
|
+
name: toolCall.name,
|
|
14956
|
+
input: toolCall.input
|
|
14899
14957
|
}
|
|
14900
14958
|
};
|
|
14901
14959
|
}
|
|
14902
|
-
fnCallBuilders.clear();
|
|
14903
14960
|
const resp = event.response;
|
|
14904
14961
|
const output = resp?.output ?? [];
|
|
14905
14962
|
const hasToolCalls = output.some((i) => i.type === "function_call");
|
|
@@ -15565,10 +15622,296 @@ var GeminiProvider = class {
|
|
|
15565
15622
|
|
|
15566
15623
|
// src/providers/circuit-breaker.ts
|
|
15567
15624
|
init_errors();
|
|
15625
|
+
var DEFAULT_CIRCUIT_BREAKER_CONFIG = {
|
|
15626
|
+
failureThreshold: 5,
|
|
15627
|
+
resetTimeout: 3e4,
|
|
15628
|
+
halfOpenRequests: 1
|
|
15629
|
+
};
|
|
15630
|
+
var CircuitOpenError = class extends ProviderError {
|
|
15631
|
+
remainingTime;
|
|
15632
|
+
constructor(provider, remainingTime) {
|
|
15633
|
+
super(`Circuit breaker is open for provider: ${provider}`, {
|
|
15634
|
+
provider,
|
|
15635
|
+
retryable: true
|
|
15636
|
+
});
|
|
15637
|
+
this.name = "CircuitOpenError";
|
|
15638
|
+
this.remainingTime = remainingTime;
|
|
15639
|
+
}
|
|
15640
|
+
};
|
|
15641
|
+
var CircuitBreaker = class {
|
|
15642
|
+
config;
|
|
15643
|
+
state = "closed";
|
|
15644
|
+
failureCount = 0;
|
|
15645
|
+
lastFailureTime = null;
|
|
15646
|
+
halfOpenSuccesses = 0;
|
|
15647
|
+
providerId;
|
|
15648
|
+
/**
|
|
15649
|
+
* Create a new circuit breaker
|
|
15650
|
+
*
|
|
15651
|
+
* @param config - Circuit breaker configuration
|
|
15652
|
+
* @param providerId - Provider identifier for error messages
|
|
15653
|
+
*/
|
|
15654
|
+
constructor(config, providerId = "unknown") {
|
|
15655
|
+
this.config = { ...DEFAULT_CIRCUIT_BREAKER_CONFIG, ...config };
|
|
15656
|
+
this.providerId = providerId;
|
|
15657
|
+
}
|
|
15658
|
+
/**
|
|
15659
|
+
* Get the current circuit state
|
|
15660
|
+
*/
|
|
15661
|
+
getState() {
|
|
15662
|
+
this.checkStateTransition();
|
|
15663
|
+
return this.state;
|
|
15664
|
+
}
|
|
15665
|
+
/**
|
|
15666
|
+
* Check if the circuit is currently open (blocking requests)
|
|
15667
|
+
*/
|
|
15668
|
+
isOpen() {
|
|
15669
|
+
this.checkStateTransition();
|
|
15670
|
+
return this.state === "open";
|
|
15671
|
+
}
|
|
15672
|
+
/**
|
|
15673
|
+
* Get the current failure count
|
|
15674
|
+
*/
|
|
15675
|
+
getFailureCount() {
|
|
15676
|
+
return this.failureCount;
|
|
15677
|
+
}
|
|
15678
|
+
/**
|
|
15679
|
+
* Record a successful request
|
|
15680
|
+
* Resets failure count in closed state, or counts toward closing in half-open
|
|
15681
|
+
*/
|
|
15682
|
+
recordSuccess() {
|
|
15683
|
+
if (this.state === "half-open") {
|
|
15684
|
+
this.halfOpenSuccesses++;
|
|
15685
|
+
if (this.halfOpenSuccesses >= this.config.halfOpenRequests) {
|
|
15686
|
+
this.close();
|
|
15687
|
+
}
|
|
15688
|
+
} else if (this.state === "closed") {
|
|
15689
|
+
this.failureCount = 0;
|
|
15690
|
+
}
|
|
15691
|
+
}
|
|
15692
|
+
/**
|
|
15693
|
+
* Record a failed request
|
|
15694
|
+
* Increments failure count and may open the circuit
|
|
15695
|
+
*/
|
|
15696
|
+
recordFailure() {
|
|
15697
|
+
this.lastFailureTime = Date.now();
|
|
15698
|
+
this.failureCount++;
|
|
15699
|
+
if (this.state === "half-open") {
|
|
15700
|
+
this.open();
|
|
15701
|
+
} else if (this.state === "closed" && this.failureCount >= this.config.failureThreshold) {
|
|
15702
|
+
this.open();
|
|
15703
|
+
}
|
|
15704
|
+
}
|
|
15705
|
+
/**
|
|
15706
|
+
* Execute a function with circuit breaker protection
|
|
15707
|
+
*
|
|
15708
|
+
* @param fn - Async function to execute
|
|
15709
|
+
* @returns Result of the function
|
|
15710
|
+
* @throws CircuitOpenError if circuit is open
|
|
15711
|
+
* @throws Original error if function fails
|
|
15712
|
+
*/
|
|
15713
|
+
async execute(fn) {
|
|
15714
|
+
this.checkStateTransition();
|
|
15715
|
+
if (this.state === "open") {
|
|
15716
|
+
const elapsed = Date.now() - (this.lastFailureTime ?? Date.now());
|
|
15717
|
+
const remaining = this.config.resetTimeout - elapsed;
|
|
15718
|
+
throw new CircuitOpenError(this.providerId, remaining);
|
|
15719
|
+
}
|
|
15720
|
+
try {
|
|
15721
|
+
const result = await fn();
|
|
15722
|
+
this.recordSuccess();
|
|
15723
|
+
return result;
|
|
15724
|
+
} catch (error) {
|
|
15725
|
+
this.recordFailure();
|
|
15726
|
+
throw error;
|
|
15727
|
+
}
|
|
15728
|
+
}
|
|
15729
|
+
/**
|
|
15730
|
+
* Manually reset the circuit breaker to closed state
|
|
15731
|
+
*/
|
|
15732
|
+
reset() {
|
|
15733
|
+
this.close();
|
|
15734
|
+
}
|
|
15735
|
+
/**
|
|
15736
|
+
* Check and perform state transitions based on time
|
|
15737
|
+
*/
|
|
15738
|
+
checkStateTransition() {
|
|
15739
|
+
if (this.state === "open" && this.lastFailureTime !== null) {
|
|
15740
|
+
const elapsed = Date.now() - this.lastFailureTime;
|
|
15741
|
+
if (elapsed >= this.config.resetTimeout) {
|
|
15742
|
+
this.halfOpen();
|
|
15743
|
+
}
|
|
15744
|
+
}
|
|
15745
|
+
}
|
|
15746
|
+
/**
|
|
15747
|
+
* Transition to closed state
|
|
15748
|
+
*/
|
|
15749
|
+
close() {
|
|
15750
|
+
this.state = "closed";
|
|
15751
|
+
this.failureCount = 0;
|
|
15752
|
+
this.halfOpenSuccesses = 0;
|
|
15753
|
+
this.lastFailureTime = null;
|
|
15754
|
+
}
|
|
15755
|
+
/**
|
|
15756
|
+
* Transition to open state
|
|
15757
|
+
*/
|
|
15758
|
+
open() {
|
|
15759
|
+
this.state = "open";
|
|
15760
|
+
this.halfOpenSuccesses = 0;
|
|
15761
|
+
}
|
|
15762
|
+
/**
|
|
15763
|
+
* Transition to half-open state
|
|
15764
|
+
*/
|
|
15765
|
+
halfOpen() {
|
|
15766
|
+
this.state = "half-open";
|
|
15767
|
+
this.halfOpenSuccesses = 0;
|
|
15768
|
+
}
|
|
15769
|
+
};
|
|
15568
15770
|
|
|
15569
15771
|
// src/providers/fallback.ts
|
|
15570
15772
|
init_errors();
|
|
15571
15773
|
|
|
15774
|
+
// src/providers/resilient.ts
|
|
15775
|
+
var DEFAULT_STREAM_RETRY = {
|
|
15776
|
+
maxRetries: 1,
|
|
15777
|
+
initialDelayMs: 500,
|
|
15778
|
+
maxDelayMs: 5e3,
|
|
15779
|
+
backoffMultiplier: 2,
|
|
15780
|
+
jitterFactor: 0.1
|
|
15781
|
+
};
|
|
15782
|
+
function sleep2(ms) {
|
|
15783
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
15784
|
+
}
|
|
15785
|
+
function computeRetryDelay(attempt, config) {
|
|
15786
|
+
const exp = config.initialDelayMs * Math.pow(config.backoffMultiplier, attempt);
|
|
15787
|
+
const capped = Math.min(exp, config.maxDelayMs);
|
|
15788
|
+
const jitter = capped * config.jitterFactor * (Math.random() * 2 - 1);
|
|
15789
|
+
return Math.max(0, Math.min(capped + jitter, config.maxDelayMs));
|
|
15790
|
+
}
|
|
15791
|
+
var ResilientProvider = class {
|
|
15792
|
+
id;
|
|
15793
|
+
name;
|
|
15794
|
+
provider;
|
|
15795
|
+
breaker;
|
|
15796
|
+
retryConfig;
|
|
15797
|
+
streamRetryConfig;
|
|
15798
|
+
constructor(provider, config = {}) {
|
|
15799
|
+
this.provider = provider;
|
|
15800
|
+
this.id = provider.id;
|
|
15801
|
+
this.name = provider.name;
|
|
15802
|
+
this.retryConfig = { ...DEFAULT_RETRY_CONFIG, ...config.retry };
|
|
15803
|
+
this.streamRetryConfig = { ...DEFAULT_STREAM_RETRY, ...config.streamRetry };
|
|
15804
|
+
this.breaker = new CircuitBreaker(
|
|
15805
|
+
{ ...DEFAULT_CIRCUIT_BREAKER_CONFIG, ...config.circuitBreaker },
|
|
15806
|
+
provider.id
|
|
15807
|
+
);
|
|
15808
|
+
}
|
|
15809
|
+
async initialize(config) {
|
|
15810
|
+
await this.provider.initialize(config);
|
|
15811
|
+
}
|
|
15812
|
+
async chat(messages, options) {
|
|
15813
|
+
return this.breaker.execute(
|
|
15814
|
+
() => withRetry(() => this.provider.chat(messages, options), this.retryConfig)
|
|
15815
|
+
);
|
|
15816
|
+
}
|
|
15817
|
+
async chatWithTools(messages, options) {
|
|
15818
|
+
return this.breaker.execute(
|
|
15819
|
+
() => withRetry(() => this.provider.chatWithTools(messages, options), this.retryConfig)
|
|
15820
|
+
);
|
|
15821
|
+
}
|
|
15822
|
+
async *stream(messages, options) {
|
|
15823
|
+
yield* this.streamWithPolicy(() => this.provider.stream(messages, options));
|
|
15824
|
+
}
|
|
15825
|
+
async *streamWithTools(messages, options) {
|
|
15826
|
+
yield* this.streamWithPolicy(() => this.provider.streamWithTools(messages, options));
|
|
15827
|
+
}
|
|
15828
|
+
countTokens(text) {
|
|
15829
|
+
return this.provider.countTokens(text);
|
|
15830
|
+
}
|
|
15831
|
+
getContextWindow() {
|
|
15832
|
+
return this.provider.getContextWindow();
|
|
15833
|
+
}
|
|
15834
|
+
async isAvailable() {
|
|
15835
|
+
try {
|
|
15836
|
+
return await this.breaker.execute(() => this.provider.isAvailable());
|
|
15837
|
+
} catch (error) {
|
|
15838
|
+
if (error instanceof CircuitOpenError) {
|
|
15839
|
+
return false;
|
|
15840
|
+
}
|
|
15841
|
+
return false;
|
|
15842
|
+
}
|
|
15843
|
+
}
|
|
15844
|
+
getCircuitState() {
|
|
15845
|
+
return this.breaker.getState();
|
|
15846
|
+
}
|
|
15847
|
+
resetCircuit() {
|
|
15848
|
+
this.breaker.reset();
|
|
15849
|
+
}
|
|
15850
|
+
async *streamWithPolicy(createStream) {
|
|
15851
|
+
let attempt = 0;
|
|
15852
|
+
while (attempt <= this.streamRetryConfig.maxRetries) {
|
|
15853
|
+
if (this.breaker.isOpen()) {
|
|
15854
|
+
throw new CircuitOpenError(this.id, 0);
|
|
15855
|
+
}
|
|
15856
|
+
let emittedChunk = false;
|
|
15857
|
+
try {
|
|
15858
|
+
for await (const chunk of createStream()) {
|
|
15859
|
+
emittedChunk = true;
|
|
15860
|
+
yield chunk;
|
|
15861
|
+
}
|
|
15862
|
+
this.breaker.recordSuccess();
|
|
15863
|
+
return;
|
|
15864
|
+
} catch (error) {
|
|
15865
|
+
this.breaker.recordFailure();
|
|
15866
|
+
const shouldRetry = !emittedChunk && attempt < this.streamRetryConfig.maxRetries && isRetryableError(error);
|
|
15867
|
+
if (!shouldRetry) {
|
|
15868
|
+
throw error;
|
|
15869
|
+
}
|
|
15870
|
+
const delay = computeRetryDelay(attempt, this.streamRetryConfig);
|
|
15871
|
+
await sleep2(delay);
|
|
15872
|
+
attempt++;
|
|
15873
|
+
}
|
|
15874
|
+
}
|
|
15875
|
+
}
|
|
15876
|
+
};
|
|
15877
|
+
function getDefaultResilienceConfig(providerId) {
|
|
15878
|
+
if (providerId === "ollama" || providerId === "lmstudio") {
|
|
15879
|
+
return {
|
|
15880
|
+
retry: {
|
|
15881
|
+
maxRetries: 1,
|
|
15882
|
+
initialDelayMs: 300,
|
|
15883
|
+
maxDelayMs: 1500
|
|
15884
|
+
},
|
|
15885
|
+
streamRetry: {
|
|
15886
|
+
maxRetries: 0
|
|
15887
|
+
},
|
|
15888
|
+
circuitBreaker: {
|
|
15889
|
+
failureThreshold: 3,
|
|
15890
|
+
resetTimeout: 1e4
|
|
15891
|
+
}
|
|
15892
|
+
};
|
|
15893
|
+
}
|
|
15894
|
+
return {
|
|
15895
|
+
retry: {
|
|
15896
|
+
maxRetries: 3,
|
|
15897
|
+
initialDelayMs: 1e3,
|
|
15898
|
+
maxDelayMs: 3e4
|
|
15899
|
+
},
|
|
15900
|
+
streamRetry: {
|
|
15901
|
+
maxRetries: 1,
|
|
15902
|
+
initialDelayMs: 500,
|
|
15903
|
+
maxDelayMs: 5e3
|
|
15904
|
+
},
|
|
15905
|
+
circuitBreaker: {
|
|
15906
|
+
failureThreshold: 5,
|
|
15907
|
+
resetTimeout: 3e4
|
|
15908
|
+
}
|
|
15909
|
+
};
|
|
15910
|
+
}
|
|
15911
|
+
function createResilientProvider(provider, config) {
|
|
15912
|
+
return new ResilientProvider(provider, getDefaultResilienceConfig(provider.id));
|
|
15913
|
+
}
|
|
15914
|
+
|
|
15572
15915
|
// src/providers/index.ts
|
|
15573
15916
|
init_copilot();
|
|
15574
15917
|
init_errors();
|
|
@@ -15601,12 +15944,10 @@ async function createProvider(type, config = {}) {
|
|
|
15601
15944
|
break;
|
|
15602
15945
|
case "kimi":
|
|
15603
15946
|
provider = createKimiProvider(mergedConfig);
|
|
15604
|
-
|
|
15605
|
-
return provider;
|
|
15947
|
+
break;
|
|
15606
15948
|
case "kimi-code":
|
|
15607
15949
|
provider = createKimiCodeProvider(mergedConfig);
|
|
15608
|
-
|
|
15609
|
-
return provider;
|
|
15950
|
+
break;
|
|
15610
15951
|
case "lmstudio":
|
|
15611
15952
|
provider = new OpenAIProvider("lmstudio", "LM Studio");
|
|
15612
15953
|
mergedConfig.baseUrl = mergedConfig.baseUrl ?? "http://localhost:1234/v1";
|
|
@@ -15651,7 +15992,10 @@ async function createProvider(type, config = {}) {
|
|
|
15651
15992
|
});
|
|
15652
15993
|
}
|
|
15653
15994
|
await provider.initialize(mergedConfig);
|
|
15654
|
-
|
|
15995
|
+
const resilienceEnabled = !["0", "false", "off"].includes(
|
|
15996
|
+
(process.env["COCO_PROVIDER_RESILIENCE"] ?? "1").toLowerCase()
|
|
15997
|
+
);
|
|
15998
|
+
return resilienceEnabled ? createResilientProvider(provider) : provider;
|
|
15655
15999
|
}
|
|
15656
16000
|
|
|
15657
16001
|
// src/orchestrator/orchestrator.ts
|