diff --git a/package.json b/package.json index d848a81bf8c..62e4ac826fa 100644 --- a/package.json +++ b/package.json @@ -79,12 +79,12 @@ "json": "^11.0.0", "lodash": "^4.17.21", "memfs": "^4.17.2", + "mnemonist": "^0.40.3", "mock-fs": "^5.5.0", "prettier": "^3.5.3", "react-devtools-core": "^4.28.5", "typescript-eslint": "^8.30.1", "vitest": "^3.2.4", - "yargs": "^17.7.2", - "mnemonist": "^0.40.3" + "yargs": "^17.7.2" } } diff --git a/packages/cli/src/ui/commands/restoreCommand.test.ts b/packages/cli/src/ui/commands/restoreCommand.test.ts index 23f7149918a..cf8e7baca55 100644 --- a/packages/cli/src/ui/commands/restoreCommand.test.ts +++ b/packages/cli/src/ui/commands/restoreCommand.test.ts @@ -213,7 +213,7 @@ describe('restoreCommand', () => { type: 'message', messageType: 'error', // A more specific error message would be ideal, but for now, we can assert the current behavior. - content: expect.stringContaining('Could not read restorable tool calls.'), + content: 'Checkpoint file is missing toolCall data.', }); }); diff --git a/packages/cli/src/ui/commands/restoreCommand.ts b/packages/cli/src/ui/commands/restoreCommand.ts index 84259288dcc..f89fb2a3aab 100644 --- a/packages/cli/src/ui/commands/restoreCommand.ts +++ b/packages/cli/src/ui/commands/restoreCommand.ts @@ -13,6 +13,7 @@ import { CommandKind, } from './types.js'; import { Config } from '@google/gemini-cli-core'; +import { z } from 'zod'; async function restoreAction( context: CommandContext, @@ -76,7 +77,27 @@ async function restoreAction( const filePath = path.join(checkpointDir, selectedFile); const data = await fs.readFile(filePath, 'utf-8'); - const toolCallData = JSON.parse(data); + const parsedData = JSON.parse(data); + + const toolCallDataSchema = z.object({ + history: z.array(z.any()).optional(), + clientHistory: z.array(z.any()).optional(), + commitHash: z.string().optional(), + toolCall: z.object({ + name: z.string(), + args: z.any(), + }).optional(), + }); + + const toolCallData = toolCallDataSchema.parse(parsedData); + + if (!toolCallData.toolCall) { + return { + type: 'message', + messageType: 'error', + content: 'Checkpoint file is missing toolCall data.', + }; + } if (toolCallData.history) { if (!loadHistory) { diff --git a/packages/core/src/utils/errors.test.ts b/packages/core/src/utils/errors.test.ts index ec42a3f954f..67362d48cc6 100644 --- a/packages/core/src/utils/errors.test.ts +++ b/packages/core/src/utils/errors.test.ts @@ -4,7 +4,7 @@ import { BadRequestError, UnauthorizedError, ForbiddenError, -} from './errors'; +} from './errors.js'; describe('toFriendlyError', () => { it('should return the original error if it is not an object', () => {