addLlmTrans
This commit is contained in:
		
							parent
							
								
									08b131ec33
								
							
						
					
					
						commit
						9ef78e2b86
					
				|  | @ -0,0 +1,36 @@ | |||
| /* | ||||
|  * SPDX-FileCopyrightText: syuilo and misskey-project | ||||
|  * SPDX-License-Identifier: AGPL-3.0-only | ||||
|  */ | ||||
| 
 | ||||
| export class  AddLlmTranslatorSupport1740989976502 { | ||||
|     name = 'AddLlmTranslatorSupport1740989976502' | ||||
| 
 | ||||
|     async up(queryRunner) { | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "enableLlmTranslator" boolean NOT NULL DEFAULT false`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "enableLlmTranslatorRedisCache" boolean NOT NULL DEFAULT false`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "llmTranslatorRedisCacheTtl" integer NOT NULL DEFAULT '2880'`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "llmTranslatorBaseUrl" character varying(1024)`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "llmTranslatorApiKey" character varying(1024)`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "llmTranslatorModel" character varying(1024)`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "llmTranslatorTemperature" real`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "llmTranslatorTopP" real`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "llmTranslatorMaxTokens" integer`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "llmTranslatorSysPrompt" character varying(1024)`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" ADD "llmTranslatorUserPrompt" character varying(1024)`); | ||||
|     } | ||||
| 
 | ||||
|     async down(queryRunner) { | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableLlmTranslator"`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableLlmTranslatorRedisCache"`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "llmTranslatorRedisCacheTtl"`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "llmTranslatorBaseUrl"`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "llmTranslatorApiKey"`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "llmTranslatorModel"`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "llmTranslatorTemperature"`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "llmTranslatorTopP"`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "llmTranslatorMaxTokens"`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "llmTranslatorSysPrompt"`); | ||||
|         await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "llmTranslatorUserPrompt"`); | ||||
|     } | ||||
| } | ||||
|  | @ -147,6 +147,7 @@ | |||
| 		"oauth": "0.10.2", | ||||
| 		"oauth2orize": "1.12.0", | ||||
| 		"oauth2orize-pkce": "0.1.2", | ||||
| 		"openai": "4.86.1", | ||||
| 		"os-utils": "0.0.14", | ||||
| 		"otpauth": "9.3.6", | ||||
| 		"parse5": "7.2.1", | ||||
|  |  | |||
|  | @ -121,7 +121,7 @@ export class MetaEntityService { | |||
| 			enableEmail: instance.enableEmail, | ||||
| 			enableServiceWorker: instance.enableServiceWorker, | ||||
| 
 | ||||
| 			translatorAvailable: instance.deeplAuthKey != null, | ||||
| 			translatorAvailable: instance.deeplAuthKey != null || instance.enableLlmTranslator, | ||||
| 
 | ||||
| 			serverRules: instance.serverRules, | ||||
| 
 | ||||
|  |  | |||
|  | @ -664,4 +664,64 @@ export class MiMeta { | |||
| 		nullable: true, | ||||
| 	}) | ||||
| 	public googleAnalyticsMeasurementId: string | null; | ||||
| 
 | ||||
| 	@Column('boolean',{ | ||||
| 		default: false, | ||||
| 	}) | ||||
| 	public enableLlmTranslator: boolean; | ||||
| 
 | ||||
| 	@Column('boolean',{ | ||||
| 		default: false, | ||||
| 	}) | ||||
| 	public enableLlmTranslatorRedisCache: boolean; | ||||
| 
 | ||||
| 	@Column('integer', { | ||||
| 		default: 2880, | ||||
| 	}) | ||||
| 	public llmTranslatorRedisCacheTtl: number; | ||||
| 
 | ||||
| 	@Column('varchar', { | ||||
| 		length: 1024, | ||||
| 		nullable: true, | ||||
| 	}) | ||||
| 	public llmTranslatorBaseUrl: string | null; | ||||
| 
 | ||||
| 	@Column('varchar', { | ||||
| 		length: 1024, | ||||
| 		nullable: true, | ||||
| 	}) | ||||
| 	public llmTranslatorApiKey: string | null; | ||||
| 
 | ||||
| 	@Column('varchar', { | ||||
| 		length: 1024, | ||||
| 		nullable: true, | ||||
| 	}) | ||||
| 	public llmTranslatorModel: string | null; | ||||
| 
 | ||||
| 	@Column('real', { | ||||
| 		nullable: true, | ||||
| 	}) | ||||
| 	public llmTranslatorTemperature: number | null; | ||||
| 
 | ||||
| 	@Column('real', { | ||||
| 		nullable: true, | ||||
| 	}) | ||||
| 	public llmTranslatorTopP: number | null; | ||||
| 
 | ||||
| 	@Column('integer', { | ||||
| 		nullable: true, | ||||
| 	}) | ||||
| 	public llmTranslatorMaxTokens: number | null; | ||||
| 
 | ||||
| 	@Column('varchar', { | ||||
| 		length: 1024, | ||||
| 		nullable: true, | ||||
| 	}) | ||||
| 	public llmTranslatorSysPrompt: string | null; | ||||
| 
 | ||||
| 	@Column('varchar', { | ||||
| 		length: 1024, | ||||
| 		nullable: true, | ||||
| 	}) | ||||
| 	public llmTranslatorUserPrompt: string | null; | ||||
| } | ||||
|  |  | |||
|  | @ -528,6 +528,50 @@ export const meta = { | |||
| 					optional: false, nullable: false, | ||||
| 				}, | ||||
| 			}, | ||||
| 			enableLlmTranslator: { | ||||
| 				type: 'boolean', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			enableLlmTranslatorRedisCache: { | ||||
| 				type: 'boolean', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			llmTranslatorRedisCacheTtl: { | ||||
| 				type: 'number', | ||||
| 				optional: false, nullable: false, | ||||
| 			}, | ||||
| 			llmTranslatorBaseUrl: { | ||||
| 				type: 'string', | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			llmTranslatorApiKey: { | ||||
| 				type: 'string', | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			llmTranslatorModel: { | ||||
| 				type: 'string', | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			llmTranslatorTemperature: { | ||||
| 				type: 'number', | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			llmTranslatorTopP: { | ||||
| 				type: 'number', | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			llmTranslatorMaxTokens: { | ||||
| 				type: 'number', | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			llmTranslatorSysPrompt: { | ||||
| 				type: 'string', | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 			llmTranslatorUserPrompt: { | ||||
| 				type: 'string', | ||||
| 				optional: false, nullable: true, | ||||
| 			}, | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
|  | @ -597,7 +641,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 				defaultDarkTheme: instance.defaultDarkTheme, | ||||
| 				enableEmail: instance.enableEmail, | ||||
| 				enableServiceWorker: instance.enableServiceWorker, | ||||
| 				translatorAvailable: instance.deeplAuthKey != null, | ||||
| 				translatorAvailable: instance.deeplAuthKey != null || instance.enableLlmTranslator, | ||||
| 				cacheRemoteFiles: instance.cacheRemoteFiles, | ||||
| 				cacheRemoteSensitiveFiles: instance.cacheRemoteSensitiveFiles, | ||||
| 				pinnedUsers: instance.pinnedUsers, | ||||
|  | @ -672,6 +716,17 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 				urlPreviewSummaryProxyUrl: instance.urlPreviewSummaryProxyUrl, | ||||
| 				federation: instance.federation, | ||||
| 				federationHosts: instance.federationHosts, | ||||
| 				enableLlmTranslator: instance.enableLlmTranslator, | ||||
| 				enableLlmTranslatorRedisCache: instance.enableLlmTranslatorRedisCache, | ||||
| 				llmTranslatorRedisCacheTtl: instance.llmTranslatorRedisCacheTtl, | ||||
| 				llmTranslatorBaseUrl: instance.llmTranslatorBaseUrl, | ||||
| 				llmTranslatorApiKey: instance.llmTranslatorApiKey, | ||||
| 				llmTranslatorModel: instance.llmTranslatorModel, | ||||
| 				llmTranslatorMaxTokens: instance.llmTranslatorMaxTokens, | ||||
| 				llmTranslatorTemperature: instance.llmTranslatorTemperature, | ||||
| 				llmTranslatorTopP: instance.llmTranslatorTopP, | ||||
| 				llmTranslatorSysPrompt: instance.llmTranslatorSysPrompt, | ||||
| 				llmTranslatorUserPrompt: instance.llmTranslatorUserPrompt, | ||||
| 			}; | ||||
| 		}); | ||||
| 	} | ||||
|  |  | |||
|  | @ -185,6 +185,17 @@ export const paramDef = { | |||
| 				type: 'string', | ||||
| 			}, | ||||
| 		}, | ||||
| 		enableLlmTranslator: { type: 'boolean' }, | ||||
| 		enableLlmTranslatorRedisCache: { type: 'boolean' }, | ||||
| 		llmTranslatorRedisCacheTtl: { type: 'integer' , nullable: true}, | ||||
| 		llmTranslatorBaseUrl: { type: 'string' , nullable: true}, | ||||
| 		llmTranslatorApiKey: { type: 'string' , nullable: true}, | ||||
| 		llmTranslatorModel: { type: 'string' , nullable: true}, | ||||
| 		llmTranslatorTemperature: { type: 'number' , nullable: true}, | ||||
| 		llmTranslatorTopP: { type: 'number' , nullable: true}, | ||||
| 		llmTranslatorMaxTokens: { type: 'integer' , nullable: true}, | ||||
| 		llmTranslatorSysPrompt: { type: 'string' , nullable: true}, | ||||
| 		llmTranslatorUserPrompt: { type: 'string' , nullable: true}, | ||||
| 	}, | ||||
| 	required: [], | ||||
| } as const; | ||||
|  | @ -675,6 +686,70 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 				set.federationHosts = ps.federationHosts.filter(Boolean).map(x => x.toLowerCase()); | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.enableLlmTranslator !== undefined) { | ||||
| 				set.enableLlmTranslator = ps.enableLlmTranslator; | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.enableLlmTranslatorRedisCache !== undefined) { | ||||
| 				set.enableLlmTranslatorRedisCache = ps.enableLlmTranslatorRedisCache; | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.llmTranslatorRedisCacheTtl !== undefined) { | ||||
| 				set.llmTranslatorRedisCacheTtl = ps.llmTranslatorRedisCacheTtl; | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.llmTranslatorBaseUrl !== undefined) { | ||||
| 				if (ps.llmTranslatorBaseUrl === '') { | ||||
| 					set.llmTranslatorBaseUrl = null; | ||||
| 				} else { | ||||
| 					set.llmTranslatorBaseUrl = ps.llmTranslatorBaseUrl; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.llmTranslatorApiKey !== undefined) { | ||||
| 				if (ps.llmTranslatorApiKey === '') { | ||||
| 					set.llmTranslatorApiKey = null; | ||||
| 				} else { | ||||
| 					set.llmTranslatorApiKey = ps.llmTranslatorApiKey; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.llmTranslatorModel !== undefined) { | ||||
| 				if (ps.llmTranslatorModel === '') { | ||||
| 					set.llmTranslatorModel = null; | ||||
| 				} else { | ||||
| 					set.llmTranslatorModel = ps.llmTranslatorModel; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.llmTranslatorTemperature !== undefined) { | ||||
| 				set.llmTranslatorTemperature = ps.llmTranslatorTemperature; | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.llmTranslatorTopP !== undefined) { | ||||
| 				set.llmTranslatorTopP = ps.llmTranslatorTopP; | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.llmTranslatorMaxTokens !== undefined) { | ||||
| 				set.llmTranslatorMaxTokens = ps.llmTranslatorMaxTokens; | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.llmTranslatorSysPrompt !== undefined) { | ||||
| 				if (ps.llmTranslatorSysPrompt === '') { | ||||
| 					set.llmTranslatorSysPrompt = null; | ||||
| 				} else { | ||||
| 					set.llmTranslatorSysPrompt = ps.llmTranslatorSysPrompt; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if (ps.llmTranslatorUserPrompt !== undefined) { | ||||
| 				if (ps.llmTranslatorUserPrompt === '') { | ||||
| 					set.llmTranslatorUserPrompt = null; | ||||
| 				} else { | ||||
| 					set.llmTranslatorUserPrompt = ps.llmTranslatorUserPrompt; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			const before = await this.metaService.fetch(true); | ||||
| 
 | ||||
| 			await this.metaService.update(set); | ||||
|  |  | |||
|  | @ -13,6 +13,8 @@ import { RoleService } from '@/core/RoleService.js'; | |||
| import { ApiError } from '../../error.js'; | ||||
| import { MiMeta } from '@/models/_.js'; | ||||
| import { DI } from '@/di-symbols.js'; | ||||
| import { OpenAI } from "openai"; | ||||
| import * as Redis from 'ioredis'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['notes'], | ||||
|  | @ -63,6 +65,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 		@Inject(DI.meta) | ||||
| 		private serverSettings: MiMeta, | ||||
| 
 | ||||
| 		@Inject(DI.redis) | ||||
| 		private redisClient: Redis.Redis, | ||||
| 
 | ||||
| 		private noteEntityService: NoteEntityService, | ||||
| 		private getterService: GetterService, | ||||
| 		private httpRequestService: HttpRequestService, | ||||
|  | @ -87,6 +92,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
| 			if (this.serverSettings.enableLlmTranslator) { | ||||
| 				const res = await this.llmTranslate(note.text, ps.targetLang, note.id); | ||||
| 				return { | ||||
| 					text: res, | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			if (this.serverSettings.deeplAuthKey == null) { | ||||
| 				throw new ApiError(meta.errors.unavailable); | ||||
| 			} | ||||
|  | @ -123,4 +135,46 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- | |||
| 			}; | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	private async llmTranslate(text: string, targetLang: string, noteId: string): Promise<string | null> { | ||||
| 		if (this.serverSettings.enableLlmTranslatorRedisCache) { | ||||
| 			const key = `llmTranslate:${targetLang}:${noteId}`; | ||||
| 			const cached = await this.redisClient.get(key); | ||||
| 			if (cached != null) { | ||||
| 				this.redisClient.expire(key, this.serverSettings.llmTranslatorRedisCacheTtl*60); | ||||
| 				return cached; | ||||
| 			} | ||||
| 			const res = await this.getLlmRes(text, targetLang); | ||||
| 			await this.redisClient.set(key, res ?? ''); | ||||
| 			this.redisClient.expire(key, this.serverSettings.llmTranslatorRedisCacheTtl*60); | ||||
| 			return res; | ||||
| 		} | ||||
| 		else { | ||||
| 			return this.getLlmRes(text, targetLang); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	private async getLlmRes(text: string, targetLang: string): Promise<string | null> { | ||||
| 		const client = new OpenAI({ | ||||
| 			baseURL: this.serverSettings.llmTranslatorBaseUrl, | ||||
| 			apiKey: this.serverSettings.llmTranslatorApiKey ?? '', | ||||
| 		}); | ||||
| 		const message = []; | ||||
| 		if (this.serverSettings.llmTranslatorSysPrompt) { | ||||
| 			message.push({ role: 'system' as const, content: this.serverSettings.llmTranslatorSysPrompt.replace('{targetLang}', targetLang).replace('{text}', text) }); | ||||
| 		} | ||||
| 		if (this.serverSettings.llmTranslatorUserPrompt) { | ||||
| 			message.push({ role: 'user' as const, content: this.serverSettings.llmTranslatorUserPrompt.replace('{targetLang}', targetLang).replace('{text}', text) }); | ||||
| 		} | ||||
| 		const completion = await client.chat.completions.create({ | ||||
| 			messages: message, | ||||
| 			model: this.serverSettings.llmTranslatorModel ?? '', | ||||
| 			temperature: this.serverSettings.llmTranslatorTemperature, | ||||
| 			max_tokens: this.serverSettings.llmTranslatorMaxTokens, | ||||
| 			top_p: this.serverSettings.llmTranslatorTopP, | ||||
| 		}) | ||||
| 
 | ||||
| 		return completion.choices[0].message.content | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -81,7 +81,7 @@ SPDX-License-Identifier: AGPL-3.0-only | |||
| 						<div v-if="translating || translation" :class="$style.translation"> | ||||
| 							<MkLoading v-if="translating" mini/> | ||||
| 							<div v-else-if="translation"> | ||||
| 								<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b> | ||||
| 								<b v-if="translation.sourceLang">{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b> | ||||
| 								<Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis" class="_selectable"/> | ||||
| 							</div> | ||||
| 						</div> | ||||
|  |  | |||
|  | @ -103,7 +103,7 @@ SPDX-License-Identifier: AGPL-3.0-only | |||
| 				<div v-if="translating || translation" :class="$style.translation"> | ||||
| 					<MkLoading v-if="translating" mini/> | ||||
| 					<div v-else-if="translation"> | ||||
| 						<b>{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b> | ||||
| 						<b v-if="translation.sourceLang">{{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: </b> | ||||
| 						<Mfm :text="translation.text" :author="appearNote.user" :nyaize="'respect'" :emojiUrls="appearNote.emojis" class="_selectable"/> | ||||
| 					</div> | ||||
| 				</div> | ||||
|  |  | |||
|  | @ -35,6 +35,58 @@ SPDX-License-Identifier: AGPL-3.0-only | |||
| 						<MkButton primary @click="save_deepl">Save</MkButton> | ||||
| 					</div> | ||||
| 				</MkFolder> | ||||
| 
 | ||||
| 				<MkFolder> | ||||
| 					<template #label>Llm Translation</template> | ||||
| 
 | ||||
| 					<div class="_gaps_m"> | ||||
| 						<MkSwitch v-model="llmTranslatorEnabled"> | ||||
| 							<template #label>Enable</template> | ||||
| 							<template #caption>Enable/disable AI-powered(LLM) translation functionality</template> | ||||
| 						</MkSwitch> | ||||
| 						<MkInput v-model="llmTranslatorBaseUrl" :placeholder="'https://example.com'"> | ||||
| 							<template #label>Base URL</template> | ||||
| 							<template #caption>The base URL for openai compatible API</template> | ||||
| 						</MkInput> | ||||
| 						<MkInput v-model="llmTranslatorApiKey"> | ||||
| 							<template #prefix><i class="ti ti-key"></i></template> | ||||
| 							<template #label>API Key</template> | ||||
| 						</MkInput> | ||||
| 						<MkInput v-model="llmTranslatorModel"> | ||||
| 							<template #label>Model Name</template> | ||||
| 							<template #caption>Llm model to use (e.g., gpt-3.5-turbo, text-davinci-003, deepseek-chat)</template> | ||||
| 						</MkInput> | ||||
| 						<MkInput v-model="llmTranslatorTemperature" type="number"> | ||||
| 							<template #label>Temperature</template> | ||||
| 							<template #caption>Sampling temperature (higher = more random/creative)</template> | ||||
| 						</MkInput> | ||||
| 						<MkInput v-model="llmTranslatorTopP" type="number"> | ||||
| 							<template #label>Top P</template> | ||||
| 							<template #caption>Nucleus sampling threshold (0-1, alternative to temperature)</template> | ||||
| 						</MkInput> | ||||
| 						<MkInput v-model="llmTranslatorMaxTokens" type="number"> | ||||
| 							<template #label>Max Tokens</template> | ||||
| 							<template #caption>Maximum length of response in tokens (affects response length)</template> | ||||
| 						</MkInput> | ||||
| 						<MkTextarea v-model="llmTranslatorSysPrompt"> | ||||
| 							<template #label>System Prompt</template> | ||||
| 							<template #caption>Initial system-level instructions for the llm (can use {text} and {targetLang} as placeholders)<br>Example: "You are a translation specialist. Translate content between languages while preserving technical terms."</template> | ||||
| 						</MkTextarea> | ||||
| 						<MkTextarea v-model="llmTranslatorUserPrompt"> | ||||
| 							<template #label>User Prompt</template> | ||||
| 							<template #caption>Translation instruction template (may include {text} for source text and {targetLang} for target language)<br>Example: "Translate this to {targetLang}: {text}"</template> | ||||
| 						</MkTextarea> | ||||
| 						<MkSwitch v-model="llmTranslatorRedisCacheEnabled"> | ||||
| 							<template #label>Redis Cache Enable</template> | ||||
| 							<template #caption>Cache translations by using redis to reduce API calls and costs</template> | ||||
| 						</MkSwitch> | ||||
| 						<MkInput v-model="llmTranslatorRedisCacheTtl" type="number"> | ||||
| 							<template #label>Redis Cache TTL</template> | ||||
| 							<template #caption>Cache expiration time in minutes</template> | ||||
| 						</MkInput> | ||||
| 						<MkButton primary @click="save_llm">Save</MkButton> | ||||
| 					</div> | ||||
| 				</MkFolder> | ||||
| 			</div> | ||||
| 		</FormSuspense> | ||||
| 	</MkSpacer> | ||||
|  | @ -45,6 +97,7 @@ SPDX-License-Identifier: AGPL-3.0-only | |||
| import { ref, computed } from 'vue'; | ||||
| import XHeader from './_header_.vue'; | ||||
| import MkInput from '@/components/MkInput.vue'; | ||||
| import MkTextarea from '@/components/MkTextarea.vue'; | ||||
| import MkButton from '@/components/MkButton.vue'; | ||||
| import MkSwitch from '@/components/MkSwitch.vue'; | ||||
| import FormSuspense from '@/components/form/suspense.vue'; | ||||
|  | @ -60,11 +113,35 @@ const deeplIsPro = ref<boolean>(false); | |||
| 
 | ||||
| const googleAnalyticsMeasurementId = ref<string>(''); | ||||
| 
 | ||||
| const llmTranslatorEnabled = ref<boolean>(false); | ||||
| const llmTranslatorBaseUrl = ref<string>(''); | ||||
| const llmTranslatorApiKey = ref<string>(''); | ||||
| const llmTranslatorModel = ref<string>(''); | ||||
| const llmTranslatorTemperature = ref<number>(1); | ||||
| const llmTranslatorTopP = ref<number>(1); | ||||
| const llmTranslatorMaxTokens = ref<number>(1); | ||||
| const llmTranslatorSysPrompt = ref<string>(''); | ||||
| const llmTranslatorUserPrompt = ref<string>(''); | ||||
| const llmTranslatorRedisCacheEnabled = ref<boolean>(false); | ||||
| const llmTranslatorRedisCacheTtl = ref<number>(0); | ||||
| 
 | ||||
| 
 | ||||
| async function init() { | ||||
| 	const meta = await misskeyApi('admin/meta'); | ||||
| 	deeplAuthKey.value = meta.deeplAuthKey ?? ''; | ||||
| 	deeplIsPro.value = meta.deeplIsPro; | ||||
| 	googleAnalyticsMeasurementId.value = meta.googleAnalyticsMeasurementId ?? ''; | ||||
| 	llmTranslatorEnabled.value = meta.enableLlmTranslator; | ||||
| 	llmTranslatorBaseUrl.value = meta.llmTranslatorBaseUrl ?? ''; | ||||
| 	llmTranslatorApiKey.value = meta.llmTranslatorApiKey ?? ''; | ||||
| 	llmTranslatorModel.value = meta.llmTranslatorModel ?? ''; | ||||
| 	llmTranslatorTemperature.value = meta.llmTranslatorTemperature; | ||||
| 	llmTranslatorTopP.value = meta.llmTranslatorTopP; | ||||
| 	llmTranslatorMaxTokens.value = meta.llmTranslatorMaxTokens; | ||||
| 	llmTranslatorSysPrompt.value = meta.llmTranslatorSysPrompt ?? ''; | ||||
| 	llmTranslatorUserPrompt.value = meta.llmTranslatorUserPrompt ?? ''; | ||||
| 	llmTranslatorRedisCacheEnabled.value = meta.enableLlmTranslatorRedisCache; | ||||
| 	llmTranslatorRedisCacheTtl.value = meta.llmTranslatorRedisCacheTtl; | ||||
| } | ||||
| 
 | ||||
| function save_deepl() { | ||||
|  | @ -84,6 +161,24 @@ function save_googleAnalytics() { | |||
| 	}); | ||||
| } | ||||
| 
 | ||||
| function save_llm() { | ||||
| 	os.apiWithDialog('admin/update-meta', { | ||||
| 		enableLlmTranslator: llmTranslatorEnabled.value, | ||||
| 		llmTranslatorBaseUrl: llmTranslatorBaseUrl.value, | ||||
| 		llmTranslatorApiKey: llmTranslatorApiKey.value, | ||||
| 		llmTranslatorModel: llmTranslatorModel.value, | ||||
| 		llmTranslatorTemperature: llmTranslatorTemperature.value, | ||||
| 		llmTranslatorTopP: llmTranslatorTopP.value, | ||||
| 		llmTranslatorMaxTokens: llmTranslatorMaxTokens.value, | ||||
| 		llmTranslatorSysPrompt: llmTranslatorSysPrompt.value, | ||||
| 		llmTranslatorUserPrompt: llmTranslatorUserPrompt.value, | ||||
| 		enableLlmTranslatorRedisCache: llmTranslatorRedisCacheEnabled.value, | ||||
| 		llmTranslatorRedisCacheTtl: llmTranslatorRedisCacheTtl.value, | ||||
| 	}).then(() => { | ||||
| 		fetchInstance(true); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| const headerActions = computed(() => []); | ||||
| 
 | ||||
| const headerTabs = computed(() => []); | ||||
|  |  | |||
							
								
								
									
										117
									
								
								pnpm-lock.yaml
								
								
								
								
							
							
						
						
									
										117
									
								
								pnpm-lock.yaml
								
								
								
								
							|  | @ -332,6 +332,9 @@ importers: | |||
|       oauth2orize-pkce: | ||||
|         specifier: 0.1.2 | ||||
|         version: 0.1.2 | ||||
|       openai: | ||||
|         specifier: 4.86.1 | ||||
|         version: 4.86.1(encoding@0.1.13)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@6.0.5)) | ||||
|       os-utils: | ||||
|         specifier: 0.0.14 | ||||
|         version: 0.0.14 | ||||
|  | @ -2434,67 +2437,79 @@ packages: | |||
|     resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@img/sharp-libvips-linux-arm@1.0.5': | ||||
|     resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} | ||||
|     cpu: [arm] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@img/sharp-libvips-linux-s390x@1.0.4': | ||||
|     resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} | ||||
|     cpu: [s390x] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@img/sharp-libvips-linux-x64@1.0.4': | ||||
|     resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@img/sharp-libvips-linuxmusl-arm64@1.0.4': | ||||
|     resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@img/sharp-libvips-linuxmusl-x64@1.0.4': | ||||
|     resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@img/sharp-linux-arm64@0.33.5': | ||||
|     resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} | ||||
|     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@img/sharp-linux-arm@0.33.5': | ||||
|     resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} | ||||
|     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} | ||||
|     cpu: [arm] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@img/sharp-linux-s390x@0.33.5': | ||||
|     resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} | ||||
|     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} | ||||
|     cpu: [s390x] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@img/sharp-linux-x64@0.33.5': | ||||
|     resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} | ||||
|     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@img/sharp-linuxmusl-arm64@0.33.5': | ||||
|     resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} | ||||
|     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@img/sharp-linuxmusl-x64@0.33.5': | ||||
|     resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} | ||||
|     engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@img/sharp-wasm32@0.33.5': | ||||
|     resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} | ||||
|  | @ -2781,30 +2796,35 @@ packages: | |||
|     engines: {node: '>= 10'} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@napi-rs/canvas-linux-arm64-musl@0.1.68': | ||||
|     resolution: {integrity: sha512-IQzts91rCdOALXBWQxLZRCEDrfFTGDtNRJMNu+2SKZ1uT8cmPQkPwVk5rycvFpvgAcmiFiOSCp1aRrlfU8KPpQ==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@napi-rs/canvas-linux-riscv64-gnu@0.1.68': | ||||
|     resolution: {integrity: sha512-e9AS5UttoIKqXSmBzKZdd3NErSVyOEYzJfNOCGtafGk1//gibTwQXGlSXmAKuErqMp09pyk9aqQRSYzm1AQfBw==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [riscv64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@napi-rs/canvas-linux-x64-gnu@0.1.68': | ||||
|     resolution: {integrity: sha512-Pa/I36VE3j57I3Obhrr+J48KGFfkZk2cJN/2NmW/vCgmoF7kCP6aTVq5n+cGdGWLd/cN9CJ9JvNwEoMRDghu0g==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@napi-rs/canvas-linux-x64-musl@0.1.68': | ||||
|     resolution: {integrity: sha512-9c6rkc5195wNxuUHJdf4/mmnq433OQey9TNvQ9LspJazvHbfSkTij8wtKjASVQsJyPDva4fkWOeV/OQ7cLw0GQ==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@napi-rs/canvas-win32-x64-msvc@0.1.68': | ||||
|     resolution: {integrity: sha512-Fc5Dez23u0FoSATurT6/w1oMytiRnKWEinHivdMvXpge6nG4YvhrASrtqMk8dGJMVQpHr8QJYF45rOrx2YU2Aw==} | ||||
|  | @ -3156,36 +3176,42 @@ packages: | |||
|     engines: {node: '>= 10.0.0'} | ||||
|     cpu: [arm] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@parcel/watcher-linux-arm-musl@2.5.0': | ||||
|     resolution: {integrity: sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==} | ||||
|     engines: {node: '>= 10.0.0'} | ||||
|     cpu: [arm] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@parcel/watcher-linux-arm64-glibc@2.5.0': | ||||
|     resolution: {integrity: sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==} | ||||
|     engines: {node: '>= 10.0.0'} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@parcel/watcher-linux-arm64-musl@2.5.0': | ||||
|     resolution: {integrity: sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==} | ||||
|     engines: {node: '>= 10.0.0'} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@parcel/watcher-linux-x64-glibc@2.5.0': | ||||
|     resolution: {integrity: sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==} | ||||
|     engines: {node: '>= 10.0.0'} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@parcel/watcher-linux-x64-musl@2.5.0': | ||||
|     resolution: {integrity: sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==} | ||||
|     engines: {node: '>= 10.0.0'} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@parcel/watcher-win32-arm64@2.5.0': | ||||
|     resolution: {integrity: sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==} | ||||
|  | @ -3316,51 +3342,61 @@ packages: | |||
|     resolution: {integrity: sha512-bvXVU42mOVcF4le6XSjscdXjqx8okv4n5vmwgzcmtvFdifQ5U4dXFYaCB87namDRKlUL9ybVtLQ9ztnawaSzvg==} | ||||
|     cpu: [arm] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@rollup/rollup-linux-arm-musleabihf@4.36.0': | ||||
|     resolution: {integrity: sha512-JFIQrDJYrxOnyDQGYkqnNBtjDwTgbasdbUiQvcU8JmGDfValfH1lNpng+4FWlhaVIR4KPkeddYjsVVbmJYvDcg==} | ||||
|     cpu: [arm] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@rollup/rollup-linux-arm64-gnu@4.36.0': | ||||
|     resolution: {integrity: sha512-KqjYVh3oM1bj//5X7k79PSCZ6CvaVzb7Qs7VMWS+SlWB5M8p3FqufLP9VNp4CazJ0CsPDLwVD9r3vX7Ci4J56A==} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@rollup/rollup-linux-arm64-musl@4.36.0': | ||||
|     resolution: {integrity: sha512-QiGnhScND+mAAtfHqeT+cB1S9yFnNQ/EwCg5yE3MzoaZZnIV0RV9O5alJAoJKX/sBONVKeZdMfO8QSaWEygMhw==} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@rollup/rollup-linux-loongarch64-gnu@4.36.0': | ||||
|     resolution: {integrity: sha512-1ZPyEDWF8phd4FQtTzMh8FQwqzvIjLsl6/84gzUxnMNFBtExBtpL51H67mV9xipuxl1AEAerRBgBwFNpkw8+Lg==} | ||||
|     cpu: [loong64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@rollup/rollup-linux-powerpc64le-gnu@4.36.0': | ||||
|     resolution: {integrity: sha512-VMPMEIUpPFKpPI9GZMhJrtu8rxnp6mJR3ZzQPykq4xc2GmdHj3Q4cA+7avMyegXy4n1v+Qynr9fR88BmyO74tg==} | ||||
|     cpu: [ppc64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@rollup/rollup-linux-riscv64-gnu@4.36.0': | ||||
|     resolution: {integrity: sha512-ttE6ayb/kHwNRJGYLpuAvB7SMtOeQnVXEIpMtAvx3kepFQeowVED0n1K9nAdraHUPJ5hydEMxBpIR7o4nrm8uA==} | ||||
|     cpu: [riscv64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@rollup/rollup-linux-s390x-gnu@4.36.0': | ||||
|     resolution: {integrity: sha512-4a5gf2jpS0AIe7uBjxDeUMNcFmaRTbNv7NxI5xOCs4lhzsVyGR/0qBXduPnoWf6dGC365saTiwag8hP1imTgag==} | ||||
|     cpu: [s390x] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@rollup/rollup-linux-x64-gnu@4.36.0': | ||||
|     resolution: {integrity: sha512-5KtoW8UWmwFKQ96aQL3LlRXX16IMwyzMq/jSSVIIyAANiE1doaQsx/KRyhAvpHlPjPiSU/AYX/8m+lQ9VToxFQ==} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@rollup/rollup-linux-x64-musl@4.36.0': | ||||
|     resolution: {integrity: sha512-sycrYZPrv2ag4OCvaN5js+f01eoZ2U+RmT5as8vhxiFz+kxwlHrsxOwKPSA8WyS+Wc6Epid9QeI/IkQ9NkgYyQ==} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@rollup/rollup-win32-arm64-msvc@4.36.0': | ||||
|     resolution: {integrity: sha512-qbqt4N7tokFwwSVlWDsjfoHgviS3n/vZ8LK0h1uLG9TYIRuUTJC88E1xb3LM2iqZ/WTqNQjYrtmtGmrmmawB6A==} | ||||
|  | @ -4011,24 +4047,28 @@ packages: | |||
|     engines: {node: '>=10'} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@swc/core-linux-arm64-musl@1.11.11': | ||||
|     resolution: {integrity: sha512-nR2tfdQRRzwqR2XYw9NnBk9Fdvff/b8IiJzDL28gRR2QiJWLaE8LsRovtWrzCOYq6o5Uu9cJ3WbabWthLo4jLw==} | ||||
|     engines: {node: '>=10'} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@swc/core-linux-x64-gnu@1.11.11': | ||||
|     resolution: {integrity: sha512-b4gBp5HA9xNWNC5gsYbdzGBJWx4vKSGybGMGOVWWuF+ynx10+0sA/o4XJGuNHm8TEDuNh9YLKf6QkIO8+GPJ1g==} | ||||
|     engines: {node: '>=10'} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   '@swc/core-linux-x64-musl@1.11.11': | ||||
|     resolution: {integrity: sha512-dEvqmQVswjNvMBwXNb8q5uSvhWrJLdttBSef3s6UC5oDSwOr00t3RQPzyS3n5qmGJ8UMTdPRmsopxmqaODISdg==} | ||||
|     engines: {node: '>=10'} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   '@swc/core-win32-arm64-msvc@1.11.11': | ||||
|     resolution: {integrity: sha512-aZNZznem9WRnw2FbTqVpnclvl8Q2apOBW2B316gZK+qxbe+ktjOUnYaMhdCG3+BYggyIBDOnaJeQrXbKIMmNdw==} | ||||
|  | @ -4335,6 +4375,9 @@ packages: | |||
|   '@types/node-fetch@2.6.11': | ||||
|     resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==} | ||||
| 
 | ||||
|   '@types/node@18.19.81': | ||||
|     resolution: {integrity: sha512-7KO9oZ2//ivtSsryp0LQUqq79zyGXzwq1WqfywpC9ucjY7YyltMMmxWgtRFRKCxwa7VPxVBVy4kHf5UC1E8Lug==} | ||||
| 
 | ||||
|   '@types/node@22.13.10': | ||||
|     resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==} | ||||
| 
 | ||||
|  | @ -4833,6 +4876,10 @@ packages: | |||
|     resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} | ||||
|     engines: {node: '>= 14'} | ||||
| 
 | ||||
|   agentkeepalive@4.6.0: | ||||
|     resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} | ||||
|     engines: {node: '>= 8.0.0'} | ||||
| 
 | ||||
|   aggregate-error@3.1.0: | ||||
|     resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} | ||||
|     engines: {node: '>=8'} | ||||
|  | @ -6578,6 +6625,9 @@ packages: | |||
|   forever-agent@0.6.1: | ||||
|     resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} | ||||
| 
 | ||||
|   form-data-encoder@1.7.2: | ||||
|     resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} | ||||
| 
 | ||||
|   form-data-encoder@2.1.4: | ||||
|     resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} | ||||
|     engines: {node: '>= 14.17'} | ||||
|  | @ -6590,6 +6640,10 @@ packages: | |||
|     resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} | ||||
|     engines: {node: '>= 6'} | ||||
| 
 | ||||
|   formdata-node@4.4.1: | ||||
|     resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} | ||||
|     engines: {node: '>= 12.20'} | ||||
| 
 | ||||
|   formdata-polyfill@4.0.10: | ||||
|     resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} | ||||
|     engines: {node: '>=12.20.0'} | ||||
|  | @ -6991,6 +7045,9 @@ packages: | |||
|     resolution: {integrity: sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==} | ||||
|     engines: {node: '>=18.18.0'} | ||||
| 
 | ||||
|   humanize-ms@1.2.1: | ||||
|     resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} | ||||
| 
 | ||||
|   iconv-lite@0.4.24: | ||||
|     resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} | ||||
|     engines: {node: '>=0.10.0'} | ||||
|  | @ -8450,6 +8507,18 @@ packages: | |||
|     resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} | ||||
|     engines: {node: '>=12'} | ||||
| 
 | ||||
|   openai@4.86.1: | ||||
|     resolution: {integrity: sha512-x3iCLyaC3yegFVZaxOmrYJjitKxZ9hpVbLi+ZlT5UHuHTMlEQEbKXkGOM78z9qm2T5GF+XRUZCP2/aV4UPFPJQ==} | ||||
|     hasBin: true | ||||
|     peerDependencies: | ||||
|       ws: ^8.18.0 | ||||
|       zod: ^3.23.8 | ||||
|     peerDependenciesMeta: | ||||
|       ws: | ||||
|         optional: true | ||||
|       zod: | ||||
|         optional: true | ||||
| 
 | ||||
|   openapi-types@12.1.3: | ||||
|     resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} | ||||
| 
 | ||||
|  | @ -9628,24 +9697,28 @@ packages: | |||
|     engines: {node: '>= 10'} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   slacc-linux-arm64-musl@0.0.10: | ||||
|     resolution: {integrity: sha512-3lUX7752f6Okn54aONioaA+9M5TvifqXBAart+u2lNXEdWmmh003cVSU2Vcwg7nJ9lLHtju2DkDmKKfJjFuShA==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [arm64] | ||||
|     os: [linux] | ||||
|     libc: [musl] | ||||
| 
 | ||||
|   slacc-linux-x64-gnu@0.0.10: | ||||
|     resolution: {integrity: sha512-BxxvylF9zlOLRLCpiyMvKTIUpdLlpetNBJ+DSMDh5+Ggq+AmQz2NUGawmcBJw58F8nMCj9TpWLlGNWc2AuY+JQ==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   slacc-linux-x64-musl@0.0.10: | ||||
|     resolution: {integrity: sha512-TYJi8LOtJiTFcZvka4du7bMjF9Bz1RHRwyLnScr5E5yjjgoLRrsvgSu7bxp87xH+rgJ3CdEwE3w3Ux8EiewHpA==} | ||||
|     engines: {node: '>= 10'} | ||||
|     cpu: [x64] | ||||
|     os: [linux] | ||||
|     libc: [glibc] | ||||
| 
 | ||||
|   slacc-win32-arm64-msvc@0.0.10: | ||||
|     resolution: {integrity: sha512-1CHPLiDB4exzFyT5ndtJDsRRhBxNg8mGz6I6eJEMjelGkJR2KZPT9LZuby/1bS/bcVOr7zuJvGNfbEGBeHRwPQ==} | ||||
|  | @ -10373,6 +10446,9 @@ packages: | |||
|   undefsafe@2.0.5: | ||||
|     resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} | ||||
| 
 | ||||
|   undici-types@5.26.5: | ||||
|     resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} | ||||
| 
 | ||||
|   undici-types@6.20.0: | ||||
|     resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} | ||||
| 
 | ||||
|  | @ -10719,6 +10795,10 @@ packages: | |||
|     resolution: {integrity: sha512-0zJXHRAYEjM2tUfZ2DiSOHAa2aw1tisnnhU3ufD57R8iefL+DcdJyRBRyJpG+NUimDgbTI/lH+gAE1PAvV3Cgw==} | ||||
|     engines: {node: '>= 8'} | ||||
| 
 | ||||
|   web-streams-polyfill@4.0.0-beta.3: | ||||
|     resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} | ||||
|     engines: {node: '>= 14'} | ||||
| 
 | ||||
|   webidl-conversions@3.0.1: | ||||
|     resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} | ||||
| 
 | ||||
|  | @ -14594,6 +14674,10 @@ snapshots: | |||
|       '@types/node': 22.13.11 | ||||
|       form-data: 4.0.2 | ||||
| 
 | ||||
|   '@types/node@18.19.81': | ||||
|     dependencies: | ||||
|       undici-types: 5.26.5 | ||||
| 
 | ||||
|   '@types/node@22.13.10': | ||||
|     dependencies: | ||||
|       undici-types: 6.20.0 | ||||
|  | @ -15244,6 +15328,10 @@ snapshots: | |||
| 
 | ||||
|   agent-base@7.1.3: {} | ||||
| 
 | ||||
|   agentkeepalive@4.6.0: | ||||
|     dependencies: | ||||
|       humanize-ms: 1.2.1 | ||||
| 
 | ||||
|   aggregate-error@3.1.0: | ||||
|     dependencies: | ||||
|       clean-stack: 2.2.0 | ||||
|  | @ -17550,6 +17638,8 @@ snapshots: | |||
| 
 | ||||
|   forever-agent@0.6.1: {} | ||||
| 
 | ||||
|   form-data-encoder@1.7.2: {} | ||||
| 
 | ||||
|   form-data-encoder@2.1.4: {} | ||||
| 
 | ||||
|   form-data-encoder@4.0.2: {} | ||||
|  | @ -17561,6 +17651,11 @@ snapshots: | |||
|       es-set-tostringtag: 2.1.0 | ||||
|       mime-types: 2.1.35 | ||||
| 
 | ||||
|   formdata-node@4.4.1: | ||||
|     dependencies: | ||||
|       node-domexception: 1.0.0 | ||||
|       web-streams-polyfill: 4.0.0-beta.3 | ||||
| 
 | ||||
|   formdata-polyfill@4.0.10: | ||||
|     dependencies: | ||||
|       fetch-blob: 3.2.0 | ||||
|  | @ -18019,6 +18114,10 @@ snapshots: | |||
| 
 | ||||
|   human-signals@8.0.0: {} | ||||
| 
 | ||||
|   humanize-ms@1.2.1: | ||||
|     dependencies: | ||||
|       ms: 2.1.3 | ||||
| 
 | ||||
|   iconv-lite@0.4.24: | ||||
|     dependencies: | ||||
|       safer-buffer: 2.1.2 | ||||
|  | @ -19954,6 +20053,20 @@ snapshots: | |||
|       is-docker: 2.2.1 | ||||
|       is-wsl: 2.2.0 | ||||
| 
 | ||||
|   openai@4.86.1(encoding@0.1.13)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@6.0.5)): | ||||
|     dependencies: | ||||
|       '@types/node': 18.19.81 | ||||
|       '@types/node-fetch': 2.6.11 | ||||
|       abort-controller: 3.0.0 | ||||
|       agentkeepalive: 4.6.0 | ||||
|       form-data-encoder: 1.7.2 | ||||
|       formdata-node: 4.4.1 | ||||
|       node-fetch: 2.7.0(encoding@0.1.13) | ||||
|     optionalDependencies: | ||||
|       ws: 8.18.1(bufferutil@4.0.9)(utf-8-validate@6.0.5) | ||||
|     transitivePeerDependencies: | ||||
|       - encoding | ||||
| 
 | ||||
|   openapi-types@12.1.3: {} | ||||
| 
 | ||||
|   openapi-typescript@6.7.6: | ||||
|  | @ -21970,6 +22083,8 @@ snapshots: | |||
| 
 | ||||
|   undefsafe@2.0.5: {} | ||||
| 
 | ||||
|   undici-types@5.26.5: {} | ||||
| 
 | ||||
|   undici-types@6.20.0: {} | ||||
| 
 | ||||
|   undici@5.28.5: | ||||
|  | @ -22347,6 +22462,8 @@ snapshots: | |||
|   web-streams-polyfill@4.0.0: | ||||
|     optional: true | ||||
| 
 | ||||
|   web-streams-polyfill@4.0.0-beta.3: {} | ||||
| 
 | ||||
|   webidl-conversions@3.0.1: {} | ||||
| 
 | ||||
|   webidl-conversions@7.0.0: {} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue