phase 5: remove migration repair flow (#1215)

This commit is contained in:
ben
2026-03-29 17:26:13 -07:00
committed by GitHub
parent 999858cca3
commit 32a27cf3a3
12 changed files with 35 additions and 395 deletions

View File

@@ -3977,22 +3977,6 @@ export default function App() {
);
const refreshActiveWorkspaceServerConfig = workspaceStore.refreshRuntimeWorkspaceConfig;
const activePermissionMemo = createMemo(() => activePermission());
const migrationRepairUnavailableReason = createMemo<string | null>(() => {
if (workspaceStore.canRepairOpencodeMigration()) return null;
if (!isTauriRuntime()) {
return t("app.migration.desktop_required", currentLocale());
}
if (selectedWorkspaceDisplay().workspaceType !== "local") {
return t("app.migration.local_only", currentLocale());
}
if (!workspaceStore.selectedWorkspacePath().trim()) {
return t("app.migration.workspace_required", currentLocale());
}
return t("app.migration.local_only", currentLocale());
});
const [expandedStepIds, setExpandedStepIds] = createSignal<Set<string>>(
new Set()
@@ -5524,11 +5508,6 @@ export default function App() {
sandboxCreateProgressLast: workspaceStore.lastSandboxCreateProgress(),
clearWorkspaceDebugEvents: workspaceStore.clearWorkspaceDebugEvents,
safeStringify,
repairOpencodeMigration: workspaceStore.repairOpencodeMigration,
migrationRepairBusy: workspaceStore.migrationRepairBusy(),
migrationRepairResult: workspaceStore.migrationRepairResult(),
migrationRepairAvailable: workspaceStore.canRepairOpencodeMigration(),
migrationRepairUnavailableReason: migrationRepairUnavailableReason(),
repairOpencodeCache,
cacheRepairBusy: cacheRepairBusy(),
cacheRepairResult: cacheRepairResult(),

View File

@@ -39,7 +39,6 @@ import { downloadDir, homeDir } from "@tauri-apps/api/path";
import {
engineDoctor,
engineInfo,
opencodeDbMigrate,
engineInstall,
engineStart,
engineStop,
@@ -103,11 +102,6 @@ export type SandboxCreateProgressState = {
export type SandboxCreatePhase = "idle" | "preflight" | "provisioning" | "finalizing";
export type MigrationRepairResult = {
ok: boolean;
message: string;
};
type RuntimeWorkspaceLookup = {
workspaceId?: string | null;
directoryHint?: string | null;
@@ -211,13 +205,6 @@ export function createWorkspaceStore(options: {
const LONG_BOOT_CONNECT_REASONS = new Set(["host-start", "bootstrap-local"]);
const DEFAULT_WORKSPACE_HOME_FOLDER_NAME = "OpenWork";
const FIRST_RUN_WELCOME_WORKSPACE_NAME = "Welcome";
const DB_MIGRATE_UNSUPPORTED_PATTERNS = [
/unknown(?:\s+sub)?command\s+['"`]?db['"`]?/i,
/unrecognized(?:\s+sub)?command\s+['"`]?db['"`]?/i,
/no such command[:\s]+db/i,
/found argument ['"`]db['"`] which wasn't expected/i,
] as const;
const preferredInitialSessionTitleForPreset = (preset: WorkspacePreset) => {
const trimmed = defaultBlueprintSessionsForPreset(preset)
.find((session) => session.openOnFirstLoad === true)?.title?.trim();
@@ -269,18 +256,6 @@ export function createWorkspaceStore(options: {
return DEFAULT_CONNECT_HEALTH_TIMEOUT_MS;
};
const formatExecOutput = (result: { stdout: string; stderr: string }) => {
const stderr = result.stderr.trim();
const stdout = result.stdout.trim();
return [stderr, stdout].filter(Boolean).join("\n\n");
};
const isDbMigrateUnsupported = (output: string) => {
const normalized = output.trim();
if (!normalized) return false;
return DB_MIGRATE_UNSUPPORTED_PATTERNS.some((pattern) => pattern.test(normalized));
};
const [engine, setEngine] = createSignal<EngineInfo | null>(null);
const [engineAuth, setEngineAuth] = createSignal<OpencodeAuth | null>(null);
const [engineDoctorResult, setEngineDoctorResult] = createSignal<EngineDoctorResult | null>(null);
@@ -402,9 +377,6 @@ export function createWorkspaceStore(options: {
>({});
const [exportingWorkspaceConfig, setExportingWorkspaceConfig] = createSignal(false);
const [importingWorkspaceConfig, setImportingWorkspaceConfig] = createSignal(false);
const [migrationRepairBusy, setMigrationRepairBusy] = createSignal(false);
const [migrationRepairResult, setMigrationRepairResult] = createSignal<MigrationRepairResult | null>(null);
const selectedWorkspaceInfo = createMemo(() => workspaces().find((w) => w.id === selectedWorkspaceId()) ?? null);
const connectedWorkspaceInfo = createMemo(() => {
const id = connectedWorkspaceId()?.trim() ?? "";
@@ -3175,109 +3147,6 @@ export function createWorkspaceStore(options: {
}
}
function canRepairOpencodeMigration() {
if (!isTauriRuntime()) return false;
const workspace = selectedWorkspaceInfo();
if (!workspace || workspace.workspaceType !== "local") return false;
return Boolean(selectedWorkspacePath().trim());
}
async function repairOpencodeMigration(optionsOverride?: { navigate?: boolean }) {
if (!isTauriRuntime()) {
const message = t("app.migration.desktop_required", currentLocale());
setMigrationRepairResult({ ok: false, message });
options.setError(message);
return false;
}
if (migrationRepairBusy()) return false;
const workspace = selectedWorkspaceInfo();
if (!workspace || workspace.workspaceType !== "local") {
const message = t("app.migration.local_only", currentLocale());
setMigrationRepairResult({ ok: false, message });
options.setError(message);
return false;
}
const root = selectedWorkspacePath().trim();
if (!root) {
const message = t("app.migration.workspace_required", currentLocale());
setMigrationRepairResult({ ok: false, message });
options.setError(message);
return false;
}
setMigrationRepairBusy(true);
setMigrationRepairResult(null);
options.setError(null);
options.setBusy(true);
options.setBusyLabel("status.repairing_migration");
options.setBusyStartedAt(Date.now());
try {
if (engine()?.running) {
const info = await engineStop();
setEngine(info);
}
const source = options.engineSource();
const result = await opencodeDbMigrate({
projectDir: root,
preferSidecar: source === "sidecar",
opencodeBinPath: source === "custom" ? options.engineCustomBinPath?.().trim() || null : null,
});
if (!result.ok) {
const output = formatExecOutput(result);
if (isDbMigrateUnsupported(output)) {
const message = t("app.migration.unsupported", currentLocale());
setMigrationRepairResult({ ok: false, message });
options.setError(message);
return false;
}
const fallback = t("app.migration.failed", currentLocale());
const message = output ? `${fallback}\n\n${output}` : fallback;
setMigrationRepairResult({ ok: false, message });
options.setError(addOpencodeCacheHint(message));
return false;
}
const started = await startHost({
workspacePath: root,
navigate: optionsOverride?.navigate ?? false,
});
if (!started) {
const message = t("app.migration.restart_failed", currentLocale());
setMigrationRepairResult({ ok: false, message });
return false;
}
setMigrationRepairResult({ ok: true, message: t("app.migration.success", currentLocale()) });
return true;
} catch (error) {
const message = addOpencodeCacheHint(error instanceof Error ? error.message : safeStringify(error));
setMigrationRepairResult({ ok: false, message });
options.setError(message);
return false;
} finally {
setMigrationRepairBusy(false);
options.setBusy(false);
options.setBusyLabel(null);
options.setBusyStartedAt(null);
}
}
async function onRepairOpencodeMigration() {
options.setStartupPreference("local");
options.setOnboardingStep("connecting");
const ok = await repairOpencodeMigration({ navigate: true });
if (!ok) {
options.setOnboardingStep("local");
}
}
async function startHost(optionsOverride?: { workspacePath?: string; navigate?: boolean }) {
if (!isTauriRuntime()) {
options.setError(t("app.error.tauri_required", currentLocale()));
@@ -3329,7 +3198,6 @@ export function createWorkspaceStore(options: {
}
options.setError(null);
setMigrationRepairResult(null);
options.setBusy(true);
options.setBusyLabel("status.starting_engine");
options.setBusyStartedAt(Date.now());
@@ -3989,8 +3857,6 @@ export function createWorkspaceStore(options: {
workspaceConnectionStateById,
exportingWorkspaceConfig,
importingWorkspaceConfig,
migrationRepairBusy,
migrationRepairResult,
selectedWorkspaceInfo,
selectedWorkspaceDisplay,
selectedWorkspacePath,
@@ -4024,8 +3890,6 @@ export function createWorkspaceStore(options: {
pickWorkspaceFolder,
exportWorkspaceConfig,
importWorkspaceConfig,
canRepairOpencodeMigration,
repairOpencodeMigration,
startHost,
stopHost,
reloadWorkspaceEngine,
@@ -4034,7 +3898,6 @@ export function createWorkspaceStore(options: {
onSelectStartup,
onBackToWelcome,
onStartHost,
onRepairOpencodeMigration,
onAttachHost,
onConnectClient,
onRememberStartupToggle,

View File

@@ -864,23 +864,6 @@ export async function setOpenCodeRouterGroupsEnabled(enabled: boolean): Promise<
}
}
export async function opencodeDbMigrate(input: {
projectDir: string;
preferSidecar?: boolean;
opencodeBinPath?: string | null;
}): Promise<ExecResult> {
const safeProjectDir = input.projectDir.trim();
if (!safeProjectDir) {
throw new Error("project_dir is required");
}
return invoke<ExecResult>("opencode_db_migrate", {
projectDir: safeProjectDir,
preferSidecar: input.preferSidecar ?? false,
opencodeBinPath: input.opencodeBinPath ?? null,
});
}
export async function opencodeMcpAuth(
projectDir: string,
serverName: string,

View File

@@ -260,11 +260,6 @@ export type DashboardViewProps = {
sandboxCreateProgressLast: unknown;
clearWorkspaceDebugEvents: () => void;
safeStringify: (value: unknown) => string;
repairOpencodeMigration: () => void;
migrationRepairBusy: boolean;
migrationRepairResult: { ok: boolean; message: string } | null;
migrationRepairAvailable: boolean;
migrationRepairUnavailableReason: string | null;
repairOpencodeCache: () => void;
cacheRepairBusy: boolean;
cacheRepairResult: string | null;
@@ -1385,11 +1380,6 @@ export default function DashboardView(props: DashboardViewProps) {
sandboxCreateProgressLast={props.sandboxCreateProgressLast}
clearWorkspaceDebugEvents={props.clearWorkspaceDebugEvents}
safeStringify={props.safeStringify}
repairOpencodeMigration={props.repairOpencodeMigration}
migrationRepairBusy={props.migrationRepairBusy}
migrationRepairResult={props.migrationRepairResult}
migrationRepairAvailable={props.migrationRepairAvailable}
migrationRepairUnavailableReason={props.migrationRepairUnavailableReason}
repairOpencodeCache={props.repairOpencodeCache}
cacheRepairBusy={props.cacheRepairBusy}
cacheRepairResult={props.cacheRepairResult}

View File

@@ -174,11 +174,6 @@ export type SettingsViewProps = {
sandboxCreateProgressLast: unknown;
clearWorkspaceDebugEvents: () => void;
safeStringify: (value: unknown) => string;
repairOpencodeMigration: () => void;
migrationRepairBusy: boolean;
migrationRepairResult: { ok: boolean; message: string } | null;
migrationRepairAvailable: boolean;
migrationRepairUnavailableReason: string | null;
repairOpencodeCache: () => void;
cacheRepairBusy: boolean;
cacheRepairResult: string | null;
@@ -2380,103 +2375,47 @@ export default function SettingsView(props: SettingsViewProps) {
<Match when={activeTab() === "recovery"}>
<div class="space-y-6">
<div class={`${settingsPanelClass} space-y-4`}>
<div>
<div class="text-sm font-medium text-gray-12">
{translate("settings.migration_recovery_label")}
</div>
<div class="text-xs text-gray-9">
{translate("settings.migration_recovery_hint")}
</div>
<div class={`${settingsPanelClass} space-y-3`}>
<div class="text-sm font-medium text-gray-12">
Workspace config
</div>
<div class="text-xs text-gray-10">
Reveal or reset `.opencode/openwork.json` defaults for this
app workspace.
</div>
<div class="text-[11px] text-gray-7 font-mono break-all">
{workspaceConfigPath() || "No active local workspace."}
</div>
<div class="flex flex-wrap items-center gap-2">
<Button
variant="secondary"
variant="outline"
class="text-xs h-8 py-0 px-3"
onClick={props.repairOpencodeMigration}
onClick={revealWorkspaceConfig}
disabled={
webDeployment() ||
props.busy ||
props.migrationRepairBusy ||
!props.migrationRepairAvailable
!isTauriRuntime() ||
revealConfigBusy() ||
!workspaceConfigPath()
}
title={
webDeployment()
? "Migration repair requires the desktop app."
: (props.migrationRepairUnavailableReason ?? "")
!isTauriRuntime()
? "Reveal config requires the desktop app"
: ""
}
>
{props.migrationRepairBusy
? translate("settings.fixing_migration")
: translate("settings.fix_migration")}
<FolderOpen size={13} class="mr-1.5" />
{revealConfigBusy() ? "Opening..." : "Reveal config"}
</Button>
</div>
<Show when={props.migrationRepairUnavailableReason}>
{(reason) => (
<div class="text-xs text-amber-11">{reason()}</div>
)}
</Show>
<Show when={props.migrationRepairBusy}>
<div class="text-xs text-gray-10">
{translate("status.repairing_migration")}
</div>
</Show>
<Show when={props.migrationRepairResult}>
{(result) => (
<div
class={`rounded-xl border px-3 py-2 text-xs ${
result().ok
? "border-green-7/30 bg-green-2/30 text-green-12"
: "border-red-7/30 bg-red-2/30 text-red-12"
}`}
>
{result().message}
</div>
)}
</Show>
</div>
<div class={`${settingsPanelClass} space-y-3`}>
<div class="text-sm font-medium text-gray-12">
Workspace config
</div>
<div class="text-xs text-gray-10">
Reveal or reset `.opencode/openwork.json` defaults for this
app workspace.
</div>
<div class="text-[11px] text-gray-7 font-mono break-all">
{workspaceConfigPath() || "No active local workspace."}
</div>
<div class="flex flex-wrap items-center gap-2">
<Button
variant="outline"
class="text-xs h-8 py-0 px-3"
onClick={revealWorkspaceConfig}
disabled={
!isTauriRuntime() ||
revealConfigBusy() ||
!workspaceConfigPath()
}
title={
!isTauriRuntime()
? "Reveal config requires the desktop app"
: ""
}
>
<FolderOpen size={13} class="mr-1.5" />
{revealConfigBusy() ? "Opening..." : "Reveal config"}
</Button>
<Button
variant="danger"
class="text-xs h-8 py-0 px-3"
onClick={resetAppConfigDefaults}
disabled={resetConfigBusy() || props.anyActiveRuns}
title={
props.anyActiveRuns
? "Stop active runs before resetting config"
: ""
}
>
<Button
variant="danger"
class="text-xs h-8 py-0 px-3"
onClick={resetAppConfigDefaults}
disabled={resetConfigBusy() || props.anyActiveRuns}
title={
props.anyActiveRuns
? "Stop active runs before resetting config"
: ""
}
>
{resetConfigBusy()
? "Resetting..."
: "Reset config defaults"}

View File

@@ -697,11 +697,6 @@ export default {
"settings.developer_title": "Developer",
"settings.opencode_cache_label": "OpenCode cache",
"settings.opencode_cache_hint": "Repairs cached data used to start the engine. Safe to run.",
"settings.migration_recovery_label": "Migration recovery",
"settings.migration_recovery_hint": "Use this if local startup fails while moving from legacy JSON data.",
"settings.fix_migration": "Fix migration",
"settings.fixing_migration": "Fixing migration...",
"settings.migration_repair_requires_desktop": "Migration repair requires the desktop app",
"settings.pending_permissions_label": "Pending permissions",
"settings.recent_events_label": "Recent events",
"settings.stop_active_runs_hint": "Stop active runs to update",
@@ -775,9 +770,6 @@ export default {
"onboarding.cli_install_commands": "Install OpenCode with one of the commands below, then restart OpenWork.",
"onboarding.show_search_notes": "Show search notes",
"onboarding.last_checked": "Last checked {time}",
"onboarding.fix_migration": "Fix migration",
"onboarding.fixing_migration": "Fixing migration...",
"onboarding.fix_migration_hint": "Stops local engine, runs opencode db migrate, then retries startup.",
"onboarding.server_url_placeholder": "http://localhost:8088",
"onboarding.directory_placeholder": "my-project",
"onboarding.connect_host": "Connect to server",
@@ -847,7 +839,6 @@ export default {
"status.reloading_engine": "Reloading engine",
"status.restarting_engine": "Restarting engine",
"status.installing_opencode": "Installing OpenCode",
"status.repairing_migration": "Repairing migration",
"status.disconnecting": "Disconnecting",
// ==================== Workspace Switching ====================
@@ -868,13 +859,6 @@ export default {
"app.error.host_requires_local": "Select a local workspace to start the engine.",
"app.error.sidecar_unsupported_windows": "Sidecar OpenCode is bundled on Windows when available. Falling back to PATH.",
"app.error.install_failed": "OpenCode install failed. See logs above.",
"app.migration.desktop_required": "Migration repair requires the desktop app.",
"app.migration.local_only": "Migration repair is only available for local workers.",
"app.migration.workspace_required": "Pick a local workspace folder before repairing migration.",
"app.migration.unsupported": "This OpenCode binary does not support `opencode db migrate`. Update to the OpenWork-pinned OpenCode version or switch to bundled engine.",
"app.migration.failed": "OpenCode migration failed.",
"app.migration.restart_failed": "Migration completed, but OpenWork could not restart the local engine.",
"app.migration.success": "Migration repaired. Local startup was retried.",
"app.error.command_name_template_required": "Command name and instructions are required.",
"app.error.workspace_commands_desktop": "Commands require the desktop app.",
"app.error.command_scope_unknown": "This command can't be managed in this mode.",

View File

@@ -679,11 +679,6 @@ export default {
"settings.developer_title": "デベロッパー",
"settings.opencode_cache_label": "OpenCodeキャッシュ",
"settings.opencode_cache_hint": "エンジンの起動に使用されるキャッシュデータを修復します。安全に実行できます。",
"settings.migration_recovery_label": "マイグレーション修復",
"settings.migration_recovery_hint": "レガシーJSONデータからの移行中にローカル起動が失敗した場合に使用してください。",
"settings.fix_migration": "マイグレーションを修正",
"settings.fixing_migration": "マイグレーション修正中...",
"settings.migration_repair_requires_desktop": "マイグレーション修復にはデスクトップアプリが必要です",
"settings.pending_permissions_label": "保留中の権限",
"settings.recent_events_label": "最近のイベント",
"settings.stop_active_runs_hint": "アップデートするにはアクティブな実行を停止してください",
@@ -757,9 +752,6 @@ export default {
"onboarding.cli_install_commands": "以下のコマンドでOpenCodeをインストールしてからOpenWorkを再起動してください。",
"onboarding.show_search_notes": "検索メモを表示",
"onboarding.last_checked": "最終確認 {time}",
"onboarding.fix_migration": "マイグレーションを修正",
"onboarding.fixing_migration": "マイグレーション修正中...",
"onboarding.fix_migration_hint": "ローカルエンジンを停止し、opencode db migrate を実行してから起動を再試行します。",
"onboarding.server_url_placeholder": "http://localhost:8088",
"onboarding.directory_placeholder": "my-project",
"onboarding.connect_host": "サーバーに接続",
@@ -829,7 +821,6 @@ export default {
"status.reloading_engine": "エンジンをリロード中",
"status.restarting_engine": "エンジンを再起動中",
"status.installing_opencode": "OpenCodeをインストール中",
"status.repairing_migration": "マイグレーションを修復中",
"status.disconnecting": "切断中",
// ==================== Workspace Switching ====================
@@ -850,13 +841,6 @@ export default {
"app.error.host_requires_local": "エンジンを起動するにはローカルワーカーを選択してください。",
"app.error.sidecar_unsupported_windows": "サイドカーOpenCodeは利用可能な場合にWindowsにバンドルされます。PATHにフォールバックします。",
"app.error.install_failed": "OpenCodeのインストールに失敗しました。上のログをご確認ください。",
"app.migration.desktop_required": "マイグレーション修復にはデスクトップアプリが必要です。",
"app.migration.local_only": "マイグレーション修復はローカルワーカーでのみ利用可能です。",
"app.migration.workspace_required": "マイグレーション修復の前にローカルワーカーフォルダを選択してください。",
"app.migration.unsupported": "このOpenCodeバイナリは `opencode db migrate` をサポートしていません。OpenWorkで固定しているOpenCodeバージョンへ更新するか、バンドルされたエンジンに切り替えてください。",
"app.migration.failed": "OpenCodeのマイグレーションに失敗しました。",
"app.migration.restart_failed": "マイグレーションは完了しましたが、OpenWorkがローカルエンジンを再起動できませんでした。",
"app.migration.success": "マイグレーションが修復されました。ローカル起動を再試行しました。",
"app.error.command_name_template_required": "コマンド名と手順が必要です。",
"app.error.workspace_commands_desktop": "コマンドにはデスクトップアプリが必要です。",
"app.error.command_scope_unknown": "このモードではこのコマンドを管理できません。",

View File

@@ -680,11 +680,6 @@ export default {
"settings.developer_title": "Desenvolvedor",
"settings.opencode_cache_label": "Cache do OpenCode",
"settings.opencode_cache_hint": "Repara dados em cache usados para iniciar o engine. Seguro de executar.",
"settings.migration_recovery_label": "Recuperação de migração",
"settings.migration_recovery_hint": "Use isso se a inicialização local falhar ao migrar de dados JSON legados.",
"settings.fix_migration": "Corrigir migração",
"settings.fixing_migration": "Corrigindo migração...",
"settings.migration_repair_requires_desktop": "O reparo de migração requer o app desktop",
"settings.pending_permissions_label": "Permissões pendentes",
"settings.recent_events_label": "Eventos recentes",
"settings.stop_active_runs_hint": "Pare as execuções ativas para atualizar",
@@ -758,9 +753,6 @@ export default {
"onboarding.cli_install_commands": "Instale o OpenCode com um dos comandos abaixo e reinicie o OpenWork.",
"onboarding.show_search_notes": "Mostrar notas de busca",
"onboarding.last_checked": "Última verificação {time}",
"onboarding.fix_migration": "Corrigir migração",
"onboarding.fixing_migration": "Corrigindo migração...",
"onboarding.fix_migration_hint": "Para o engine local, executa opencode db migrate e tenta inicializar novamente.",
"onboarding.server_url_placeholder": "http://localhost:8088",
"onboarding.directory_placeholder": "meu-projeto",
"onboarding.connect_host": "Conectar ao servidor",
@@ -830,7 +822,6 @@ export default {
"status.reloading_engine": "Recarregando engine",
"status.restarting_engine": "Reiniciando engine",
"status.installing_opencode": "Instalando OpenCode",
"status.repairing_migration": "Reparando migração",
"status.disconnecting": "Desconectando",
// ==================== Workspace Switching ====================
@@ -851,13 +842,6 @@ export default {
"app.error.host_requires_local": "Selecione um workspace local para iniciar o engine.",
"app.error.sidecar_unsupported_windows": "O OpenCode Sidecar é integrado no Windows quando disponível. Usando PATH como alternativa.",
"app.error.install_failed": "Falha na instalação do OpenCode. Veja os logs acima.",
"app.migration.desktop_required": "O reparo de migração requer o app desktop.",
"app.migration.local_only": "O reparo de migração está disponível apenas para workers locais.",
"app.migration.workspace_required": "Selecione uma pasta de workspace local antes de reparar a migração.",
"app.migration.unsupported": "Este binário do OpenCode não suporta `opencode db migrate`. Atualize o OpenCode para >=1.2.6 ou mude para o engine integrado.",
"app.migration.failed": "Falha na migração do OpenCode.",
"app.migration.restart_failed": "Migração concluída, mas o OpenWork não conseguiu reiniciar o engine local.",
"app.migration.success": "Migração reparada. A inicialização local foi tentada novamente.",
"app.error.command_name_template_required": "O nome e as instruções do comando são obrigatórios.",
"app.error.workspace_commands_desktop": "Comandos requerem o app desktop.",
"app.error.command_scope_unknown": "Este comando não pode ser gerenciado neste modo.",

View File

@@ -658,11 +658,6 @@ export default {
"settings.developer_title": "Nhà phát triển",
"settings.opencode_cache_label": "Bộ nhớ đệm OpenCode",
"settings.opencode_cache_hint": "Sửa dữ liệu đệm dùng để khởi động engine. An toàn để chạy.",
"settings.migration_recovery_label": "Khôi phục di chuyển dữ liệu",
"settings.migration_recovery_hint": "Dùng khi khởi động nội bộ bị lỗi trong lúc chuyển từ dữ liệu JSON cũ.",
"settings.fix_migration": "Sửa di chuyển dữ liệu",
"settings.fixing_migration": "Đang sửa di chuyển dữ liệu...",
"settings.migration_repair_requires_desktop": "Sửa di chuyển dữ liệu yêu cầu ứng dụng desktop",
"settings.pending_permissions_label": "Quyền đang chờ",
"settings.recent_events_label": "Sự kiện gần đây",
"settings.stop_active_runs_hint": "Dừng task đang chạy để cập nhật",
@@ -736,9 +731,6 @@ export default {
"onboarding.cli_install_commands": "Cài đặt OpenCode bằng một trong các lệnh bên dưới, sau đó khởi động lại OpenWork.",
"onboarding.show_search_notes": "Hiện ghi chú tìm kiếm",
"onboarding.last_checked": "Kiểm tra lần cuối {time}",
"onboarding.fix_migration": "Sửa di chuyển dữ liệu",
"onboarding.fixing_migration": "Đang sửa di chuyển dữ liệu...",
"onboarding.fix_migration_hint": "Dừng engine nội bộ, chạy opencode db migrate, sau đó thử khởi động lại.",
"onboarding.server_url_placeholder": "http://localhost:8088",
"onboarding.directory_placeholder": "my-project",
"onboarding.connect_host": "Kết nối máy chủ",
@@ -808,7 +800,6 @@ export default {
"status.reloading_engine": "Đang tải lại engine",
"status.restarting_engine": "Đang khởi động lại engine",
"status.installing_opencode": "Đang cài đặt OpenCode",
"status.repairing_migration": "Đang sửa di chuyển dữ liệu",
"status.disconnecting": "Đang ngắt kết nối",
// ==================== Workspace Switching ====================
@@ -829,13 +820,6 @@ export default {
"app.error.host_requires_local": "Chọn worker nội bộ để khởi động engine.",
"app.error.sidecar_unsupported_windows": "Sidecar OpenCode trên Windows sẽ được đi kèm khi có. Tạm dùng PATH.",
"app.error.install_failed": "Cài đặt OpenCode thất bại. Xem nhật ký ở trên.",
"app.migration.desktop_required": "Sửa di chuyển dữ liệu yêu cầu ứng dụng desktop.",
"app.migration.local_only": "Sửa di chuyển dữ liệu chỉ khả dụng cho worker nội bộ.",
"app.migration.workspace_required": "Chọn thư mục worker nội bộ trước khi sửa di chuyển dữ liệu.",
"app.migration.unsupported": "Bản OpenCode này không hỗ trợ `opencode db migrate`. Hãy cập nhật lên phiên bản OpenCode được OpenWork ghim cố định hoặc chuyển sang engine đi kèm.",
"app.migration.failed": "Di chuyển dữ liệu OpenCode thất bại.",
"app.migration.restart_failed": "Di chuyển dữ liệu hoàn tất, nhưng OpenWork không thể khởi động lại engine nội bộ.",
"app.migration.success": "Đã sửa di chuyển dữ liệu. Đã thử khởi động lại nội bộ.",
"app.error.command_name_template_required": "Tên command và hướng dẫn là bắt buộc.",
"app.error.workspace_commands_desktop": "Commands yêu cầu ứng dụng desktop.",
"app.error.command_scope_unknown": "Không thể quản lý command này trong chế độ hiện tại.",

View File

@@ -619,11 +619,6 @@ export default {
"settings.developer_title": "开发者",
"settings.opencode_cache_label": "OpenCode 缓存",
"settings.opencode_cache_hint": "修复用于启动引擎的缓存数据。安全运行。",
"settings.migration_recovery_label": "迁移修复",
"settings.migration_recovery_hint": "如果本地启动在从旧版 JSON 数据迁移时失败,请使用此操作。",
"settings.fix_migration": "修复迁移",
"settings.fixing_migration": "正在修复迁移...",
"settings.migration_repair_requires_desktop": "迁移修复需要桌面应用",
"settings.pending_permissions_label": "待处理的权限",
"settings.recent_events_label": "最近的事件",
"settings.stop_active_runs_hint": "停止活动运行以更新",
@@ -696,9 +691,6 @@ export default {
"onboarding.cli_install_commands": "使用以下命令之一安装 OpenCode然后重启 OpenWork。",
"onboarding.show_search_notes": "显示搜索说明",
"onboarding.last_checked": "上次检查时间 {time}",
"onboarding.fix_migration": "修复迁移",
"onboarding.fixing_migration": "正在修复迁移...",
"onboarding.fix_migration_hint": "会停止本地引擎,执行 opencode db migrate然后重试启动。",
"onboarding.server_url_placeholder": "http://localhost:8088",
"onboarding.directory_placeholder": "my-project",
"onboarding.connect_host": "连接服务器",
@@ -768,7 +760,6 @@ export default {
"status.reloading_engine": "正在重新加载引擎",
"status.restarting_engine": "正在重启引擎",
"status.installing_opencode": "正在安装 OpenCode",
"status.repairing_migration": "正在修复迁移",
"status.disconnecting": "正在断开连接",
// ==================== Workspace Switching ====================
@@ -789,13 +780,6 @@ export default {
"app.error.host_requires_local": "请先选择本地工作区以启动引擎。",
"app.error.sidecar_unsupported_windows": "Windows 上的 Sidecar OpenCode 可用时会内置。将回退到 PATH。",
"app.error.install_failed": "OpenCode 安装失败。请查看上方日志。",
"app.migration.desktop_required": "迁移修复需要桌面应用。",
"app.migration.local_only": "迁移修复仅适用于本地工作区。",
"app.migration.workspace_required": "请先选择本地工作区文件夹再修复迁移。",
"app.migration.unsupported": "当前 OpenCode 二进制不支持 `opencode db migrate`。请更新到 OpenWork 固定的 OpenCode 版本,或切换为内置引擎。",
"app.migration.failed": "OpenCode 迁移失败。",
"app.migration.restart_failed": "迁移已完成,但 OpenWork 无法重启本地引擎。",
"app.migration.success": "迁移已修复,已重试本地启动。",
"app.error.command_name_template_required": "命令名称和指令为必填项。",
"app.error.workspace_commands_desktop": "命令需要桌面应用。",
"app.error.command_scope_unknown": "此命令无法在当前模式下管理。",

View File

@@ -474,38 +474,6 @@ pub fn nuke_openwork_and_opencode_config_and_exit(
Ok(())
}
#[tauri::command]
pub fn opencode_db_migrate(
app: AppHandle,
project_dir: String,
prefer_sidecar: Option<bool>,
opencode_bin_path: Option<String>,
) -> Result<ExecResult, String> {
let project_dir = validate_project_dir(&app, &project_dir)?;
let program =
resolve_opencode_program(&app, prefer_sidecar.unwrap_or(false), opencode_bin_path)?;
let mut command = command_for_program(&program);
for (key, value) in crate::bun_env::bun_env_overrides() {
command.env(key, value);
}
let output = command
.arg("db")
.arg("migrate")
.current_dir(&project_dir)
.output()
.map_err(|e| format!("Failed to run opencode db migrate: {e}"))?;
let status = output.status.code().unwrap_or(-1);
Ok(ExecResult {
ok: output.status.success(),
status,
stdout: String::from_utf8_lossy(&output.stdout).to_string(),
stderr: String::from_utf8_lossy(&output.stderr).to_string(),
})
}
/// Run `opencode mcp auth <server_name>` in the given project directory.
/// This spawns the process detached so the OAuth flow can open a browser.
#[tauri::command]

View File

@@ -24,8 +24,8 @@ use commands::engine::{
engine_doctor, engine_info, engine_install, engine_restart, engine_start, engine_stop,
};
use commands::misc::{
app_build_info, nuke_openwork_and_opencode_config_and_exit, opencode_db_migrate,
opencode_mcp_auth, reset_opencode_cache, reset_openwork_state,
app_build_info, nuke_openwork_and_opencode_config_and_exit, opencode_mcp_auth,
reset_opencode_cache, reset_openwork_state,
};
use commands::opencode_router::{
opencodeRouter_config_set, opencodeRouter_info, opencodeRouter_start, opencodeRouter_status,
@@ -47,9 +47,8 @@ use commands::window::set_window_decorations;
use commands::workspace::{
workspace_add_authorized_root, workspace_bootstrap, workspace_create, workspace_create_remote,
workspace_export_config, workspace_forget, workspace_import_config, workspace_openwork_read,
workspace_openwork_write, workspace_set_active, workspace_set_runtime_active, workspace_set_selected,
workspace_update_display_name,
workspace_update_remote,
workspace_openwork_write, workspace_set_active, workspace_set_runtime_active,
workspace_set_selected, workspace_update_display_name, workspace_update_remote,
};
use engine::manager::EngineManager;
use opencode_router::manager::OpenCodeRouterManager;
@@ -217,7 +216,6 @@ pub fn run() {
nuke_openwork_and_opencode_config_and_exit,
reset_openwork_state,
reset_opencode_cache,
opencode_db_migrate,
opencode_mcp_auth,
scheduler_list_jobs,
scheduler_delete_job,