mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-16 23:41:06 +00:00
feat(zoo-migration): new service to support community-driven extension
This commit is contained in:
parent
ad25634905
commit
e6ea70f7b9
43 changed files with 912 additions and 1 deletions
|
|
@ -42,6 +42,7 @@ export const commandIds = [
|
|||
|
||||
"setCustomStoragePath",
|
||||
"importSettings",
|
||||
"prepareZooMigration",
|
||||
|
||||
"focusInput",
|
||||
"acceptInput",
|
||||
|
|
|
|||
|
|
@ -150,6 +150,68 @@ const mockFs = {
|
|||
throw error
|
||||
}),
|
||||
|
||||
rm: vi.fn().mockImplementation(async (targetPath: string, options?: { recursive?: boolean; force?: boolean }) => {
|
||||
if (mockFiles.has(targetPath)) {
|
||||
mockFiles.delete(targetPath)
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
if (mockDirectories.has(targetPath)) {
|
||||
for (const filePath of Array.from(mockFiles.keys())) {
|
||||
if (filePath.startsWith(`${targetPath}/`)) {
|
||||
mockFiles.delete(filePath)
|
||||
}
|
||||
}
|
||||
for (const dirPath of Array.from(mockDirectories.values()) as string[]) {
|
||||
if (dirPath === targetPath || dirPath.startsWith(`${targetPath}/`)) {
|
||||
mockDirectories.delete(dirPath)
|
||||
}
|
||||
}
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
if (options?.force) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
const error = new Error(`ENOENT: no such file or directory, rm '${targetPath}'`)
|
||||
;(error as any).code = "ENOENT"
|
||||
throw error
|
||||
}),
|
||||
|
||||
cp: vi.fn().mockImplementation(async (sourcePath: string, destinationPath: string) => {
|
||||
if (mockFiles.has(sourcePath)) {
|
||||
const parentDir = destinationPath.split("/").slice(0, -1).join("/")
|
||||
ensureDirectoryExists(parentDir)
|
||||
mockFiles.set(destinationPath, mockFiles.get(sourcePath))
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
if (mockDirectories.has(sourcePath)) {
|
||||
ensureDirectoryExists(destinationPath)
|
||||
for (const dirPath of Array.from(mockDirectories.values()) as string[]) {
|
||||
if (dirPath.startsWith(`${sourcePath}/`)) {
|
||||
ensureDirectoryExists(destinationPath + dirPath.slice(sourcePath.length))
|
||||
}
|
||||
}
|
||||
for (const [filePath, content] of Array.from(mockFiles.entries())) {
|
||||
if (filePath.startsWith(`${sourcePath}/`)) {
|
||||
const copiedPath = destinationPath + filePath.slice(sourcePath.length)
|
||||
const parentDir = copiedPath.split("/").slice(0, -1).join("/")
|
||||
ensureDirectoryExists(parentDir)
|
||||
mockFiles.set(copiedPath, content)
|
||||
}
|
||||
}
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
const error = new Error(`ENOENT: no such file or directory, cp '${sourcePath}'`)
|
||||
;(error as any).code = "ENOENT"
|
||||
throw error
|
||||
}),
|
||||
|
||||
chmod: vi.fn().mockResolvedValue(undefined),
|
||||
|
||||
constants: require("fs").constants,
|
||||
|
||||
// Expose mock data for test assertions
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { handleNewTask } from "./handleTask"
|
|||
import { CodeIndexManager } from "../services/code-index/manager"
|
||||
import { importSettingsWithFeedback } from "../core/config/importExport"
|
||||
import { MdmService } from "../services/mdm/MdmService"
|
||||
import { createZooMigrationHandoff, promptAndCreateZooMigrationHandoff } from "../services/zoo-migration/ZooMigration"
|
||||
import { t } from "../i18n"
|
||||
|
||||
/**
|
||||
|
|
@ -155,6 +156,30 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
|
|||
filePath,
|
||||
)
|
||||
},
|
||||
prepareZooMigration: async (options?: { skipPrompt?: boolean; includeSecrets?: boolean }) => {
|
||||
try {
|
||||
const migrationOptions = {
|
||||
context,
|
||||
contextProxy: provider.contextProxy,
|
||||
providerSettingsManager: provider.providerSettingsManager,
|
||||
outputChannel,
|
||||
}
|
||||
|
||||
if (options?.skipPrompt) {
|
||||
return await createZooMigrationHandoff({
|
||||
...migrationOptions,
|
||||
includeSecrets: options.includeSecrets ?? false,
|
||||
})
|
||||
}
|
||||
|
||||
return await promptAndCreateZooMigrationHandoff(migrationOptions)
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error)
|
||||
outputChannel.appendLine(`[Zoo Migration] Failed to prepare migration handoff: ${message}`)
|
||||
await vscode.window.showErrorMessage(t("common:zooMigration.handoffFailed", { error: message }))
|
||||
return undefined
|
||||
}
|
||||
},
|
||||
focusInput: async () => {
|
||||
try {
|
||||
await focusPanel(tabPanel, sidebarPanel)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import { MdmService } from "./services/mdm/MdmService"
|
|||
import { migrateSettings } from "./utils/migrateSettings"
|
||||
import { autoImportSettings } from "./utils/autoImportSettings"
|
||||
import { API } from "./extension/api"
|
||||
import { showZooMigrationNotice } from "./services/zoo-migration/ZooMigration"
|
||||
|
||||
import {
|
||||
handleUri,
|
||||
|
|
@ -317,6 +318,12 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
|
||||
registerCommands({ context, outputChannel, provider })
|
||||
|
||||
void showZooMigrationNotice(context, { outputChannel }).catch((error) => {
|
||||
outputChannel.appendLine(
|
||||
`[Zoo Migration] Failed to show migration notice: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
})
|
||||
|
||||
/**
|
||||
* We use the text document content provider API to show the left side for diff
|
||||
* view by creating a virtual document for the original content. This makes it
|
||||
|
|
|
|||
16
src/i18n/locales/ca/common.json
generated
16
src/i18n/locales/ca/common.json
generated
|
|
@ -23,6 +23,22 @@
|
|||
"delete_config_profile": "Estàs segur que vols eliminar aquest perfil de configuració?",
|
||||
"delete_custom_mode_with_rules": "Esteu segur que voleu suprimir aquest mode {scope}?\n\nAixò també suprimirà la carpeta de regles associada a:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Instal·la Zoo",
|
||||
"prepareMigration": "Prepara la migració",
|
||||
"learnMore": "Més informació",
|
||||
"later": "Més tard",
|
||||
"includeApiKeys": "Inclou les claus d'API",
|
||||
"skipApiKeys": "Omet les claus d'API",
|
||||
"cancel": "Cancel·la"
|
||||
},
|
||||
"notice": "Roo Code està passant a Zoo Code. Pots preparar un paquet de migració basat en còpia per a Zoo sense eliminar les teves dades de Roo.",
|
||||
"zooNotPublished": "Zoo Code encara no s'ha publicat amb un id d'extensió confirmat al Marketplace. S'ha obert la vista d'extensions amb una cerca de Zoo Code.",
|
||||
"preparePrompt": "Vols preparar un paquet de migració local de Zoo Code? Si inclous les claus d'API, els secrets del proveïdor s'escriuran en un fitxer local perquè Zoo els pugui importar i després eliminar el paquet.",
|
||||
"handoffPrepared": "Paquet de migració de Zoo Code preparat a {{path}}. Instal·la Zoo Code i importa des d'aquest paquet.",
|
||||
"handoffFailed": "No s'ha pogut preparar el paquet de migració de Zoo Code: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Format d'URI de dades no vàlid",
|
||||
"error_copying_image": "Error copiant la imatge: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/de/common.json
generated
16
src/i18n/locales/de/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "Möchtest du dieses Konfigurationsprofil wirklich löschen?",
|
||||
"delete_custom_mode_with_rules": "Bist du sicher, dass du diesen {scope}-Modus löschen möchtest?\n\nDadurch wird auch der zugehörige Regelordner unter folgender Adresse gelöscht:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Zoo Installieren",
|
||||
"prepareMigration": "Migration Vorbereiten",
|
||||
"learnMore": "Mehr Erfahren",
|
||||
"later": "Später",
|
||||
"includeApiKeys": "API-Schlüssel Einschließen",
|
||||
"skipApiKeys": "API-Schlüssel Überspringen",
|
||||
"cancel": "Abbrechen"
|
||||
},
|
||||
"notice": "Roo Code wechselt zu Zoo Code. Du kannst eine kopierbasierte Migrationsübergabe für Zoo vorbereiten, ohne deine Roo-Daten zu löschen.",
|
||||
"zooNotPublished": "Zoo Code ist noch nicht unter einer bestätigten Marketplace-Erweiterungs-ID veröffentlicht. Die Erweiterungsansicht wurde mit einer Suche nach Zoo Code geöffnet.",
|
||||
"preparePrompt": "Lokale Zoo Code-Migrationsübergabe vorbereiten? Wenn du API-Schlüssel einschließt, werden Provider-Secrets in eine lokale Datei geschrieben, damit Zoo sie importieren und die Übergabe danach löschen kann.",
|
||||
"handoffPrepared": "Zoo Code-Migrationsübergabe unter {{path}} vorbereitet. Installiere Zoo Code und importiere aus dieser Übergabe.",
|
||||
"handoffFailed": "Zoo Code-Migrationsübergabe konnte nicht vorbereitet werden: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Ungültiges Daten-URI-Format",
|
||||
"error_copying_image": "Fehler beim Kopieren des Bildes: {{errorMessage}}",
|
||||
|
|
|
|||
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "Are you sure you want to delete this configuration profile?",
|
||||
"delete_custom_mode_with_rules": "Are you sure you want to delete this {scope} mode?\n\nThis will also delete the associated rules folder at:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Install Zoo",
|
||||
"prepareMigration": "Prepare Migration",
|
||||
"learnMore": "Learn More",
|
||||
"later": "Later",
|
||||
"includeApiKeys": "Include API keys",
|
||||
"skipApiKeys": "Skip API keys",
|
||||
"cancel": "Cancel"
|
||||
},
|
||||
"notice": "Roo Code is transitioning to Zoo Code. You can prepare a copy-based migration handoff for Zoo without deleting your Roo data.",
|
||||
"zooNotPublished": "Zoo Code is not published under a confirmed Marketplace extension id yet. The Extensions view has been opened with a Zoo Code search.",
|
||||
"preparePrompt": "Prepare a local Zoo Code migration handoff? Including API keys writes provider secrets to a local file so Zoo can import them, then delete the handoff after import.",
|
||||
"handoffPrepared": "Zoo Code migration handoff prepared at {{path}}. Install Zoo Code and import from this handoff.",
|
||||
"handoffFailed": "Failed to prepare Zoo Code migration handoff: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Invalid data URI format",
|
||||
"error_copying_image": "Error copying image: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/es/common.json
generated
16
src/i18n/locales/es/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "¿Estás seguro de que deseas eliminar este perfil de configuración?",
|
||||
"delete_custom_mode_with_rules": "¿Estás seguro de que quieres eliminar este modo {scope}?\n\nEsto también eliminará la carpeta de reglas asociada en:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Instalar Zoo",
|
||||
"prepareMigration": "Preparar Migración",
|
||||
"learnMore": "Más Información",
|
||||
"later": "Más Tarde",
|
||||
"includeApiKeys": "Incluir claves de API",
|
||||
"skipApiKeys": "Omitir claves de API",
|
||||
"cancel": "Cancelar"
|
||||
},
|
||||
"notice": "Roo Code está pasando a Zoo Code. Puedes preparar una entrega de migración basada en copia para Zoo sin eliminar tus datos de Roo.",
|
||||
"zooNotPublished": "Zoo Code aún no está publicado con un id de extensión confirmado en Marketplace. Se abrió la vista de Extensiones con una búsqueda de Zoo Code.",
|
||||
"preparePrompt": "¿Preparar una entrega local de migración a Zoo Code? Si incluyes claves de API, los secrets del proveedor se escribirán en un archivo local para que Zoo pueda importarlos y luego eliminar la entrega.",
|
||||
"handoffPrepared": "Entrega de migración a Zoo Code preparada en {{path}}. Instala Zoo Code e importa desde esta entrega.",
|
||||
"handoffFailed": "No se pudo preparar la entrega de migración a Zoo Code: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Formato de URI de datos no válido",
|
||||
"error_copying_image": "Error copiando la imagen: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/fr/common.json
generated
16
src/i18n/locales/fr/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "Êtes-vous sûr de vouloir supprimer ce profil de configuration ?",
|
||||
"delete_custom_mode_with_rules": "Êtes-vous sûr de vouloir supprimer ce mode {scope} ?\n\nCela supprimera également le dossier de règles associé à l'adresse :\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Installer Zoo",
|
||||
"prepareMigration": "Préparer la Migration",
|
||||
"learnMore": "En Savoir Plus",
|
||||
"later": "Plus Tard",
|
||||
"includeApiKeys": "Inclure les clés API",
|
||||
"skipApiKeys": "Ignorer les clés API",
|
||||
"cancel": "Annuler"
|
||||
},
|
||||
"notice": "Roo Code passe à Zoo Code. Tu peux préparer un transfert de migration par copie pour Zoo sans supprimer tes données Roo.",
|
||||
"zooNotPublished": "Zoo Code n'est pas encore publié avec un id d'extension Marketplace confirmé. La vue Extensions a été ouverte avec une recherche Zoo Code.",
|
||||
"preparePrompt": "Préparer un transfert local de migration Zoo Code ? Inclure les clés API écrit les secrets du fournisseur dans un fichier local afin que Zoo puisse les importer, puis supprimer le transfert après import.",
|
||||
"handoffPrepared": "Transfert de migration Zoo Code préparé dans {{path}}. Installe Zoo Code et importe depuis ce transfert.",
|
||||
"handoffFailed": "Échec de la préparation du transfert de migration Zoo Code : {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Format d'URI de données invalide",
|
||||
"error_copying_image": "Erreur lors de la copie de l'image : {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/hi/common.json
generated
16
src/i18n/locales/hi/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "क्या आप वाकई इस कॉन्फ़िगरेशन प्रोफ़ाइल को हटाना चाहते हैं?",
|
||||
"delete_custom_mode_with_rules": "क्या आप वाकई इस {scope} मोड को हटाना चाहते हैं?\n\nयह संबंधित नियम फ़ोल्डर को भी यहाँ हटा देगा:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Zoo इंस्टॉल करें",
|
||||
"prepareMigration": "माइग्रेशन तैयार करें",
|
||||
"learnMore": "और जानें",
|
||||
"later": "बाद में",
|
||||
"includeApiKeys": "API कुंजियां शामिल करें",
|
||||
"skipApiKeys": "API कुंजियां छोड़ें",
|
||||
"cancel": "रद्द करें"
|
||||
},
|
||||
"notice": "Roo Code, Zoo Code में बदल रहा है। आप Roo डेटा हटाए बिना Zoo के लिए कॉपी-आधारित माइग्रेशन हैंडऑफ तैयार कर सकते हैं।",
|
||||
"zooNotPublished": "Zoo Code अभी तक पुष्टि किए गए Marketplace एक्सटेंशन id के तहत प्रकाशित नहीं है। Extensions दृश्य Zoo Code खोज के साथ खोल दिया गया है।",
|
||||
"preparePrompt": "स्थानीय Zoo Code माइग्रेशन हैंडऑफ तैयार करें? API कुंजियां शामिल करने से प्रदाता secrets एक स्थानीय फ़ाइल में लिखे जाएंगे ताकि Zoo उन्हें आयात कर सके और फिर आयात के बाद हैंडऑफ हटा सके।",
|
||||
"handoffPrepared": "Zoo Code माइग्रेशन हैंडऑफ {{path}} पर तैयार है। Zoo Code इंस्टॉल करें और इस हैंडऑफ से आयात करें।",
|
||||
"handoffFailed": "Zoo Code माइग्रेशन हैंडऑफ तैयार करने में विफल: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "अमान्य डेटा URI फॉर्मेट",
|
||||
"error_copying_image": "छवि कॉपी करने में त्रुटि: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/id/common.json
generated
16
src/i18n/locales/id/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "Apakah kamu yakin ingin menghapus profil konfigurasi ini?",
|
||||
"delete_custom_mode_with_rules": "Anda yakin ingin menghapus mode {scope} ini?\n\nIni juga akan menghapus folder aturan terkait di:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Instal Zoo",
|
||||
"prepareMigration": "Siapkan Migrasi",
|
||||
"learnMore": "Pelajari Selengkapnya",
|
||||
"later": "Nanti",
|
||||
"includeApiKeys": "Sertakan kunci API",
|
||||
"skipApiKeys": "Lewati kunci API",
|
||||
"cancel": "Batal"
|
||||
},
|
||||
"notice": "Roo Code sedang beralih ke Zoo Code. Kamu bisa menyiapkan handoff migrasi berbasis salinan untuk Zoo tanpa menghapus data Roo-mu.",
|
||||
"zooNotPublished": "Zoo Code belum diterbitkan dengan id ekstensi Marketplace yang terkonfirmasi. Tampilan Extensions telah dibuka dengan pencarian Zoo Code.",
|
||||
"preparePrompt": "Siapkan handoff migrasi Zoo Code lokal? Menyertakan kunci API akan menulis secret penyedia ke file lokal agar Zoo bisa mengimpornya, lalu menghapus handoff setelah impor.",
|
||||
"handoffPrepared": "Handoff migrasi Zoo Code disiapkan di {{path}}. Instal Zoo Code dan impor dari handoff ini.",
|
||||
"handoffFailed": "Gagal menyiapkan handoff migrasi Zoo Code: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Format data URI tidak valid",
|
||||
"error_copying_image": "Error menyalin gambar: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/it/common.json
generated
16
src/i18n/locales/it/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "Sei sicuro di voler eliminare questo profilo di configurazione?",
|
||||
"delete_custom_mode_with_rules": "Sei sicuro di voler eliminare questa modalità {scope}?\n\nQuesto eliminerà anche la cartella delle regole associata in:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Installa Zoo",
|
||||
"prepareMigration": "Prepara Migrazione",
|
||||
"learnMore": "Scopri di Più",
|
||||
"later": "Più Tardi",
|
||||
"includeApiKeys": "Includi chiavi API",
|
||||
"skipApiKeys": "Salta chiavi API",
|
||||
"cancel": "Annulla"
|
||||
},
|
||||
"notice": "Roo Code sta passando a Zoo Code. Puoi preparare un handoff di migrazione basato su copia per Zoo senza eliminare i tuoi dati Roo.",
|
||||
"zooNotPublished": "Zoo Code non è ancora pubblicato con un id estensione Marketplace confermato. La vista Estensioni è stata aperta con una ricerca di Zoo Code.",
|
||||
"preparePrompt": "Preparare un handoff locale di migrazione Zoo Code? Includere le chiavi API scrive i secret dei provider in un file locale, così Zoo può importarli e poi eliminare l'handoff dopo l'importazione.",
|
||||
"handoffPrepared": "Handoff di migrazione Zoo Code preparato in {{path}}. Installa Zoo Code e importa da questo handoff.",
|
||||
"handoffFailed": "Impossibile preparare l'handoff di migrazione Zoo Code: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Formato URI dati non valido",
|
||||
"error_copying_image": "Errore durante la copia dell'immagine: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/ja/common.json
generated
16
src/i18n/locales/ja/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "この設定プロファイルを削除してもよろしいですか?",
|
||||
"delete_custom_mode_with_rules": "この{scope}モードを削除してもよろしいですか?\n\nこれにより、関連するルールフォルダも次の場所で削除されます:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Zoo をインストール",
|
||||
"prepareMigration": "移行を準備",
|
||||
"learnMore": "詳しく見る",
|
||||
"later": "後で",
|
||||
"includeApiKeys": "API キーを含める",
|
||||
"skipApiKeys": "API キーをスキップ",
|
||||
"cancel": "キャンセル"
|
||||
},
|
||||
"notice": "Roo Code は Zoo Code へ移行しています。Roo のデータを削除せずに、Zoo 用のコピー方式の移行ハンドオフを準備できます。",
|
||||
"zooNotPublished": "Zoo Code は、確認済みの Marketplace 拡張機能 id ではまだ公開されていません。拡張機能ビューで Zoo Code の検索を開きました。",
|
||||
"preparePrompt": "ローカルの Zoo Code 移行ハンドオフを準備しますか?API キーを含めると、Zoo がインポートできるようにプロバイダーの secret がローカルファイルに書き込まれ、インポート後にハンドオフを削除できます。",
|
||||
"handoffPrepared": "Zoo Code 移行ハンドオフを {{path}} に準備しました。Zoo Code をインストールして、このハンドオフからインポートしてください。",
|
||||
"handoffFailed": "Zoo Code 移行ハンドオフの準備に失敗しました: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "データURIフォーマットが無効です",
|
||||
"error_copying_image": "画像のコピー中にエラーが発生しました:{{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/ko/common.json
generated
16
src/i18n/locales/ko/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "이 구성 프로필을 삭제하시겠습니까?",
|
||||
"delete_custom_mode_with_rules": "이 {scope} 모드를 삭제하시겠습니까?\n\n이렇게 하면 연결된 규칙 폴더도 다음 위치에서 삭제됩니다:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Zoo 설치",
|
||||
"prepareMigration": "마이그레이션 준비",
|
||||
"learnMore": "자세히 보기",
|
||||
"later": "나중에",
|
||||
"includeApiKeys": "API 키 포함",
|
||||
"skipApiKeys": "API 키 건너뛰기",
|
||||
"cancel": "취소"
|
||||
},
|
||||
"notice": "Roo Code가 Zoo Code로 전환됩니다. Roo 데이터를 삭제하지 않고 Zoo용 복사 기반 마이그레이션 핸드오프를 준비할 수 있습니다.",
|
||||
"zooNotPublished": "Zoo Code는 아직 확인된 Marketplace 확장 id로 게시되지 않았습니다. Extensions 보기에서 Zoo Code 검색을 열었습니다.",
|
||||
"preparePrompt": "로컬 Zoo Code 마이그레이션 핸드오프를 준비할까요? API 키를 포함하면 Zoo가 가져올 수 있도록 공급자 secrets가 로컬 파일에 기록되고, 가져온 후 핸드오프를 삭제할 수 있습니다.",
|
||||
"handoffPrepared": "Zoo Code 마이그레이션 핸드오프가 {{path}}에 준비되었습니다. Zoo Code를 설치하고 이 핸드오프에서 가져오세요.",
|
||||
"handoffFailed": "Zoo Code 마이그레이션 핸드오프 준비 실패: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "잘못된 데이터 URI 형식",
|
||||
"error_copying_image": "이미지 복사 중 오류 발생: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/nl/common.json
generated
16
src/i18n/locales/nl/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "Weet je zeker dat je dit configuratieprofiel wilt verwijderen?",
|
||||
"delete_custom_mode_with_rules": "Weet je zeker dat je deze {scope}-modus wilt verwijderen?\n\nDit verwijdert ook de bijbehorende regelsmap op:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Zoo Installeren",
|
||||
"prepareMigration": "Migratie Voorbereiden",
|
||||
"learnMore": "Meer Informatie",
|
||||
"later": "Later",
|
||||
"includeApiKeys": "API-sleutels Opnemen",
|
||||
"skipApiKeys": "API-sleutels Overslaan",
|
||||
"cancel": "Annuleren"
|
||||
},
|
||||
"notice": "Roo Code stapt over naar Zoo Code. Je kunt een kopie-gebaseerde migratiehandoff voor Zoo voorbereiden zonder je Roo-gegevens te verwijderen.",
|
||||
"zooNotPublished": "Zoo Code is nog niet gepubliceerd onder een bevestigde Marketplace-extensie-id. De extensieweergave is geopend met een zoekopdracht naar Zoo Code.",
|
||||
"preparePrompt": "Een lokale Zoo Code-migratiehandoff voorbereiden? Als je API-sleutels opneemt, worden provider-secrets naar een lokaal bestand geschreven zodat Zoo ze kan importeren en de handoff daarna kan verwijderen.",
|
||||
"handoffPrepared": "Zoo Code-migratiehandoff voorbereid op {{path}}. Installeer Zoo Code en importeer vanuit deze handoff.",
|
||||
"handoffFailed": "Kan Zoo Code-migratiehandoff niet voorbereiden: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Ongeldig data-URI-formaat",
|
||||
"error_copying_image": "Fout bij kopiëren van afbeelding: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/pl/common.json
generated
16
src/i18n/locales/pl/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "Czy na pewno chcesz usunąć ten profil konfiguracyjny?",
|
||||
"delete_custom_mode_with_rules": "Czy na pewno chcesz usunąć ten tryb {scope}?\n\nSpowoduje to również usunięcie powiązanego folderu reguł pod adresem:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Zainstaluj Zoo",
|
||||
"prepareMigration": "Przygotuj Migrację",
|
||||
"learnMore": "Dowiedz się Więcej",
|
||||
"later": "Później",
|
||||
"includeApiKeys": "Dołącz klucze API",
|
||||
"skipApiKeys": "Pomiń klucze API",
|
||||
"cancel": "Anuluj"
|
||||
},
|
||||
"notice": "Roo Code przechodzi na Zoo Code. Możesz przygotować dla Zoo migrację przez kopię bez usuwania danych Roo.",
|
||||
"zooNotPublished": "Zoo Code nie jest jeszcze opublikowany pod potwierdzonym id rozszerzenia Marketplace. Widok Rozszerzenia został otwarty z wyszukiwaniem Zoo Code.",
|
||||
"preparePrompt": "Przygotować lokalną migrację Zoo Code? Dołączenie kluczy API zapisze secrets dostawców do lokalnego pliku, aby Zoo mogło je zaimportować, a następnie usunąć plik po imporcie.",
|
||||
"handoffPrepared": "Migracja Zoo Code została przygotowana w {{path}}. Zainstaluj Zoo Code i zaimportuj dane z tego pliku.",
|
||||
"handoffFailed": "Nie udało się przygotować migracji Zoo Code: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Nieprawidłowy format URI danych",
|
||||
"error_copying_image": "Błąd kopiowania obrazu: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/pt-BR/common.json
generated
16
src/i18n/locales/pt-BR/common.json
generated
|
|
@ -23,6 +23,22 @@
|
|||
"delete_config_profile": "Tem certeza de que deseja excluir este perfil de configuração?",
|
||||
"delete_custom_mode_with_rules": "Tem certeza de que deseja excluir este modo {scope}?\n\nIsso também excluirá a pasta de regras associada em:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Instalar Zoo",
|
||||
"prepareMigration": "Preparar Migração",
|
||||
"learnMore": "Saiba Mais",
|
||||
"later": "Mais Tarde",
|
||||
"includeApiKeys": "Incluir chaves de API",
|
||||
"skipApiKeys": "Ignorar chaves de API",
|
||||
"cancel": "Cancelar"
|
||||
},
|
||||
"notice": "Roo Code está migrando para Zoo Code. Você pode preparar uma entrega de migração baseada em cópia para o Zoo sem excluir seus dados do Roo.",
|
||||
"zooNotPublished": "Zoo Code ainda não foi publicado com um id de extensão confirmado no Marketplace. A visualização de Extensões foi aberta com uma busca por Zoo Code.",
|
||||
"preparePrompt": "Preparar uma entrega local de migração para o Zoo Code? Incluir chaves de API grava os secrets dos provedores em um arquivo local para que o Zoo possa importá-los e depois excluir a entrega após a importação.",
|
||||
"handoffPrepared": "Entrega de migração do Zoo Code preparada em {{path}}. Instale o Zoo Code e importe a partir desta entrega.",
|
||||
"handoffFailed": "Falha ao preparar a entrega de migração do Zoo Code: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Formato de URI de dados inválido",
|
||||
"error_copying_image": "Erro ao copiar imagem: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/ru/common.json
generated
16
src/i18n/locales/ru/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "Вы уверены, что хотите удалить этот профиль конфигурации?",
|
||||
"delete_custom_mode_with_rules": "Вы уверены, что хотите удалить этот режим {scope}?\n\nЭто также приведет к удалению соответствующей папки правил по адресу:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Установить Zoo",
|
||||
"prepareMigration": "Подготовить миграцию",
|
||||
"learnMore": "Подробнее",
|
||||
"later": "Позже",
|
||||
"includeApiKeys": "Включить API-ключи",
|
||||
"skipApiKeys": "Пропустить API-ключи",
|
||||
"cancel": "Отмена"
|
||||
},
|
||||
"notice": "Roo Code переходит на Zoo Code. Вы можете подготовить копируемый пакет миграции для Zoo, не удаляя данные Roo.",
|
||||
"zooNotPublished": "Zoo Code еще не опубликован с подтвержденным id расширения Marketplace. Открыт раздел расширений с поиском Zoo Code.",
|
||||
"preparePrompt": "Подготовить локальный пакет миграции Zoo Code? Если включить API-ключи, secrets провайдеров будут записаны в локальный файл, чтобы Zoo мог импортировать их, а затем удалить пакет после импорта.",
|
||||
"handoffPrepared": "Пакет миграции Zoo Code подготовлен в {{path}}. Установите Zoo Code и импортируйте данные из этого пакета.",
|
||||
"handoffFailed": "Не удалось подготовить пакет миграции Zoo Code: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Неверный формат URI данных",
|
||||
"error_copying_image": "Ошибка копирования изображения: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/tr/common.json
generated
16
src/i18n/locales/tr/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "Bu yapılandırma profilini silmek istediğinizden emin misiniz?",
|
||||
"delete_custom_mode_with_rules": "Bu {scope} modunu silmek istediğinizden emin misiniz?\n\nBu işlem, ilişkili kurallar klasörünü de şu konumdan silecektir:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Zoo'yu Yükle",
|
||||
"prepareMigration": "Geçişi Hazırla",
|
||||
"learnMore": "Daha Fazla Bilgi",
|
||||
"later": "Daha Sonra",
|
||||
"includeApiKeys": "API anahtarlarını dahil et",
|
||||
"skipApiKeys": "API anahtarlarını atla",
|
||||
"cancel": "İptal"
|
||||
},
|
||||
"notice": "Roo Code, Zoo Code'a geçiyor. Roo verilerini silmeden Zoo için kopya tabanlı bir geçiş handoff'u hazırlayabilirsin.",
|
||||
"zooNotPublished": "Zoo Code henüz doğrulanmış bir Marketplace eklenti id'siyle yayınlanmadı. Eklentiler görünümü Zoo Code aramasıyla açıldı.",
|
||||
"preparePrompt": "Yerel bir Zoo Code geçiş handoff'u hazırlansın mı? API anahtarlarını dahil etmek, sağlayıcı secrets değerlerini Zoo'nun içe aktarabilmesi ve içe aktarma sonrası handoff'u silebilmesi için yerel bir dosyaya yazar.",
|
||||
"handoffPrepared": "Zoo Code geçiş handoff'u {{path}} konumunda hazırlandı. Zoo Code'u yükle ve bu handoff'tan içe aktar.",
|
||||
"handoffFailed": "Zoo Code geçiş handoff'u hazırlanamadı: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Geçersiz veri URI formatı",
|
||||
"error_copying_image": "Resim kopyalanırken hata oluştu: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/vi/common.json
generated
16
src/i18n/locales/vi/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "Bạn có chắc chắn muốn xóa hồ sơ cấu hình này không?",
|
||||
"delete_custom_mode_with_rules": "Bạn có chắc chắn muốn xóa chế độ {scope} này không?\n\nThao tác này cũng sẽ xóa thư mục quy tắc liên quan tại:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "Cài đặt Zoo",
|
||||
"prepareMigration": "Chuẩn bị Di chuyển",
|
||||
"learnMore": "Tìm hiểu Thêm",
|
||||
"later": "Để sau",
|
||||
"includeApiKeys": "Bao gồm khóa API",
|
||||
"skipApiKeys": "Bỏ qua khóa API",
|
||||
"cancel": "Hủy"
|
||||
},
|
||||
"notice": "Roo Code đang chuyển sang Zoo Code. Bạn có thể chuẩn bị handoff di chuyển dạng sao chép cho Zoo mà không xóa dữ liệu Roo của mình.",
|
||||
"zooNotPublished": "Zoo Code chưa được phát hành với id tiện ích Marketplace đã xác nhận. Khung Extensions đã được mở với tìm kiếm Zoo Code.",
|
||||
"preparePrompt": "Chuẩn bị handoff di chuyển Zoo Code cục bộ? Bao gồm khóa API sẽ ghi secrets của nhà cung cấp vào một tệp cục bộ để Zoo có thể nhập chúng, rồi xóa handoff sau khi nhập.",
|
||||
"handoffPrepared": "Handoff di chuyển Zoo Code đã được chuẩn bị tại {{path}}. Cài đặt Zoo Code và nhập từ handoff này.",
|
||||
"handoffFailed": "Không thể chuẩn bị handoff di chuyển Zoo Code: {{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "Định dạng URI dữ liệu không hợp lệ",
|
||||
"error_copying_image": "Lỗi khi sao chép hình ảnh: {{errorMessage}}",
|
||||
|
|
|
|||
16
src/i18n/locales/zh-CN/common.json
generated
16
src/i18n/locales/zh-CN/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "您确定要删除此配置文件吗?",
|
||||
"delete_custom_mode_with_rules": "您确定要删除此 {scope} 模式吗?\n\n这也将删除位于以下位置的关联规则文件夹:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "安装 Zoo",
|
||||
"prepareMigration": "准备迁移",
|
||||
"learnMore": "了解更多",
|
||||
"later": "稍后",
|
||||
"includeApiKeys": "包含 API 密钥",
|
||||
"skipApiKeys": "跳过 API 密钥",
|
||||
"cancel": "取消"
|
||||
},
|
||||
"notice": "Roo Code 正在迁移到 Zoo Code。你可以为 Zoo 准备基于复制的迁移交接包,而不会删除你的 Roo 数据。",
|
||||
"zooNotPublished": "Zoo Code 尚未以确认的 Marketplace 扩展 id 发布。已打开扩展视图并搜索 Zoo Code。",
|
||||
"preparePrompt": "要准备本地 Zoo Code 迁移交接包吗?包含 API 密钥会将提供商 secrets 写入本地文件,以便 Zoo 导入,并在导入后删除该交接包。",
|
||||
"handoffPrepared": "Zoo Code 迁移交接包已准备在 {{path}}。请安装 Zoo Code 并从此交接包导入。",
|
||||
"handoffFailed": "无法准备 Zoo Code 迁移交接包:{{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_mcp_config": "项目MCP配置格式无效",
|
||||
"invalid_mcp_settings_format": "MCP设置JSON格式无效。请确保您的设置遵循正确的JSON格式。",
|
||||
|
|
|
|||
16
src/i18n/locales/zh-TW/common.json
generated
16
src/i18n/locales/zh-TW/common.json
generated
|
|
@ -19,6 +19,22 @@
|
|||
"delete_config_profile": "您確定要刪除此設定檔案嗎?",
|
||||
"delete_custom_mode_with_rules": "您確定要刪除此 {scope} 模式嗎?\n\n這也將刪除位於以下位置的關聯規則資料夾:\n{rulesFolderPath}"
|
||||
},
|
||||
"zooMigration": {
|
||||
"actions": {
|
||||
"installZoo": "安裝 Zoo",
|
||||
"prepareMigration": "準備遷移",
|
||||
"learnMore": "瞭解更多",
|
||||
"later": "稍後",
|
||||
"includeApiKeys": "包含 API 金鑰",
|
||||
"skipApiKeys": "略過 API 金鑰",
|
||||
"cancel": "取消"
|
||||
},
|
||||
"notice": "Roo Code 正在遷移到 Zoo Code。你可以為 Zoo 準備以複製為基礎的遷移交接包,而不會刪除你的 Roo 資料。",
|
||||
"zooNotPublished": "Zoo Code 尚未以確認的 Marketplace 擴充功能 id 發布。已開啟擴充功能檢視並搜尋 Zoo Code。",
|
||||
"preparePrompt": "要準備本機 Zoo Code 遷移交接包嗎?包含 API 金鑰會將供應商 secrets 寫入本機檔案,讓 Zoo 匯入,然後在匯入後刪除交接包。",
|
||||
"handoffPrepared": "Zoo Code 遷移交接包已準備在 {{path}}。請安裝 Zoo Code 並從此交接包匯入。",
|
||||
"handoffFailed": "無法準備 Zoo Code 遷移交接包:{{error}}"
|
||||
},
|
||||
"errors": {
|
||||
"invalid_data_uri": "資料 URI 格式無效",
|
||||
"error_copying_image": "複製圖片時發生錯誤:{{errorMessage}}",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"displayName": "%extension.displayName%",
|
||||
"description": "%extension.description%",
|
||||
"publisher": "RooVeterinaryInc",
|
||||
"version": "3.53.0",
|
||||
"version": "3.53.1",
|
||||
"icon": "assets/icons/icon.png",
|
||||
"galleryBanner": {
|
||||
"color": "#617A91",
|
||||
|
|
@ -155,6 +155,11 @@
|
|||
"title": "%command.importSettings.title%",
|
||||
"category": "%configuration.title%"
|
||||
},
|
||||
{
|
||||
"command": "roo-cline.prepareZooMigration",
|
||||
"title": "%command.prepareZooMigration.title%",
|
||||
"category": "%configuration.title%"
|
||||
},
|
||||
{
|
||||
"command": "roo-cline.focusInput",
|
||||
"title": "%command.focusInput.title%",
|
||||
|
|
|
|||
1
src/package.nls.ca.json
generated
1
src/package.nls.ca.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "Enfocar Camp d'Entrada",
|
||||
"command.setCustomStoragePath.title": "Establir Ruta d'Emmagatzematge Personalitzada",
|
||||
"command.importSettings.title": "Importar Configuració",
|
||||
"command.prepareZooMigration.title": "Prepara la migració a Zoo Code",
|
||||
"command.terminal.addToContext.title": "Afegir Contingut del Terminal al Context",
|
||||
"command.terminal.fixCommand.title": "Corregir Aquesta Ordre",
|
||||
"command.terminal.explainCommand.title": "Explicar Aquesta Ordre",
|
||||
|
|
|
|||
1
src/package.nls.de.json
generated
1
src/package.nls.de.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "Eingabefeld Fokussieren",
|
||||
"command.setCustomStoragePath.title": "Benutzerdefinierten Speicherpfad Festlegen",
|
||||
"command.importSettings.title": "Einstellungen Importieren",
|
||||
"command.prepareZooMigration.title": "Zoo Code-Migration Vorbereiten",
|
||||
"command.terminal.addToContext.title": "Terminal-Inhalt zum Kontext Hinzufügen",
|
||||
"command.terminal.fixCommand.title": "Diesen Befehl Reparieren",
|
||||
"command.terminal.explainCommand.title": "Diesen Befehl Erklären",
|
||||
|
|
|
|||
1
src/package.nls.es.json
generated
1
src/package.nls.es.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "Enfocar Campo de Entrada",
|
||||
"command.setCustomStoragePath.title": "Establecer Ruta de Almacenamiento Personalizada",
|
||||
"command.importSettings.title": "Importar Configuración",
|
||||
"command.prepareZooMigration.title": "Preparar Migración a Zoo Code",
|
||||
"command.terminal.addToContext.title": "Añadir Contenido de Terminal al Contexto",
|
||||
"command.terminal.fixCommand.title": "Corregir Este Comando",
|
||||
"command.terminal.explainCommand.title": "Explicar Este Comando",
|
||||
|
|
|
|||
1
src/package.nls.fr.json
generated
1
src/package.nls.fr.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "Focus sur le Champ de Saisie",
|
||||
"command.setCustomStoragePath.title": "Définir le Chemin de Stockage Personnalisé",
|
||||
"command.importSettings.title": "Importer les Paramètres",
|
||||
"command.prepareZooMigration.title": "Préparer la Migration vers Zoo Code",
|
||||
"command.terminal.addToContext.title": "Ajouter le Contenu du Terminal au Contexte",
|
||||
"command.terminal.fixCommand.title": "Corriger cette Commande",
|
||||
"command.terminal.explainCommand.title": "Expliquer cette Commande",
|
||||
|
|
|
|||
1
src/package.nls.hi.json
generated
1
src/package.nls.hi.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "इनपुट फ़ील्ड पर फोकस करें",
|
||||
"command.setCustomStoragePath.title": "कस्टम स्टोरेज पाथ सेट करें",
|
||||
"command.importSettings.title": "सेटिंग्स इम्पोर्ट करें",
|
||||
"command.prepareZooMigration.title": "Zoo Code माइग्रेशन तैयार करें",
|
||||
"command.terminal.addToContext.title": "टर्मिनल सामग्री को संदर्भ में जोड़ें",
|
||||
"command.terminal.fixCommand.title": "यह कमांड ठीक करें",
|
||||
"command.terminal.explainCommand.title": "यह कमांड समझाएं",
|
||||
|
|
|
|||
1
src/package.nls.id.json
generated
1
src/package.nls.id.json
generated
|
|
@ -20,6 +20,7 @@
|
|||
"command.focusInput.title": "Fokus ke Field Input",
|
||||
"command.setCustomStoragePath.title": "Atur Path Penyimpanan Kustom",
|
||||
"command.importSettings.title": "Impor Pengaturan",
|
||||
"command.prepareZooMigration.title": "Siapkan Migrasi Zoo Code",
|
||||
"command.terminal.addToContext.title": "Tambahkan Konten Terminal ke Konteks",
|
||||
"command.terminal.fixCommand.title": "Perbaiki Perintah Ini",
|
||||
"command.terminal.explainCommand.title": "Jelaskan Perintah Ini",
|
||||
|
|
|
|||
1
src/package.nls.it.json
generated
1
src/package.nls.it.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "Focalizza Campo di Input",
|
||||
"command.setCustomStoragePath.title": "Imposta Percorso di Archiviazione Personalizzato",
|
||||
"command.importSettings.title": "Importa Impostazioni",
|
||||
"command.prepareZooMigration.title": "Prepara la Migrazione a Zoo Code",
|
||||
"command.terminal.addToContext.title": "Aggiungi Contenuto del Terminale al Contesto",
|
||||
"command.terminal.fixCommand.title": "Correggi Questo Comando",
|
||||
"command.terminal.explainCommand.title": "Spiega Questo Comando",
|
||||
|
|
|
|||
1
src/package.nls.ja.json
generated
1
src/package.nls.ja.json
generated
|
|
@ -20,6 +20,7 @@
|
|||
"command.focusInput.title": "入力フィールドにフォーカス",
|
||||
"command.setCustomStoragePath.title": "カスタムストレージパスの設定",
|
||||
"command.importSettings.title": "設定をインポート",
|
||||
"command.prepareZooMigration.title": "Zoo Code への移行を準備",
|
||||
"command.terminal.addToContext.title": "ターミナルの内容をコンテキストに追加",
|
||||
"command.terminal.fixCommand.title": "このコマンドを修正",
|
||||
"command.terminal.explainCommand.title": "このコマンドを説明",
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
"command.focusInput.title": "Focus Input Field",
|
||||
"command.setCustomStoragePath.title": "Set Custom Storage Path",
|
||||
"command.importSettings.title": "Import Settings",
|
||||
"command.prepareZooMigration.title": "Prepare Zoo Code Migration",
|
||||
"command.terminal.addToContext.title": "Add Terminal Content to Context",
|
||||
"command.terminal.fixCommand.title": "Fix This Command",
|
||||
"command.terminal.explainCommand.title": "Explain This Command",
|
||||
|
|
|
|||
1
src/package.nls.ko.json
generated
1
src/package.nls.ko.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "입력 필드 포커스",
|
||||
"command.setCustomStoragePath.title": "사용자 지정 저장소 경로 설정",
|
||||
"command.importSettings.title": "설정 가져오기",
|
||||
"command.prepareZooMigration.title": "Zoo Code 마이그레이션 준비",
|
||||
"command.terminal.addToContext.title": "터미널 내용을 컨텍스트에 추가",
|
||||
"command.terminal.fixCommand.title": "이 명령어 수정",
|
||||
"command.terminal.explainCommand.title": "이 명령어 설명",
|
||||
|
|
|
|||
1
src/package.nls.nl.json
generated
1
src/package.nls.nl.json
generated
|
|
@ -20,6 +20,7 @@
|
|||
"command.focusInput.title": "Focus op Invoerveld",
|
||||
"command.setCustomStoragePath.title": "Aangepast Opslagpad Instellen",
|
||||
"command.importSettings.title": "Instellingen Importeren",
|
||||
"command.prepareZooMigration.title": "Zoo Code-migratie Voorbereiden",
|
||||
"command.terminal.addToContext.title": "Terminalinhoud aan Context Toevoegen",
|
||||
"command.terminal.fixCommand.title": "Repareer Dit Commando",
|
||||
"command.terminal.explainCommand.title": "Leg Dit Commando Uit",
|
||||
|
|
|
|||
1
src/package.nls.pl.json
generated
1
src/package.nls.pl.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "Fokus na Pole Wprowadzania",
|
||||
"command.setCustomStoragePath.title": "Ustaw Niestandardową Ścieżkę Przechowywania",
|
||||
"command.importSettings.title": "Importuj Ustawienia",
|
||||
"command.prepareZooMigration.title": "Przygotuj Migrację do Zoo Code",
|
||||
"command.terminal.addToContext.title": "Dodaj Zawartość Terminala do Kontekstu",
|
||||
"command.terminal.fixCommand.title": "Napraw tę Komendę",
|
||||
"command.terminal.explainCommand.title": "Wyjaśnij tę Komendę",
|
||||
|
|
|
|||
1
src/package.nls.pt-BR.json
generated
1
src/package.nls.pt-BR.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "Focar Campo de Entrada",
|
||||
"command.setCustomStoragePath.title": "Definir Caminho de Armazenamento Personalizado",
|
||||
"command.importSettings.title": "Importar Configurações",
|
||||
"command.prepareZooMigration.title": "Preparar Migração para o Zoo Code",
|
||||
"command.terminal.addToContext.title": "Adicionar Conteúdo do Terminal ao Contexto",
|
||||
"command.terminal.fixCommand.title": "Corrigir Este Comando",
|
||||
"command.terminal.explainCommand.title": "Explicar Este Comando",
|
||||
|
|
|
|||
1
src/package.nls.ru.json
generated
1
src/package.nls.ru.json
generated
|
|
@ -20,6 +20,7 @@
|
|||
"command.focusInput.title": "Фокус на поле ввода",
|
||||
"command.setCustomStoragePath.title": "Указать путь хранения",
|
||||
"command.importSettings.title": "Импортировать настройки",
|
||||
"command.prepareZooMigration.title": "Подготовить миграцию в Zoo Code",
|
||||
"command.terminal.addToContext.title": "Добавить содержимое терминала в контекст",
|
||||
"command.terminal.fixCommand.title": "Исправить эту команду",
|
||||
"command.terminal.explainCommand.title": "Объяснить эту команду",
|
||||
|
|
|
|||
1
src/package.nls.tr.json
generated
1
src/package.nls.tr.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "Giriş Alanına Odaklan",
|
||||
"command.setCustomStoragePath.title": "Özel Depolama Yolunu Ayarla",
|
||||
"command.importSettings.title": "Ayarları İçe Aktar",
|
||||
"command.prepareZooMigration.title": "Zoo Code Geçişini Hazırla",
|
||||
"command.terminal.addToContext.title": "Terminal İçeriğini Bağlama Ekle",
|
||||
"command.terminal.fixCommand.title": "Bu Komutu Düzelt",
|
||||
"command.terminal.explainCommand.title": "Bu Komutu Açıkla",
|
||||
|
|
|
|||
1
src/package.nls.vi.json
generated
1
src/package.nls.vi.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "Tập Trung vào Trường Nhập",
|
||||
"command.setCustomStoragePath.title": "Đặt Đường Dẫn Lưu Trữ Tùy Chỉnh",
|
||||
"command.importSettings.title": "Nhập Cài Đặt",
|
||||
"command.prepareZooMigration.title": "Chuẩn bị Di chuyển sang Zoo Code",
|
||||
"command.terminal.addToContext.title": "Thêm Nội Dung Terminal vào Ngữ Cảnh",
|
||||
"command.terminal.fixCommand.title": "Sửa Lệnh Này",
|
||||
"command.terminal.explainCommand.title": "Giải Thích Lệnh Này",
|
||||
|
|
|
|||
1
src/package.nls.zh-CN.json
generated
1
src/package.nls.zh-CN.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "聚焦输入框",
|
||||
"command.setCustomStoragePath.title": "设置自定义存储路径",
|
||||
"command.importSettings.title": "导入设置",
|
||||
"command.prepareZooMigration.title": "准备迁移到 Zoo Code",
|
||||
"command.terminal.addToContext.title": "将终端内容添加到上下文",
|
||||
"command.terminal.fixCommand.title": "修复此命令",
|
||||
"command.terminal.explainCommand.title": "解释此命令",
|
||||
|
|
|
|||
1
src/package.nls.zh-TW.json
generated
1
src/package.nls.zh-TW.json
generated
|
|
@ -10,6 +10,7 @@
|
|||
"command.focusInput.title": "聚焦輸入框",
|
||||
"command.setCustomStoragePath.title": "設定自訂儲存路徑",
|
||||
"command.importSettings.title": "匯入設定",
|
||||
"command.prepareZooMigration.title": "準備遷移到 Zoo Code",
|
||||
"command.terminal.addToContext.title": "將終端內容新增到上下文",
|
||||
"command.terminal.fixCommand.title": "修復此命令",
|
||||
"command.terminal.explainCommand.title": "解釋此命令",
|
||||
|
|
|
|||
297
src/services/zoo-migration/ZooMigration.ts
Normal file
297
src/services/zoo-migration/ZooMigration.ts
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
import * as fs from "fs/promises"
|
||||
import * as path from "path"
|
||||
import * as vscode from "vscode"
|
||||
|
||||
import type { GlobalSettings } from "@roo-code/types"
|
||||
|
||||
import { ContextProxy } from "../../core/config/ContextProxy"
|
||||
import type { ProviderProfiles } from "../../core/config/ProviderSettingsManager"
|
||||
import { t } from "../../i18n"
|
||||
import { Package } from "../../shared/package"
|
||||
import { fileExistsAtPath } from "../../utils/fs"
|
||||
import { getStorageBasePath } from "../../utils/storage"
|
||||
|
||||
const HANDOFF_SCHEMA_VERSION = 1
|
||||
const HANDOFF_DIR_NAME = "zoo-migration"
|
||||
const HANDOFF_FILE_NAME = "handoff-v1.json"
|
||||
|
||||
const ZOO_REPOSITORY_URL = "https://github.com/Zoo-Code-Org/Zoo-Code"
|
||||
const ZOO_ANNOUNCEMENT_URL = "https://www.reddit.com/r/RooCode/comments/1syufn1/roo_is_back_as_zoo/"
|
||||
const ZOO_EXTENSION_ID = process.env.ZOO_CODE_EXTENSION_ID
|
||||
|
||||
const CONFIGURATION_KEYS = [
|
||||
"allowedCommands",
|
||||
"deniedCommands",
|
||||
"commandExecutionTimeout",
|
||||
"commandTimeoutAllowlist",
|
||||
"preventCompletionWithOpenTodos",
|
||||
"vsCodeLmModelSelector",
|
||||
"customStoragePath",
|
||||
"enableCodeActions",
|
||||
"autoImportSettingsPath",
|
||||
"maximumIndexedFilesForFileSearch",
|
||||
"useAgentRules",
|
||||
"apiRequestTimeout",
|
||||
"newTaskRequireTodos",
|
||||
"codeIndex.embeddingBatchSize",
|
||||
"debug",
|
||||
"debugProxy.enabled",
|
||||
"debugProxy.serverUrl",
|
||||
"debugProxy.tlsInsecure",
|
||||
] as const
|
||||
|
||||
type ConfigurationValue = {
|
||||
value: unknown
|
||||
globalValue?: unknown
|
||||
workspaceValue?: unknown
|
||||
workspaceFolderValue?: unknown
|
||||
}
|
||||
|
||||
type HandoffCopiedData = {
|
||||
settings?: string
|
||||
tasks?: string
|
||||
}
|
||||
|
||||
export type ZooMigrationHandoff = {
|
||||
schemaVersion: typeof HANDOFF_SCHEMA_VERSION
|
||||
createdAt: string
|
||||
source: {
|
||||
extensionId: string
|
||||
publisher: string
|
||||
name: string
|
||||
version: string
|
||||
globalStoragePath: string
|
||||
storageBasePath: string
|
||||
}
|
||||
zoo: {
|
||||
repositoryUrl: string
|
||||
announcementUrl: string
|
||||
extensionId?: string
|
||||
}
|
||||
containsSecrets: boolean
|
||||
globalSettings?: GlobalSettings
|
||||
vscodeConfiguration: Record<string, ConfigurationValue>
|
||||
providerProfiles?: ProviderProfiles
|
||||
copiedData: HandoffCopiedData
|
||||
}
|
||||
|
||||
export type CreateZooMigrationHandoffOptions = {
|
||||
context: vscode.ExtensionContext
|
||||
contextProxy: ContextProxy
|
||||
providerSettingsManager: {
|
||||
export: () => Promise<ProviderProfiles>
|
||||
}
|
||||
includeSecrets: boolean
|
||||
outputChannel?: vscode.OutputChannel
|
||||
}
|
||||
|
||||
export type CreateZooMigrationHandoffResult = {
|
||||
handoffPath: string
|
||||
handoff: ZooMigrationHandoff
|
||||
}
|
||||
|
||||
export type ShowZooMigrationNoticeOptions = {
|
||||
outputChannel?: vscode.OutputChannel
|
||||
delayMs?: number
|
||||
}
|
||||
|
||||
export async function createZooMigrationHandoff({
|
||||
context,
|
||||
contextProxy,
|
||||
providerSettingsManager,
|
||||
includeSecrets,
|
||||
outputChannel,
|
||||
}: CreateZooMigrationHandoffOptions): Promise<CreateZooMigrationHandoffResult> {
|
||||
const createdAt = new Date().toISOString()
|
||||
const migrationDir = path.join(context.globalStorageUri.fsPath, HANDOFF_DIR_NAME)
|
||||
const dataDir = path.join(migrationDir, "data")
|
||||
const storageBasePath = await getStorageBasePath(context.globalStorageUri.fsPath)
|
||||
const copiedData: HandoffCopiedData = {}
|
||||
|
||||
await fs.mkdir(dataDir, { recursive: true })
|
||||
|
||||
await copyDataDirectory({
|
||||
sourcePath: path.join(storageBasePath, "settings"),
|
||||
destinationPath: path.join(dataDir, "settings"),
|
||||
relativePath: "data/settings",
|
||||
copiedData,
|
||||
key: "settings",
|
||||
outputChannel,
|
||||
})
|
||||
|
||||
await copyDataDirectory({
|
||||
sourcePath: path.join(storageBasePath, "tasks"),
|
||||
destinationPath: path.join(dataDir, "tasks"),
|
||||
relativePath: "data/tasks",
|
||||
copiedData,
|
||||
key: "tasks",
|
||||
outputChannel,
|
||||
})
|
||||
|
||||
const globalSettings = await contextProxy.export()
|
||||
const providerProfiles = includeSecrets ? await providerSettingsManager.export() : undefined
|
||||
const handoff: ZooMigrationHandoff = {
|
||||
schemaVersion: HANDOFF_SCHEMA_VERSION,
|
||||
createdAt,
|
||||
source: {
|
||||
extensionId: `${Package.publisher}.${Package.name}`,
|
||||
publisher: Package.publisher,
|
||||
name: Package.name,
|
||||
version: Package.version,
|
||||
globalStoragePath: context.globalStorageUri.fsPath,
|
||||
storageBasePath,
|
||||
},
|
||||
zoo: {
|
||||
repositoryUrl: ZOO_REPOSITORY_URL,
|
||||
announcementUrl: ZOO_ANNOUNCEMENT_URL,
|
||||
extensionId: ZOO_EXTENSION_ID,
|
||||
},
|
||||
containsSecrets: includeSecrets,
|
||||
globalSettings,
|
||||
vscodeConfiguration: getRooConfigurationValues(),
|
||||
providerProfiles,
|
||||
copiedData,
|
||||
}
|
||||
|
||||
const handoffPath = path.join(migrationDir, HANDOFF_FILE_NAME)
|
||||
await fs.writeFile(handoffPath, JSON.stringify(handoff, null, 2), "utf-8")
|
||||
await restrictFilePermissions(handoffPath, outputChannel)
|
||||
|
||||
outputChannel?.appendLine(`[Zoo Migration] Prepared handoff at ${handoffPath}`)
|
||||
|
||||
return { handoffPath, handoff }
|
||||
}
|
||||
|
||||
export async function showZooMigrationNotice(
|
||||
context: vscode.ExtensionContext,
|
||||
{ outputChannel, delayMs = 1500 }: ShowZooMigrationNoticeOptions = {},
|
||||
): Promise<void> {
|
||||
if (delayMs > 0) {
|
||||
await new Promise((resolve) => setTimeout(resolve, delayMs))
|
||||
}
|
||||
|
||||
const installAction = t("common:zooMigration.actions.installZoo")
|
||||
const migrateAction = t("common:zooMigration.actions.prepareMigration")
|
||||
const learnMoreAction = t("common:zooMigration.actions.learnMore")
|
||||
const laterAction = t("common:zooMigration.actions.later")
|
||||
outputChannel?.appendLine(`[Zoo Migration] Showing migration notice for ${Package.version}`)
|
||||
const result = await vscode.window.showInformationMessage(
|
||||
t("common:zooMigration.notice"),
|
||||
installAction,
|
||||
migrateAction,
|
||||
learnMoreAction,
|
||||
laterAction,
|
||||
)
|
||||
|
||||
if (!result) {
|
||||
outputChannel?.appendLine("[Zoo Migration] Migration notice dismissed without selection; it may be shown again")
|
||||
return
|
||||
}
|
||||
|
||||
outputChannel?.appendLine(`[Zoo Migration] Migration notice selected: ${result}`)
|
||||
|
||||
if (result === installAction) {
|
||||
await installOrShowZooExtension()
|
||||
} else if (result === migrateAction) {
|
||||
await vscode.commands.executeCommand(`${Package.name}.prepareZooMigration`)
|
||||
} else if (result === learnMoreAction) {
|
||||
await vscode.env.openExternal(vscode.Uri.parse(ZOO_REPOSITORY_URL))
|
||||
}
|
||||
}
|
||||
|
||||
export async function installOrShowZooExtension(): Promise<void> {
|
||||
if (ZOO_EXTENSION_ID) {
|
||||
await vscode.commands.executeCommand("workbench.extensions.installExtension", ZOO_EXTENSION_ID)
|
||||
return
|
||||
}
|
||||
|
||||
await vscode.commands.executeCommand("workbench.extensions.search", "Zoo Code")
|
||||
await vscode.window.showInformationMessage(t("common:zooMigration.zooNotPublished"))
|
||||
}
|
||||
|
||||
export async function promptAndCreateZooMigrationHandoff(options: {
|
||||
context: vscode.ExtensionContext
|
||||
contextProxy: ContextProxy
|
||||
providerSettingsManager: CreateZooMigrationHandoffOptions["providerSettingsManager"]
|
||||
outputChannel?: vscode.OutputChannel
|
||||
}): Promise<CreateZooMigrationHandoffResult | undefined> {
|
||||
const includeSecretsAction = t("common:zooMigration.actions.includeApiKeys")
|
||||
const noSecretsAction = t("common:zooMigration.actions.skipApiKeys")
|
||||
const cancelAction = t("common:zooMigration.actions.cancel")
|
||||
const result = await vscode.window.showWarningMessage(
|
||||
t("common:zooMigration.preparePrompt"),
|
||||
{ modal: true },
|
||||
includeSecretsAction,
|
||||
noSecretsAction,
|
||||
cancelAction,
|
||||
)
|
||||
|
||||
if (!result || result === cancelAction) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const handoffResult = await createZooMigrationHandoff({
|
||||
...options,
|
||||
includeSecrets: result === includeSecretsAction,
|
||||
})
|
||||
|
||||
await vscode.window.showInformationMessage(
|
||||
t("common:zooMigration.handoffPrepared", { path: handoffResult.handoffPath }),
|
||||
)
|
||||
|
||||
return handoffResult
|
||||
}
|
||||
|
||||
function getRooConfigurationValues(): Record<string, ConfigurationValue> {
|
||||
const configuration = vscode.workspace.getConfiguration(Package.name)
|
||||
|
||||
return Object.fromEntries(
|
||||
CONFIGURATION_KEYS.map((key) => {
|
||||
const inspected = typeof configuration.inspect === "function" ? configuration.inspect(key) : undefined
|
||||
return [
|
||||
key,
|
||||
{
|
||||
value: configuration.get(key),
|
||||
globalValue: inspected?.globalValue,
|
||||
workspaceValue: inspected?.workspaceValue,
|
||||
workspaceFolderValue: inspected?.workspaceFolderValue,
|
||||
},
|
||||
]
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
async function copyDataDirectory({
|
||||
sourcePath,
|
||||
destinationPath,
|
||||
relativePath,
|
||||
copiedData,
|
||||
key,
|
||||
outputChannel,
|
||||
}: {
|
||||
sourcePath: string
|
||||
destinationPath: string
|
||||
relativePath: string
|
||||
copiedData: HandoffCopiedData
|
||||
key: keyof HandoffCopiedData
|
||||
outputChannel?: vscode.OutputChannel
|
||||
}) {
|
||||
if (!(await fileExistsAtPath(sourcePath))) {
|
||||
outputChannel?.appendLine(`[Zoo Migration] No ${key} directory found at ${sourcePath}; skipping`)
|
||||
return
|
||||
}
|
||||
|
||||
await fs.rm(destinationPath, { recursive: true, force: true })
|
||||
await fs.cp(sourcePath, destinationPath, { recursive: true })
|
||||
copiedData[key] = relativePath
|
||||
}
|
||||
|
||||
async function restrictFilePermissions(filePath: string, outputChannel?: vscode.OutputChannel) {
|
||||
try {
|
||||
await fs.chmod(filePath, 0o600)
|
||||
} catch (error) {
|
||||
outputChannel?.appendLine(
|
||||
`[Zoo Migration] Could not restrict handoff permissions: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
208
src/services/zoo-migration/__tests__/ZooMigration.spec.ts
Normal file
208
src/services/zoo-migration/__tests__/ZooMigration.spec.ts
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
import * as fs from "fs/promises"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
import * as vscode from "vscode"
|
||||
|
||||
import { createZooMigrationHandoff, showZooMigrationNotice } from "../ZooMigration"
|
||||
|
||||
describe("createZooMigrationHandoff", () => {
|
||||
let tmpDir: string
|
||||
|
||||
beforeEach(async () => {
|
||||
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "roo-zoo-migration-"))
|
||||
vi.spyOn(vscode.workspace, "getConfiguration").mockReturnValue({
|
||||
get: vi.fn((key: string, defaultValue?: unknown) => {
|
||||
if (key === "customStoragePath") {
|
||||
return ""
|
||||
}
|
||||
return defaultValue
|
||||
}),
|
||||
inspect: vi.fn((key: string) => ({
|
||||
globalValue: key === "allowedCommands" ? ["git diff"] : undefined,
|
||||
})),
|
||||
} as any)
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
vi.restoreAllMocks()
|
||||
await fs.rm(tmpDir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
it("creates a copy-based handoff with settings and tasks but excludes cache data", async () => {
|
||||
const context = makeContext(tmpDir)
|
||||
await fs.mkdir(path.join(tmpDir, "settings"), { recursive: true })
|
||||
await fs.mkdir(path.join(tmpDir, "tasks", "task-1"), { recursive: true })
|
||||
await fs.mkdir(path.join(tmpDir, "cache"), { recursive: true })
|
||||
await fs.writeFile(path.join(tmpDir, "settings", "mcp_settings.json"), "{}")
|
||||
await fs.writeFile(path.join(tmpDir, "tasks", "task-1", "history_item.json"), "{}")
|
||||
await fs.writeFile(path.join(tmpDir, "cache", "openrouter_models.json"), "{}")
|
||||
|
||||
const result = await createZooMigrationHandoff({
|
||||
context,
|
||||
contextProxy: { export: vi.fn().mockResolvedValue({ mode: "code" }) } as any,
|
||||
providerSettingsManager: { export: vi.fn().mockResolvedValue({ currentApiConfigName: "default" }) },
|
||||
includeSecrets: false,
|
||||
})
|
||||
|
||||
const handoffJson = JSON.parse(await fs.readFile(result.handoffPath, "utf-8"))
|
||||
expect(handoffJson.containsSecrets).toBe(false)
|
||||
expect(handoffJson.providerProfiles).toBeUndefined()
|
||||
expect(handoffJson.globalSettings).toEqual({ mode: "code" })
|
||||
expect(handoffJson.copiedData).toEqual({
|
||||
settings: "data/settings",
|
||||
tasks: "data/tasks",
|
||||
})
|
||||
await expect(
|
||||
fs.readFile(path.join(tmpDir, "zoo-migration", "data", "settings", "mcp_settings.json"), "utf-8"),
|
||||
).resolves.toBe("{}")
|
||||
await expect(
|
||||
fs.readFile(path.join(tmpDir, "zoo-migration", "data", "tasks", "task-1", "history_item.json"), "utf-8"),
|
||||
).resolves.toBe("{}")
|
||||
await expect(
|
||||
fs.access(path.join(tmpDir, "zoo-migration", "data", "cache", "openrouter_models.json")),
|
||||
).rejects.toThrow()
|
||||
})
|
||||
|
||||
it("exports provider profiles only when the user opts into secret migration", async () => {
|
||||
const context = makeContext(tmpDir)
|
||||
const providerProfiles = {
|
||||
currentApiConfigName: "default",
|
||||
apiConfigs: {
|
||||
default: {
|
||||
id: "profile-1",
|
||||
apiProvider: "openai",
|
||||
openAiApiKey: "secret-key",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const result = await createZooMigrationHandoff({
|
||||
context,
|
||||
contextProxy: { export: vi.fn().mockResolvedValue({}) } as any,
|
||||
providerSettingsManager: { export: vi.fn().mockResolvedValue(providerProfiles as any) },
|
||||
includeSecrets: true,
|
||||
})
|
||||
|
||||
const handoffJson = JSON.parse(await fs.readFile(result.handoffPath, "utf-8"))
|
||||
expect(handoffJson.containsSecrets).toBe(true)
|
||||
expect(handoffJson.providerProfiles).toEqual(providerProfiles)
|
||||
})
|
||||
|
||||
it("uses a configured custom storage path as the source data path", async () => {
|
||||
const customStoragePath = path.join(tmpDir, "custom-storage")
|
||||
const context = makeContext(path.join(tmpDir, "global-storage"))
|
||||
await fs.mkdir(path.join(customStoragePath, "settings"), { recursive: true })
|
||||
await fs.writeFile(path.join(customStoragePath, "settings", "custom_modes.yaml"), "customModes: []\n")
|
||||
|
||||
vi.spyOn(vscode.workspace, "getConfiguration").mockReturnValue({
|
||||
get: vi.fn((key: string, defaultValue?: unknown) => {
|
||||
if (key === "customStoragePath") {
|
||||
return customStoragePath
|
||||
}
|
||||
return defaultValue
|
||||
}),
|
||||
inspect: vi.fn(),
|
||||
} as any)
|
||||
|
||||
const result = await createZooMigrationHandoff({
|
||||
context,
|
||||
contextProxy: { export: vi.fn().mockResolvedValue({}) } as any,
|
||||
providerSettingsManager: { export: vi.fn().mockResolvedValue({ currentApiConfigName: "default" }) },
|
||||
includeSecrets: false,
|
||||
})
|
||||
|
||||
expect(result.handoff.source.storageBasePath).toBe(customStoragePath)
|
||||
await expect(
|
||||
fs.readFile(
|
||||
path.join(tmpDir, "global-storage", "zoo-migration", "data", "settings", "custom_modes.yaml"),
|
||||
"utf-8",
|
||||
),
|
||||
).resolves.toBe("customModes: []\n")
|
||||
})
|
||||
})
|
||||
|
||||
describe("showZooMigrationNotice", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
it("shows the migration notice on activation", async () => {
|
||||
const update = vi.fn().mockResolvedValue(undefined)
|
||||
const context = {
|
||||
globalState: {
|
||||
get: vi.fn().mockReturnValue(undefined),
|
||||
update,
|
||||
},
|
||||
} as any
|
||||
const outputChannel = { appendLine: vi.fn() } as any
|
||||
const showInformationMessage = vi
|
||||
.spyOn(vscode.window, "showInformationMessage")
|
||||
.mockImplementation((async (_message: string, ...actions: unknown[]) => actions.at(-1)) as any)
|
||||
|
||||
await showZooMigrationNotice(context, { outputChannel, delayMs: 0 })
|
||||
|
||||
expect(showInformationMessage).toHaveBeenCalled()
|
||||
expect(update).not.toHaveBeenCalled()
|
||||
expect(outputChannel.appendLine).toHaveBeenCalledWith("[Zoo Migration] Showing migration notice for 3.53.1")
|
||||
})
|
||||
|
||||
it("does not mark the notice shown when VS Code dismisses it without a user selection", async () => {
|
||||
const update = vi.fn().mockResolvedValue(undefined)
|
||||
const context = {
|
||||
globalState: {
|
||||
get: vi.fn().mockReturnValue(undefined),
|
||||
update,
|
||||
},
|
||||
} as any
|
||||
vi.spyOn(vscode.window, "showInformationMessage").mockResolvedValue(undefined)
|
||||
|
||||
await showZooMigrationNotice(context, { delayMs: 0 })
|
||||
|
||||
expect(update).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("does not mark the notice shown when the user chooses Learn More", async () => {
|
||||
const update = vi.fn().mockResolvedValue(undefined)
|
||||
const context = {
|
||||
globalState: {
|
||||
get: vi.fn().mockReturnValue(undefined),
|
||||
update,
|
||||
},
|
||||
} as any
|
||||
vi.spyOn(vscode.window, "showInformationMessage").mockImplementation((async (
|
||||
_message: string,
|
||||
...actions: unknown[]
|
||||
) => actions.at(2)) as any)
|
||||
const openExternal = vi.spyOn(vscode.env, "openExternal").mockResolvedValue(true)
|
||||
|
||||
await showZooMigrationNotice(context, { delayMs: 0 })
|
||||
|
||||
expect(openExternal).toHaveBeenCalled()
|
||||
expect(update).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("shows the notice even when older persistent state says it was already shown", async () => {
|
||||
const context = {
|
||||
globalState: {
|
||||
get: vi.fn().mockReturnValue(true),
|
||||
update: vi.fn(),
|
||||
},
|
||||
} as any
|
||||
const showInformationMessage = vi.spyOn(vscode.window, "showInformationMessage").mockResolvedValue(undefined)
|
||||
|
||||
await showZooMigrationNotice(context, { delayMs: 0 })
|
||||
|
||||
expect(showInformationMessage).toHaveBeenCalled()
|
||||
expect(context.globalState.update).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
function makeContext(globalStoragePath: string): vscode.ExtensionContext {
|
||||
return {
|
||||
globalStorageUri: vscode.Uri.file(globalStoragePath),
|
||||
globalState: {
|
||||
get: vi.fn(),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
},
|
||||
} as any
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue