Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
965ca5a
feat(rewind): add file restoration support to /rewind command (#3697)
doudouOUC May 11, 2026
cd29277
fix(rewind): replace findLast with reverse loop for ES2022 compat
doudouOUC May 11, 2026
1b7192e
fix(rewind): add missing i18n translations and fix test expectation
doudouOUC May 11, 2026
6de02c2
fix(rewind): add getFileHistoryService mock to tool tests
doudouOUC May 11, 2026
6e7d445
fix(rewind): allow Esc during diff loading and add missing i18n foote…
doudouOUC May 11, 2026
bcfe0ba
fix(rewind): address review feedback — restoreBackup correctness, mis…
doudouOUC May 12, 2026
f12dcf2
fix(rewind): correct diff direction, truncate snapshots on rewind, ad…
doudouOUC May 12, 2026
dcf76d3
test(tools): assert trackEdit is called before file writes
doudouOUC May 12, 2026
b7517ec
fix(i18n): add missing rewind UI locale keys across all 9 locales
doudouOUC May 12, 2026
3edc484
fix(core): reset fileHistoryService on session change, clean up dead …
doudouOUC May 12, 2026
4d04582
fix(rewind): validate conversation before file restore, preserve snap…
doudouOUC May 13, 2026
7debc1b
fix: correct trackEdit race comment — overwrite not orphan
doudouOUC May 13, 2026
dc96cf5
fix(types): use HistoryItemWithoutId for addItem to preserve union me…
doudouOUC May 13, 2026
67148d7
fix(types): revert addItem type change, use cast at call site for pro…
doudouOUC May 13, 2026
b3fcc97
fix(rewind): guard onRewind calls with .catch() to prevent unhandled …
doudouOUC May 13, 2026
6942d1c
fix(rewind): only truncate snapshot timeline when conversation trunca…
doudouOUC May 13, 2026
73eefde
fix(rewind): address tanzhenxin review - gate, partial failure, tests
doudouOUC May 13, 2026
c0e26f8
fix(rewind): defensive trackEdit + fix version collision on re-track
doudouOUC May 13, 2026
66ce09f
fix(rewind): add missing i18n keys + fix makeSnapshot version collision
doudouOUC May 13, 2026
750c4df
fix(rewind): set hasRestoreFailure when promptId is missing
doudouOUC May 13, 2026
4fc6a83
fix(rewind): show loading state during async restore, close selector …
doudouOUC May 14, 2026
a569e33
fix(rewind): skip timeline truncation on partial failure + fix wording
doudouOUC May 14, 2026
34d355a
fix(rewind): address review — TOCTOU in createBackup + outer catch in…
doudouOUC May 14, 2026
5415b7d
test(rewind): cover restoreFromSnapshots, trackEdit no-snapshot path,…
doudouOUC May 14, 2026
3b12022
fix(rewind): clean up orphaned backups, surface no-client states, polish
doudouOUC May 15, 2026
1db8429
fix(rewind): use path separator constant in maybeShortenFilePath
doudouOUC May 15, 2026
e56caa3
Merge remote-tracking branch 'origin/main' into feat/file-history-rewind
doudouOUC May 15, 2026
ceb2e7c
test(rewind): cover trackEdit best-effort guarantees and unchanged-fi…
doudouOUC May 15, 2026
91fc811
fix(rewind): align fileCheckpointing default + surface backup-missing…
doudouOUC May 16, 2026
d598383
fix(rewind): mark per-file backup failures so rewind surfaces them
doudouOUC May 16, 2026
22d5969
fix(rewind): polish — i18n, type tightening, resumed-session UX hint
doudouOUC May 16, 2026
ac07f63
fix(rewind): unstick failed marker on the unchanged-file fast path
doudouOUC May 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions packages/cli/src/i18n/locales/ca.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,46 @@ export default {
'Canviar el nom de la conversa actual. --auto permet que el model ràpid triï un títol.',
'Rewind conversation to a previous turn':
'Rebobinar la conversa fins a un torn anterior',
'Rewind Conversation': 'Rebobinar la conversa',
'No user turns to rewind to.': "No hi ha torns d'usuari per rebobinar.",
'Rewind to: ': 'Rebobinar a: ',
'Restore code and conversation': 'Restaura el codi i la conversa',
'Restore conversation only': 'Restaura només la conversa',
'Restore code only': 'Restaura només el codi',
'Never mind': 'Tant és',
'Computing file changes...': "S'estan calculant els canvis als fitxers...",
'Restoring...': "S'està restaurant...",
'Restored {{count}} file(s).': "S'han restaurat {{count}} fitxer(s).",
'Failed to restore files: {{error}}':
'Error en restaurar els fitxers: {{error}}',
'Rewind failed: {{error}}': 'Error en retrocedir: {{error}}',
'Cannot rewind conversation: no active model client.':
'No es pot retrocedir la conversa: cap client de model actiu.',
'Code restored, but conversation could not be rewound (no active client).':
'Codi restaurat, però la conversa no s’ha pogut retrocedir (cap client actiu).',
'Conversation rewound. Edit your prompt and press Enter to continue.':
'Conversa retrocedida. Edita la teva indicació i prem Retorn per continuar.',
'Rewinding does not affect files edited manually or via shell commands.':
'El retrocés no afecta els fitxers editats manualment o mitjançant comandes de shell.',
'Cannot rewind to a turn that was compressed. Try a more recent turn.':
'No es pot retrocedir a un torn que ha estat comprimit. Prova amb un torn més recent.',
'File restore is unavailable for this turn (no captured file changes, or this turn predates the current session).':
'La restauració de fitxers no està disponible per a aquest torn (no s’han capturat canvis, o aquest torn és anterior a la sessió actual).',
'(+{{insertions}} -{{deletions}} in {{count}} file)':
'(+{{insertions}} -{{deletions}} en {{count}} fitxer)',
'(+{{insertions}} -{{deletions}} in {{count}} files)':
'(+{{insertions}} -{{deletions}} en {{count}} fitxers)',
'Failed to restore {{count}} file(s): {{files}}':
'Error en restaurar {{count}} fitxer(s): {{files}}',
'Cannot restore files: this turn was created before file checkpointing was enabled.':
'No es poden restaurar els fitxers: aquest torn es va crear abans que el punt de control de fitxers estigués habilitat.',
'No files needed to be restored.': 'Cap fitxer necessitava restauració.',
'↑↓ to navigate · Enter to select · Esc to go back':
'↑↓ per navegar · Enter per seleccionar · Esc per tornar',
'↑↓ to navigate · Enter to select · Esc to cancel':
'↑↓ per navegar · Enter per seleccionar · Esc per cancel·lar',
'Enter/Y to confirm · Esc/N to go back':
'Enter/Y per confirmar · Esc/N per tornar',
'change the theme': 'canviar el tema',
'Select Theme': 'Seleccionar tema',
Preview: 'Previsualització',
Expand Down
40 changes: 40 additions & 0 deletions packages/cli/src/i18n/locales/de.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,46 @@ export default {
'Die aktuelle Unterhaltung umbenennen. Mit --auto lässt du das schnelle Modell einen Titel wählen.',
'Rewind conversation to a previous turn':
'Die Unterhaltung auf einen früheren Gesprächsschritt zurücksetzen',
'Rewind Conversation': 'Unterhaltung zurückspulen',
'No user turns to rewind to.': 'Keine Benutzerrunden zum Zurückspulen.',
'Rewind to: ': 'Zurückspulen zu: ',
'Restore code and conversation': 'Code und Unterhaltung wiederherstellen',
'Restore conversation only': 'Nur Unterhaltung wiederherstellen',
'Restore code only': 'Nur Code wiederherstellen',
'Never mind': 'Egal',
'Computing file changes...': 'Dateiänderungen werden berechnet...',
'Restoring...': 'Wiederherstellung läuft...',
'Restored {{count}} file(s).': '{{count}} Datei(en) wiederhergestellt.',
'Failed to restore files: {{error}}':
'Fehler beim Wiederherstellen der Dateien: {{error}}',
'Rewind failed: {{error}}': 'Zurückspulen fehlgeschlagen: {{error}}',
'Cannot rewind conversation: no active model client.':
'Konversation kann nicht zurückgespult werden: kein aktiver Modell-Client.',
'Code restored, but conversation could not be rewound (no active client).':
'Code wiederhergestellt, aber Konversation konnte nicht zurückgespult werden (kein aktiver Client).',
'Conversation rewound. Edit your prompt and press Enter to continue.':
'Konversation zurückgespult. Bearbeite deinen Prompt und drücke Enter, um fortzufahren.',
'Rewinding does not affect files edited manually or via shell commands.':
'Das Zurückspulen wirkt sich nicht auf Dateien aus, die manuell oder per Shell-Befehl geändert wurden.',
'Cannot rewind to a turn that was compressed. Try a more recent turn.':
'Zu einem komprimierten Turn kann nicht zurückgespult werden. Bitte einen aktuelleren Turn versuchen.',
'File restore is unavailable for this turn (no captured file changes, or this turn predates the current session).':
'Datei-Wiederherstellung ist für diesen Turn nicht verfügbar (keine erfassten Dateiänderungen, oder dieser Turn liegt vor der aktuellen Sitzung).',
'(+{{insertions}} -{{deletions}} in {{count}} file)':
'(+{{insertions}} -{{deletions}} in {{count}} Datei)',
'(+{{insertions}} -{{deletions}} in {{count}} files)':
'(+{{insertions}} -{{deletions}} in {{count}} Dateien)',
'Failed to restore {{count}} file(s): {{files}}':
'{{count}} Datei(en) konnten nicht wiederhergestellt werden: {{files}}',
'Cannot restore files: this turn was created before file checkpointing was enabled.':
'Dateien können nicht wiederhergestellt werden: Dieser Turn wurde erstellt, bevor Datei-Checkpointing aktiviert war.',
'No files needed to be restored.':
'Keine Dateien mussten wiederhergestellt werden.',
'↑↓ to navigate · Enter to select · Esc to go back':
'↑↓ navigieren · Enter auswählen · Esc zurück',
'↑↓ to navigate · Enter to select · Esc to cancel':
'↑↓ navigieren · Enter auswählen · Esc abbrechen',
'Enter/Y to confirm · Esc/N to go back': 'Enter/Y bestätigen · Esc/N zurück',
'change the theme': 'Design ändern',
'Select Theme': 'Design auswählen',
Preview: 'Vorschau',
Expand Down
39 changes: 39 additions & 0 deletions packages/cli/src/i18n/locales/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,45 @@ export default {
'Rename the current conversation. --auto lets the fast model pick a title.',
'Rewind conversation to a previous turn':
'Rewind conversation to a previous turn',
'Rewind Conversation': 'Rewind Conversation',
'No user turns to rewind to.': 'No user turns to rewind to.',
'Rewind to: ': 'Rewind to: ',
'Restore code and conversation': 'Restore code and conversation',
'Restore conversation only': 'Restore conversation only',
'Restore code only': 'Restore code only',
'Never mind': 'Never mind',
'Computing file changes...': 'Computing file changes...',
'Restoring...': 'Restoring...',
'Restored {{count}} file(s).': 'Restored {{count}} file(s).',
'Failed to restore files: {{error}}': 'Failed to restore files: {{error}}',
'Rewind failed: {{error}}': 'Rewind failed: {{error}}',
'Cannot rewind conversation: no active model client.':
'Cannot rewind conversation: no active model client.',
'Code restored, but conversation could not be rewound (no active client).':
'Code restored, but conversation could not be rewound (no active client).',
'Conversation rewound. Edit your prompt and press Enter to continue.':
'Conversation rewound. Edit your prompt and press Enter to continue.',
'Rewinding does not affect files edited manually or via shell commands.':
'Rewinding does not affect files edited manually or via shell commands.',
'Cannot rewind to a turn that was compressed. Try a more recent turn.':
'Cannot rewind to a turn that was compressed. Try a more recent turn.',
'File restore is unavailable for this turn (no captured file changes, or this turn predates the current session).':
'File restore is unavailable for this turn (no captured file changes, or this turn predates the current session).',
'(+{{insertions}} -{{deletions}} in {{count}} file)':
'(+{{insertions}} -{{deletions}} in {{count}} file)',
'(+{{insertions}} -{{deletions}} in {{count}} files)':
'(+{{insertions}} -{{deletions}} in {{count}} files)',
'Failed to restore {{count}} file(s): {{files}}':
'Failed to restore {{count}} file(s): {{files}}',
'Cannot restore files: this turn was created before file checkpointing was enabled.':
'Cannot restore files: this turn was created before file checkpointing was enabled.',
'No files needed to be restored.': 'No files needed to be restored.',
'↑↓ to navigate · Enter to select · Esc to go back':
'↑↓ to navigate · Enter to select · Esc to go back',
'↑↓ to navigate · Enter to select · Esc to cancel':
'↑↓ to navigate · Enter to select · Esc to cancel',
'Enter/Y to confirm · Esc/N to go back':
'Enter/Y to confirm · Esc/N to go back',
'change the theme': 'change the theme',
'Select Theme': 'Select Theme',
Preview: 'Preview',
Expand Down
41 changes: 41 additions & 0 deletions packages/cli/src/i18n/locales/fr.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,47 @@ export default {
'Renommer la conversation en cours. --auto laisse le modèle rapide choisir un titre.',
'Rewind conversation to a previous turn':
'Revenir à un tour précédent de la conversation',
'Rewind Conversation': 'Rembobiner la conversation',
'No user turns to rewind to.':
'Aucun tour utilisateur vers lequel rembobiner.',
'Rewind to: ': 'Rembobiner vers : ',
'Restore code and conversation': 'Restaurer le code et la conversation',
'Restore conversation only': 'Restaurer la conversation uniquement',
'Restore code only': 'Restaurer le code uniquement',
'Never mind': 'Annuler',
'Computing file changes...': 'Calcul des modifications de fichiers...',
'Restoring...': 'Restauration en cours...',
'Restored {{count}} file(s).': '{{count}} fichier(s) restauré(s).',
'Failed to restore files: {{error}}':
'Échec de la restauration des fichiers : {{error}}',
'Rewind failed: {{error}}': 'Échec du retour en arrière : {{error}}',
'Cannot rewind conversation: no active model client.':
'Impossible de revenir en arrière sur la conversation : aucun client de modèle actif.',
'Code restored, but conversation could not be rewound (no active client).':
'Code restauré, mais la conversation n’a pas pu être ramenée en arrière (aucun client actif).',
'Conversation rewound. Edit your prompt and press Enter to continue.':
'Conversation ramenée en arrière. Modifiez votre invite et appuyez sur Entrée pour continuer.',
'Rewinding does not affect files edited manually or via shell commands.':
'Le retour en arrière n’affecte pas les fichiers édités manuellement ou via des commandes shell.',
'Cannot rewind to a turn that was compressed. Try a more recent turn.':
'Impossible de revenir à un tour qui a été compressé. Essayez un tour plus récent.',
'File restore is unavailable for this turn (no captured file changes, or this turn predates the current session).':
'La restauration des fichiers est indisponible pour ce tour (aucune modification capturée, ou ce tour est antérieur à la session actuelle).',
'(+{{insertions}} -{{deletions}} in {{count}} file)':
'(+{{insertions}} -{{deletions}} dans {{count}} fichier)',
'(+{{insertions}} -{{deletions}} in {{count}} files)':
'(+{{insertions}} -{{deletions}} dans {{count}} fichiers)',
'Failed to restore {{count}} file(s): {{files}}':
'Échec de la restauration de {{count}} fichier(s) : {{files}}',
'Cannot restore files: this turn was created before file checkpointing was enabled.':
"Impossible de restaurer les fichiers : ce tour a été créé avant l'activation des points de contrôle de fichiers.",
'No files needed to be restored.':
"Aucun fichier n'a eu besoin d'être restauré.",
'↑↓ to navigate · Enter to select · Esc to go back':
'↑↓ naviguer · Enter sélectionner · Esc retour',
'↑↓ to navigate · Enter to select · Esc to cancel':
'↑↓ naviguer · Enter sélectionner · Esc annuler',
'Enter/Y to confirm · Esc/N to go back': 'Enter/Y confirmer · Esc/N retour',
'change the theme': 'changer le thème',
'Select Theme': 'Sélectionner un thème',
Preview: 'Aperçu',
Expand Down
39 changes: 39 additions & 0 deletions packages/cli/src/i18n/locales/ja.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,45 @@ export default {
'Rename the current conversation. --auto lets the fast model pick a title.':
'現在の会話の名前を変更する。--auto を使うと高速モデルがタイトルを決めます。',
'Rewind conversation to a previous turn': '会話を前のターンまで巻き戻す',
'Rewind Conversation': '会話を巻き戻す',
'No user turns to rewind to.': '巻き戻せるユーザーターンがありません。',
'Rewind to: ': '巻き戻し先:',
'Restore code and conversation': 'コードと会話を復元',
'Restore conversation only': '会話のみ復元',
'Restore code only': 'コードのみ復元',
'Never mind': 'やめる',
'Computing file changes...': 'ファイルの変更を計算中...',
'Restoring...': '復元中...',
'Restored {{count}} file(s).': '{{count}} 個のファイルを復元しました。',
'Failed to restore files: {{error}}':
'ファイルの復元に失敗しました:{{error}}',
'Rewind failed: {{error}}': '巻き戻しに失敗しました:{{error}}',
'Cannot rewind conversation: no active model client.':
'会話を巻き戻せません:アクティブなモデルクライアントがありません。',
'Code restored, but conversation could not be rewound (no active client).':
'コードは復元されましたが、会話は巻き戻せませんでした(モデルクライアントがアクティブではありません)。',
'Conversation rewound. Edit your prompt and press Enter to continue.':
'会話を巻き戻しました。プロンプトを編集して Enter キーで続行してください。',
'Rewinding does not affect files edited manually or via shell commands.':
'巻き戻しは、手動で編集されたファイルや shell コマンドで変更されたファイルには影響しません。',
'Cannot rewind to a turn that was compressed. Try a more recent turn.':
'圧縮されたターンへは巻き戻せません。より最近のターンをお試しください。',
'File restore is unavailable for this turn (no captured file changes, or this turn predates the current session).':
'このターンではファイル復元できません(捕捉されたファイル変更がないか、現在のセッションより前のターンです)。',
'(+{{insertions}} -{{deletions}} in {{count}} file)':
'(+{{insertions}} -{{deletions}}、{{count}} 個のファイル)',
'(+{{insertions}} -{{deletions}} in {{count}} files)':
'(+{{insertions}} -{{deletions}}、{{count}} 個のファイル)',
'Failed to restore {{count}} file(s): {{files}}':
'{{count}} 個のファイルの復元に失敗しました:{{files}}',
'Cannot restore files: this turn was created before file checkpointing was enabled.':
'ファイルを復元できません:このターンはファイルチェックポイントが有効になる前に作成されました。',
'No files needed to be restored.': '復元が必要なファイルはありません。',
'↑↓ to navigate · Enter to select · Esc to go back':
'↑↓ 移動 · Enter 選択 · Esc 戻る',
'↑↓ to navigate · Enter to select · Esc to cancel':
'↑↓ 移動 · Enter 選択 · Esc キャンセル',
'Enter/Y to confirm · Esc/N to go back': 'Enter/Y 確認 · Esc/N 戻る',
'change the theme': 'テーマを変更',
'Select Theme': 'テーマを選択',
Preview: 'プレビュー',
Expand Down
39 changes: 39 additions & 0 deletions packages/cli/src/i18n/locales/pt.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,45 @@ export default {
'Renomear a conversa atual. --auto permite que o modelo rápido escolha um título.',
'Rewind conversation to a previous turn':
'Voltar a conversa para um turno anterior',
'Rewind Conversation': 'Rebobinar conversa',
'No user turns to rewind to.': 'Nenhum turno de usuário para rebobinar.',
'Rewind to: ': 'Rebobinar para: ',
'Restore code and conversation': 'Restaurar código e conversa',
'Restore conversation only': 'Restaurar apenas a conversa',
'Restore code only': 'Restaurar apenas o código',
'Never mind': 'Deixa pra lá',
'Computing file changes...': 'Calculando alterações de arquivo...',
'Restoring...': 'Restaurando...',
'Restored {{count}} file(s).': '{{count}} arquivo(s) restaurado(s).',
'Failed to restore files: {{error}}':
'Falha ao restaurar arquivos: {{error}}',
'Rewind failed: {{error}}': 'Falha ao retroceder: {{error}}',
'Cannot rewind conversation: no active model client.':
'Não é possível retroceder a conversa: nenhum cliente de modelo ativo.',
'Code restored, but conversation could not be rewound (no active client).':
'Código restaurado, mas a conversa não pôde ser retrocedida (sem cliente ativo).',
'Conversation rewound. Edit your prompt and press Enter to continue.':
'Conversa retrocedida. Edite seu prompt e pressione Enter para continuar.',
'Rewinding does not affect files edited manually or via shell commands.':
'O retrocesso não afeta arquivos editados manualmente ou por meio de comandos shell.',
'Cannot rewind to a turn that was compressed. Try a more recent turn.':
'Não é possível retroceder para um turno que foi compactado. Tente um turno mais recente.',
'File restore is unavailable for this turn (no captured file changes, or this turn predates the current session).':
'A restauração de arquivos não está disponível para este turno (sem alterações capturadas, ou o turno é anterior à sessão atual).',
'(+{{insertions}} -{{deletions}} in {{count}} file)':
'(+{{insertions}} -{{deletions}} em {{count}} arquivo)',
'(+{{insertions}} -{{deletions}} in {{count}} files)':
'(+{{insertions}} -{{deletions}} em {{count}} arquivos)',
'Failed to restore {{count}} file(s): {{files}}':
'Falha ao restaurar {{count}} arquivo(s): {{files}}',
'Cannot restore files: this turn was created before file checkpointing was enabled.':
'Não é possível restaurar arquivos: este turno foi criado antes do checkpoint de arquivos ser ativado.',
'No files needed to be restored.': 'Nenhum arquivo precisou ser restaurado.',
'↑↓ to navigate · Enter to select · Esc to go back':
'↑↓ navegar · Enter selecionar · Esc voltar',
'↑↓ to navigate · Enter to select · Esc to cancel':
'↑↓ navegar · Enter selecionar · Esc cancelar',
'Enter/Y to confirm · Esc/N to go back': 'Enter/Y confirmar · Esc/N voltar',
'change the theme': 'alterar o tema',
'Select Theme': 'Selecionar Tema',
Preview: 'Visualizar',
Expand Down
Loading
Loading