@google/gemini-cli-a2a-server 0.14.0-preview.0 → 0.15.0-nightly.20251110.c0b766ad
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/a2a-server.mjs +5835 -5713
- package/dist/src/commands/command-registry.d.ts +2 -5
- package/dist/src/commands/command-registry.js +12 -4
- package/dist/src/commands/command-registry.js.map +1 -1
- package/dist/src/commands/command-registry.test.js +63 -5
- package/dist/src/commands/command-registry.test.js.map +1 -1
- package/dist/src/commands/extensions.d.ts +19 -0
- package/dist/src/commands/extensions.js +25 -0
- package/dist/src/commands/extensions.js.map +1 -0
- package/dist/src/commands/extensions.test.js +69 -0
- package/dist/src/commands/extensions.test.js.map +1 -0
- package/dist/src/commands/types.d.ts +23 -0
- package/dist/src/commands/types.js +7 -0
- package/dist/src/commands/types.js.map +1 -0
- package/dist/src/http/app.js +29 -0
- package/dist/src/http/app.js.map +1 -1
- package/dist/src/http/app.test.js +89 -1
- package/dist/src/http/app.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/dist/src/commands/list-extensions.d.ts +0 -11
- package/dist/src/commands/list-extensions.js +0 -13
- package/dist/src/commands/list-extensions.js.map +0 -1
- package/dist/src/commands/list-extensions.test.js +0 -31
- package/dist/src/commands/list-extensions.test.js.map +0 -1
- /package/dist/src/commands/{list-extensions.test.d.ts → extensions.test.d.ts} +0 -0
|
@@ -3,16 +3,13 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import type {
|
|
7
|
-
export interface Command {
|
|
8
|
-
readonly names: string[];
|
|
9
|
-
execute(config: Config, args: string[]): Promise<unknown>;
|
|
10
|
-
}
|
|
6
|
+
import type { Command } from './types.js';
|
|
11
7
|
declare class CommandRegistry {
|
|
12
8
|
private readonly commands;
|
|
13
9
|
constructor();
|
|
14
10
|
register(command: Command): void;
|
|
15
11
|
get(commandName: string): Command | undefined;
|
|
12
|
+
getAllCommands(): Command[];
|
|
16
13
|
}
|
|
17
14
|
export declare const commandRegistry: CommandRegistry;
|
|
18
15
|
export {};
|
|
@@ -3,20 +3,28 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { ExtensionsCommand } from './extensions.js';
|
|
7
7
|
class CommandRegistry {
|
|
8
8
|
commands = new Map();
|
|
9
9
|
constructor() {
|
|
10
|
-
this.register(new
|
|
10
|
+
this.register(new ExtensionsCommand());
|
|
11
11
|
}
|
|
12
12
|
register(command) {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
if (this.commands.has(command.name)) {
|
|
14
|
+
console.warn(`Command ${command.name} already registered. Skipping.`);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
this.commands.set(command.name, command);
|
|
18
|
+
for (const subCommand of command.subCommands ?? []) {
|
|
19
|
+
this.register(subCommand);
|
|
15
20
|
}
|
|
16
21
|
}
|
|
17
22
|
get(commandName) {
|
|
18
23
|
return this.commands.get(commandName);
|
|
19
24
|
}
|
|
25
|
+
getAllCommands() {
|
|
26
|
+
return [...this.commands.values()];
|
|
27
|
+
}
|
|
20
28
|
}
|
|
21
29
|
export const commandRegistry = new CommandRegistry();
|
|
22
30
|
//# sourceMappingURL=command-registry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-registry.js","sourceRoot":"","sources":["../../../src/commands/command-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"command-registry.js","sourceRoot":"","sources":["../../../src/commands/command-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGpD,MAAM,eAAe;IACF,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAC;IAEvD;QACE,IAAI,CAAC,QAAQ,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,QAAQ,CAAC,OAAgB;QACvB,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,IAAI,gCAAgC,CAAC,CAAC;YACtE,OAAO;QACT,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEzC,KAAK,MAAM,UAAU,IAAI,OAAO,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;YACnD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,GAAG,CAAC,WAAmB;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACxC,CAAC;IAED,cAAc;QACZ,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC"}
|
|
@@ -6,20 +6,34 @@
|
|
|
6
6
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
7
7
|
describe('CommandRegistry', () => {
|
|
8
8
|
const mockListExtensionsCommandInstance = {
|
|
9
|
-
|
|
9
|
+
name: 'extensions list',
|
|
10
|
+
description: 'Lists all installed extensions.',
|
|
10
11
|
execute: vi.fn(),
|
|
11
12
|
};
|
|
12
13
|
const mockListExtensionsCommand = vi.fn(() => mockListExtensionsCommandInstance);
|
|
14
|
+
const mockExtensionsCommandInstance = {
|
|
15
|
+
name: 'extensions',
|
|
16
|
+
description: 'Manage extensions.',
|
|
17
|
+
execute: vi.fn(),
|
|
18
|
+
subCommands: [mockListExtensionsCommandInstance],
|
|
19
|
+
};
|
|
20
|
+
const mockExtensionsCommand = vi.fn(() => mockExtensionsCommandInstance);
|
|
13
21
|
beforeEach(async () => {
|
|
14
22
|
vi.resetModules();
|
|
15
|
-
vi.doMock('./
|
|
23
|
+
vi.doMock('./extensions.js', () => ({
|
|
24
|
+
ExtensionsCommand: mockExtensionsCommand,
|
|
16
25
|
ListExtensionsCommand: mockListExtensionsCommand,
|
|
17
26
|
}));
|
|
18
27
|
});
|
|
19
|
-
it('should register
|
|
28
|
+
it('should register ExtensionsCommand on initialization', async () => {
|
|
20
29
|
const { commandRegistry } = await import('./command-registry.js');
|
|
21
|
-
expect(
|
|
30
|
+
expect(mockExtensionsCommand).toHaveBeenCalled();
|
|
22
31
|
const command = commandRegistry.get('extensions');
|
|
32
|
+
expect(command).toBe(mockExtensionsCommandInstance);
|
|
33
|
+
});
|
|
34
|
+
it('should register sub commands on initialization', async () => {
|
|
35
|
+
const { commandRegistry } = await import('./command-registry.js');
|
|
36
|
+
const command = commandRegistry.get('extensions list');
|
|
23
37
|
expect(command).toBe(mockListExtensionsCommandInstance);
|
|
24
38
|
});
|
|
25
39
|
it('get() should return undefined for a non-existent command', async () => {
|
|
@@ -30,12 +44,56 @@ describe('CommandRegistry', () => {
|
|
|
30
44
|
it('register() should register a new command', async () => {
|
|
31
45
|
const { commandRegistry } = await import('./command-registry.js');
|
|
32
46
|
const mockCommand = {
|
|
33
|
-
|
|
47
|
+
name: 'test-command',
|
|
48
|
+
description: '',
|
|
49
|
+
execute: vi.fn(),
|
|
50
|
+
};
|
|
51
|
+
commandRegistry.register(mockCommand);
|
|
52
|
+
const command = commandRegistry.get('test-command');
|
|
53
|
+
expect(command).toBe(mockCommand);
|
|
54
|
+
});
|
|
55
|
+
it('register() should register a nested command', async () => {
|
|
56
|
+
const { commandRegistry } = await import('./command-registry.js');
|
|
57
|
+
const mockSubSubCommand = {
|
|
58
|
+
name: 'test-command-sub-sub',
|
|
59
|
+
description: '',
|
|
60
|
+
execute: vi.fn(),
|
|
61
|
+
};
|
|
62
|
+
const mockSubCommand = {
|
|
63
|
+
name: 'test-command-sub',
|
|
64
|
+
description: '',
|
|
65
|
+
execute: vi.fn(),
|
|
66
|
+
subCommands: [mockSubSubCommand],
|
|
67
|
+
};
|
|
68
|
+
const mockCommand = {
|
|
69
|
+
name: 'test-command',
|
|
70
|
+
description: '',
|
|
34
71
|
execute: vi.fn(),
|
|
72
|
+
subCommands: [mockSubCommand],
|
|
35
73
|
};
|
|
36
74
|
commandRegistry.register(mockCommand);
|
|
37
75
|
const command = commandRegistry.get('test-command');
|
|
76
|
+
const subCommand = commandRegistry.get('test-command-sub');
|
|
77
|
+
const subSubCommand = commandRegistry.get('test-command-sub-sub');
|
|
38
78
|
expect(command).toBe(mockCommand);
|
|
79
|
+
expect(subCommand).toBe(mockSubCommand);
|
|
80
|
+
expect(subSubCommand).toBe(mockSubSubCommand);
|
|
81
|
+
});
|
|
82
|
+
it('register() should not enter an infinite loop with a cyclic command', async () => {
|
|
83
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
84
|
+
const { commandRegistry } = await import('./command-registry.js');
|
|
85
|
+
const mockCommand = {
|
|
86
|
+
name: 'cyclic-command',
|
|
87
|
+
description: '',
|
|
88
|
+
subCommands: [],
|
|
89
|
+
execute: vi.fn(),
|
|
90
|
+
};
|
|
91
|
+
mockCommand.subCommands?.push(mockCommand); // Create cycle
|
|
92
|
+
commandRegistry.register(mockCommand);
|
|
93
|
+
expect(commandRegistry.get('cyclic-command')).toBe(mockCommand);
|
|
94
|
+
expect(warnSpy).toHaveBeenCalledWith('Command cyclic-command already registered. Skipping.');
|
|
95
|
+
// If the test finishes, it means we didn't get into an infinite loop.
|
|
96
|
+
warnSpy.mockRestore();
|
|
39
97
|
});
|
|
40
98
|
});
|
|
41
99
|
//# sourceMappingURL=command-registry.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-registry.test.js","sourceRoot":"","sources":["../../../src/commands/command-registry.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"command-registry.test.js","sourceRoot":"","sources":["../../../src/commands/command-registry.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { type Config } from '@google/gemini-cli-core';
|
|
7
|
+
import type { Command, CommandExecutionResponse } from './types.js';
|
|
8
|
+
export declare class ExtensionsCommand implements Command {
|
|
9
|
+
readonly name = "extensions";
|
|
10
|
+
readonly description = "Manage extensions.";
|
|
11
|
+
readonly subCommands: ListExtensionsCommand[];
|
|
12
|
+
readonly topLevel = true;
|
|
13
|
+
execute(config: Config, _: string[]): Promise<CommandExecutionResponse>;
|
|
14
|
+
}
|
|
15
|
+
export declare class ListExtensionsCommand implements Command {
|
|
16
|
+
readonly name = "extensions list";
|
|
17
|
+
readonly description = "Lists all installed extensions.";
|
|
18
|
+
execute(config: Config, _: string[]): Promise<CommandExecutionResponse>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { listExtensions } from '@google/gemini-cli-core';
|
|
7
|
+
export class ExtensionsCommand {
|
|
8
|
+
name = 'extensions';
|
|
9
|
+
description = 'Manage extensions.';
|
|
10
|
+
subCommands = [new ListExtensionsCommand()];
|
|
11
|
+
topLevel = true;
|
|
12
|
+
async execute(config, _) {
|
|
13
|
+
return new ListExtensionsCommand().execute(config, _);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export class ListExtensionsCommand {
|
|
17
|
+
name = 'extensions list';
|
|
18
|
+
description = 'Lists all installed extensions.';
|
|
19
|
+
async execute(config, _) {
|
|
20
|
+
const extensions = listExtensions(config);
|
|
21
|
+
const data = extensions.length ? extensions : 'No extensions installed.';
|
|
22
|
+
return { name: this.name, data };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=extensions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../../src/commands/extensions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAe,MAAM,yBAAyB,CAAC;AAGtE,MAAM,OAAO,iBAAiB;IACnB,IAAI,GAAG,YAAY,CAAC;IACpB,WAAW,GAAG,oBAAoB,CAAC;IACnC,WAAW,GAAG,CAAC,IAAI,qBAAqB,EAAE,CAAC,CAAC;IAC5C,QAAQ,GAAG,IAAI,CAAC;IAEzB,KAAK,CAAC,OAAO,CACX,MAAc,EACd,CAAW;QAEX,OAAO,IAAI,qBAAqB,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACxD,CAAC;CACF;AAED,MAAM,OAAO,qBAAqB;IACvB,IAAI,GAAG,iBAAiB,CAAC;IACzB,WAAW,GAAG,iCAAiC,CAAC;IAEzD,KAAK,CAAC,OAAO,CACX,MAAc,EACd,CAAW;QAEX,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,0BAA0B,CAAC;QAEzE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
7
|
+
import { ExtensionsCommand, ListExtensionsCommand } from './extensions.js';
|
|
8
|
+
const mockListExtensions = vi.hoisted(() => vi.fn());
|
|
9
|
+
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
|
10
|
+
const original = await importOriginal();
|
|
11
|
+
return {
|
|
12
|
+
...original,
|
|
13
|
+
listExtensions: mockListExtensions,
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
describe('ExtensionsCommand', () => {
|
|
17
|
+
it('should have the correct name', () => {
|
|
18
|
+
const command = new ExtensionsCommand();
|
|
19
|
+
expect(command.name).toEqual('extensions');
|
|
20
|
+
});
|
|
21
|
+
it('should have the correct description', () => {
|
|
22
|
+
const command = new ExtensionsCommand();
|
|
23
|
+
expect(command.description).toEqual('Manage extensions.');
|
|
24
|
+
});
|
|
25
|
+
it('should have "extensions list" as a subcommand', () => {
|
|
26
|
+
const command = new ExtensionsCommand();
|
|
27
|
+
expect(command.subCommands.map((c) => c.name)).toContain('extensions list');
|
|
28
|
+
});
|
|
29
|
+
it('should be a top-level command', () => {
|
|
30
|
+
const command = new ExtensionsCommand();
|
|
31
|
+
expect(command.topLevel).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
it('should default to listing extensions', async () => {
|
|
34
|
+
const command = new ExtensionsCommand();
|
|
35
|
+
const mockConfig = {};
|
|
36
|
+
const mockExtensions = [{ name: 'ext1' }];
|
|
37
|
+
mockListExtensions.mockReturnValue(mockExtensions);
|
|
38
|
+
const result = await command.execute(mockConfig, []);
|
|
39
|
+
expect(result).toEqual({ name: 'extensions list', data: mockExtensions });
|
|
40
|
+
expect(mockListExtensions).toHaveBeenCalledWith(mockConfig);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('ListExtensionsCommand', () => {
|
|
44
|
+
it('should have the correct name', () => {
|
|
45
|
+
const command = new ListExtensionsCommand();
|
|
46
|
+
expect(command.name).toEqual('extensions list');
|
|
47
|
+
});
|
|
48
|
+
it('should call listExtensions with the provided config', async () => {
|
|
49
|
+
const command = new ListExtensionsCommand();
|
|
50
|
+
const mockConfig = {};
|
|
51
|
+
const mockExtensions = [{ name: 'ext1' }];
|
|
52
|
+
mockListExtensions.mockReturnValue(mockExtensions);
|
|
53
|
+
const result = await command.execute(mockConfig, []);
|
|
54
|
+
expect(result).toEqual({ name: 'extensions list', data: mockExtensions });
|
|
55
|
+
expect(mockListExtensions).toHaveBeenCalledWith(mockConfig);
|
|
56
|
+
});
|
|
57
|
+
it('should return a message when no extensions are installed', async () => {
|
|
58
|
+
const command = new ListExtensionsCommand();
|
|
59
|
+
const mockConfig = {};
|
|
60
|
+
mockListExtensions.mockReturnValue([]);
|
|
61
|
+
const result = await command.execute(mockConfig, []);
|
|
62
|
+
expect(result).toEqual({
|
|
63
|
+
name: 'extensions list',
|
|
64
|
+
data: 'No extensions installed.',
|
|
65
|
+
});
|
|
66
|
+
expect(mockListExtensions).toHaveBeenCalledWith(mockConfig);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=extensions.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensions.test.js","sourceRoot":"","sources":["../../../src/commands/extensions.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAG3E,MAAM,kBAAkB,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AACrD,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IAC1D,MAAM,QAAQ,GACZ,MAAM,cAAc,EAA4C,CAAC;IAEnE,OAAO;QACL,GAAG,QAAQ;QACX,cAAc,EAAE,kBAAkB;KACnC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACxC,MAAM,UAAU,GAAG,EAAY,CAAC;QAChC,MAAM,cAAc,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1C,kBAAkB,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;QAEnD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAErD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QAC1E,MAAM,CAAC,kBAAkB,CAAC,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,OAAO,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC5C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,OAAO,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC5C,MAAM,UAAU,GAAG,EAAY,CAAC;QAChC,MAAM,cAAc,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1C,kBAAkB,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC;QAEnD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAErD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QAC1E,MAAM,CAAC,kBAAkB,CAAC,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,OAAO,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC5C,MAAM,UAAU,GAAG,EAAY,CAAC;QAChC,kBAAkB,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAEvC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAErD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,iBAAiB;YACvB,IAAI,EAAE,0BAA0B;SACjC,CAAC,CAAC;QACH,MAAM,CAAC,kBAAkB,CAAC,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import type { Config } from '@google/gemini-cli-core';
|
|
7
|
+
export interface CommandArgument {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly description: string;
|
|
10
|
+
readonly isRequired?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface Command {
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly description: string;
|
|
15
|
+
readonly arguments?: CommandArgument[];
|
|
16
|
+
readonly subCommands?: Command[];
|
|
17
|
+
readonly topLevel?: boolean;
|
|
18
|
+
execute(config: Config, args: string[]): Promise<CommandExecutionResponse>;
|
|
19
|
+
}
|
|
20
|
+
export interface CommandExecutionResponse {
|
|
21
|
+
readonly name: string;
|
|
22
|
+
readonly data: unknown;
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/commands/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
package/dist/src/http/app.js
CHANGED
|
@@ -130,6 +130,35 @@ export async function createApp() {
|
|
|
130
130
|
return res.status(500).json({ error: errorMessage });
|
|
131
131
|
}
|
|
132
132
|
});
|
|
133
|
+
expressApp.get('/listCommands', (req, res) => {
|
|
134
|
+
try {
|
|
135
|
+
const transformCommand = (command, visited) => {
|
|
136
|
+
const commandName = command.name;
|
|
137
|
+
if (visited.includes(commandName)) {
|
|
138
|
+
console.warn(`Command ${commandName} already inserted in the response, skipping`);
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
name: command.name,
|
|
143
|
+
description: command.description,
|
|
144
|
+
arguments: command.arguments ?? [],
|
|
145
|
+
subCommands: (command.subCommands ?? [])
|
|
146
|
+
.map((subCommand) => transformCommand(subCommand, visited.concat(commandName)))
|
|
147
|
+
.filter((subCommand) => !!subCommand),
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
const commands = commandRegistry
|
|
151
|
+
.getAllCommands()
|
|
152
|
+
.filter((command) => command.topLevel)
|
|
153
|
+
.map((command) => transformCommand(command, []));
|
|
154
|
+
return res.status(200).json({ commands });
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
logger.error('Error executing /listCommands:', e);
|
|
158
|
+
const errorMessage = e instanceof Error ? e.message : 'Unknown error listing commands';
|
|
159
|
+
return res.status(500).json({ error: errorMessage });
|
|
160
|
+
}
|
|
161
|
+
});
|
|
133
162
|
expressApp.get('/tasks/metadata', async (req, res) => {
|
|
134
163
|
// This endpoint is only meaningful if the task store is in-memory.
|
|
135
164
|
if (!(taskStoreForExecutor instanceof InMemoryTaskStore)) {
|
package/dist/src/http/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/http/app.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAI9B,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC,CAAC,2BAA2B;AACvF,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/http/app.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ import { GeminiEventType, ApprovalMode, } from '@google/gemini-cli-core';
|
|
|
7
7
|
import request from 'supertest';
|
|
8
8
|
import { afterAll, afterEach, beforeEach, beforeAll, describe, expect, it, vi, } from 'vitest';
|
|
9
9
|
import { createApp } from './app.js';
|
|
10
|
+
import { commandRegistry } from '../commands/command-registry.js';
|
|
10
11
|
import { assertUniqueFinalEventIsLast, assertTaskCreationAndWorkingStatus, createStreamMessageRequest, createMockConfig, } from '../utils/testing_utils.js';
|
|
11
12
|
import { MockTool } from '@google/gemini-cli-core';
|
|
12
13
|
const mockToolConfirmationFn = async () => ({});
|
|
@@ -689,6 +690,90 @@ describe('E2E Tests', () => {
|
|
|
689
690
|
expect(thoughtEvent.kind).toBe('status-update');
|
|
690
691
|
expect(thoughtEvent.metadata?.['traceId']).toBe(traceId);
|
|
691
692
|
});
|
|
693
|
+
describe('/listCommands', () => {
|
|
694
|
+
it('should return a list of top-level commands', async () => {
|
|
695
|
+
const mockCommands = [
|
|
696
|
+
{
|
|
697
|
+
name: 'test-command',
|
|
698
|
+
description: 'A test command',
|
|
699
|
+
topLevel: true,
|
|
700
|
+
arguments: [{ name: 'arg1', description: 'Argument 1' }],
|
|
701
|
+
subCommands: [
|
|
702
|
+
{
|
|
703
|
+
name: 'sub-command',
|
|
704
|
+
description: 'A sub command',
|
|
705
|
+
topLevel: false,
|
|
706
|
+
execute: vi.fn(),
|
|
707
|
+
},
|
|
708
|
+
],
|
|
709
|
+
execute: vi.fn(),
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
name: 'another-command',
|
|
713
|
+
description: 'Another test command',
|
|
714
|
+
topLevel: true,
|
|
715
|
+
execute: vi.fn(),
|
|
716
|
+
},
|
|
717
|
+
{
|
|
718
|
+
name: 'not-top-level',
|
|
719
|
+
description: 'Not a top level command',
|
|
720
|
+
topLevel: false,
|
|
721
|
+
execute: vi.fn(),
|
|
722
|
+
},
|
|
723
|
+
];
|
|
724
|
+
const getAllCommandsSpy = vi
|
|
725
|
+
.spyOn(commandRegistry, 'getAllCommands')
|
|
726
|
+
.mockReturnValue(mockCommands);
|
|
727
|
+
const agent = request.agent(app);
|
|
728
|
+
const res = await agent.get('/listCommands').expect(200);
|
|
729
|
+
expect(res.body).toEqual({
|
|
730
|
+
commands: [
|
|
731
|
+
{
|
|
732
|
+
name: 'test-command',
|
|
733
|
+
description: 'A test command',
|
|
734
|
+
arguments: [{ name: 'arg1', description: 'Argument 1' }],
|
|
735
|
+
subCommands: [
|
|
736
|
+
{
|
|
737
|
+
name: 'sub-command',
|
|
738
|
+
description: 'A sub command',
|
|
739
|
+
arguments: [],
|
|
740
|
+
subCommands: [],
|
|
741
|
+
},
|
|
742
|
+
],
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
name: 'another-command',
|
|
746
|
+
description: 'Another test command',
|
|
747
|
+
arguments: [],
|
|
748
|
+
subCommands: [],
|
|
749
|
+
},
|
|
750
|
+
],
|
|
751
|
+
});
|
|
752
|
+
expect(getAllCommandsSpy).toHaveBeenCalledOnce();
|
|
753
|
+
getAllCommandsSpy.mockRestore();
|
|
754
|
+
});
|
|
755
|
+
it('should handle cyclic commands gracefully', async () => {
|
|
756
|
+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
757
|
+
const cyclicCommand = {
|
|
758
|
+
name: 'cyclic-command',
|
|
759
|
+
description: 'A cyclic command',
|
|
760
|
+
topLevel: true,
|
|
761
|
+
execute: vi.fn(),
|
|
762
|
+
subCommands: [],
|
|
763
|
+
};
|
|
764
|
+
cyclicCommand.subCommands?.push(cyclicCommand); // Create cycle
|
|
765
|
+
const getAllCommandsSpy = vi
|
|
766
|
+
.spyOn(commandRegistry, 'getAllCommands')
|
|
767
|
+
.mockReturnValue([cyclicCommand]);
|
|
768
|
+
const agent = request.agent(app);
|
|
769
|
+
const res = await agent.get('/listCommands').expect(200);
|
|
770
|
+
expect(res.body.commands[0].name).toBe('cyclic-command');
|
|
771
|
+
expect(res.body.commands[0].subCommands).toEqual([]);
|
|
772
|
+
expect(warnSpy).toHaveBeenCalledWith('Command cyclic-command already inserted in the response, skipping');
|
|
773
|
+
getAllCommandsSpy.mockRestore();
|
|
774
|
+
warnSpy.mockRestore();
|
|
775
|
+
});
|
|
776
|
+
});
|
|
692
777
|
describe('/executeCommand', () => {
|
|
693
778
|
const mockExtensions = [{ name: 'test-extension', version: '0.0.1' }];
|
|
694
779
|
beforeEach(() => {
|
|
@@ -704,7 +789,10 @@ describe('E2E Tests', () => {
|
|
|
704
789
|
.send({ command: 'extensions list', args: [] })
|
|
705
790
|
.set('Content-Type', 'application/json')
|
|
706
791
|
.expect(200);
|
|
707
|
-
expect(res.body).toEqual(
|
|
792
|
+
expect(res.body).toEqual({
|
|
793
|
+
name: 'extensions list',
|
|
794
|
+
data: mockExtensions,
|
|
795
|
+
});
|
|
708
796
|
expect(getExtensionsSpy).toHaveBeenCalled();
|
|
709
797
|
});
|
|
710
798
|
it('should return 404 for invalid command', async () => {
|