diff --git a/packages/core/src/agents/acknowledgedAgents.test.ts b/packages/core/src/agents/acknowledgedAgents.test.ts index f6e45360db..6fc8a6437a 100644 --- a/packages/core/src/agents/acknowledgedAgents.test.ts +++ b/packages/core/src/agents/acknowledgedAgents.test.ts @@ -94,4 +94,13 @@ describe('AcknowledgedAgentsService', () => { false, ); }); + + it('should compute consistent hashes', () => { + const content = 'some content'; + const hash = AcknowledgedAgentsService.computeHash(content); + expect(hash).toBe(AcknowledgedAgentsService.computeHash(content)); + expect(hash).not.toBe( + AcknowledgedAgentsService.computeHash('other content'), + ); + }); }); diff --git a/packages/core/src/agents/acknowledgedAgents.ts b/packages/core/src/agents/acknowledgedAgents.ts index 230b62443a..ace8968b2b 100644 --- a/packages/core/src/agents/acknowledgedAgents.ts +++ b/packages/core/src/agents/acknowledgedAgents.ts @@ -6,6 +6,7 @@ import * as fs from 'node:fs/promises'; import * as path from 'node:path'; +import * as crypto from 'node:crypto'; import { Storage } from '../config/storage.js'; import { debugLogger } from '../utils/debugLogger.js'; import { getErrorMessage, isNodeError } from '../utils/errors.js'; @@ -21,6 +22,10 @@ export class AcknowledgedAgentsService { private acknowledgedAgents: AcknowledgedAgentsMap = {}; private loaded = false; + static computeHash(content: string): string { + return crypto.createHash('sha256').update(content).digest('hex'); + } + async load(): Promise { if (this.loaded) return; diff --git a/packages/core/src/agents/agentLoader.ts b/packages/core/src/agents/agentLoader.ts index 1679b52fb3..f0a77522b5 100644 --- a/packages/core/src/agents/agentLoader.ts +++ b/packages/core/src/agents/agentLoader.ts @@ -8,8 +8,8 @@ import yaml from 'js-yaml'; import * as fs from 'node:fs/promises'; import { type Dirent } from 'node:fs'; import * as path from 'node:path'; -import * as crypto from 'node:crypto'; import { z } from 'zod'; +import { AcknowledgedAgentsService } from './acknowledgedAgents.js'; import type { AgentDefinition } from './types.js'; import { isValidToolName } from '../tools/tool-names.js'; import { FRONTMATTER_REGEX } from '../skills/skillLoader.js'; @@ -347,7 +347,7 @@ export async function loadAgentsFromDirectory( const filePath = path.join(dir, entry.name); try { const content = await fs.readFile(filePath, 'utf-8'); - const hash = crypto.createHash('sha256').update(content).digest('hex'); + const hash = AcknowledgedAgentsService.computeHash(content); const agentDefs = await parseAgentMarkdown(filePath, content); for (const def of agentDefs) { const agent = markdownToAgentDefinition(def, { hash, filePath }); diff --git a/packages/test-utils/src/test-rig.ts b/packages/test-utils/src/test-rig.ts index 61d69dcbb3..8d796536c8 100644 --- a/packages/test-utils/src/test-rig.ts +++ b/packages/test-utils/src/test-rig.ts @@ -17,7 +17,6 @@ import { AcknowledgedAgentsService, } from '@google/gemini-cli-core'; import fs from 'node:fs'; -import crypto from 'node:crypto'; import * as pty from '@lydell/node-pty'; import stripAnsi from 'strip-ansi'; import * as os from 'node:os'; @@ -370,7 +369,7 @@ export class TestRig { try { const service = new AcknowledgedAgentsService(); for (const [name, content] of Object.entries(agents)) { - const hash = crypto.createHash('sha256').update(content).digest('hex'); + const hash = AcknowledgedAgentsService.computeHash(content); await service.acknowledge(projectRoot, name, hash); } } finally {