@lvce-editor/chat-view 7.10.0 → 7.12.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.
@@ -2283,7 +2283,7 @@ const getVisibleModels = (models, modelPickerSearchValue) => {
2283
2283
  };
2284
2284
 
2285
2285
  const reasoningEfforts = ['extra-high', 'high', 'medium', 'low'];
2286
- const defaultReasoningEffort = 'high';
2286
+ const defaultReasoningEffort = 'medium';
2287
2287
  const isReasoningEffort = value => {
2288
2288
  return reasoningEfforts.includes(value);
2289
2289
  };
@@ -4365,6 +4365,7 @@ const getBackendAuthUrl = (backendUrl, path) => {
4365
4365
  return `${trimTrailingSlashes(backendUrl)}${path}`;
4366
4366
  };
4367
4367
 
4368
+ const PlatformTypeElectron$1 = 2;
4368
4369
  const getCurrentHref = async () => {
4369
4370
  try {
4370
4371
  return await invoke('Layout.getHref');
@@ -4376,11 +4377,20 @@ const getCurrentHref = async () => {
4376
4377
  }
4377
4378
  return globalThis.location.href;
4378
4379
  };
4379
- const getBackendLoginUrl = async backendUrl => {
4380
- const loginUrl = new URL(getBackendAuthUrl(backendUrl, '/login'));
4381
- const redirectUri = await getCurrentHref();
4380
+ const getEffectiveRedirectUri = async (platform, uid, redirectUri) => {
4382
4381
  if (redirectUri) {
4383
- loginUrl.searchParams.set('redirect_uri', redirectUri);
4382
+ return redirectUri;
4383
+ }
4384
+ if (platform === PlatformTypeElectron$1) {
4385
+ return `http://localhost:${await invoke('OAuthServer.create', String(uid))}`;
4386
+ }
4387
+ return getCurrentHref();
4388
+ };
4389
+ const getBackendLoginUrl = async (backendUrl, platform = 0, uid = 0, redirectUri = '') => {
4390
+ const loginUrl = new URL(getBackendAuthUrl(backendUrl, '/login'));
4391
+ const effectiveRedirectUri = await getEffectiveRedirectUri(platform, uid, redirectUri);
4392
+ if (effectiveRedirectUri) {
4393
+ loginUrl.searchParams.set('redirect_uri', effectiveRedirectUri);
4384
4394
  }
4385
4395
  return loginUrl.toString();
4386
4396
  };
@@ -4561,6 +4571,25 @@ const waitForBackendLogin = async (backendUrl, timeoutMs = 30_000, pollIntervalM
4561
4571
  return getLoggedOutBackendAuthState(lastErrorMessage);
4562
4572
  };
4563
4573
 
4574
+ const hasAuthorizationCode = value => {
4575
+ return typeof value === 'string' && value.length > 0;
4576
+ };
4577
+ const waitForElectronBackendLogin = async (backendUrl, uid, timeoutMs = 30_000, pollIntervalMs = 1000) => {
4578
+ const started = Date.now();
4579
+ const deadline = started + timeoutMs;
4580
+ while (Date.now() < deadline) {
4581
+ const authorizationCode = await invoke('OAuthServer.getCode', String(uid));
4582
+ if (hasAuthorizationCode(authorizationCode)) {
4583
+ const elapsed = Date.now() - started;
4584
+ const remainingTime = Math.max(0, timeoutMs - elapsed);
4585
+ return waitForBackendLogin(backendUrl, remainingTime, pollIntervalMs);
4586
+ }
4587
+ await delay(pollIntervalMs);
4588
+ }
4589
+ return getLoggedOutBackendAuthState('Timed out waiting for backend login.');
4590
+ };
4591
+
4592
+ const PlatformTypeElectron = 2;
4564
4593
  const isLoginResponse = value => {
4565
4594
  if (!value || typeof value !== 'object') {
4566
4595
  return false;
@@ -4568,19 +4597,29 @@ const isLoginResponse = value => {
4568
4597
  return true;
4569
4598
  };
4570
4599
  const getLoggedInState = (state, response) => {
4600
+ const {
4601
+ userName,
4602
+ userSubscriptionPlan,
4603
+ userUsedTokens
4604
+ } = state;
4571
4605
  const accessToken = typeof response.accessToken === 'string' ? response.accessToken : '';
4572
4606
  return {
4573
4607
  ...state,
4574
4608
  authAccessToken: accessToken,
4575
4609
  authErrorMessage: '',
4576
- userName: typeof response.userName === 'string' ? response.userName : state.userName,
4610
+ userName: typeof response.userName === 'string' ? response.userName : userName,
4577
4611
  userState: accessToken ? 'loggedIn' : 'loggedOut',
4578
- userSubscriptionPlan: typeof response.subscriptionPlan === 'string' ? response.subscriptionPlan : state.userSubscriptionPlan,
4579
- userUsedTokens: typeof response.usedTokens === 'number' ? response.usedTokens : state.userUsedTokens
4612
+ userSubscriptionPlan: typeof response.subscriptionPlan === 'string' ? response.subscriptionPlan : userSubscriptionPlan,
4613
+ userUsedTokens: typeof response.usedTokens === 'number' ? response.usedTokens : userUsedTokens
4580
4614
  };
4581
4615
  };
4582
4616
  const handleClickLogin = async state => {
4583
- if (!state.backendUrl) {
4617
+ const {
4618
+ backendUrl,
4619
+ platform,
4620
+ uid
4621
+ } = state;
4622
+ if (!backendUrl) {
4584
4623
  return {
4585
4624
  ...state,
4586
4625
  authErrorMessage: 'Backend URL is missing.',
@@ -4592,8 +4631,8 @@ const handleClickLogin = async state => {
4592
4631
  authErrorMessage: '',
4593
4632
  userState: 'loggingIn'
4594
4633
  };
4595
- if (state.uid) {
4596
- set(state.uid, state, signingInState);
4634
+ if (uid) {
4635
+ set(uid, state, signingInState);
4597
4636
  await invoke('Chat.rerender');
4598
4637
  }
4599
4638
  try {
@@ -4615,9 +4654,9 @@ const handleClickLogin = async state => {
4615
4654
  }
4616
4655
  return getLoggedInState(signingInState, response);
4617
4656
  }
4618
- const url = await getBackendLoginUrl(state.backendUrl);
4619
- await openUrl(url, state.platform);
4620
- const authState = await waitForBackendLogin(state.backendUrl);
4657
+ const url = await getBackendLoginUrl(backendUrl, platform, uid);
4658
+ await openUrl(url, platform);
4659
+ const authState = platform === PlatformTypeElectron ? await waitForElectronBackendLogin(backendUrl, uid) : await waitForBackendLogin(backendUrl);
4621
4660
  return {
4622
4661
  ...signingInState,
4623
4662
  ...authState
@@ -4999,8 +5038,22 @@ const getBackendErrorMessage = errorResult => {
4999
5038
  }
5000
5039
  return backendCompletionFailedMessage;
5001
5040
  }
5041
+ case 'invalid-response':
5042
+ {
5043
+ const errorMessage = errorResult.errorMessage?.trim();
5044
+ if (errorMessage) {
5045
+ return `Backend completion request failed. ${errorMessage}`;
5046
+ }
5047
+ return 'Backend completion request failed. Unexpected backend response format.';
5048
+ }
5002
5049
  case 'request-failed':
5003
- return backendCompletionFailedMessage;
5050
+ {
5051
+ const errorMessage = errorResult.errorMessage?.trim();
5052
+ if (errorMessage) {
5053
+ return `Backend completion request failed. ${errorMessage}`;
5054
+ }
5055
+ return backendCompletionFailedMessage;
5056
+ }
5004
5057
  }
5005
5058
  };
5006
5059
 
@@ -7173,6 +7226,7 @@ const isOpenRouterModel = (selectedModelId, models) => {
7173
7226
  };
7174
7227
 
7175
7228
  let errorResponse;
7229
+ let successResponse;
7176
7230
  const setHttpErrorResponse = (statusCode, body) => {
7177
7231
  errorResponse = {
7178
7232
  body,
@@ -7180,11 +7234,22 @@ const setHttpErrorResponse = (statusCode, body) => {
7180
7234
  type: 'http-error'
7181
7235
  };
7182
7236
  };
7237
+ const setResponse = body => {
7238
+ successResponse = {
7239
+ body,
7240
+ type: 'success'
7241
+ };
7242
+ };
7183
7243
  const takeErrorResponse = () => {
7184
7244
  const response = errorResponse;
7185
7245
  errorResponse = undefined;
7186
7246
  return response;
7187
7247
  };
7248
+ const takeResponse = () => {
7249
+ const response = successResponse;
7250
+ successResponse = undefined;
7251
+ return response;
7252
+ };
7188
7253
 
7189
7254
  /* eslint-disable prefer-destructuring */
7190
7255
 
@@ -7230,6 +7295,109 @@ const getBackendStatusCodeFromBody = body => {
7230
7295
  }
7231
7296
  return undefined;
7232
7297
  };
7298
+ const getBackendResponseId = body => {
7299
+ if (!isObject$2(body)) {
7300
+ return undefined;
7301
+ }
7302
+ const id = Reflect.get(body, 'id');
7303
+ return typeof id === 'string' && id ? id : undefined;
7304
+ };
7305
+ const getBackendResponseStatus = body => {
7306
+ if (!isObject$2(body)) {
7307
+ return undefined;
7308
+ }
7309
+ const status = Reflect.get(body, 'status');
7310
+ return typeof status === 'string' && status ? status : undefined;
7311
+ };
7312
+ const getBackendIncompleteMessage = body => {
7313
+ if (!isObject$2(body)) {
7314
+ return undefined;
7315
+ }
7316
+ const incompleteDetails = Reflect.get(body, 'incomplete_details');
7317
+ if (!isObject$2(incompleteDetails)) {
7318
+ return undefined;
7319
+ }
7320
+ const reason = Reflect.get(incompleteDetails, 'reason');
7321
+ if (typeof reason === 'string' && reason) {
7322
+ return `Backend response was incomplete (${reason}).`;
7323
+ }
7324
+ return undefined;
7325
+ };
7326
+ const getBackendResponseFunctionCalls = body => {
7327
+ if (!isObject$2(body)) {
7328
+ return [];
7329
+ }
7330
+ const output = Reflect.get(body, 'output');
7331
+ if (!Array.isArray(output)) {
7332
+ return [];
7333
+ }
7334
+ const calls = [];
7335
+ for (const outputItem of output) {
7336
+ if (!isObject$2(outputItem)) {
7337
+ continue;
7338
+ }
7339
+ if (Reflect.get(outputItem, 'type') !== 'function_call') {
7340
+ continue;
7341
+ }
7342
+ const callId = Reflect.get(outputItem, 'call_id');
7343
+ const name = Reflect.get(outputItem, 'name');
7344
+ const rawArguments = Reflect.get(outputItem, 'arguments');
7345
+ if (typeof callId !== 'string' || !callId || typeof name !== 'string' || !name) {
7346
+ continue;
7347
+ }
7348
+ calls.push({
7349
+ arguments: typeof rawArguments === 'string' ? rawArguments : '',
7350
+ callId,
7351
+ name
7352
+ });
7353
+ }
7354
+ return calls;
7355
+ };
7356
+ const getErrorMessage = error => {
7357
+ if (error instanceof Error) {
7358
+ return error.message;
7359
+ }
7360
+ return typeof error === 'string' && error ? error : undefined;
7361
+ };
7362
+ const getBackendInvalidResponseDetails = body => {
7363
+ const errorMessage = getBackendErrorMessageFromBody(body);
7364
+ if (errorMessage) {
7365
+ return errorMessage;
7366
+ }
7367
+ const incompleteMessage = getBackendIncompleteMessage(body);
7368
+ if (incompleteMessage) {
7369
+ return incompleteMessage;
7370
+ }
7371
+ const status = getBackendResponseStatus(body);
7372
+ if (status && status !== 'completed') {
7373
+ return `Backend response status was "${status}".`;
7374
+ }
7375
+ if (isObject$2(body) && Array.isArray(Reflect.get(body, 'output'))) {
7376
+ return 'Unexpected backend response format: no assistant text or tool calls were returned.';
7377
+ }
7378
+ return 'Unexpected backend response format.';
7379
+ };
7380
+ const toExecutedToolCall = (toolCall, content) => {
7381
+ const executionStatus = getToolCallExecutionStatus(content);
7382
+ const toolCallResult = getToolCallResult(toolCall.name, content);
7383
+ return {
7384
+ arguments: toolCall.arguments,
7385
+ ...(executionStatus.errorMessage ? {
7386
+ errorMessage: executionStatus.errorMessage
7387
+ } : {}),
7388
+ ...(executionStatus.errorStack ? {
7389
+ errorStack: executionStatus.errorStack
7390
+ } : {}),
7391
+ id: toolCall.callId,
7392
+ name: toolCall.name,
7393
+ ...(toolCallResult ? {
7394
+ result: toolCallResult
7395
+ } : {}),
7396
+ ...(executionStatus.status ? {
7397
+ status: executionStatus.status
7398
+ } : {})
7399
+ };
7400
+ };
7233
7401
  const getBackendResponseOutputText = body => {
7234
7402
  if (!isObject$2(body)) {
7235
7403
  return '';
@@ -7291,14 +7459,29 @@ const getBackendResponseOutputText = body => {
7291
7459
  }
7292
7460
  return chunks.join('');
7293
7461
  };
7294
- const getBackendResponsesBody = (messages, modelId, systemPrompt, tools, maxToolCalls, webSearchEnabled, reasoningEffort, supportsReasoningEffort = false) => {
7295
- const input = messages.map(message => ({
7296
- content: getChatMessageOpenAiContent(message),
7297
- role: message.role
7298
- }));
7299
- return getOpenAiParams(input, modelId, false, false, tools, webSearchEnabled, maxToolCalls, systemPrompt, undefined, reasoningEffort, supportsReasoningEffort);
7462
+ const getBackendResponsesBody = (input, modelId, systemPrompt, tools, maxToolCalls, webSearchEnabled, previousResponseId, reasoningEffort, supportsReasoningEffort = false) => {
7463
+ return getOpenAiParams(input, modelId, false, false, tools, webSearchEnabled, maxToolCalls, systemPrompt, previousResponseId, reasoningEffort, supportsReasoningEffort);
7300
7464
  };
7301
- const getBackendAssistantText = async (messages, modelId, backendUrl, authAccessToken, systemPrompt, agentMode = defaultAgentMode, questionToolEnabled = false, toolEnablement, maxToolCalls = defaultMaxToolCalls, webSearchEnabled = false, reasoningEffort, supportsReasoningEffort = false) => {
7465
+ const getBackendAssistantText = async ({
7466
+ agentMode = defaultAgentMode,
7467
+ assetDir,
7468
+ authAccessToken,
7469
+ backendUrl,
7470
+ maxToolCalls = defaultMaxToolCalls,
7471
+ messages,
7472
+ modelId,
7473
+ onToolCallsChunk,
7474
+ platform,
7475
+ questionToolEnabled = false,
7476
+ reasoningEffort,
7477
+ sessionId,
7478
+ supportsReasoningEffort = false,
7479
+ systemPrompt,
7480
+ toolEnablement,
7481
+ useChatToolWorker,
7482
+ webSearchEnabled = false,
7483
+ workspaceUri
7484
+ }) => {
7302
7485
  const mockError = takeErrorResponse();
7303
7486
  if (mockError) {
7304
7487
  const errorMessage = getBackendErrorMessageFromBody(mockError.body);
@@ -7312,45 +7495,115 @@ const getBackendAssistantText = async (messages, modelId, backendUrl, authAccess
7312
7495
  } : {})
7313
7496
  });
7314
7497
  }
7315
- let response;
7316
- try {
7317
- const tools = await getBasicChatTools(agentMode, questionToolEnabled, toolEnablement);
7318
- response = await fetch(getBackendResponsesEndpoint(backendUrl), {
7319
- body: JSON.stringify(getBackendResponsesBody(messages, modelId, systemPrompt, tools, maxToolCalls, webSearchEnabled, reasoningEffort, supportsReasoningEffort)),
7320
- headers: {
7321
- Authorization: `Bearer ${authAccessToken}`,
7322
- 'Content-Type': 'application/json',
7323
- ...getClientRequestIdHeader()
7324
- },
7325
- method: 'POST'
7326
- });
7327
- } catch {
7328
- return getBackendErrorMessage({
7329
- details: 'request-failed'
7330
- });
7331
- }
7332
- if (!response.ok) {
7333
- const payload = await response.json().catch(() => undefined);
7334
- const errorMessage = getBackendErrorMessageFromBody(payload);
7335
- const statusCode = response.status || getBackendStatusCodeFromBody(payload);
7498
+ const mockResponse = takeResponse();
7499
+ const tools = await getBasicChatTools(agentMode, questionToolEnabled, toolEnablement);
7500
+ const input = messages.map(message => ({
7501
+ content: getChatMessageOpenAiContent(message),
7502
+ role: message.role
7503
+ }));
7504
+ let previousResponseId;
7505
+ const maxToolIterations = Math.max(0, maxToolCalls - 1);
7506
+ for (let index = 0; index <= maxToolIterations; index++) {
7507
+ let json;
7508
+ if (index === 0 && mockResponse) {
7509
+ json = mockResponse.body;
7510
+ } else {
7511
+ let response;
7512
+ try {
7513
+ response = await fetch(getBackendResponsesEndpoint(backendUrl), {
7514
+ body: JSON.stringify(getBackendResponsesBody(input, modelId, systemPrompt, tools, maxToolCalls, webSearchEnabled, previousResponseId, reasoningEffort, supportsReasoningEffort)),
7515
+ headers: {
7516
+ Authorization: `Bearer ${authAccessToken}`,
7517
+ 'Content-Type': 'application/json',
7518
+ ...getClientRequestIdHeader()
7519
+ },
7520
+ method: 'POST'
7521
+ });
7522
+ } catch (error) {
7523
+ const errorMessage = getErrorMessage(error);
7524
+ return getBackendErrorMessage({
7525
+ details: 'request-failed',
7526
+ ...(errorMessage ? {
7527
+ errorMessage
7528
+ } : {})
7529
+ });
7530
+ }
7531
+ if (!response.ok) {
7532
+ const payload = await response.json().catch(() => undefined);
7533
+ const errorMessage = getBackendErrorMessageFromBody(payload);
7534
+ const statusCode = response.status || getBackendStatusCodeFromBody(payload);
7535
+ return getBackendErrorMessage({
7536
+ details: 'http-error',
7537
+ ...(typeof statusCode === 'number' ? {
7538
+ statusCode
7539
+ } : {}),
7540
+ ...(errorMessage ? {
7541
+ errorMessage
7542
+ } : {})
7543
+ });
7544
+ }
7545
+ try {
7546
+ json = await response.json();
7547
+ } catch {
7548
+ return getBackendErrorMessage({
7549
+ details: 'invalid-response',
7550
+ errorMessage: 'Backend returned invalid JSON.'
7551
+ });
7552
+ }
7553
+ }
7554
+ const responseFunctionCalls = getBackendResponseFunctionCalls(json);
7555
+ if (responseFunctionCalls.length > 0) {
7556
+ const responseId = getBackendResponseId(json);
7557
+ if (!responseId) {
7558
+ return getBackendErrorMessage({
7559
+ details: 'invalid-response',
7560
+ errorMessage: 'Unexpected backend response format: tool calls were returned without a response id.'
7561
+ });
7562
+ }
7563
+ previousResponseId = responseId;
7564
+ input.length = 0;
7565
+ const executedToolCalls = [];
7566
+ for (const toolCall of responseFunctionCalls) {
7567
+ const content = await executeChatTool(toolCall.name, toolCall.arguments, {
7568
+ assetDir,
7569
+ platform,
7570
+ ...(sessionId ? {
7571
+ sessionId
7572
+ } : {}),
7573
+ toolCallId: toolCall.callId,
7574
+ ...(toolEnablement ? {
7575
+ toolEnablement
7576
+ } : {}),
7577
+ useChatToolWorker,
7578
+ ...(workspaceUri ? {
7579
+ workspaceUri
7580
+ } : {})
7581
+ });
7582
+ executedToolCalls.push(toExecutedToolCall(toolCall, content));
7583
+ input.push({
7584
+ call_id: toolCall.callId,
7585
+ output: content,
7586
+ type: 'function_call_output'
7587
+ });
7588
+ }
7589
+ if (onToolCallsChunk && executedToolCalls.length > 0) {
7590
+ await onToolCallsChunk(executedToolCalls);
7591
+ }
7592
+ continue;
7593
+ }
7594
+ const content = getBackendResponseOutputText(json);
7595
+ if (content) {
7596
+ return content;
7597
+ }
7336
7598
  return getBackendErrorMessage({
7337
- details: 'http-error',
7338
- ...(typeof statusCode === 'number' ? {
7339
- statusCode
7340
- } : {}),
7341
- ...(errorMessage ? {
7342
- errorMessage
7343
- } : {})
7599
+ details: 'invalid-response',
7600
+ errorMessage: getBackendInvalidResponseDetails(json)
7344
7601
  });
7345
7602
  }
7346
- let json;
7347
- try {
7348
- json = await response.json();
7349
- } catch {
7350
- return backendCompletionFailedMessage;
7351
- }
7352
- const content = getBackendResponseOutputText(json);
7353
- return typeof content === 'string' && content ? content : backendCompletionFailedMessage;
7603
+ return getBackendErrorMessage({
7604
+ details: 'invalid-response',
7605
+ errorMessage: `Backend request ended after ${maxToolCalls} tool-call rounds without a final assistant response. This usually means the model got stuck in a tool loop.`
7606
+ });
7354
7607
  };
7355
7608
  const getAiResponse = async ({
7356
7609
  agentMode = defaultAgentMode,
@@ -7458,7 +7711,30 @@ const getAiResponse = async ({
7458
7711
  if (!backendUrl) {
7459
7712
  text = backendUrlRequiredMessage;
7460
7713
  } else if (authAccessToken) {
7461
- text = await getBackendAssistantText(messages, getOpenApiModelId(selectedModelId), backendUrl, authAccessToken, systemPrompt, agentMode, questionToolEnabled, toolEnablement, safeMaxToolCalls, agentMode === 'plan' ? false : webSearchEnabled, reasoningEffort, supportsReasoningEffort);
7714
+ text = await getBackendAssistantText({
7715
+ agentMode,
7716
+ assetDir,
7717
+ authAccessToken,
7718
+ backendUrl,
7719
+ maxToolCalls: safeMaxToolCalls,
7720
+ messages,
7721
+ modelId: getOpenApiModelId(selectedModelId),
7722
+ onToolCallsChunk,
7723
+ platform,
7724
+ questionToolEnabled,
7725
+ reasoningEffort,
7726
+ supportsReasoningEffort,
7727
+ systemPrompt,
7728
+ toolEnablement,
7729
+ useChatToolWorker,
7730
+ webSearchEnabled: agentMode === 'plan' ? false : webSearchEnabled,
7731
+ ...(sessionId ? {
7732
+ sessionId
7733
+ } : {}),
7734
+ ...(workspaceUri ? {
7735
+ workspaceUri
7736
+ } : {})
7737
+ });
7462
7738
  } else {
7463
7739
  text = backendAccessTokenRequiredMessage;
7464
7740
  }
@@ -10802,6 +11078,11 @@ const mockBackendSetHttpErrorResponse = (state, statusCode, body) => {
10802
11078
  return state;
10803
11079
  };
10804
11080
 
11081
+ const mockBackendSetResponse = (state, body) => {
11082
+ setResponse(body);
11083
+ return state;
11084
+ };
11085
+
10805
11086
  const mockOpenApiRequestGetAll = _state => {
10806
11087
  return getAll();
10807
11088
  };
@@ -15888,6 +16169,7 @@ const commandMap = {
15888
16169
  'Chat.loadContent2': wrapCommand(loadContent),
15889
16170
  'Chat.mockBackendAuthResponse': wrapCommand(mockBackendAuthResponse),
15890
16171
  'Chat.mockBackendSetHttpErrorResponse': wrapCommand(mockBackendSetHttpErrorResponse),
16172
+ 'Chat.mockBackendSetResponse': wrapCommand(mockBackendSetResponse),
15891
16173
  'Chat.mockOpenApiRequestGetAll': wrapGetter(mockOpenApiRequestGetAll),
15892
16174
  'Chat.mockOpenApiRequestReset': wrapCommand(mockOpenApiRequestReset),
15893
16175
  'Chat.mockOpenApiSetHttpErrorResponse': wrapCommand(mockOpenApiSetHttpErrorResponse),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "7.10.0",
3
+ "version": "7.12.0",
4
4
  "description": "Chat View Worker",
5
5
  "repository": {
6
6
  "type": "git",