Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 6 additions & 11 deletions genkit-tools/cli/src/commands/init-ai-tools/ai-tools/claude.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ import { AIToolConfigResult, AIToolModule, InitConfigOptions } from '../types';
import {
GENKIT_PROMPT_PATH,
calculateHash,
getGenkitContext,
initOrReplaceFile,
initGenkitFile,
updateContentInPlace,
} from '../utils';

Expand Down Expand Up @@ -55,7 +54,7 @@ export const claude: AIToolModule = {
// File doesn't exist or is invalid JSON, start fresh
}

// Check if firebase server already exists
// Check if genkit server already exists
if (!existingConfig.mcpServers?.genkit) {
if (!existingConfig.mcpServers) {
existingConfig.mcpServers = {};
Expand All @@ -71,19 +70,15 @@ export const claude: AIToolModule = {
files.push({ path: CLAUDE_MCP_PATH, updated: settingsUpdated });

logger.info('Copying the Genkit context to GENKIT.md...');
const genkitContext = getGenkitContext();
const { updated: genkitContextUpdated } = await initOrReplaceFile(
GENKIT_PROMPT_PATH,
genkitContext
);
files.push({ path: GENKIT_PROMPT_PATH, updated: genkitContextUpdated });
const mdResult = await initGenkitFile();
files.push({ path: GENKIT_PROMPT_PATH, updated: mdResult.updated });

logger.info('Updating CLAUDE.md to include Genkit context...');
const claudeImportTag = `\nGenkit Framework Instructions:\n - @GENKIT.md\n`;
const claudeImportTag = `\nGenkit Framework Instructions:\n - @./GENKIT.md\n`;
const baseResult = await updateContentInPlace(
CLAUDE_PROMPT_PATH,
claudeImportTag,
{ hash: calculateHash(genkitContext) }
{ hash: calculateHash(mdResult.hash) }
);

files.push({ path: CLAUDE_PROMPT_PATH, updated: baseResult.updated });
Expand Down
10 changes: 3 additions & 7 deletions genkit-tools/cli/src/commands/init-ai-tools/ai-tools/cursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import * as path from 'path';
import { AIToolConfigResult, AIToolModule, InitConfigOptions } from '../types';
import {
GENKIT_PROMPT_PATH,
getGenkitContext,
initGenkitFile,
initOrReplaceFile,
} from '../utils';

Expand Down Expand Up @@ -57,12 +57,8 @@ export const cursor: AIToolModule = {

// Create the base GENKIT context file (GENKIT.md).
// This file contains fundamental details about the GENKIT project.
const genkitContext = getGenkitContext();
const baseResult = await initOrReplaceFile(
GENKIT_PROMPT_PATH,
genkitContext
);
files.push({ path: GENKIT_PROMPT_PATH, updated: baseResult.updated });
const mdResult = await initGenkitFile();
files.push({ path: GENKIT_PROMPT_PATH, updated: mdResult.updated });

// Handle MCP configuration - merge with existing if present.
// This allows Cursor to communicate with Genkit tools.
Expand Down
159 changes: 122 additions & 37 deletions genkit-tools/cli/src/commands/init-ai-tools/ai-tools/gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,25 @@
*/

import { logger } from '@genkit-ai/tools-common/utils';
import { mkdir } from 'fs/promises';
import { select } from '@inquirer/prompts';
import { existsSync, readFileSync } from 'fs';
import { mkdir, writeFile } from 'fs/promises';
import path from 'path';
import { AIToolConfigResult, AIToolModule, InitConfigOptions } from '../types';
import {
GENKIT_PROMPT_PATH,
getGenkitContext,
initGenkitFile,
initOrReplaceFile,
updateContentInPlace,
} from '../utils';

// Define constants at the module level for clarity and reuse.
const GENKIT_EXT_DIR = path.join('.gemini', 'extensions', 'genkit');
// GEMINI specific paths
const GEMINI_DIR = '.gemini';
const GEMINI_SETTINGS_PATH = path.join(GEMINI_DIR, 'settings.json');
const GEMINI_MD_PATH = path.join('GEMINI.md');

// GENKIT specific constants
const GENKIT_EXT_DIR = path.join(GEMINI_DIR, 'extensions', 'genkit');
const GENKIT_MD_REL_PATH = path.join('..', '..', '..', GENKIT_PROMPT_PATH);
const GENKIT_EXTENSION_CONFIG = {
name: 'genkit',
Expand All @@ -46,6 +54,10 @@ const GENKIT_EXTENSION_CONFIG = {
contextFileName: GENKIT_MD_REL_PATH,
};

const EXT_INSTALLATION = 'extension';
const MD_INSTALLATION = 'geminimd';
type InstallationType = typeof EXT_INSTALLATION | typeof MD_INSTALLATION;

/** Configuration module for Gemini CLI */
export const gemini: AIToolModule = {
name: 'gemini',
Expand All @@ -55,42 +67,115 @@ export const gemini: AIToolModule = {
* Configures the Gemini CLI extension for Genkit.
*/
async configure(options?: InitConfigOptions): Promise<AIToolConfigResult> {
// TODO(ssbushi): Support option to install as file import vs extension
const files: AIToolConfigResult['files'] = [];
let installationMethod: InstallationType = EXT_INSTALLATION;
if (!options?.yesMode) {
installationMethod = await select({
message: 'Select your preferred installation method',
choices: [
{
name: 'Gemini CLI Extension',
value: 'extension',
description:
'Use Gemini Extension to install Genkit context in a modular fashion',
},
{
name: 'GEMINI.md',
value: 'geminimd',
description: 'Incorporate Genkit context within the GEMINI.md file',
},
],
});
}

if (installationMethod === EXT_INSTALLATION) {
logger.info('Installing as part of GEMINI.md');
return await installAsExtension();
} else {
logger.info('Installing as Gemini CLI extension');
return await installInMdFile();
}
},
};

// Part 1: Generate GENKIT.md file.
async function installInMdFile(): Promise<AIToolConfigResult> {
const files: AIToolConfigResult['files'] = [];
// Part 1: Generate GENKIT.md file.

logger.info('Copying the GENKIT.md file...');
const genkitContext = getGenkitContext();
const baseResult = await initOrReplaceFile(
GENKIT_PROMPT_PATH,
genkitContext
logger.info('Installing the Genkit MCP server for Gemini CLI');
// Handle MCP configuration - merge with existing if present
let existingConfig: any = {};
let settingsUpdated = false;
try {
const fileExists = existsSync(GEMINI_SETTINGS_PATH);
if (fileExists) {
existingConfig = JSON.parse(readFileSync(GEMINI_SETTINGS_PATH, 'utf-8'));
} else {
await mkdir(GEMINI_DIR, { recursive: true });
}
} catch (e) {
// File doesn't exist or is invalid JSON, start fresh
}

// Check if genkit server already exists
if (!existingConfig.mcpServers?.genkit) {
if (!existingConfig.mcpServers) {
existingConfig.mcpServers = {};
}
existingConfig.mcpServers.genkit =
GENKIT_EXTENSION_CONFIG.mcpServers.genkit;
await writeFile(
GEMINI_SETTINGS_PATH,
JSON.stringify(existingConfig, null, 2)
);
files.push({ path: GENKIT_PROMPT_PATH, updated: baseResult.updated });

// Part 2: Configure the main gemini-extension.json file, and gemini config directory if needed.
logger.info('Configuring extentions files in user workspace...');
await mkdir(GENKIT_EXT_DIR, { recursive: true });
const extensionPath = path.join(GENKIT_EXT_DIR, 'gemini-extension.json');

let extensionUpdated = false;
try {
const { updated } = await initOrReplaceFile(
extensionPath,
JSON.stringify(GENKIT_EXTENSION_CONFIG, null, 2)
settingsUpdated = true;
}
files.push({ path: GEMINI_SETTINGS_PATH, updated: settingsUpdated });

// Copy GENKIT.md file
logger.info('Copying the GENKIT.md file...');
const baseResult = await initGenkitFile();
files.push({ path: GENKIT_PROMPT_PATH, updated: baseResult.updated });

logger.info('Updating GEMINI.md to include Genkit context');
const geminiImportTag = `\nGenkit Framework Instructions:\n - @./GENKIT.md\n`;
const { updated: mdUpdated } = await updateContentInPlace(
GEMINI_MD_PATH,
geminiImportTag,
{ hash: baseResult.hash }
);
files.push({ path: GEMINI_MD_PATH, updated: mdUpdated });

return { files };
}

async function installAsExtension(): Promise<AIToolConfigResult> {
const files: AIToolConfigResult['files'] = [];
// Part 1: Generate GENKIT.md file.
const baseResult = await initGenkitFile();
files.push({ path: GENKIT_PROMPT_PATH, updated: baseResult.updated });

// Part 2: Configure the main gemini-extension.json file, and gemini config directory if needed.
logger.info('Configuring extentions files in user workspace');
await mkdir(GENKIT_EXT_DIR, { recursive: true });
const extensionPath = path.join(GENKIT_EXT_DIR, 'gemini-extension.json');

let extensionUpdated = false;
try {
const { updated } = await initOrReplaceFile(
extensionPath,
JSON.stringify(GENKIT_EXTENSION_CONFIG, null, 2)
);
extensionUpdated = updated;
if (extensionUpdated) {
logger.info(
`Genkit extension for Gemini CLI initialized at ${extensionPath}`
);
extensionUpdated = updated;
if (extensionUpdated) {
logger.info(
`Genkit extension for Gemini CLI initialized at ${extensionPath}`
);
}
} catch (err) {
logger.error(err);
process.exit(1);
}
files.push({ path: extensionPath, updated: extensionUpdated });
} catch (err) {
logger.error(err);
process.exit(1);
}
files.push({ path: extensionPath, updated: extensionUpdated });

return { files };
},
};
return { files };
}
15 changes: 4 additions & 11 deletions genkit-tools/cli/src/commands/init-ai-tools/ai-tools/generic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@

import { logger } from '@genkit-ai/tools-common/utils';
import { AIToolConfigResult, AIToolModule, InitConfigOptions } from '../types';
import {
GENKIT_PROMPT_PATH,
getGenkitContext,
initOrReplaceFile,
} from '../utils';
import { GENKIT_PROMPT_PATH, initGenkitFile } from '../utils';

/** Configuration module for GENKIT.md context file for generic use */
export const generic: AIToolModule = {
Expand All @@ -35,12 +31,9 @@ export const generic: AIToolModule = {

// Generate GENKIT.md file.
logger.info('Updating GENKIT.md...');
const genkitContext = getGenkitContext();
const baseResult = await initOrReplaceFile(
GENKIT_PROMPT_PATH,
genkitContext
);
files.push({ path: GENKIT_PROMPT_PATH, updated: baseResult.updated });
const mdResult = await initGenkitFile();
files.push({ path: GENKIT_PROMPT_PATH, updated: mdResult.updated });

logger.info('\n');
logger.info(
'GENKIT.md updated. Provide this file as context with your AI tool.'
Expand Down
9 changes: 9 additions & 0 deletions genkit-tools/cli/src/commands/init-ai-tools/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,12 @@ export function getGenkitContext(): string {
const content = readFileSync(contextPath, 'utf8');
return content;
}

/**
* Initializes the GENKIT.md file
*/
export async function initGenkitFile() {
const genkitContext = getGenkitContext();
const result = await initOrReplaceFile(GENKIT_PROMPT_PATH, genkitContext);
return { updated: result.updated, hash: calculateHash(genkitContext) };
}
Loading