feat: Add custom URL support for the /bug command (#1017)
This commit is contained in:
parent
d5c6bb9740
commit
643bdf31d5
|
@ -44,6 +44,18 @@ When you create a `.gemini/settings.json` file for project-specific settings, or
|
|||
- **Default:** `GEMINI.md`
|
||||
- **Example:** `"contextFileName": "AGENTS.md"`
|
||||
|
||||
- **`bugCommand`** (object, optional):
|
||||
|
||||
- **Description:** Overrides the default URL for the `/bug` command.
|
||||
- **Properties:**
|
||||
- **`urlTemplate`** (string, required): A URL that can contain `{title}` and `{body}` placeholders.
|
||||
- **Example:**
|
||||
```json
|
||||
"bugCommand": {
|
||||
"urlTemplate": "https://bug.example.com/new?title={title}&body={body}"
|
||||
}
|
||||
```
|
||||
|
||||
- **`fileFiltering`** (object, optional):
|
||||
|
||||
- **Description:** Controls git-aware file filtering behavior for @ commands and file discovery tools.
|
||||
|
|
|
@ -211,6 +211,7 @@ export async function loadCliConfig(
|
|||
telemetryOtlpEndpoint:
|
||||
process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? settings.telemetryOtlpEndpoint,
|
||||
fileDiscoveryService: fileService,
|
||||
bugCommand: settings.bugCommand,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { homedir } from 'os';
|
||||
import { MCPServerConfig, getErrorMessage } from '@gemini-cli/core';
|
||||
import {
|
||||
MCPServerConfig,
|
||||
getErrorMessage,
|
||||
BugCommandSettings,
|
||||
} from '@gemini-cli/core';
|
||||
import stripJsonComments from 'strip-json-comments';
|
||||
import { DefaultLight } from '../ui/themes/default-light.js';
|
||||
import { DefaultDark } from '../ui/themes/default.js';
|
||||
|
@ -40,6 +44,7 @@ export interface Settings {
|
|||
telemetry?: boolean;
|
||||
telemetryOtlpEndpoint?: string;
|
||||
preferredEditor?: string;
|
||||
bugCommand?: BugCommandSettings;
|
||||
|
||||
// Git-aware file filtering settings
|
||||
fileFiltering?: {
|
||||
|
|
|
@ -129,6 +129,7 @@ describe('useSlashCommandProcessor', () => {
|
|||
getModel: vi.fn(() => 'test-model'),
|
||||
getProjectRoot: vi.fn(() => '/test/dir'),
|
||||
getCheckpointEnabled: vi.fn(() => true),
|
||||
getBugCommand: vi.fn(() => undefined),
|
||||
} as unknown as Config;
|
||||
mockCorgiMode = vi.fn();
|
||||
mockUseSessionStats.mockReturnValue({
|
||||
|
@ -418,6 +419,47 @@ Add any other context about the problem here.
|
|||
expect(open).toHaveBeenCalledWith(expectedUrl);
|
||||
expect(commandResult).toBe(true);
|
||||
});
|
||||
|
||||
it('should use the custom bug command URL from config if available', async () => {
|
||||
const bugCommand = {
|
||||
urlTemplate:
|
||||
'https://custom-bug-tracker.com/new?title={title}&body={body}',
|
||||
};
|
||||
mockConfig = {
|
||||
...mockConfig,
|
||||
getBugCommand: vi.fn(() => bugCommand),
|
||||
} as unknown as Config;
|
||||
|
||||
const { handleSlashCommand } = getProcessor();
|
||||
const bugDescription = 'This is a custom bug';
|
||||
const diagnosticInfo = `
|
||||
## Describe the bug
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
## Additional context
|
||||
Add any other context about the problem here.
|
||||
|
||||
## Diagnostic Information
|
||||
* **CLI Version:** unknown
|
||||
* **Git Commit:** ${GIT_COMMIT_INFO}
|
||||
* **Operating System:** test-platform test-node-version
|
||||
* **Sandbox Environment:** no sandbox
|
||||
* **Model Version:** test-model
|
||||
* **Memory Usage:** 11.8 MB
|
||||
`;
|
||||
const expectedUrl = bugCommand.urlTemplate
|
||||
.replace('{title}', encodeURIComponent(bugDescription))
|
||||
.replace('{body}', encodeURIComponent(diagnosticInfo));
|
||||
|
||||
let commandResult: SlashCommandActionReturn | boolean = false;
|
||||
await act(async () => {
|
||||
commandResult = await handleSlashCommand(`/bug ${bugDescription}`);
|
||||
});
|
||||
|
||||
expect(mockAddItem).toHaveBeenCalledTimes(2);
|
||||
expect(open).toHaveBeenCalledWith(expectedUrl);
|
||||
expect(commandResult).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('/quit and /exit commands', () => {
|
||||
|
|
|
@ -512,13 +512,14 @@ Add any other context about the problem here.
|
|||
`;
|
||||
|
||||
let bugReportUrl =
|
||||
'https://github.com/google-gemini/gemini-cli/issues/new?template=bug_report.md';
|
||||
if (bugDescription) {
|
||||
const encodedArgs = encodeURIComponent(bugDescription);
|
||||
bugReportUrl += `&title=${encodedArgs}`;
|
||||
'https://github.com/google-gemini/gemini-cli/issues/new?template=bug_report.md&title={title}&body={body}';
|
||||
const bugCommand = config?.getBugCommand();
|
||||
if (bugCommand?.urlTemplate) {
|
||||
bugReportUrl = bugCommand.urlTemplate;
|
||||
}
|
||||
const encodedBody = encodeURIComponent(diagnosticInfo);
|
||||
bugReportUrl += `&body=${encodedBody}`;
|
||||
bugReportUrl = bugReportUrl
|
||||
.replace('{title}', encodeURIComponent(bugDescription))
|
||||
.replace('{body}', encodeURIComponent(diagnosticInfo));
|
||||
|
||||
addMessage({
|
||||
type: MessageType.INFO,
|
||||
|
|
|
@ -36,6 +36,10 @@ export interface AccessibilitySettings {
|
|||
disableLoadingPhrases?: boolean;
|
||||
}
|
||||
|
||||
export interface BugCommandSettings {
|
||||
urlTemplate: string;
|
||||
}
|
||||
|
||||
export class MCPServerConfig {
|
||||
constructor(
|
||||
// For stdio transport
|
||||
|
@ -87,6 +91,7 @@ export interface ConfigParameters {
|
|||
proxy?: string;
|
||||
cwd: string;
|
||||
fileDiscoveryService?: FileDiscoveryService;
|
||||
bugCommand?: BugCommandSettings;
|
||||
}
|
||||
|
||||
export class Config {
|
||||
|
@ -121,6 +126,7 @@ export class Config {
|
|||
private readonly checkpoint: boolean;
|
||||
private readonly proxy: string | undefined;
|
||||
private readonly cwd: string;
|
||||
private readonly bugCommand: BugCommandSettings | undefined;
|
||||
|
||||
constructor(params: ConfigParameters) {
|
||||
this.sessionId = params.sessionId;
|
||||
|
@ -154,6 +160,7 @@ export class Config {
|
|||
this.proxy = params.proxy;
|
||||
this.cwd = params.cwd ?? process.cwd();
|
||||
this.fileDiscoveryService = params.fileDiscoveryService ?? null;
|
||||
this.bugCommand = params.bugCommand;
|
||||
|
||||
if (params.contextFileName) {
|
||||
setGeminiMdFilename(params.contextFileName);
|
||||
|
@ -309,6 +316,10 @@ export class Config {
|
|||
return this.cwd;
|
||||
}
|
||||
|
||||
getBugCommand(): BugCommandSettings | undefined {
|
||||
return this.bugCommand;
|
||||
}
|
||||
|
||||
async getFileService(): Promise<FileDiscoveryService> {
|
||||
if (!this.fileDiscoveryService) {
|
||||
this.fileDiscoveryService = new FileDiscoveryService(this.targetDir);
|
||||
|
|
Loading…
Reference in New Issue