feat(cli,core): expand provider ecosystem with Antigravity and Gemma

- Add Antigravity (Light Blue) and Gemma (Gemini Blue) providers
- Update Gemini CLI brand color to Purple
- Implement personality overlays for Antigravity and Gemma in core
- Ensure brand-accurate labels and colors across Marketplace and Status Bar
- Add unit tests for new provider personality overlays
This commit is contained in:
Taylor Mullen
2026-04-02 09:53:11 -07:00
parent 79cc1eb4f4
commit 1984c9d35b
10 changed files with 480 additions and 41 deletions
+1 -1
View File
@@ -211,7 +211,7 @@ const remoteAgentSchema = z.union([
type FrontmatterRemoteAgentDefinition = z.infer<typeof remoteAgentSchema>;
const externalAgentSchema = z
export const externalAgentSchema = z
.object({
kind: z.literal('external'),
name: nameSchema,
@@ -76,6 +76,30 @@ describe('ExternalAgentInvocation', () => {
);
});
it('should support Antigravity provider', () => {
const antigravityDef: ExternalAgentDefinition = {
...externalDef,
provider: 'antigravity',
};
const polyfilled = polyfillExternalAgent(antigravityDef);
expect(polyfilled.promptConfig.systemPrompt).toContain(
'Antigravity Personality Overlay',
);
});
it('should support Gemma provider', () => {
const gemmaDef: ExternalAgentDefinition = {
...externalDef,
provider: 'gemma',
};
const polyfilled = polyfillExternalAgent(gemmaDef);
expect(polyfilled.promptConfig.systemPrompt).toContain(
'Gemma Personality Overlay',
);
});
it('should include styleInstructions from providerConfig', () => {
const customDef: ExternalAgentDefinition = {
...externalDef,
@@ -101,6 +101,24 @@ You are acting as the "Codex" agent, a specialized code generation model.
- Focus on generating high-quality, idiomatic, and correct code for the requested task.
- Prioritize structural integrity and idiomatic patterns for the target language.
- Provide clear, well-documented code snippets.
${styleInstructions}`.trim();
case 'antigravity':
return `
# Antigravity Personality Overlay
You are acting as the "Antigravity" agent.
- Focus on creative problem solving and thinking "outside the box".
- Adopt a playful but highly competent engineering persona.
- Encourage unconventional but effective solutions.
${styleInstructions}`.trim();
case 'gemma':
return `
# Gemma Personality Overlay
You are acting as the "Gemma" agent, an open, lightweight, and capable model.
- Focus on accessibility and efficiency.
- Provide helpful, clear, and easy-to-understand explanations.
- Maintain a friendly and supportive persona.
${styleInstructions}`.trim();
default:
+36 -3
View File
@@ -11,7 +11,12 @@ import * as path from 'node:path';
import * as crypto from 'node:crypto';
import { z } from 'zod';
import { type TeamDefinition } from './types.js';
import { AgentLoadError, loadAgentsFromDirectory } from './agentLoader.js';
import {
AgentLoadError,
loadAgentsFromDirectory,
externalAgentSchema,
markdownToAgentDefinition,
} from './agentLoader.js';
import { FRONTMATTER_REGEX } from '../skills/skillLoader.js';
import { getErrorMessage } from '../utils/errors.js';
@@ -32,6 +37,7 @@ const teamSchema = z
name: nameSchema,
display_name: z.string().min(1),
description: z.string().min(1),
agents: z.array(externalAgentSchema).optional(),
})
.strict();
@@ -121,18 +127,45 @@ export async function loadTeamsFromDirectory(
);
}
const { name, display_name, description } = parsedFrontmatter.data;
const {
name,
display_name,
description,
agents: inlineAgentsRaw,
} = parsedFrontmatter.data;
// Load agents from agents/ subfolder
const agentsResult = await loadAgentsFromDirectory(agentsDirPath);
result.errors.push(...agentsResult.errors);
const allAgents = [...agentsResult.agents];
// Add inline agents
if (inlineAgentsRaw) {
for (const inline of inlineAgentsRaw) {
try {
const agent = markdownToAgentDefinition(inline, {
hash,
filePath: teamMdPath,
});
allAgents.push(agent);
} catch (error) {
result.errors.push(
new AgentLoadError(
teamMdPath,
`Error loading inline agent "${inline.name}": ${getErrorMessage(error)}`,
),
);
}
}
}
result.teams.push({
name,
displayName: display_name,
description,
instructions,
agents: agentsResult.agents,
agents: allAgents,
metadata: {
hash,
filePath: teamMdPath,