@lvce-editor/chat-view 2.2.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.
@@ -1478,6 +1478,7 @@ const createDefaultState = () => {
1478
1478
  listItemHeight: 40,
1479
1479
  maxComposerRows: 5,
1480
1480
  messagesScrollTop: 0,
1481
+ mockAiResponseDelay: 800,
1481
1482
  mockApiCommandId: '',
1482
1483
  models: getDefaultModels(),
1483
1484
  nextMessageId: 1,
@@ -2138,10 +2139,14 @@ const replaySession$1 = (id, summary, events) => {
2138
2139
  }
2139
2140
  return {
2140
2141
  ...message,
2141
- inProgress: event.inProgress,
2142
+ ...(event.inProgress === undefined ? {} : {
2143
+ inProgress: event.inProgress
2144
+ }),
2142
2145
  text: event.text,
2143
2146
  time: event.time,
2144
- toolCalls: event.toolCalls
2147
+ ...(event.toolCalls === undefined ? {} : {
2148
+ toolCalls: event.toolCalls
2149
+ })
2145
2150
  };
2146
2151
  });
2147
2152
  continue;
@@ -2439,10 +2444,14 @@ const replaySession = (id, title, events) => {
2439
2444
  }
2440
2445
  return {
2441
2446
  ...message,
2442
- inProgress: event.inProgress,
2447
+ ...(event.inProgress === undefined ? {} : {
2448
+ inProgress: event.inProgress
2449
+ }),
2443
2450
  text: event.text,
2444
2451
  time: event.time,
2445
- toolCalls: event.toolCalls
2452
+ ...(event.toolCalls === undefined ? {} : {
2453
+ toolCalls: event.toolCalls
2454
+ })
2446
2455
  };
2447
2456
  });
2448
2457
  continue;
@@ -2656,18 +2665,45 @@ const delay = async ms => {
2656
2665
  await new Promise(resolve => setTimeout(resolve, ms));
2657
2666
  };
2658
2667
 
2659
- const getMockAiResponse = async userMessage => {
2660
- await delay(800);
2668
+ const getMockAiResponse = async (userMessage, delayInMs) => {
2669
+ await delay(delayInMs);
2661
2670
  return `Mock AI response: I received "${userMessage}".`;
2662
2671
  };
2663
2672
 
2664
2673
  let queue = [];
2665
2674
  let waiters = [];
2666
2675
  let finished = false;
2676
+ let errorResult;
2667
2677
  const reset$1 = () => {
2668
2678
  queue = [];
2669
2679
  waiters = [];
2670
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;
2671
2707
  };
2672
2708
  const pushChunk = chunk => {
2673
2709
  if (waiters.length > 0) {
@@ -2695,12 +2731,19 @@ const readNextChunk = async () => {
2695
2731
  if (finished) {
2696
2732
  return undefined;
2697
2733
  }
2698
- return new Promise(resolve => {
2699
- waiters.push(resolve);
2700
- });
2734
+ const {
2735
+ promise,
2736
+ resolve
2737
+ } = Promise.withResolvers();
2738
+ waiters.push(resolve);
2739
+ return promise;
2701
2740
  };
2702
2741
 
2703
2742
  const getMockOpenApiAssistantText = async (stream, onTextChunk) => {
2743
+ const error = takeErrorResponse();
2744
+ if (error) {
2745
+ return error;
2746
+ }
2704
2747
  let text = '';
2705
2748
  while (true) {
2706
2749
  const chunk = await readNextChunk();
@@ -2750,13 +2793,23 @@ const normalizeLimitInfo = value => {
2750
2793
  const usage = Reflect.get(value, 'usage');
2751
2794
  const usageDaily = Reflect.get(value, 'usageDaily');
2752
2795
  const normalized = {
2753
- limitRemaining: typeof limitRemaining === 'number' || limitRemaining === null ? limitRemaining : undefined,
2754
- limitReset: typeof limitReset === 'string' || limitReset === null ? limitReset : undefined,
2755
- retryAfter: typeof retryAfter === 'string' || retryAfter === null ? retryAfter : undefined,
2756
- usage: typeof usage === 'number' ? usage : undefined,
2757
- usageDaily: typeof usageDaily === 'number' ? usageDaily : undefined
2796
+ ...(typeof limitRemaining === 'number' || limitRemaining === null ? {
2797
+ limitRemaining
2798
+ } : {}),
2799
+ ...(typeof limitReset === 'string' || limitReset === null ? {
2800
+ limitReset
2801
+ } : {}),
2802
+ ...(typeof retryAfter === 'string' || retryAfter === null ? {
2803
+ retryAfter
2804
+ } : {}),
2805
+ ...(typeof usage === 'number' ? {
2806
+ usage
2807
+ } : {}),
2808
+ ...(typeof usageDaily === 'number' ? {
2809
+ usageDaily
2810
+ } : {})
2758
2811
  };
2759
- const hasDetails = normalized.limitRemaining !== undefined || normalized.limitReset !== undefined || normalized.retryAfter !== undefined || normalized.usage !== undefined || normalized.usageDaily !== undefined;
2812
+ const hasDetails = typeof limitRemaining === 'number' || limitRemaining === null || typeof limitReset === 'string' || limitReset === null || typeof retryAfter === 'string' || retryAfter === null || typeof usage === 'number' || typeof usageDaily === 'number';
2760
2813
  return hasDetails ? normalized : undefined;
2761
2814
  };
2762
2815
 
@@ -2792,11 +2845,18 @@ const normalizeMockResult = value => {
2792
2845
  if (details === 'request-failed' || details === 'too-many-requests' || details === 'http-error') {
2793
2846
  const rawMessage = Reflect.get(value, 'rawMessage');
2794
2847
  const statusCode = Reflect.get(value, 'statusCode');
2848
+ const limitInfo = normalizeLimitInfo(Reflect.get(value, 'limitInfo'));
2795
2849
  return {
2796
2850
  details,
2797
- limitInfo: normalizeLimitInfo(Reflect.get(value, 'limitInfo')),
2798
- rawMessage: typeof rawMessage === 'string' ? rawMessage : undefined,
2799
- statusCode: typeof statusCode === 'number' ? statusCode : undefined,
2851
+ ...(limitInfo ? {
2852
+ limitInfo
2853
+ } : {}),
2854
+ ...(typeof rawMessage === 'string' ? {
2855
+ rawMessage
2856
+ } : {}),
2857
+ ...(typeof statusCode === 'number' ? {
2858
+ statusCode
2859
+ } : {}),
2800
2860
  type: 'error'
2801
2861
  };
2802
2862
  }
@@ -3027,11 +3087,8 @@ const getClientRequestIdHeader = () => {
3027
3087
  };
3028
3088
  };
3029
3089
 
3030
- const getOpenApiApiEndpoint = (openApiApiBaseUrl, stream) => {
3031
- if (stream) {
3032
- return `${openApiApiBaseUrl}/chat/completions?stream=true`;
3033
- }
3034
- return `${openApiApiBaseUrl}/chat/completions`;
3090
+ const getOpenApiApiEndpoint = openApiApiBaseUrl => {
3091
+ return `${openApiApiBaseUrl}/responses`;
3035
3092
  };
3036
3093
 
3037
3094
  const getTextContent = content => {
@@ -3055,18 +3112,50 @@ const getTextContent = content => {
3055
3112
  return textParts.join('\n');
3056
3113
  };
3057
3114
 
3058
- const getOpenAiParams = (completionMessages, modelId, stream, includeObfuscation, tools) => {
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) => {
3059
3143
  return {
3060
- messages: completionMessages,
3144
+ input,
3061
3145
  model: modelId,
3062
3146
  ...(stream ? {
3063
- stream: true
3147
+ stream: true,
3148
+ ...(includeObfuscation ? {} : {
3149
+ stream_options: {
3150
+ include_obfuscation: false
3151
+ }
3152
+ })
3064
3153
  } : {}),
3065
- ...(includeObfuscation ? {
3066
- include_obfuscation: true
3154
+ ...(previousResponseId ? {
3155
+ previous_response_id: previousResponseId
3067
3156
  } : {}),
3068
3157
  tool_choice: 'auto',
3069
- tools
3158
+ tools: getOpenAiTools(tools)
3070
3159
  };
3071
3160
  };
3072
3161
  const getStreamChunkText = content => {
@@ -3084,6 +3173,75 @@ const getStreamChunkText = content => {
3084
3173
  return typeof text === 'string' ? text : '';
3085
3174
  }).join('');
3086
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
+ };
3087
3245
  const parseSseEvent = eventChunk => {
3088
3246
  const lines = eventChunk.split('\n');
3089
3247
  const dataLines = [];
@@ -3130,7 +3288,11 @@ const updateToolCallAccumulator = (accumulator, chunk) => {
3130
3288
  }
3131
3289
  const next = {
3132
3290
  arguments: args,
3133
- id: typeof id === 'string' ? id : current.id,
3291
+ ...(typeof id === 'string' ? {
3292
+ id
3293
+ } : current.id ? {
3294
+ id: current.id
3295
+ } : {}),
3134
3296
  name
3135
3297
  };
3136
3298
  if (JSON.stringify(next) !== JSON.stringify(current)) {
@@ -3159,7 +3321,136 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
3159
3321
  let remainder = '';
3160
3322
  let text = '';
3161
3323
  let done = false;
3324
+ let finishedNotified = false;
3162
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
+ };
3163
3454
  while (!done) {
3164
3455
  const {
3165
3456
  done: streamDone,
@@ -3185,9 +3476,7 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
3185
3476
  }
3186
3477
  for (const line of dataLines) {
3187
3478
  if (line === '[DONE]') {
3188
- if (onEventStreamFinished) {
3189
- await onEventStreamFinished();
3190
- }
3479
+ await notifyFinished();
3191
3480
  done = true;
3192
3481
  break;
3193
3482
  }
@@ -3197,41 +3486,7 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
3197
3486
  } catch {
3198
3487
  continue;
3199
3488
  }
3200
- if (!parsed || typeof parsed !== 'object') {
3201
- continue;
3202
- }
3203
- if (onDataEvent) {
3204
- await onDataEvent(parsed);
3205
- }
3206
- const choices = Reflect.get(parsed, 'choices');
3207
- if (!Array.isArray(choices)) {
3208
- continue;
3209
- }
3210
- const firstChoice = choices[0];
3211
- if (!firstChoice || typeof firstChoice !== 'object') {
3212
- continue;
3213
- }
3214
- const delta = Reflect.get(firstChoice, 'delta');
3215
- if (!delta || typeof delta !== 'object') {
3216
- continue;
3217
- }
3218
- const toolCalls = Reflect.get(delta, 'tool_calls');
3219
- const updatedToolCallResult = Array.isArray(toolCalls) ? updateToolCallAccumulator(toolCallAccumulator, toolCalls) : undefined;
3220
- if (updatedToolCallResult) {
3221
- toolCallAccumulator = updatedToolCallResult.nextAccumulator;
3222
- }
3223
- if (updatedToolCallResult && onToolCallsChunk) {
3224
- await onToolCallsChunk(updatedToolCallResult.toolCalls);
3225
- }
3226
- const content = Reflect.get(delta, 'content');
3227
- const chunkText = getStreamChunkText(content);
3228
- if (!chunkText) {
3229
- continue;
3230
- }
3231
- text += chunkText;
3232
- if (onTextChunk) {
3233
- await onTextChunk(chunkText);
3234
- }
3489
+ await handleParsedStreamEvent(parsed);
3235
3490
  }
3236
3491
  }
3237
3492
  }
@@ -3239,9 +3494,7 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
3239
3494
  const dataLines = parseSseEvent(remainder);
3240
3495
  for (const line of dataLines) {
3241
3496
  if (line === '[DONE]') {
3242
- if (onEventStreamFinished) {
3243
- await onEventStreamFinished();
3244
- }
3497
+ await notifyFinished();
3245
3498
  continue;
3246
3499
  }
3247
3500
  let parsed;
@@ -3250,43 +3503,10 @@ const parseOpenApiStream = async (response, onTextChunk, onToolCallsChunk, onDat
3250
3503
  } catch {
3251
3504
  continue;
3252
3505
  }
3253
- if (!parsed || typeof parsed !== 'object') {
3254
- continue;
3255
- }
3256
- if (onDataEvent) {
3257
- await onDataEvent(parsed);
3258
- }
3259
- const choices = Reflect.get(parsed, 'choices');
3260
- if (!Array.isArray(choices)) {
3261
- continue;
3262
- }
3263
- const firstChoice = choices[0];
3264
- if (!firstChoice || typeof firstChoice !== 'object') {
3265
- continue;
3266
- }
3267
- const delta = Reflect.get(firstChoice, 'delta');
3268
- if (!delta || typeof delta !== 'object') {
3269
- continue;
3270
- }
3271
- const toolCalls = Reflect.get(delta, 'tool_calls');
3272
- const updatedToolCallResult = Array.isArray(toolCalls) ? updateToolCallAccumulator(toolCallAccumulator, toolCalls) : undefined;
3273
- if (updatedToolCallResult) {
3274
- toolCallAccumulator = updatedToolCallResult.nextAccumulator;
3275
- }
3276
- if (updatedToolCallResult && onToolCallsChunk) {
3277
- await onToolCallsChunk(updatedToolCallResult.toolCalls);
3278
- }
3279
- const content = Reflect.get(delta, 'content');
3280
- const chunkText = getStreamChunkText(content);
3281
- if (!chunkText) {
3282
- continue;
3283
- }
3284
- text += chunkText;
3285
- if (onTextChunk) {
3286
- await onTextChunk(chunkText);
3287
- }
3506
+ await handleParsedStreamEvent(parsed);
3288
3507
  }
3289
3508
  }
3509
+ await notifyFinished();
3290
3510
  return {
3291
3511
  text,
3292
3512
  type: 'success'
@@ -3310,9 +3530,15 @@ const getOpenApiErrorDetails = async response => {
3310
3530
  const errorMessage = Reflect.get(error, 'message');
3311
3531
  const errorType = Reflect.get(error, 'type');
3312
3532
  return {
3313
- errorCode: typeof errorCode === 'string' ? errorCode : undefined,
3314
- errorMessage: typeof errorMessage === 'string' ? errorMessage : undefined,
3315
- errorType: typeof errorType === 'string' ? errorType : undefined
3533
+ ...(typeof errorCode === 'string' ? {
3534
+ errorCode
3535
+ } : {}),
3536
+ ...(typeof errorMessage === 'string' ? {
3537
+ errorMessage
3538
+ } : {}),
3539
+ ...(typeof errorType === 'string' ? {
3540
+ errorType
3541
+ } : {})
3316
3542
  };
3317
3543
  };
3318
3544
  const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApiApiBaseUrl, assetDir, platform, options) => {
@@ -3326,17 +3552,18 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
3326
3552
  } = options ?? {
3327
3553
  stream: false
3328
3554
  };
3329
- const completionMessages = messages.map(message => ({
3555
+ const openAiInput = messages.map(message => ({
3330
3556
  content: message.text,
3331
3557
  role: message.role
3332
3558
  }));
3333
3559
  const tools = getBasicChatTools();
3334
3560
  const maxToolIterations = 4;
3561
+ let previousResponseId;
3335
3562
  for (let i = 0; i <= maxToolIterations; i++) {
3336
3563
  let response;
3337
3564
  try {
3338
- response = await fetch(getOpenApiApiEndpoint(openApiApiBaseUrl, stream), {
3339
- body: JSON.stringify(getOpenAiParams(completionMessages, modelId, stream, includeObfuscation, tools)),
3565
+ response = await fetch(getOpenApiApiEndpoint(openApiApiBaseUrl), {
3566
+ body: JSON.stringify(getOpenAiParams(openAiInput, modelId, stream, includeObfuscation, tools, previousResponseId)),
3340
3567
  headers: {
3341
3568
  Authorization: `Bearer ${openApiApiKey}`,
3342
3569
  'Content-Type': 'application/json',
@@ -3358,9 +3585,15 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
3358
3585
  } = await getOpenApiErrorDetails(response);
3359
3586
  return {
3360
3587
  details: 'http-error',
3361
- errorCode,
3362
- errorMessage,
3363
- errorType,
3588
+ ...(errorCode ? {
3589
+ errorCode
3590
+ } : {}),
3591
+ ...(errorMessage ? {
3592
+ errorMessage
3593
+ } : {}),
3594
+ ...(errorType ? {
3595
+ errorType
3596
+ } : {}),
3364
3597
  statusCode: response.status,
3365
3598
  type: 'error'
3366
3599
  };
@@ -3383,56 +3616,83 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
3383
3616
  type: 'success'
3384
3617
  };
3385
3618
  }
3386
- const choices = Reflect.get(parsed, 'choices');
3387
- if (!Array.isArray(choices)) {
3388
- return {
3389
- text: '',
3390
- type: 'success'
3391
- };
3619
+ const parsedResponseId = Reflect.get(parsed, 'id');
3620
+ if (typeof parsedResponseId === 'string' && parsedResponseId) {
3621
+ previousResponseId = parsedResponseId;
3392
3622
  }
3393
- const firstChoice = choices[0];
3394
- if (!firstChoice || typeof firstChoice !== 'object') {
3395
- return {
3396
- text: '',
3397
- type: 'success'
3398
- };
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;
3399
3638
  }
3400
- const message = Reflect.get(firstChoice, 'message');
3401
- if (!message || typeof message !== 'object') {
3639
+ const outputText = getResponseOutputText(parsed);
3640
+ if (outputText) {
3402
3641
  return {
3403
- text: '',
3642
+ text: outputText,
3404
3643
  type: 'success'
3405
3644
  };
3406
3645
  }
3407
- const toolCalls = Reflect.get(message, 'tool_calls');
3408
- if (Array.isArray(toolCalls) && toolCalls.length > 0) {
3409
- completionMessages.push(message);
3410
- for (const toolCall of toolCalls) {
3411
- if (!toolCall || typeof toolCall !== 'object') {
3412
- continue;
3413
- }
3414
- const id = Reflect.get(toolCall, 'id');
3415
- const toolFunction = Reflect.get(toolCall, 'function');
3416
- if (typeof id !== 'string' || !toolFunction || typeof toolFunction !== 'object') {
3417
- continue;
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
+ });
3418
3685
  }
3419
- const name = Reflect.get(toolFunction, 'name');
3420
- const rawArguments = Reflect.get(toolFunction, 'arguments');
3421
- const content = typeof name === 'string' ? await executeChatTool(name, rawArguments, {
3422
- assetDir,
3423
- platform
3424
- }) : '{}';
3425
- completionMessages.push({
3426
- content,
3427
- role: 'tool',
3428
- tool_call_id: id
3429
- });
3686
+ continue;
3430
3687
  }
3431
- continue;
3688
+ const content = Reflect.get(message, 'content');
3689
+ return {
3690
+ text: getTextContent(content),
3691
+ type: 'success'
3692
+ };
3432
3693
  }
3433
- const content = Reflect.get(message, 'content');
3434
3694
  return {
3435
- text: getTextContent(content),
3695
+ text: '',
3436
3696
  type: 'success'
3437
3697
  };
3438
3698
  }
@@ -3568,10 +3828,18 @@ const getOpenRouterLimitInfo = async (openRouterApiKey, openRouterApiBaseUrl) =>
3568
3828
  const usage = Reflect.get(data, 'usage');
3569
3829
  const usageDaily = Reflect.get(data, 'usage_daily');
3570
3830
  const normalizedLimitInfo = {
3571
- limitRemaining: typeof limitRemaining === 'number' || limitRemaining === null ? limitRemaining : undefined,
3572
- limitReset: typeof limitReset === 'string' || limitReset === null ? limitReset : undefined,
3573
- usage: typeof usage === 'number' ? usage : undefined,
3574
- usageDaily: typeof usageDaily === 'number' ? usageDaily : undefined
3831
+ ...(typeof limitRemaining === 'number' || limitRemaining === null ? {
3832
+ limitRemaining
3833
+ } : {}),
3834
+ ...(typeof limitReset === 'string' || limitReset === null ? {
3835
+ limitReset
3836
+ } : {}),
3837
+ ...(typeof usage === 'number' ? {
3838
+ usage
3839
+ } : {}),
3840
+ ...(typeof usageDaily === 'number' ? {
3841
+ usageDaily
3842
+ } : {})
3575
3843
  };
3576
3844
  const hasLimitInfo = normalizedLimitInfo.limitRemaining !== undefined || normalizedLimitInfo.limitReset !== undefined || normalizedLimitInfo.usage !== undefined || normalizedLimitInfo.usageDaily !== undefined;
3577
3845
  if (!hasLimitInfo) {
@@ -3616,11 +3884,17 @@ const getOpenRouterAssistantText = async (messages, modelId, openRouterApiKey, o
3616
3884
  const limitInfo = await getOpenRouterLimitInfo(openRouterApiKey, openRouterApiBaseUrl);
3617
3885
  return {
3618
3886
  details: 'too-many-requests',
3619
- limitInfo: limitInfo || retryAfter ? {
3620
- ...limitInfo,
3621
- retryAfter
3622
- } : undefined,
3623
- rawMessage,
3887
+ ...(limitInfo || retryAfter ? {
3888
+ limitInfo: {
3889
+ ...limitInfo,
3890
+ ...(retryAfter ? {
3891
+ retryAfter
3892
+ } : {})
3893
+ }
3894
+ } : {}),
3895
+ ...(rawMessage ? {
3896
+ rawMessage
3897
+ } : {}),
3624
3898
  statusCode: 429,
3625
3899
  type: 'error'
3626
3900
  };
@@ -3782,6 +4056,7 @@ const getAiResponse = async ({
3782
4056
  assetDir,
3783
4057
  messageId,
3784
4058
  messages,
4059
+ mockAiResponseDelay = 800,
3785
4060
  mockApiCommandId,
3786
4061
  models,
3787
4062
  onDataEvent,
@@ -3816,10 +4091,18 @@ const getAiResponse = async ({
3816
4091
  } else if (openApiApiKey) {
3817
4092
  const result = await getOpenApiAssistantText(messages, getOpenApiModelId(selectedModelId), openApiApiKey, openApiApiBaseUrl, assetDir, platform, {
3818
4093
  includeObfuscation: passIncludeObfuscation,
3819
- onDataEvent,
3820
- onEventStreamFinished,
3821
- onTextChunk,
3822
- onToolCallsChunk,
4094
+ ...(onDataEvent ? {
4095
+ onDataEvent
4096
+ } : {}),
4097
+ ...(onEventStreamFinished ? {
4098
+ onEventStreamFinished
4099
+ } : {}),
4100
+ ...(onTextChunk ? {
4101
+ onTextChunk
4102
+ } : {}),
4103
+ ...(onToolCallsChunk ? {
4104
+ onToolCallsChunk
4105
+ } : {}),
3823
4106
  stream: streamingEnabled
3824
4107
  });
3825
4108
  if (result.type === 'success') {
@@ -3860,7 +4143,7 @@ const getAiResponse = async ({
3860
4143
  }
3861
4144
  }
3862
4145
  if (!text && !usesOpenApiModel && !usesOpenRouterModel) {
3863
- text = await getMockAiResponse(userText);
4146
+ text = await getMockAiResponse(userText, mockAiResponseDelay);
3864
4147
  }
3865
4148
  const assistantTime = new Date().toLocaleTimeString([], {
3866
4149
  hour: '2-digit',
@@ -3920,6 +4203,7 @@ const handleClickSaveOpenApiApiKey = async state => {
3920
4203
  const assistantMessage = await getAiResponse({
3921
4204
  assetDir: updatedState.assetDir,
3922
4205
  messages: retryMessages,
4206
+ mockAiResponseDelay: updatedState.mockAiResponseDelay,
3923
4207
  mockApiCommandId: updatedState.mockApiCommandId,
3924
4208
  models: updatedState.models,
3925
4209
  openApiApiBaseUrl: updatedState.openApiApiBaseUrl,
@@ -3999,6 +4283,7 @@ const handleClickSaveOpenRouterApiKey = async state => {
3999
4283
  const assistantMessage = await getAiResponse({
4000
4284
  assetDir: updatedState.assetDir,
4001
4285
  messages: retryMessages,
4286
+ mockAiResponseDelay: updatedState.mockAiResponseDelay,
4002
4287
  mockApiCommandId: updatedState.mockApiCommandId,
4003
4288
  models: updatedState.models,
4004
4289
  openApiApiBaseUrl: updatedState.openApiApiBaseUrl,
@@ -4091,13 +4376,6 @@ const handleTextChunkFunction = async (uid, assistantMessageId, chunk, handleTex
4091
4376
  previousState: handleTextChunkState.previousState
4092
4377
  };
4093
4378
  }
4094
- await appendChatViewEvent({
4095
- content: chunk,
4096
- messageId: assistantMessageId,
4097
- sessionId: handleTextChunkState.latestState.selectedSessionId,
4098
- timestamp: new Date().toISOString(),
4099
- type: 'handle-response-chunk'
4100
- });
4101
4379
  const updatedText = assistantMessage.text + chunk;
4102
4380
  const updatedSessions = updateMessageTextInSelectedSession(handleTextChunkState.latestState.sessions, handleTextChunkState.latestState.selectedSessionId, assistantMessageId, updatedText, true);
4103
4381
  const nextState = {
@@ -4156,6 +4434,7 @@ const handleSubmit = async state => {
4156
4434
  const {
4157
4435
  assetDir,
4158
4436
  composerValue,
4437
+ mockAiResponseDelay,
4159
4438
  mockApiCommandId,
4160
4439
  models,
4161
4440
  nextMessageId,
@@ -4276,6 +4555,7 @@ const handleSubmit = async state => {
4276
4555
  assetDir,
4277
4556
  messageId: assistantMessageId,
4278
4557
  messages,
4558
+ mockAiResponseDelay,
4279
4559
  mockApiCommandId,
4280
4560
  models,
4281
4561
  onDataEvent: async value => {
@@ -4294,7 +4574,9 @@ const handleSubmit = async state => {
4294
4574
  value: '[DONE]'
4295
4575
  });
4296
4576
  },
4297
- onTextChunk: handleTextChunkFunctionRef,
4577
+ ...(handleTextChunkFunctionRef ? {
4578
+ onTextChunk: handleTextChunkFunctionRef
4579
+ } : {}),
4298
4580
  onToolCallsChunk: async toolCalls => {
4299
4581
  handleTextChunkState = await handleToolCallsChunkFunction(state.uid, assistantMessageId, toolCalls, handleTextChunkState);
4300
4582
  },
@@ -4815,13 +5097,6 @@ const loadPreferences = async () => {
4815
5097
  };
4816
5098
  };
4817
5099
 
4818
- const toSummarySession = session => {
4819
- return {
4820
- id: session.id,
4821
- messages: [],
4822
- title: session.title
4823
- };
4824
- };
4825
5100
  const loadSelectedSessionMessages = async (sessions, selectedSessionId) => {
4826
5101
  if (!selectedSessionId) {
4827
5102
  return sessions;
@@ -4837,6 +5112,14 @@ const loadSelectedSessionMessages = async (sessions, selectedSessionId) => {
4837
5112
  return loadedSession;
4838
5113
  });
4839
5114
  };
5115
+
5116
+ const toSummarySession = session => {
5117
+ return {
5118
+ id: session.id,
5119
+ messages: [],
5120
+ title: session.title
5121
+ };
5122
+ };
4840
5123
  const loadContent = async (state, savedState) => {
4841
5124
  const savedSelectedModelId = getSavedSelectedModelId(savedState);
4842
5125
  const savedViewMode = getSavedViewMode(savedState);
@@ -4888,6 +5171,11 @@ const loadContent = async (state, savedState) => {
4888
5171
  };
4889
5172
  };
4890
5173
 
5174
+ const mockOpenApiSetHttpErrorResponse = (state, statusCode, body) => {
5175
+ setHttpErrorResponse(statusCode, body);
5176
+ return state;
5177
+ };
5178
+
4891
5179
  const mockOpenApiStreamFinish = state => {
4892
5180
  finish();
4893
5181
  return state;
@@ -5060,6 +5348,18 @@ const getModelOptionDOm = (model, selectedModelId) => {
5060
5348
  }, text(getModelLabel(model))];
5061
5349
  };
5062
5350
 
5351
+ const getChatSelectVirtualDom = (models, selectedModelId) => {
5352
+ const modelOptions = models.flatMap(model => getModelOptionDOm(model, selectedModelId));
5353
+ return [{
5354
+ childCount: models.length,
5355
+ className: Select,
5356
+ name: Model,
5357
+ onInput: HandleModelChange,
5358
+ type: Select$1,
5359
+ value: selectedModelId
5360
+ }, ...modelOptions];
5361
+ };
5362
+
5063
5363
  const getSendButtonClassName = isSendDisabled => {
5064
5364
  return isSendDisabled ? `${IconButton} ${SendButtonDisabled}` : `${IconButton}`;
5065
5365
  };
@@ -5119,7 +5419,6 @@ const getUsageOverviewDom = (tokensUsed, tokensMax) => {
5119
5419
 
5120
5420
  const getChatSendAreaDom = (composerValue, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, composerHeight = 28, composerFontSize = 13, composerFontFamily = 'system-ui', composerLineHeight = 20) => {
5121
5421
  const isSendDisabled = composerValue.trim() === '';
5122
- const modelOptions = models.flatMap(model => getModelOptionDOm(model, selectedModelId));
5123
5422
  return [{
5124
5423
  childCount: 1,
5125
5424
  className: ChatSendArea,
@@ -5135,21 +5434,13 @@ const getChatSendAreaDom = (composerValue, models, selectedModelId, usageOvervie
5135
5434
  onFocus: HandleFocus,
5136
5435
  onInput: HandleInput,
5137
5436
  placeholder: composePlaceholder(),
5138
- // style: `height:${composerHeight}px;font-size:${composerFontSize}px;font-family:${composerFontFamily};line-height:${composerLineHeight}px;`,
5139
5437
  type: TextArea,
5140
5438
  value: composerValue
5141
5439
  }, {
5142
5440
  childCount: usageOverviewEnabled ? 3 : 2,
5143
5441
  className: ChatSendAreaBottom,
5144
5442
  type: Div
5145
- }, {
5146
- childCount: models.length,
5147
- className: Select,
5148
- name: Model,
5149
- onInput: HandleModelChange,
5150
- type: Select$1,
5151
- value: selectedModelId
5152
- }, ...modelOptions, ...(usageOverviewEnabled ? getUsageOverviewDom(tokensUsed, tokensMax) : []), ...getSendButtonDom(isSendDisabled)];
5443
+ }, ...getChatSelectVirtualDom(models, selectedModelId), ...(usageOverviewEnabled ? getUsageOverviewDom(tokensUsed, tokensMax) : []), ...getSendButtonDom(isSendDisabled)];
5153
5444
  };
5154
5445
 
5155
5446
  const getBackButtonVirtualDom = () => {
@@ -5295,6 +5586,61 @@ const getMissingOpenRouterApiKeyDom = (openRouterApiKeyInput, openRouterApiKeySt
5295
5586
  });
5296
5587
  };
5297
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
+
5298
5644
  const orderedListItemRegex = /^\s*\d+\.\s+(.*)$/;
5299
5645
  const parseMessageContent = rawMessage => {
5300
5646
  if (rawMessage === '') {
@@ -5375,32 +5721,6 @@ const getMessageContentDom = nodes => {
5375
5721
  });
5376
5722
  };
5377
5723
 
5378
- const getToolCallArgumentPreview = rawArguments => {
5379
- if (!rawArguments.trim()) {
5380
- return '""';
5381
- }
5382
- let parsed;
5383
- try {
5384
- parsed = JSON.parse(rawArguments);
5385
- } catch {
5386
- return rawArguments;
5387
- }
5388
- if (!parsed || typeof parsed !== 'object') {
5389
- return rawArguments;
5390
- }
5391
- const path = Reflect.get(parsed, 'path');
5392
- if (typeof path === 'string') {
5393
- return `"${path}"`;
5394
- }
5395
- const keys = Object.keys(parsed);
5396
- if (keys.length === 1) {
5397
- const value = Reflect.get(parsed, keys[0]);
5398
- if (typeof value === 'string') {
5399
- return `"${value}"`;
5400
- }
5401
- }
5402
- return rawArguments;
5403
- };
5404
5724
  const getToolCallsDom = message => {
5405
5725
  if (message.role !== 'assistant' || !message.toolCalls || message.toolCalls.length === 0) {
5406
5726
  return [];
@@ -5415,32 +5735,6 @@ const getToolCallsDom = message => {
5415
5735
  }, text(label)];
5416
5736
  });
5417
5737
  };
5418
- const getOpenRouterRequestFailedDom = () => {
5419
- return [{
5420
- childCount: openRouterRequestFailureReasons.length,
5421
- className: ChatOrderedList,
5422
- type: Ol
5423
- }, ...openRouterRequestFailureReasons.flatMap(reason => {
5424
- return [{
5425
- childCount: 1,
5426
- className: ChatOrderedListItem,
5427
- type: Li
5428
- }, text(reason)];
5429
- })];
5430
- };
5431
- const getOpenRouterTooManyRequestsDom = () => {
5432
- return [{
5433
- childCount: openRouterTooManyRequestsReasons.length,
5434
- className: ChatOrderedList,
5435
- type: Ol
5436
- }, ...openRouterTooManyRequestsReasons.flatMap(reason => {
5437
- return [{
5438
- childCount: 1,
5439
- className: ChatOrderedListItem,
5440
- type: Li
5441
- }, text(reason)];
5442
- })];
5443
- };
5444
5738
  const getChatMessageDom = (message, openRouterApiKeyInput, openApiApiKeyInput = '', openRouterApiKeyState = 'idle') => {
5445
5739
  const roleClassName = message.role === 'user' ? MessageUser : MessageAssistant;
5446
5740
  const isOpenApiApiKeyMissingMessage = message.role === 'assistant' && message.text === openApiApiKeyRequiredMessage;
@@ -5577,7 +5871,7 @@ const getChatModeUnsupportedVirtualDom = () => {
5577
5871
  }, text(unknownViewMode())];
5578
5872
  };
5579
5873
 
5580
- const getChatVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openApiApiKeyInput = '', openRouterApiKeyState = 'idle', composerHeight = 28, composerFontSize = 13, composerFontFamily = 'system-ui', composerLineHeight = 20, chatListScrollTop = 0, messagesScrollTop = 0) => {
5874
+ const getChatVirtualDom = (sessions, selectedSessionId, composerValue, openRouterApiKeyInput, viewMode, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openApiApiKeyInput, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, chatListScrollTop, messagesScrollTop) => {
5581
5875
  switch (viewMode) {
5582
5876
  case 'detail':
5583
5877
  return getChatModeDetailVirtualDom(sessions, selectedSessionId, composerValue, openRouterApiKeyInput, openApiApiKeyInput, models, selectedModelId, usageOverviewEnabled, tokensUsed, tokensMax, openRouterApiKeyState, composerHeight, composerFontSize, composerFontFamily, composerLineHeight, messagesScrollTop);
@@ -5746,6 +6040,7 @@ const reset = async state => {
5746
6040
  ...state,
5747
6041
  composerHeight: getMinComposerHeightForState(state),
5748
6042
  composerValue: '',
6043
+ mockAiResponseDelay: 0,
5749
6044
  openRouterApiKey: '',
5750
6045
  selectedModelId: 'test',
5751
6046
  selectedSessionId: '',
@@ -5864,6 +6159,7 @@ const commandMap = {
5864
6159
  'Chat.initialize': initialize,
5865
6160
  'Chat.loadContent': wrapCommand(loadContent),
5866
6161
  'Chat.loadContent2': wrapCommand(loadContent),
6162
+ 'Chat.mockOpenApiSetHttpErrorResponse': wrapCommand(mockOpenApiSetHttpErrorResponse),
5867
6163
  'Chat.mockOpenApiStreamFinish': wrapCommand(mockOpenApiStreamFinish),
5868
6164
  'Chat.mockOpenApiStreamPushChunk': wrapCommand(mockOpenApiStreamPushChunk),
5869
6165
  'Chat.mockOpenApiStreamReset': wrapCommand(mockOpenApiStreamReset),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "2.2.0",
3
+ "version": "2.4.0",
4
4
  "description": "Chat View Worker",
5
5
  "repository": {
6
6
  "type": "git",