@lvce-editor/chat-view 2.3.0 → 2.4.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/chatViewWorkerMain.js +420 -199
- package/package.json +1 -1
|
@@ -2673,10 +2673,37 @@ const getMockAiResponse = async (userMessage, delayInMs) => {
|
|
|
2673
2673
|
let queue = [];
|
|
2674
2674
|
let waiters = [];
|
|
2675
2675
|
let finished = false;
|
|
2676
|
+
let errorResult;
|
|
2676
2677
|
const reset$1 = () => {
|
|
2677
2678
|
queue = [];
|
|
2678
2679
|
waiters = [];
|
|
2679
2680
|
finished = false;
|
|
2681
|
+
errorResult = undefined;
|
|
2682
|
+
};
|
|
2683
|
+
const setHttpErrorResponse = (statusCode, body) => {
|
|
2684
|
+
const rawError = body && typeof body === 'object' ? Reflect.get(body, 'error') : undefined;
|
|
2685
|
+
const errorCode = rawError && typeof rawError === 'object' ? Reflect.get(rawError, 'code') : undefined;
|
|
2686
|
+
const errorMessage = rawError && typeof rawError === 'object' ? Reflect.get(rawError, 'message') : undefined;
|
|
2687
|
+
const errorType = rawError && typeof rawError === 'object' ? Reflect.get(rawError, 'type') : undefined;
|
|
2688
|
+
errorResult = {
|
|
2689
|
+
details: 'http-error',
|
|
2690
|
+
...(typeof errorCode === 'string' ? {
|
|
2691
|
+
errorCode
|
|
2692
|
+
} : {}),
|
|
2693
|
+
...(typeof errorMessage === 'string' ? {
|
|
2694
|
+
errorMessage
|
|
2695
|
+
} : {}),
|
|
2696
|
+
...(typeof errorType === 'string' ? {
|
|
2697
|
+
errorType
|
|
2698
|
+
} : {}),
|
|
2699
|
+
statusCode,
|
|
2700
|
+
type: 'error'
|
|
2701
|
+
};
|
|
2702
|
+
};
|
|
2703
|
+
const takeErrorResponse = () => {
|
|
2704
|
+
const error = errorResult;
|
|
2705
|
+
errorResult = undefined;
|
|
2706
|
+
return error;
|
|
2680
2707
|
};
|
|
2681
2708
|
const pushChunk = chunk => {
|
|
2682
2709
|
if (waiters.length > 0) {
|
|
@@ -2704,12 +2731,19 @@ const readNextChunk = async () => {
|
|
|
2704
2731
|
if (finished) {
|
|
2705
2732
|
return undefined;
|
|
2706
2733
|
}
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2734
|
+
const {
|
|
2735
|
+
promise,
|
|
2736
|
+
resolve
|
|
2737
|
+
} = Promise.withResolvers();
|
|
2738
|
+
waiters.push(resolve);
|
|
2739
|
+
return promise;
|
|
2710
2740
|
};
|
|
2711
2741
|
|
|
2712
2742
|
const getMockOpenApiAssistantText = async (stream, onTextChunk) => {
|
|
2743
|
+
const error = takeErrorResponse();
|
|
2744
|
+
if (error) {
|
|
2745
|
+
return error;
|
|
2746
|
+
}
|
|
2713
2747
|
let text = '';
|
|
2714
2748
|
while (true) {
|
|
2715
2749
|
const chunk = await readNextChunk();
|
|
@@ -3053,11 +3087,8 @@ const getClientRequestIdHeader = () => {
|
|
|
3053
3087
|
};
|
|
3054
3088
|
};
|
|
3055
3089
|
|
|
3056
|
-
const getOpenApiApiEndpoint =
|
|
3057
|
-
|
|
3058
|
-
return `${openApiApiBaseUrl}/chat/completions?stream=true`;
|
|
3059
|
-
}
|
|
3060
|
-
return `${openApiApiBaseUrl}/chat/completions`;
|
|
3090
|
+
const getOpenApiApiEndpoint = openApiApiBaseUrl => {
|
|
3091
|
+
return `${openApiApiBaseUrl}/responses`;
|
|
3061
3092
|
};
|
|
3062
3093
|
|
|
3063
3094
|
const getTextContent = content => {
|
|
@@ -3081,18 +3112,50 @@ const getTextContent = content => {
|
|
|
3081
3112
|
return textParts.join('\n');
|
|
3082
3113
|
};
|
|
3083
3114
|
|
|
3084
|
-
const
|
|
3115
|
+
const getOpenAiTools = tools => {
|
|
3116
|
+
return tools.map(tool => {
|
|
3117
|
+
if (!tool || typeof tool !== 'object') {
|
|
3118
|
+
return tool;
|
|
3119
|
+
}
|
|
3120
|
+
const type = Reflect.get(tool, 'type');
|
|
3121
|
+
const toolFunction = Reflect.get(tool, 'function');
|
|
3122
|
+
if (type !== 'function' || !toolFunction || typeof toolFunction !== 'object') {
|
|
3123
|
+
return tool;
|
|
3124
|
+
}
|
|
3125
|
+
const name = Reflect.get(toolFunction, 'name');
|
|
3126
|
+
const description = Reflect.get(toolFunction, 'description');
|
|
3127
|
+
const parameters = Reflect.get(toolFunction, 'parameters');
|
|
3128
|
+
return {
|
|
3129
|
+
...(typeof description === 'string' ? {
|
|
3130
|
+
description
|
|
3131
|
+
} : {}),
|
|
3132
|
+
...(typeof name === 'string' ? {
|
|
3133
|
+
name
|
|
3134
|
+
} : {}),
|
|
3135
|
+
...(parameters && typeof parameters === 'object' ? {
|
|
3136
|
+
parameters
|
|
3137
|
+
} : {}),
|
|
3138
|
+
type: 'function'
|
|
3139
|
+
};
|
|
3140
|
+
});
|
|
3141
|
+
};
|
|
3142
|
+
const getOpenAiParams = (input, modelId, stream, includeObfuscation, tools, previousResponseId) => {
|
|
3085
3143
|
return {
|
|
3086
|
-
|
|
3144
|
+
input,
|
|
3087
3145
|
model: modelId,
|
|
3088
3146
|
...(stream ? {
|
|
3089
|
-
stream: true
|
|
3147
|
+
stream: true,
|
|
3148
|
+
...(includeObfuscation ? {} : {
|
|
3149
|
+
stream_options: {
|
|
3150
|
+
include_obfuscation: false
|
|
3151
|
+
}
|
|
3152
|
+
})
|
|
3090
3153
|
} : {}),
|
|
3091
|
-
...(
|
|
3092
|
-
|
|
3154
|
+
...(previousResponseId ? {
|
|
3155
|
+
previous_response_id: previousResponseId
|
|
3093
3156
|
} : {}),
|
|
3094
3157
|
tool_choice: 'auto',
|
|
3095
|
-
tools
|
|
3158
|
+
tools: getOpenAiTools(tools)
|
|
3096
3159
|
};
|
|
3097
3160
|
};
|
|
3098
3161
|
const getStreamChunkText = content => {
|
|
@@ -3110,6 +3173,75 @@ const getStreamChunkText = content => {
|
|
|
3110
3173
|
return typeof text === 'string' ? text : '';
|
|
3111
3174
|
}).join('');
|
|
3112
3175
|
};
|
|
3176
|
+
const getResponseOutputText = parsed => {
|
|
3177
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
3178
|
+
return '';
|
|
3179
|
+
}
|
|
3180
|
+
const outputText = Reflect.get(parsed, 'output_text');
|
|
3181
|
+
if (typeof outputText === 'string') {
|
|
3182
|
+
return outputText;
|
|
3183
|
+
}
|
|
3184
|
+
const output = Reflect.get(parsed, 'output');
|
|
3185
|
+
if (!Array.isArray(output)) {
|
|
3186
|
+
return '';
|
|
3187
|
+
}
|
|
3188
|
+
const chunks = [];
|
|
3189
|
+
for (const outputItem of output) {
|
|
3190
|
+
if (!outputItem || typeof outputItem !== 'object') {
|
|
3191
|
+
continue;
|
|
3192
|
+
}
|
|
3193
|
+
const itemType = Reflect.get(outputItem, 'type');
|
|
3194
|
+
if (itemType !== 'message') {
|
|
3195
|
+
continue;
|
|
3196
|
+
}
|
|
3197
|
+
const content = Reflect.get(outputItem, 'content');
|
|
3198
|
+
if (!Array.isArray(content)) {
|
|
3199
|
+
continue;
|
|
3200
|
+
}
|
|
3201
|
+
for (const part of content) {
|
|
3202
|
+
if (!part || typeof part !== 'object') {
|
|
3203
|
+
continue;
|
|
3204
|
+
}
|
|
3205
|
+
const partType = Reflect.get(part, 'type');
|
|
3206
|
+
const text = Reflect.get(part, 'text');
|
|
3207
|
+
if ((partType === 'output_text' || partType === 'text') && typeof text === 'string') {
|
|
3208
|
+
chunks.push(text);
|
|
3209
|
+
}
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
return chunks.join('');
|
|
3213
|
+
};
|
|
3214
|
+
const getResponseFunctionCalls = parsed => {
|
|
3215
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
3216
|
+
return [];
|
|
3217
|
+
}
|
|
3218
|
+
const output = Reflect.get(parsed, 'output');
|
|
3219
|
+
if (!Array.isArray(output)) {
|
|
3220
|
+
return [];
|
|
3221
|
+
}
|
|
3222
|
+
const calls = [];
|
|
3223
|
+
for (const outputItem of output) {
|
|
3224
|
+
if (!outputItem || typeof outputItem !== 'object') {
|
|
3225
|
+
continue;
|
|
3226
|
+
}
|
|
3227
|
+
const itemType = Reflect.get(outputItem, 'type');
|
|
3228
|
+
if (itemType !== 'function_call') {
|
|
3229
|
+
continue;
|
|
3230
|
+
}
|
|
3231
|
+
const callId = Reflect.get(outputItem, 'call_id');
|
|
3232
|
+
const name = Reflect.get(outputItem, 'name');
|
|
3233
|
+
const rawArguments = Reflect.get(outputItem, 'arguments');
|
|
3234
|
+
if (typeof callId !== 'string' || typeof name !== 'string') {
|
|
3235
|
+
continue;
|
|
3236
|
+
}
|
|
3237
|
+
calls.push({
|
|
3238
|
+
arguments: typeof rawArguments === 'string' ? rawArguments : '',
|
|
3239
|
+
callId,
|
|
3240
|
+
name
|
|
3241
|
+
});
|
|
3242
|
+
}
|
|
3243
|
+
return calls;
|
|
3244
|
+
};
|
|
3113
3245
|
const parseSseEvent = eventChunk => {
|
|
3114
3246
|
const lines = eventChunk.split('\n');
|
|
3115
3247
|
const dataLines = [];
|
|
@@ -3189,7 +3321,136 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
|
|
|
3189
3321
|
let remainder = '';
|
|
3190
3322
|
let text = '';
|
|
3191
3323
|
let done = false;
|
|
3324
|
+
let finishedNotified = false;
|
|
3192
3325
|
let toolCallAccumulator = {};
|
|
3326
|
+
const notifyFinished = async () => {
|
|
3327
|
+
if (finishedNotified) {
|
|
3328
|
+
return;
|
|
3329
|
+
}
|
|
3330
|
+
finishedNotified = true;
|
|
3331
|
+
if (onEventStreamFinished) {
|
|
3332
|
+
await onEventStreamFinished();
|
|
3333
|
+
}
|
|
3334
|
+
};
|
|
3335
|
+
const emitToolCallAccumulator = async () => {
|
|
3336
|
+
if (!onToolCallsChunk) {
|
|
3337
|
+
return;
|
|
3338
|
+
}
|
|
3339
|
+
const toolCalls = Object.entries(toolCallAccumulator).toSorted((a, b) => Number(a[0]) - Number(b[0])).map(entry => entry[1]).filter(toolCall => !!toolCall.name);
|
|
3340
|
+
if (toolCalls.length === 0) {
|
|
3341
|
+
return;
|
|
3342
|
+
}
|
|
3343
|
+
await onToolCallsChunk(toolCalls);
|
|
3344
|
+
};
|
|
3345
|
+
const handleParsedStreamEvent = async parsed => {
|
|
3346
|
+
if (onDataEvent) {
|
|
3347
|
+
await onDataEvent(parsed);
|
|
3348
|
+
}
|
|
3349
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
3350
|
+
return;
|
|
3351
|
+
}
|
|
3352
|
+
const eventType = Reflect.get(parsed, 'type');
|
|
3353
|
+
if (eventType === 'response.completed') {
|
|
3354
|
+
await notifyFinished();
|
|
3355
|
+
return;
|
|
3356
|
+
}
|
|
3357
|
+
if (eventType === 'response.output_text.delta') {
|
|
3358
|
+
const delta = Reflect.get(parsed, 'delta');
|
|
3359
|
+
if (typeof delta !== 'string' || !delta) {
|
|
3360
|
+
return;
|
|
3361
|
+
}
|
|
3362
|
+
text += delta;
|
|
3363
|
+
if (onTextChunk) {
|
|
3364
|
+
await onTextChunk(delta);
|
|
3365
|
+
}
|
|
3366
|
+
return;
|
|
3367
|
+
}
|
|
3368
|
+
if (eventType === 'response.output_item.added') {
|
|
3369
|
+
const outputIndex = Reflect.get(parsed, 'output_index');
|
|
3370
|
+
const item = Reflect.get(parsed, 'item');
|
|
3371
|
+
if (typeof outputIndex !== 'number' || !item || typeof item !== 'object') {
|
|
3372
|
+
return;
|
|
3373
|
+
}
|
|
3374
|
+
const itemType = Reflect.get(item, 'type');
|
|
3375
|
+
if (itemType !== 'function_call') {
|
|
3376
|
+
return;
|
|
3377
|
+
}
|
|
3378
|
+
const callId = Reflect.get(item, 'call_id');
|
|
3379
|
+
const name = Reflect.get(item, 'name');
|
|
3380
|
+
const rawArguments = Reflect.get(item, 'arguments');
|
|
3381
|
+
const next = {
|
|
3382
|
+
arguments: typeof rawArguments === 'string' ? rawArguments : '',
|
|
3383
|
+
...(typeof callId === 'string' ? {
|
|
3384
|
+
id: callId
|
|
3385
|
+
} : {}),
|
|
3386
|
+
name: typeof name === 'string' ? name : ''
|
|
3387
|
+
};
|
|
3388
|
+
toolCallAccumulator = {
|
|
3389
|
+
...toolCallAccumulator,
|
|
3390
|
+
[outputIndex]: next
|
|
3391
|
+
};
|
|
3392
|
+
await emitToolCallAccumulator();
|
|
3393
|
+
return;
|
|
3394
|
+
}
|
|
3395
|
+
if (eventType === 'response.function_call_arguments.delta' || eventType === 'response.function_call_arguments.done') {
|
|
3396
|
+
const outputIndex = Reflect.get(parsed, 'output_index');
|
|
3397
|
+
if (typeof outputIndex !== 'number') {
|
|
3398
|
+
return;
|
|
3399
|
+
}
|
|
3400
|
+
const current = toolCallAccumulator[outputIndex] || {
|
|
3401
|
+
arguments: '',
|
|
3402
|
+
name: ''
|
|
3403
|
+
};
|
|
3404
|
+
const name = Reflect.get(parsed, 'name');
|
|
3405
|
+
const callId = Reflect.get(parsed, 'call_id');
|
|
3406
|
+
const delta = Reflect.get(parsed, 'delta');
|
|
3407
|
+
const rawArguments = Reflect.get(parsed, 'arguments');
|
|
3408
|
+
const next = {
|
|
3409
|
+
arguments: typeof rawArguments === 'string' ? rawArguments : typeof delta === 'string' ? `${current.arguments}${delta}` : current.arguments,
|
|
3410
|
+
...(typeof callId === 'string' ? {
|
|
3411
|
+
id: callId
|
|
3412
|
+
} : current.id ? {
|
|
3413
|
+
id: current.id
|
|
3414
|
+
} : {}),
|
|
3415
|
+
name: typeof name === 'string' && name ? name : current.name
|
|
3416
|
+
};
|
|
3417
|
+
toolCallAccumulator = {
|
|
3418
|
+
...toolCallAccumulator,
|
|
3419
|
+
[outputIndex]: next
|
|
3420
|
+
};
|
|
3421
|
+
await emitToolCallAccumulator();
|
|
3422
|
+
return;
|
|
3423
|
+
}
|
|
3424
|
+
const choices = Reflect.get(parsed, 'choices');
|
|
3425
|
+
if (!Array.isArray(choices)) {
|
|
3426
|
+
return;
|
|
3427
|
+
}
|
|
3428
|
+
const firstChoice = choices[0];
|
|
3429
|
+
if (!firstChoice || typeof firstChoice !== 'object') {
|
|
3430
|
+
return;
|
|
3431
|
+
}
|
|
3432
|
+
const delta = Reflect.get(firstChoice, 'delta');
|
|
3433
|
+
if (!delta || typeof delta !== 'object') {
|
|
3434
|
+
return;
|
|
3435
|
+
}
|
|
3436
|
+
const toolCalls = Reflect.get(delta, 'tool_calls');
|
|
3437
|
+
const updatedToolCallResult = Array.isArray(toolCalls) ? updateToolCallAccumulator(toolCallAccumulator, toolCalls) : undefined;
|
|
3438
|
+
if (updatedToolCallResult) {
|
|
3439
|
+
toolCallAccumulator = updatedToolCallResult.nextAccumulator;
|
|
3440
|
+
}
|
|
3441
|
+
if (updatedToolCallResult && onToolCallsChunk) {
|
|
3442
|
+
await onToolCallsChunk(updatedToolCallResult.toolCalls);
|
|
3443
|
+
}
|
|
3444
|
+
const content = Reflect.get(delta, 'content');
|
|
3445
|
+
const chunkText = getStreamChunkText(content);
|
|
3446
|
+
if (!chunkText) {
|
|
3447
|
+
return;
|
|
3448
|
+
}
|
|
3449
|
+
text += chunkText;
|
|
3450
|
+
if (onTextChunk) {
|
|
3451
|
+
await onTextChunk(chunkText);
|
|
3452
|
+
}
|
|
3453
|
+
};
|
|
3193
3454
|
while (!done) {
|
|
3194
3455
|
const {
|
|
3195
3456
|
done: streamDone,
|
|
@@ -3215,9 +3476,7 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
|
|
|
3215
3476
|
}
|
|
3216
3477
|
for (const line of dataLines) {
|
|
3217
3478
|
if (line === '[DONE]') {
|
|
3218
|
-
|
|
3219
|
-
await onEventStreamFinished();
|
|
3220
|
-
}
|
|
3479
|
+
await notifyFinished();
|
|
3221
3480
|
done = true;
|
|
3222
3481
|
break;
|
|
3223
3482
|
}
|
|
@@ -3227,41 +3486,7 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
|
|
|
3227
3486
|
} catch {
|
|
3228
3487
|
continue;
|
|
3229
3488
|
}
|
|
3230
|
-
|
|
3231
|
-
continue;
|
|
3232
|
-
}
|
|
3233
|
-
if (onDataEvent) {
|
|
3234
|
-
await onDataEvent(parsed);
|
|
3235
|
-
}
|
|
3236
|
-
const choices = Reflect.get(parsed, 'choices');
|
|
3237
|
-
if (!Array.isArray(choices)) {
|
|
3238
|
-
continue;
|
|
3239
|
-
}
|
|
3240
|
-
const firstChoice = choices[0];
|
|
3241
|
-
if (!firstChoice || typeof firstChoice !== 'object') {
|
|
3242
|
-
continue;
|
|
3243
|
-
}
|
|
3244
|
-
const delta = Reflect.get(firstChoice, 'delta');
|
|
3245
|
-
if (!delta || typeof delta !== 'object') {
|
|
3246
|
-
continue;
|
|
3247
|
-
}
|
|
3248
|
-
const toolCalls = Reflect.get(delta, 'tool_calls');
|
|
3249
|
-
const updatedToolCallResult = Array.isArray(toolCalls) ? updateToolCallAccumulator(toolCallAccumulator, toolCalls) : undefined;
|
|
3250
|
-
if (updatedToolCallResult) {
|
|
3251
|
-
toolCallAccumulator = updatedToolCallResult.nextAccumulator;
|
|
3252
|
-
}
|
|
3253
|
-
if (updatedToolCallResult && onToolCallsChunk) {
|
|
3254
|
-
await onToolCallsChunk(updatedToolCallResult.toolCalls);
|
|
3255
|
-
}
|
|
3256
|
-
const content = Reflect.get(delta, 'content');
|
|
3257
|
-
const chunkText = getStreamChunkText(content);
|
|
3258
|
-
if (!chunkText) {
|
|
3259
|
-
continue;
|
|
3260
|
-
}
|
|
3261
|
-
text += chunkText;
|
|
3262
|
-
if (onTextChunk) {
|
|
3263
|
-
await onTextChunk(chunkText);
|
|
3264
|
-
}
|
|
3489
|
+
await handleParsedStreamEvent(parsed);
|
|
3265
3490
|
}
|
|
3266
3491
|
}
|
|
3267
3492
|
}
|
|
@@ -3269,9 +3494,7 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
|
|
|
3269
3494
|
const dataLines = parseSseEvent(remainder);
|
|
3270
3495
|
for (const line of dataLines) {
|
|
3271
3496
|
if (line === '[DONE]') {
|
|
3272
|
-
|
|
3273
|
-
await onEventStreamFinished();
|
|
3274
|
-
}
|
|
3497
|
+
await notifyFinished();
|
|
3275
3498
|
continue;
|
|
3276
3499
|
}
|
|
3277
3500
|
let parsed;
|
|
@@ -3280,43 +3503,10 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
|
|
|
3280
3503
|
} catch {
|
|
3281
3504
|
continue;
|
|
3282
3505
|
}
|
|
3283
|
-
|
|
3284
|
-
continue;
|
|
3285
|
-
}
|
|
3286
|
-
if (onDataEvent) {
|
|
3287
|
-
await onDataEvent(parsed);
|
|
3288
|
-
}
|
|
3289
|
-
const choices = Reflect.get(parsed, 'choices');
|
|
3290
|
-
if (!Array.isArray(choices)) {
|
|
3291
|
-
continue;
|
|
3292
|
-
}
|
|
3293
|
-
const firstChoice = choices[0];
|
|
3294
|
-
if (!firstChoice || typeof firstChoice !== 'object') {
|
|
3295
|
-
continue;
|
|
3296
|
-
}
|
|
3297
|
-
const delta = Reflect.get(firstChoice, 'delta');
|
|
3298
|
-
if (!delta || typeof delta !== 'object') {
|
|
3299
|
-
continue;
|
|
3300
|
-
}
|
|
3301
|
-
const toolCalls = Reflect.get(delta, 'tool_calls');
|
|
3302
|
-
const updatedToolCallResult = Array.isArray(toolCalls) ? updateToolCallAccumulator(toolCallAccumulator, toolCalls) : undefined;
|
|
3303
|
-
if (updatedToolCallResult) {
|
|
3304
|
-
toolCallAccumulator = updatedToolCallResult.nextAccumulator;
|
|
3305
|
-
}
|
|
3306
|
-
if (updatedToolCallResult && onToolCallsChunk) {
|
|
3307
|
-
await onToolCallsChunk(updatedToolCallResult.toolCalls);
|
|
3308
|
-
}
|
|
3309
|
-
const content = Reflect.get(delta, 'content');
|
|
3310
|
-
const chunkText = getStreamChunkText(content);
|
|
3311
|
-
if (!chunkText) {
|
|
3312
|
-
continue;
|
|
3313
|
-
}
|
|
3314
|
-
text += chunkText;
|
|
3315
|
-
if (onTextChunk) {
|
|
3316
|
-
await onTextChunk(chunkText);
|
|
3317
|
-
}
|
|
3506
|
+
await handleParsedStreamEvent(parsed);
|
|
3318
3507
|
}
|
|
3319
3508
|
}
|
|
3509
|
+
await notifyFinished();
|
|
3320
3510
|
return {
|
|
3321
3511
|
text,
|
|
3322
3512
|
type: 'success'
|
|
@@ -3362,17 +3552,18 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
|
|
|
3362
3552
|
} = options ?? {
|
|
3363
3553
|
stream: false
|
|
3364
3554
|
};
|
|
3365
|
-
const
|
|
3555
|
+
const openAiInput = messages.map(message => ({
|
|
3366
3556
|
content: message.text,
|
|
3367
3557
|
role: message.role
|
|
3368
3558
|
}));
|
|
3369
3559
|
const tools = getBasicChatTools();
|
|
3370
3560
|
const maxToolIterations = 4;
|
|
3561
|
+
let previousResponseId;
|
|
3371
3562
|
for (let i = 0; i <= maxToolIterations; i++) {
|
|
3372
3563
|
let response;
|
|
3373
3564
|
try {
|
|
3374
|
-
response = await fetch(getOpenApiApiEndpoint(openApiApiBaseUrl
|
|
3375
|
-
body: JSON.stringify(getOpenAiParams(
|
|
3565
|
+
response = await fetch(getOpenApiApiEndpoint(openApiApiBaseUrl), {
|
|
3566
|
+
body: JSON.stringify(getOpenAiParams(openAiInput, modelId, stream, includeObfuscation, tools, previousResponseId)),
|
|
3376
3567
|
headers: {
|
|
3377
3568
|
Authorization: `Bearer ${openApiApiKey}`,
|
|
3378
3569
|
'Content-Type': 'application/json',
|
|
@@ -3425,56 +3616,83 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
|
|
|
3425
3616
|
type: 'success'
|
|
3426
3617
|
};
|
|
3427
3618
|
}
|
|
3428
|
-
const
|
|
3429
|
-
if (
|
|
3430
|
-
|
|
3431
|
-
text: '',
|
|
3432
|
-
type: 'success'
|
|
3433
|
-
};
|
|
3619
|
+
const parsedResponseId = Reflect.get(parsed, 'id');
|
|
3620
|
+
if (typeof parsedResponseId === 'string' && parsedResponseId) {
|
|
3621
|
+
previousResponseId = parsedResponseId;
|
|
3434
3622
|
}
|
|
3435
|
-
const
|
|
3436
|
-
if (
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3623
|
+
const responseFunctionCalls = getResponseFunctionCalls(parsed);
|
|
3624
|
+
if (responseFunctionCalls.length > 0) {
|
|
3625
|
+
openAiInput.length = 0;
|
|
3626
|
+
for (const toolCall of responseFunctionCalls) {
|
|
3627
|
+
const content = await executeChatTool(toolCall.name, toolCall.arguments, {
|
|
3628
|
+
assetDir,
|
|
3629
|
+
platform
|
|
3630
|
+
});
|
|
3631
|
+
openAiInput.push({
|
|
3632
|
+
call_id: toolCall.callId,
|
|
3633
|
+
output: content,
|
|
3634
|
+
type: 'function_call_output'
|
|
3635
|
+
});
|
|
3636
|
+
}
|
|
3637
|
+
continue;
|
|
3441
3638
|
}
|
|
3442
|
-
const
|
|
3443
|
-
if (
|
|
3639
|
+
const outputText = getResponseOutputText(parsed);
|
|
3640
|
+
if (outputText) {
|
|
3444
3641
|
return {
|
|
3445
|
-
text:
|
|
3642
|
+
text: outputText,
|
|
3446
3643
|
type: 'success'
|
|
3447
3644
|
};
|
|
3448
3645
|
}
|
|
3449
|
-
const
|
|
3450
|
-
if (Array.isArray(
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3646
|
+
const choices = Reflect.get(parsed, 'choices');
|
|
3647
|
+
if (Array.isArray(choices)) {
|
|
3648
|
+
const firstChoice = choices[0];
|
|
3649
|
+
if (!firstChoice || typeof firstChoice !== 'object') {
|
|
3650
|
+
return {
|
|
3651
|
+
text: '',
|
|
3652
|
+
type: 'success'
|
|
3653
|
+
};
|
|
3654
|
+
}
|
|
3655
|
+
const message = Reflect.get(firstChoice, 'message');
|
|
3656
|
+
if (!message || typeof message !== 'object') {
|
|
3657
|
+
return {
|
|
3658
|
+
text: '',
|
|
3659
|
+
type: 'success'
|
|
3660
|
+
};
|
|
3661
|
+
}
|
|
3662
|
+
const toolCalls = Reflect.get(message, 'tool_calls');
|
|
3663
|
+
if (Array.isArray(toolCalls) && toolCalls.length > 0) {
|
|
3664
|
+
openAiInput.length = 0;
|
|
3665
|
+
for (const toolCall of toolCalls) {
|
|
3666
|
+
if (!toolCall || typeof toolCall !== 'object') {
|
|
3667
|
+
continue;
|
|
3668
|
+
}
|
|
3669
|
+
const id = Reflect.get(toolCall, 'id');
|
|
3670
|
+
const toolFunction = Reflect.get(toolCall, 'function');
|
|
3671
|
+
if (typeof id !== 'string' || !toolFunction || typeof toolFunction !== 'object') {
|
|
3672
|
+
continue;
|
|
3673
|
+
}
|
|
3674
|
+
const name = Reflect.get(toolFunction, 'name');
|
|
3675
|
+
const rawArguments = Reflect.get(toolFunction, 'arguments');
|
|
3676
|
+
const content = typeof name === 'string' ? await executeChatTool(name, rawArguments, {
|
|
3677
|
+
assetDir,
|
|
3678
|
+
platform
|
|
3679
|
+
}) : '{}';
|
|
3680
|
+
openAiInput.push({
|
|
3681
|
+
call_id: id,
|
|
3682
|
+
output: content,
|
|
3683
|
+
type: 'function_call_output'
|
|
3684
|
+
});
|
|
3460
3685
|
}
|
|
3461
|
-
|
|
3462
|
-
const rawArguments = Reflect.get(toolFunction, 'arguments');
|
|
3463
|
-
const content = typeof name === 'string' ? await executeChatTool(name, rawArguments, {
|
|
3464
|
-
assetDir,
|
|
3465
|
-
platform
|
|
3466
|
-
}) : '{}';
|
|
3467
|
-
completionMessages.push({
|
|
3468
|
-
content,
|
|
3469
|
-
role: 'tool',
|
|
3470
|
-
tool_call_id: id
|
|
3471
|
-
});
|
|
3686
|
+
continue;
|
|
3472
3687
|
}
|
|
3473
|
-
|
|
3688
|
+
const content = Reflect.get(message, 'content');
|
|
3689
|
+
return {
|
|
3690
|
+
text: getTextContent(content),
|
|
3691
|
+
type: 'success'
|
|
3692
|
+
};
|
|
3474
3693
|
}
|
|
3475
|
-
const content = Reflect.get(message, 'content');
|
|
3476
3694
|
return {
|
|
3477
|
-
text:
|
|
3695
|
+
text: '',
|
|
3478
3696
|
type: 'success'
|
|
3479
3697
|
};
|
|
3480
3698
|
}
|
|
@@ -4158,13 +4376,6 @@ const handleTextChunkFunction = async (uid, assistantMessageId, chunk, handleTex
|
|
|
4158
4376
|
previousState: handleTextChunkState.previousState
|
|
4159
4377
|
};
|
|
4160
4378
|
}
|
|
4161
|
-
await appendChatViewEvent({
|
|
4162
|
-
content: chunk,
|
|
4163
|
-
messageId: assistantMessageId,
|
|
4164
|
-
sessionId: handleTextChunkState.latestState.selectedSessionId,
|
|
4165
|
-
timestamp: new Date().toISOString(),
|
|
4166
|
-
type: 'handle-response-chunk'
|
|
4167
|
-
});
|
|
4168
4379
|
const updatedText = assistantMessage.text + chunk;
|
|
4169
4380
|
const updatedSessions = updateMessageTextInSelectedSession(handleTextChunkState.latestState.sessions, handleTextChunkState.latestState.selectedSessionId, assistantMessageId, updatedText, true);
|
|
4170
4381
|
const nextState = {
|
|
@@ -4886,13 +5097,6 @@ const loadPreferences = async () => {
|
|
|
4886
5097
|
};
|
|
4887
5098
|
};
|
|
4888
5099
|
|
|
4889
|
-
const toSummarySession = session => {
|
|
4890
|
-
return {
|
|
4891
|
-
id: session.id,
|
|
4892
|
-
messages: [],
|
|
4893
|
-
title: session.title
|
|
4894
|
-
};
|
|
4895
|
-
};
|
|
4896
5100
|
const loadSelectedSessionMessages = async (sessions, selectedSessionId) => {
|
|
4897
5101
|
if (!selectedSessionId) {
|
|
4898
5102
|
return sessions;
|
|
@@ -4908,6 +5112,14 @@ const loadSelectedSessionMessages = async (sessions, selectedSessionId) => {
|
|
|
4908
5112
|
return loadedSession;
|
|
4909
5113
|
});
|
|
4910
5114
|
};
|
|
5115
|
+
|
|
5116
|
+
const toSummarySession = session => {
|
|
5117
|
+
return {
|
|
5118
|
+
id: session.id,
|
|
5119
|
+
messages: [],
|
|
5120
|
+
title: session.title
|
|
5121
|
+
};
|
|
5122
|
+
};
|
|
4911
5123
|
const loadContent = async (state, savedState) => {
|
|
4912
5124
|
const savedSelectedModelId = getSavedSelectedModelId(savedState);
|
|
4913
5125
|
const savedViewMode = getSavedViewMode(savedState);
|
|
@@ -4959,6 +5171,11 @@ const loadContent = async (state, savedState) => {
|
|
|
4959
5171
|
};
|
|
4960
5172
|
};
|
|
4961
5173
|
|
|
5174
|
+
const mockOpenApiSetHttpErrorResponse = (state, statusCode, body) => {
|
|
5175
|
+
setHttpErrorResponse(statusCode, body);
|
|
5176
|
+
return state;
|
|
5177
|
+
};
|
|
5178
|
+
|
|
4962
5179
|
const mockOpenApiStreamFinish = state => {
|
|
4963
5180
|
finish();
|
|
4964
5181
|
return state;
|
|
@@ -5369,6 +5586,61 @@ const getMissingOpenRouterApiKeyDom = (openRouterApiKeyInput, openRouterApiKeySt
|
|
|
5369
5586
|
});
|
|
5370
5587
|
};
|
|
5371
5588
|
|
|
5589
|
+
const getOpenRouterRequestFailedDom = () => {
|
|
5590
|
+
return [{
|
|
5591
|
+
childCount: openRouterRequestFailureReasons.length,
|
|
5592
|
+
className: ChatOrderedList,
|
|
5593
|
+
type: Ol
|
|
5594
|
+
}, ...openRouterRequestFailureReasons.flatMap(reason => {
|
|
5595
|
+
return [{
|
|
5596
|
+
childCount: 1,
|
|
5597
|
+
className: ChatOrderedListItem,
|
|
5598
|
+
type: Li
|
|
5599
|
+
}, text(reason)];
|
|
5600
|
+
})];
|
|
5601
|
+
};
|
|
5602
|
+
|
|
5603
|
+
const getOpenRouterTooManyRequestsDom = () => {
|
|
5604
|
+
return [{
|
|
5605
|
+
childCount: openRouterTooManyRequestsReasons.length,
|
|
5606
|
+
className: ChatOrderedList,
|
|
5607
|
+
type: Ol
|
|
5608
|
+
}, ...openRouterTooManyRequestsReasons.flatMap(reason => {
|
|
5609
|
+
return [{
|
|
5610
|
+
childCount: 1,
|
|
5611
|
+
className: ChatOrderedListItem,
|
|
5612
|
+
type: Li
|
|
5613
|
+
}, text(reason)];
|
|
5614
|
+
})];
|
|
5615
|
+
};
|
|
5616
|
+
|
|
5617
|
+
const getToolCallArgumentPreview = rawArguments => {
|
|
5618
|
+
if (!rawArguments.trim()) {
|
|
5619
|
+
return '""';
|
|
5620
|
+
}
|
|
5621
|
+
let parsed;
|
|
5622
|
+
try {
|
|
5623
|
+
parsed = JSON.parse(rawArguments);
|
|
5624
|
+
} catch {
|
|
5625
|
+
return rawArguments;
|
|
5626
|
+
}
|
|
5627
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
5628
|
+
return rawArguments;
|
|
5629
|
+
}
|
|
5630
|
+
const path = Reflect.get(parsed, 'path');
|
|
5631
|
+
if (typeof path === 'string') {
|
|
5632
|
+
return `"${path}"`;
|
|
5633
|
+
}
|
|
5634
|
+
const keys = Object.keys(parsed);
|
|
5635
|
+
if (keys.length === 1) {
|
|
5636
|
+
const value = Reflect.get(parsed, keys[0]);
|
|
5637
|
+
if (typeof value === 'string') {
|
|
5638
|
+
return `"${value}"`;
|
|
5639
|
+
}
|
|
5640
|
+
}
|
|
5641
|
+
return rawArguments;
|
|
5642
|
+
};
|
|
5643
|
+
|
|
5372
5644
|
const orderedListItemRegex = /^\s*\d+\.\s+(.*)$/;
|
|
5373
5645
|
const parseMessageContent = rawMessage => {
|
|
5374
5646
|
if (rawMessage === '') {
|
|
@@ -5449,32 +5721,6 @@ const getMessageContentDom = nodes => {
|
|
|
5449
5721
|
});
|
|
5450
5722
|
};
|
|
5451
5723
|
|
|
5452
|
-
const getToolCallArgumentPreview = rawArguments => {
|
|
5453
|
-
if (!rawArguments.trim()) {
|
|
5454
|
-
return '""';
|
|
5455
|
-
}
|
|
5456
|
-
let parsed;
|
|
5457
|
-
try {
|
|
5458
|
-
parsed = JSON.parse(rawArguments);
|
|
5459
|
-
} catch {
|
|
5460
|
-
return rawArguments;
|
|
5461
|
-
}
|
|
5462
|
-
if (!parsed || typeof parsed !== 'object') {
|
|
5463
|
-
return rawArguments;
|
|
5464
|
-
}
|
|
5465
|
-
const path = Reflect.get(parsed, 'path');
|
|
5466
|
-
if (typeof path === 'string') {
|
|
5467
|
-
return `"${path}"`;
|
|
5468
|
-
}
|
|
5469
|
-
const keys = Object.keys(parsed);
|
|
5470
|
-
if (keys.length === 1) {
|
|
5471
|
-
const value = Reflect.get(parsed, keys[0]);
|
|
5472
|
-
if (typeof value === 'string') {
|
|
5473
|
-
return `"${value}"`;
|
|
5474
|
-
}
|
|
5475
|
-
}
|
|
5476
|
-
return rawArguments;
|
|
5477
|
-
};
|
|
5478
5724
|
const getToolCallsDom = message => {
|
|
5479
5725
|
if (message.role !== 'assistant' || !message.toolCalls || message.toolCalls.length === 0) {
|
|
5480
5726
|
return [];
|
|
@@ -5489,32 +5735,6 @@ const getToolCallsDom = message => {
|
|
|
5489
5735
|
}, text(label)];
|
|
5490
5736
|
});
|
|
5491
5737
|
};
|
|
5492
|
-
const getOpenRouterRequestFailedDom = () => {
|
|
5493
|
-
return [{
|
|
5494
|
-
childCount: openRouterRequestFailureReasons.length,
|
|
5495
|
-
className: ChatOrderedList,
|
|
5496
|
-
type: Ol
|
|
5497
|
-
}, ...openRouterRequestFailureReasons.flatMap(reason => {
|
|
5498
|
-
return [{
|
|
5499
|
-
childCount: 1,
|
|
5500
|
-
className: ChatOrderedListItem,
|
|
5501
|
-
type: Li
|
|
5502
|
-
}, text(reason)];
|
|
5503
|
-
})];
|
|
5504
|
-
};
|
|
5505
|
-
const getOpenRouterTooManyRequestsDom = () => {
|
|
5506
|
-
return [{
|
|
5507
|
-
childCount: openRouterTooManyRequestsReasons.length,
|
|
5508
|
-
className: ChatOrderedList,
|
|
5509
|
-
type: Ol
|
|
5510
|
-
}, ...openRouterTooManyRequestsReasons.flatMap(reason => {
|
|
5511
|
-
return [{
|
|
5512
|
-
childCount: 1,
|
|
5513
|
-
className: ChatOrderedListItem,
|
|
5514
|
-
type: Li
|
|
5515
|
-
}, text(reason)];
|
|
5516
|
-
})];
|
|
5517
|
-
};
|
|
5518
5738
|
const getChatMessageDom = (message, openRouterApiKeyInput, openApiApiKeyInput = '', openRouterApiKeyState = 'idle') => {
|
|
5519
5739
|
const roleClassName = message.role === 'user' ? MessageUser : MessageAssistant;
|
|
5520
5740
|
const isOpenApiApiKeyMissingMessage = message.role === 'assistant' && message.text === openApiApiKeyRequiredMessage;
|
|
@@ -5939,6 +6159,7 @@ const commandMap = {
|
|
|
5939
6159
|
'Chat.initialize': initialize,
|
|
5940
6160
|
'Chat.loadContent': wrapCommand(loadContent),
|
|
5941
6161
|
'Chat.loadContent2': wrapCommand(loadContent),
|
|
6162
|
+
'Chat.mockOpenApiSetHttpErrorResponse': wrapCommand(mockOpenApiSetHttpErrorResponse),
|
|
5942
6163
|
'Chat.mockOpenApiStreamFinish': wrapCommand(mockOpenApiStreamFinish),
|
|
5943
6164
|
'Chat.mockOpenApiStreamPushChunk': wrapCommand(mockOpenApiStreamPushChunk),
|
|
5944
6165
|
'Chat.mockOpenApiStreamReset': wrapCommand(mockOpenApiStreamReset),
|