@google/gemini-cli-core 0.24.0-nightly.20260103.30f5c4af4 → 0.24.0-preview.0
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/docs/cli/settings.md +1 -0
- package/dist/docs/cli/skills.md +156 -0
- package/dist/docs/cli/telemetry.md +3 -3
- package/dist/docs/cli/tutorials/skills-getting-started.md +124 -0
- package/dist/docs/cli/tutorials.md +4 -0
- package/dist/docs/get-started/configuration.md +32 -5
- package/dist/docs/sidebar.json +4 -0
- package/dist/src/agents/a2a-client-manager.d.ts +5 -0
- package/dist/src/agents/a2a-client-manager.js +130 -0
- package/dist/src/agents/a2a-client-manager.js.map +1 -1
- package/dist/src/agents/a2a-client-manager.test.js +27 -1
- package/dist/src/agents/a2a-client-manager.test.js.map +1 -1
- package/dist/src/agents/a2aUtils.d.ts +28 -0
- package/dist/src/agents/a2aUtils.js +111 -0
- package/dist/src/agents/a2aUtils.js.map +1 -0
- package/dist/src/agents/a2aUtils.test.js +147 -0
- package/dist/src/agents/a2aUtils.test.js.map +1 -0
- package/dist/src/agents/delegate-to-agent-tool.d.ts +2 -2
- package/dist/src/agents/delegate-to-agent-tool.js +6 -6
- package/dist/src/agents/delegate-to-agent-tool.js.map +1 -1
- package/dist/src/agents/delegate-to-agent-tool.test.js +37 -7
- package/dist/src/agents/delegate-to-agent-tool.test.js.map +1 -1
- package/dist/src/agents/introspection-agent.js +2 -2
- package/dist/src/agents/introspection-agent.js.map +1 -1
- package/dist/src/agents/introspection-agent.test.js +2 -2
- package/dist/src/agents/introspection-agent.test.js.map +1 -1
- package/dist/src/agents/local-executor.js +1 -1
- package/dist/src/agents/local-executor.js.map +1 -1
- package/dist/src/agents/local-executor.test.js +2 -2
- package/dist/src/agents/local-executor.test.js.map +1 -1
- package/dist/src/agents/local-invocation.d.ts +2 -2
- package/dist/src/agents/local-invocation.js +3 -3
- package/dist/src/agents/local-invocation.js.map +1 -1
- package/dist/src/agents/local-invocation.test.js +7 -5
- package/dist/src/agents/local-invocation.test.js.map +1 -1
- package/dist/src/agents/remote-invocation.d.ts +17 -3
- package/dist/src/agents/remote-invocation.js +104 -6
- package/dist/src/agents/remote-invocation.js.map +1 -1
- package/dist/src/agents/remote-invocation.test.js +184 -18
- package/dist/src/agents/remote-invocation.test.js.map +1 -1
- package/dist/src/agents/subagent-tool-wrapper.d.ts +2 -2
- package/dist/src/agents/subagent-tool-wrapper.js +6 -5
- package/dist/src/agents/subagent-tool-wrapper.js.map +1 -1
- package/dist/src/agents/subagent-tool-wrapper.test.js +17 -10
- package/dist/src/agents/subagent-tool-wrapper.test.js.map +1 -1
- package/dist/src/agents/types.d.ts +6 -0
- package/dist/src/code_assist/oauth2.js +31 -1
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +75 -3
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/code_assist/server.d.ts +5 -0
- package/dist/src/code_assist/server.js +19 -4
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +19 -0
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/setup.js +6 -4
- package/dist/src/code_assist/setup.js.map +1 -1
- package/dist/src/code_assist/setup.test.js +63 -0
- package/dist/src/code_assist/setup.test.js.map +1 -1
- package/dist/src/code_assist/types.d.ts +18 -0
- package/dist/src/config/config.d.ts +19 -3
- package/dist/src/config/config.js +49 -25
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +81 -4
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/models.js +6 -4
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/models.test.js +21 -1
- package/dist/src/config/models.test.js.map +1 -1
- package/dist/src/core/client.js +39 -7
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +93 -0
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.js +1 -1
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +1 -1
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolHookTriggers.test.js +11 -9
- package/dist/src/core/coreToolHookTriggers.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +1 -0
- package/dist/src/core/coreToolScheduler.js +30 -106
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +21 -21
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.js +14 -2
- package/dist/src/core/loggingContentGenerator.js.map +1 -1
- package/dist/src/core/prompts.js +1 -1
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/sessionHookTriggers.d.ts +3 -2
- package/dist/src/core/sessionHookTriggers.js +8 -1
- package/dist/src/core/sessionHookTriggers.js.map +1 -1
- package/dist/src/core/turn.d.ts +16 -2
- package/dist/src/core/turn.js +2 -0
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/generated/git-commit.js.map +1 -1
- package/dist/src/hooks/hookEventHandler.d.ts +6 -2
- package/dist/src/hooks/hookEventHandler.js +24 -3
- package/dist/src/hooks/hookEventHandler.js.map +1 -1
- package/dist/src/hooks/hookEventHandler.test.js +31 -8
- package/dist/src/hooks/hookEventHandler.test.js.map +1 -1
- package/dist/src/hooks/hookRunner.d.ts +2 -2
- package/dist/src/hooks/hookRunner.js +12 -4
- package/dist/src/hooks/hookRunner.js.map +1 -1
- package/dist/src/hooks/hookRunner.test.js +33 -0
- package/dist/src/hooks/hookRunner.test.js.map +1 -1
- package/dist/src/index.d.ts +3 -1
- package/dist/src/index.js +3 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/policy/config.js +60 -22
- package/dist/src/policy/config.js.map +1 -1
- package/dist/src/policy/config.test.js +21 -0
- package/dist/src/policy/config.test.js.map +1 -1
- package/dist/src/policy/persistence.test.js +1 -1
- package/dist/src/policy/persistence.test.js.map +1 -1
- package/dist/src/policy/policy-engine.js +22 -6
- package/dist/src/policy/policy-engine.js.map +1 -1
- package/dist/src/policy/policy-engine.test.js +206 -1
- package/dist/src/policy/policy-engine.test.js.map +1 -1
- package/dist/src/policy/toml-loader.d.ts +0 -8
- package/dist/src/policy/toml-loader.js +7 -70
- package/dist/src/policy/toml-loader.js.map +1 -1
- package/dist/src/policy/toml-loader.test.js +16 -6
- package/dist/src/policy/toml-loader.test.js.map +1 -1
- package/dist/src/policy/utils.d.ts +21 -0
- package/dist/src/policy/utils.js +42 -0
- package/dist/src/policy/utils.js.map +1 -0
- package/dist/src/policy/utils.test.js +64 -0
- package/dist/src/policy/utils.test.js.map +1 -0
- package/dist/src/scheduler/tool-executor.d.ts +22 -0
- package/dist/src/scheduler/tool-executor.js +198 -0
- package/dist/src/scheduler/tool-executor.js.map +1 -0
- package/dist/src/scheduler/tool-executor.test.d.ts +6 -0
- package/dist/src/scheduler/tool-executor.test.js +231 -0
- package/dist/src/scheduler/tool-executor.test.js.map +1 -0
- package/dist/src/skills/skillLoader.d.ts +28 -0
- package/dist/src/skills/skillLoader.js +77 -0
- package/dist/src/skills/skillLoader.js.map +1 -0
- package/dist/src/skills/skillLoader.test.d.ts +6 -0
- package/dist/src/skills/skillLoader.test.js +73 -0
- package/dist/src/skills/skillLoader.test.js.map +1 -0
- package/dist/src/{services → skills}/skillManager.d.ts +10 -20
- package/dist/src/skills/skillManager.js +89 -0
- package/dist/src/skills/skillManager.js.map +1 -0
- package/dist/src/skills/skillManager.test.d.ts +6 -0
- package/dist/src/skills/skillManager.test.js +128 -0
- package/dist/src/skills/skillManager.test.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +5 -5
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +8 -8
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +2 -2
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +4 -4
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +3 -3
- package/dist/src/telemetry/loggers.js +4 -4
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +6 -5
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +7 -7
- package/dist/src/telemetry/types.js +10 -10
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/test-utils/mock-message-bus.d.ts +1 -0
- package/dist/src/test-utils/mock-message-bus.js +29 -0
- package/dist/src/test-utils/mock-message-bus.js.map +1 -1
- package/dist/src/test-utils/mock-tool.d.ts +5 -3
- package/dist/src/test-utils/mock-tool.js +11 -10
- package/dist/src/test-utils/mock-tool.js.map +1 -1
- package/dist/src/tools/activate-skill.d.ts +2 -2
- package/dist/src/tools/activate-skill.js +6 -1
- package/dist/src/tools/activate-skill.js.map +1 -1
- package/dist/src/tools/activate-skill.test.js +7 -5
- package/dist/src/tools/activate-skill.test.js.map +1 -1
- package/dist/src/tools/confirmation-policy.test.js +2 -12
- package/dist/src/tools/confirmation-policy.test.js.map +1 -1
- package/dist/src/tools/edit.d.ts +27 -5
- package/dist/src/tools/edit.js +444 -137
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +257 -525
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/get-internal-docs.d.ts +2 -2
- package/dist/src/tools/get-internal-docs.js +6 -6
- package/dist/src/tools/get-internal-docs.js.map +1 -1
- package/dist/src/tools/get-internal-docs.test.js +2 -1
- package/dist/src/tools/get-internal-docs.test.js.map +1 -1
- package/dist/src/tools/glob.d.ts +2 -2
- package/dist/src/tools/glob.js +1 -1
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +2 -1
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.d.ts +2 -2
- package/dist/src/tools/grep.js +1 -1
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/grep.test.js +5 -4
- package/dist/src/tools/grep.test.js.map +1 -1
- package/dist/src/tools/ls.d.ts +2 -2
- package/dist/src/tools/ls.js +2 -2
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +2 -1
- package/dist/src/tools/ls.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +2 -2
- package/dist/src/tools/mcp-client.js +2 -1
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +2 -2
- package/dist/src/tools/mcp-tool.js +7 -7
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/mcp-tool.test.js +11 -6
- package/dist/src/tools/mcp-tool.test.js.map +1 -1
- package/dist/src/tools/memoryTool.d.ts +3 -3
- package/dist/src/tools/memoryTool.js +2 -2
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/memoryTool.test.js +5 -2
- package/dist/src/tools/memoryTool.test.js.map +1 -1
- package/dist/src/tools/message-bus-integration.test.js +10 -37
- package/dist/src/tools/message-bus-integration.test.js.map +1 -1
- package/dist/src/tools/read-file.d.ts +2 -2
- package/dist/src/tools/read-file.js +1 -1
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +3 -2
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.d.ts +2 -2
- package/dist/src/tools/read-many-files.js +2 -3
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +3 -2
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/ripGrep.d.ts +2 -2
- package/dist/src/tools/ripGrep.js +3 -4
- package/dist/src/tools/ripGrep.js.map +1 -1
- package/dist/src/tools/ripGrep.test.js +7 -6
- package/dist/src/tools/ripGrep.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +3 -4
- package/dist/src/tools/shell.js +9 -35
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +40 -57
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +11 -6
- package/dist/src/tools/tool-registry.js +13 -8
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +14 -10
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +5 -5
- package/dist/src/tools/tools.js +15 -17
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/tools.test.js +3 -1
- package/dist/src/tools/tools.test.js.map +1 -1
- package/dist/src/tools/web-fetch.d.ts +2 -2
- package/dist/src/tools/web-fetch.js +4 -4
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +17 -19
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/web-search.d.ts +2 -2
- package/dist/src/tools/web-search.js +3 -4
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/web-search.test.js +2 -1
- package/dist/src/tools/web-search.test.js.map +1 -1
- package/dist/src/tools/write-file.d.ts +2 -2
- package/dist/src/tools/write-file.js +3 -3
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +4 -1
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/tools/write-todos.d.ts +2 -2
- package/dist/src/tools/write-todos.js +5 -4
- package/dist/src/tools/write-todos.js.map +1 -1
- package/dist/src/tools/write-todos.test.js +2 -1
- package/dist/src/tools/write-todos.test.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +1 -1
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/events.d.ts +46 -1
- package/dist/src/utils/events.js +21 -0
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/events.test.js +25 -0
- package/dist/src/utils/events.test.js.map +1 -1
- package/dist/src/utils/shell-permissions.test.js +27 -0
- package/dist/src/utils/shell-permissions.test.js.map +1 -1
- package/dist/src/utils/terminal.d.ts +2 -0
- package/dist/src/utils/terminal.js +6 -0
- package/dist/src/utils/terminal.js.map +1 -1
- package/dist/src/utils/tokenCalculation.js +20 -5
- package/dist/src/utils/tokenCalculation.js.map +1 -1
- package/dist/src/utils/tokenCalculation.test.js +11 -2
- package/dist/src/utils/tokenCalculation.test.js.map +1 -1
- package/dist/src/utils/tool-utils.test.js +2 -1
- package/dist/src/utils/tool-utils.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/dist/google-gemini-cli-core-0.24.0-nightly.20251227.37be16243.tgz +0 -0
- package/dist/src/services/skillManager.js +0 -157
- package/dist/src/services/skillManager.js.map +0 -1
- package/dist/src/services/skillManager.test.js +0 -169
- package/dist/src/services/skillManager.test.js.map +0 -1
- package/dist/src/tools/smart-edit.d.ts +0 -78
- package/dist/src/tools/smart-edit.js +0 -722
- package/dist/src/tools/smart-edit.js.map +0 -1
- package/dist/src/tools/smart-edit.test.js +0 -591
- package/dist/src/tools/smart-edit.test.js.map +0 -1
- /package/dist/src/{services/skillManager.test.d.ts → agents/a2aUtils.test.d.ts} +0 -0
- /package/dist/src/{tools/smart-edit.test.d.ts → policy/utils.test.d.ts} +0 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import { ToolExecutor } from './tool-executor.js';
|
|
8
|
+
import { makeFakeConfig } from '../test-utils/config.js';
|
|
9
|
+
import { MockTool } from '../test-utils/mock-tool.js';
|
|
10
|
+
import { SHELL_TOOL_NAME } from '../tools/tool-names.js';
|
|
11
|
+
import * as fileUtils from '../utils/fileUtils.js';
|
|
12
|
+
import * as coreToolHookTriggers from '../core/coreToolHookTriggers.js';
|
|
13
|
+
import { ShellToolInvocation } from '../tools/shell.js';
|
|
14
|
+
import { createMockMessageBus } from '../test-utils/mock-message-bus.js';
|
|
15
|
+
// Mock file utils
|
|
16
|
+
vi.mock('../utils/fileUtils.js', () => ({
|
|
17
|
+
saveTruncatedContent: vi.fn(),
|
|
18
|
+
}));
|
|
19
|
+
// Mock executeToolWithHooks
|
|
20
|
+
vi.mock('../core/coreToolHookTriggers.js', () => ({
|
|
21
|
+
executeToolWithHooks: vi.fn(),
|
|
22
|
+
}));
|
|
23
|
+
describe('ToolExecutor', () => {
|
|
24
|
+
let config;
|
|
25
|
+
let executor;
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
// Use the standard fake config factory
|
|
28
|
+
config = makeFakeConfig();
|
|
29
|
+
executor = new ToolExecutor(config);
|
|
30
|
+
// Reset mocks
|
|
31
|
+
vi.resetAllMocks();
|
|
32
|
+
// Default mock implementation for saveTruncatedContent
|
|
33
|
+
vi.mocked(fileUtils.saveTruncatedContent).mockImplementation(async (_content, _callId, _tempDir, _threshold, _lines) => ({
|
|
34
|
+
content: 'TruncatedContent...',
|
|
35
|
+
outputFile: '/tmp/truncated_output.txt',
|
|
36
|
+
}));
|
|
37
|
+
});
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
vi.restoreAllMocks();
|
|
40
|
+
});
|
|
41
|
+
it('should execute a tool successfully', async () => {
|
|
42
|
+
const mockTool = new MockTool({
|
|
43
|
+
name: 'testTool',
|
|
44
|
+
execute: async () => ({
|
|
45
|
+
llmContent: 'Tool output',
|
|
46
|
+
returnDisplay: 'Tool output',
|
|
47
|
+
}),
|
|
48
|
+
});
|
|
49
|
+
const invocation = mockTool.build({});
|
|
50
|
+
// Mock executeToolWithHooks to return success
|
|
51
|
+
vi.mocked(coreToolHookTriggers.executeToolWithHooks).mockResolvedValue({
|
|
52
|
+
llmContent: 'Tool output',
|
|
53
|
+
returnDisplay: 'Tool output',
|
|
54
|
+
});
|
|
55
|
+
const scheduledCall = {
|
|
56
|
+
status: 'scheduled',
|
|
57
|
+
request: {
|
|
58
|
+
callId: 'call-1',
|
|
59
|
+
name: 'testTool',
|
|
60
|
+
args: {},
|
|
61
|
+
isClientInitiated: false,
|
|
62
|
+
prompt_id: 'prompt-1',
|
|
63
|
+
},
|
|
64
|
+
tool: mockTool,
|
|
65
|
+
invocation: invocation,
|
|
66
|
+
startTime: Date.now(),
|
|
67
|
+
};
|
|
68
|
+
const onUpdateToolCall = vi.fn();
|
|
69
|
+
const result = await executor.execute({
|
|
70
|
+
call: scheduledCall,
|
|
71
|
+
signal: new AbortController().signal,
|
|
72
|
+
onUpdateToolCall,
|
|
73
|
+
});
|
|
74
|
+
expect(result.status).toBe('success');
|
|
75
|
+
if (result.status === 'success') {
|
|
76
|
+
const response = result.response.responseParts[0]?.functionResponse
|
|
77
|
+
?.response;
|
|
78
|
+
expect(response).toEqual({ output: 'Tool output' });
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
it('should handle execution errors', async () => {
|
|
82
|
+
const mockTool = new MockTool({
|
|
83
|
+
name: 'failTool',
|
|
84
|
+
});
|
|
85
|
+
const invocation = mockTool.build({});
|
|
86
|
+
// Mock executeToolWithHooks to throw
|
|
87
|
+
vi.mocked(coreToolHookTriggers.executeToolWithHooks).mockRejectedValue(new Error('Tool Failed'));
|
|
88
|
+
const scheduledCall = {
|
|
89
|
+
status: 'scheduled',
|
|
90
|
+
request: {
|
|
91
|
+
callId: 'call-2',
|
|
92
|
+
name: 'failTool',
|
|
93
|
+
args: {},
|
|
94
|
+
isClientInitiated: false,
|
|
95
|
+
prompt_id: 'prompt-2',
|
|
96
|
+
},
|
|
97
|
+
tool: mockTool,
|
|
98
|
+
invocation: invocation,
|
|
99
|
+
startTime: Date.now(),
|
|
100
|
+
};
|
|
101
|
+
const result = await executor.execute({
|
|
102
|
+
call: scheduledCall,
|
|
103
|
+
signal: new AbortController().signal,
|
|
104
|
+
onUpdateToolCall: vi.fn(),
|
|
105
|
+
});
|
|
106
|
+
expect(result.status).toBe('error');
|
|
107
|
+
if (result.status === 'error') {
|
|
108
|
+
expect(result.response.error?.message).toBe('Tool Failed');
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
it('should return cancelled result when signal is aborted', async () => {
|
|
112
|
+
const mockTool = new MockTool({
|
|
113
|
+
name: 'slowTool',
|
|
114
|
+
});
|
|
115
|
+
const invocation = mockTool.build({});
|
|
116
|
+
// Mock executeToolWithHooks to simulate slow execution or cancellation check
|
|
117
|
+
vi.mocked(coreToolHookTriggers.executeToolWithHooks).mockImplementation(async () => {
|
|
118
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
119
|
+
return { llmContent: 'Done', returnDisplay: 'Done' };
|
|
120
|
+
});
|
|
121
|
+
const scheduledCall = {
|
|
122
|
+
status: 'scheduled',
|
|
123
|
+
request: {
|
|
124
|
+
callId: 'call-3',
|
|
125
|
+
name: 'slowTool',
|
|
126
|
+
args: {},
|
|
127
|
+
isClientInitiated: false,
|
|
128
|
+
prompt_id: 'prompt-3',
|
|
129
|
+
},
|
|
130
|
+
tool: mockTool,
|
|
131
|
+
invocation: invocation,
|
|
132
|
+
startTime: Date.now(),
|
|
133
|
+
};
|
|
134
|
+
const controller = new AbortController();
|
|
135
|
+
const promise = executor.execute({
|
|
136
|
+
call: scheduledCall,
|
|
137
|
+
signal: controller.signal,
|
|
138
|
+
onUpdateToolCall: vi.fn(),
|
|
139
|
+
});
|
|
140
|
+
controller.abort();
|
|
141
|
+
const result = await promise;
|
|
142
|
+
expect(result.status).toBe('cancelled');
|
|
143
|
+
});
|
|
144
|
+
it('should truncate large shell output', async () => {
|
|
145
|
+
// 1. Setup Config for Truncation
|
|
146
|
+
vi.spyOn(config, 'getEnableToolOutputTruncation').mockReturnValue(true);
|
|
147
|
+
vi.spyOn(config, 'getTruncateToolOutputThreshold').mockReturnValue(10);
|
|
148
|
+
vi.spyOn(config, 'getTruncateToolOutputLines').mockReturnValue(5);
|
|
149
|
+
const mockTool = new MockTool({ name: SHELL_TOOL_NAME });
|
|
150
|
+
const invocation = mockTool.build({});
|
|
151
|
+
const longOutput = 'This is a very long output that should be truncated.';
|
|
152
|
+
// 2. Mock execution returning long content
|
|
153
|
+
vi.mocked(coreToolHookTriggers.executeToolWithHooks).mockResolvedValue({
|
|
154
|
+
llmContent: longOutput,
|
|
155
|
+
returnDisplay: longOutput,
|
|
156
|
+
});
|
|
157
|
+
const scheduledCall = {
|
|
158
|
+
status: 'scheduled',
|
|
159
|
+
request: {
|
|
160
|
+
callId: 'call-trunc',
|
|
161
|
+
name: SHELL_TOOL_NAME,
|
|
162
|
+
args: { command: 'echo long' },
|
|
163
|
+
isClientInitiated: false,
|
|
164
|
+
prompt_id: 'prompt-trunc',
|
|
165
|
+
},
|
|
166
|
+
tool: mockTool,
|
|
167
|
+
invocation: invocation,
|
|
168
|
+
startTime: Date.now(),
|
|
169
|
+
};
|
|
170
|
+
// 3. Execute
|
|
171
|
+
const result = await executor.execute({
|
|
172
|
+
call: scheduledCall,
|
|
173
|
+
signal: new AbortController().signal,
|
|
174
|
+
onUpdateToolCall: vi.fn(),
|
|
175
|
+
});
|
|
176
|
+
// 4. Verify Truncation Logic
|
|
177
|
+
expect(fileUtils.saveTruncatedContent).toHaveBeenCalledWith(longOutput, 'call-trunc', expect.any(String), // temp dir
|
|
178
|
+
10, // threshold
|
|
179
|
+
5);
|
|
180
|
+
expect(result.status).toBe('success');
|
|
181
|
+
if (result.status === 'success') {
|
|
182
|
+
const response = result.response.responseParts[0]?.functionResponse
|
|
183
|
+
?.response;
|
|
184
|
+
// The content should be the *truncated* version returned by the mock saveTruncatedContent
|
|
185
|
+
expect(response).toEqual({ output: 'TruncatedContent...' });
|
|
186
|
+
expect(result.response.outputFile).toBe('/tmp/truncated_output.txt');
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
it('should report PID updates for shell tools', async () => {
|
|
190
|
+
// 1. Setup ShellToolInvocation
|
|
191
|
+
const messageBus = createMockMessageBus();
|
|
192
|
+
const shellInvocation = new ShellToolInvocation(config, { command: 'sleep 10' }, messageBus);
|
|
193
|
+
// We need a dummy tool that matches the invocation just for structure
|
|
194
|
+
const mockTool = new MockTool({ name: SHELL_TOOL_NAME });
|
|
195
|
+
// 2. Mock executeToolWithHooks to trigger the PID callback
|
|
196
|
+
const testPid = 12345;
|
|
197
|
+
vi.mocked(coreToolHookTriggers.executeToolWithHooks).mockImplementation(async (_inv, _name, _sig, _bus, _hooks, _tool, _liveCb, _shellCfg, setPidCallback) => {
|
|
198
|
+
// Simulate the shell tool reporting a PID
|
|
199
|
+
if (setPidCallback) {
|
|
200
|
+
setPidCallback(testPid);
|
|
201
|
+
}
|
|
202
|
+
return { llmContent: 'done', returnDisplay: 'done' };
|
|
203
|
+
});
|
|
204
|
+
const scheduledCall = {
|
|
205
|
+
status: 'scheduled',
|
|
206
|
+
request: {
|
|
207
|
+
callId: 'call-pid',
|
|
208
|
+
name: SHELL_TOOL_NAME,
|
|
209
|
+
args: { command: 'sleep 10' },
|
|
210
|
+
isClientInitiated: false,
|
|
211
|
+
prompt_id: 'prompt-pid',
|
|
212
|
+
},
|
|
213
|
+
tool: mockTool,
|
|
214
|
+
invocation: shellInvocation,
|
|
215
|
+
startTime: Date.now(),
|
|
216
|
+
};
|
|
217
|
+
const onUpdateToolCall = vi.fn();
|
|
218
|
+
// 3. Execute
|
|
219
|
+
await executor.execute({
|
|
220
|
+
call: scheduledCall,
|
|
221
|
+
signal: new AbortController().signal,
|
|
222
|
+
onUpdateToolCall,
|
|
223
|
+
});
|
|
224
|
+
// 4. Verify PID was reported
|
|
225
|
+
expect(onUpdateToolCall).toHaveBeenCalledWith(expect.objectContaining({
|
|
226
|
+
status: 'executing',
|
|
227
|
+
pid: testPid,
|
|
228
|
+
}));
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
//# sourceMappingURL=tool-executor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-executor.test.js","sourceRoot":"","sources":["../../../src/scheduler/tool-executor.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Represents the definition of an Agent Skill.
|
|
8
|
+
*/
|
|
9
|
+
export interface SkillDefinition {
|
|
10
|
+
/** The unique name of the skill. */
|
|
11
|
+
name: string;
|
|
12
|
+
/** A concise description of what the skill does. */
|
|
13
|
+
description: string;
|
|
14
|
+
/** The absolute path to the skill's source file on disk. */
|
|
15
|
+
location: string;
|
|
16
|
+
/** The core logic/instructions of the skill. */
|
|
17
|
+
body: string;
|
|
18
|
+
/** Whether the skill is currently disabled. */
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Discovers and loads all skills in the provided directory.
|
|
23
|
+
*/
|
|
24
|
+
export declare function loadSkillsFromDir(dir: string): Promise<SkillDefinition[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Loads a single skill from a SKILL.md file.
|
|
27
|
+
*/
|
|
28
|
+
export declare function loadSkillFromFile(filePath: string): Promise<SkillDefinition | null>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from 'node:fs/promises';
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
import { glob } from 'glob';
|
|
9
|
+
import yaml from 'js-yaml';
|
|
10
|
+
import { debugLogger } from '../utils/debugLogger.js';
|
|
11
|
+
import { coreEvents } from '../utils/events.js';
|
|
12
|
+
const FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)/;
|
|
13
|
+
/**
|
|
14
|
+
* Discovers and loads all skills in the provided directory.
|
|
15
|
+
*/
|
|
16
|
+
export async function loadSkillsFromDir(dir) {
|
|
17
|
+
const discoveredSkills = [];
|
|
18
|
+
try {
|
|
19
|
+
const absoluteSearchPath = path.resolve(dir);
|
|
20
|
+
const stats = await fs.stat(absoluteSearchPath).catch(() => null);
|
|
21
|
+
if (!stats || !stats.isDirectory()) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const skillFiles = await glob('*/SKILL.md', {
|
|
25
|
+
cwd: absoluteSearchPath,
|
|
26
|
+
absolute: true,
|
|
27
|
+
nodir: true,
|
|
28
|
+
});
|
|
29
|
+
for (const skillFile of skillFiles) {
|
|
30
|
+
const metadata = await loadSkillFromFile(skillFile);
|
|
31
|
+
if (metadata) {
|
|
32
|
+
discoveredSkills.push(metadata);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (discoveredSkills.length === 0) {
|
|
36
|
+
const files = await fs.readdir(absoluteSearchPath);
|
|
37
|
+
if (files.length > 0) {
|
|
38
|
+
coreEvents.emitFeedback('warning', `Failed to load skills from ${absoluteSearchPath}. The directory is not empty but no valid skills were discovered. Please ensure SKILL.md files are present in subdirectories and have valid frontmatter.`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
coreEvents.emitFeedback('warning', `Error discovering skills in ${dir}:`, error);
|
|
44
|
+
}
|
|
45
|
+
return discoveredSkills;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Loads a single skill from a SKILL.md file.
|
|
49
|
+
*/
|
|
50
|
+
export async function loadSkillFromFile(filePath) {
|
|
51
|
+
try {
|
|
52
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
53
|
+
const match = content.match(FRONTMATTER_REGEX);
|
|
54
|
+
if (!match) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const frontmatter = yaml.load(match[1]);
|
|
58
|
+
if (!frontmatter || typeof frontmatter !== 'object') {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const { name, description } = frontmatter;
|
|
62
|
+
if (typeof name !== 'string' || typeof description !== 'string') {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
name,
|
|
67
|
+
description,
|
|
68
|
+
location: filePath,
|
|
69
|
+
body: match[2].trim(),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
debugLogger.log(`Error parsing skill file ${filePath}:`, error);
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=skillLoader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skillLoader.js","sourceRoot":"","sources":["../../../src/skills/skillLoader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
7
|
+
import * as fs from 'node:fs/promises';
|
|
8
|
+
import * as os from 'node:os';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import { loadSkillsFromDir } from './skillLoader.js';
|
|
11
|
+
import { coreEvents } from '../utils/events.js';
|
|
12
|
+
describe('skillLoader', () => {
|
|
13
|
+
let testRootDir;
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
testRootDir = await fs.mkdtemp(path.join(os.tmpdir(), 'skill-loader-test-'));
|
|
16
|
+
vi.spyOn(coreEvents, 'emitFeedback');
|
|
17
|
+
});
|
|
18
|
+
afterEach(async () => {
|
|
19
|
+
await fs.rm(testRootDir, { recursive: true, force: true });
|
|
20
|
+
vi.restoreAllMocks();
|
|
21
|
+
});
|
|
22
|
+
it('should load skills from a directory with valid SKILL.md', async () => {
|
|
23
|
+
const skillDir = path.join(testRootDir, 'my-skill');
|
|
24
|
+
await fs.mkdir(skillDir, { recursive: true });
|
|
25
|
+
const skillFile = path.join(skillDir, 'SKILL.md');
|
|
26
|
+
await fs.writeFile(skillFile, `---\nname: my-skill\ndescription: A test skill\n---\n# Instructions\nDo something.\n`);
|
|
27
|
+
const skills = await loadSkillsFromDir(testRootDir);
|
|
28
|
+
expect(skills).toHaveLength(1);
|
|
29
|
+
expect(skills[0].name).toBe('my-skill');
|
|
30
|
+
expect(skills[0].description).toBe('A test skill');
|
|
31
|
+
expect(skills[0].location).toBe(skillFile);
|
|
32
|
+
expect(skills[0].body).toBe('# Instructions\nDo something.');
|
|
33
|
+
expect(coreEvents.emitFeedback).not.toHaveBeenCalled();
|
|
34
|
+
});
|
|
35
|
+
it('should emit feedback when no valid skills are found in a non-empty directory', async () => {
|
|
36
|
+
const notASkillDir = path.join(testRootDir, 'not-a-skill');
|
|
37
|
+
await fs.mkdir(notASkillDir, { recursive: true });
|
|
38
|
+
await fs.writeFile(path.join(notASkillDir, 'some-file.txt'), 'hello');
|
|
39
|
+
const skills = await loadSkillsFromDir(testRootDir);
|
|
40
|
+
expect(skills).toHaveLength(0);
|
|
41
|
+
expect(coreEvents.emitFeedback).toHaveBeenCalledWith('warning', expect.stringContaining('Failed to load skills from'));
|
|
42
|
+
});
|
|
43
|
+
it('should ignore empty directories and not emit feedback', async () => {
|
|
44
|
+
const skills = await loadSkillsFromDir(testRootDir);
|
|
45
|
+
expect(skills).toHaveLength(0);
|
|
46
|
+
expect(coreEvents.emitFeedback).not.toHaveBeenCalled();
|
|
47
|
+
});
|
|
48
|
+
it('should ignore directories without SKILL.md', async () => {
|
|
49
|
+
const notASkillDir = path.join(testRootDir, 'not-a-skill');
|
|
50
|
+
await fs.mkdir(notASkillDir, { recursive: true });
|
|
51
|
+
// With a subdirectory, even if empty, it might still trigger readdir
|
|
52
|
+
// But my current logic is if discoveredSkills.length === 0, then check readdir
|
|
53
|
+
// If readdir is empty, it's fine.
|
|
54
|
+
const skills = await loadSkillsFromDir(testRootDir);
|
|
55
|
+
expect(skills).toHaveLength(0);
|
|
56
|
+
// If notASkillDir is empty, no warning.
|
|
57
|
+
});
|
|
58
|
+
it('should ignore SKILL.md without valid frontmatter and emit warning if directory is not empty', async () => {
|
|
59
|
+
const skillDir = path.join(testRootDir, 'invalid-skill');
|
|
60
|
+
await fs.mkdir(skillDir, { recursive: true });
|
|
61
|
+
const skillFile = path.join(skillDir, 'SKILL.md');
|
|
62
|
+
await fs.writeFile(skillFile, '# No frontmatter here');
|
|
63
|
+
const skills = await loadSkillsFromDir(testRootDir);
|
|
64
|
+
expect(skills).toHaveLength(0);
|
|
65
|
+
expect(coreEvents.emitFeedback).toHaveBeenCalledWith('warning', expect.stringContaining('Failed to load skills from'));
|
|
66
|
+
});
|
|
67
|
+
it('should return empty array for non-existent directory', async () => {
|
|
68
|
+
const skills = await loadSkillsFromDir('/non/existent/path');
|
|
69
|
+
expect(skills).toEqual([]);
|
|
70
|
+
expect(coreEvents.emitFeedback).not.toHaveBeenCalled();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
//# sourceMappingURL=skillLoader.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skillLoader.test.js","sourceRoot":"","sources":["../../../src/skills/skillLoader.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,13 +4,9 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
import { Storage } from '../config/storage.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
location: string;
|
|
11
|
-
body: string;
|
|
12
|
-
disabled?: boolean;
|
|
13
|
-
}
|
|
7
|
+
import { type SkillDefinition } from './skillLoader.js';
|
|
8
|
+
import type { GeminiCLIExtension } from '../config/config.js';
|
|
9
|
+
export { type SkillDefinition };
|
|
14
10
|
export declare class SkillManager {
|
|
15
11
|
private skills;
|
|
16
12
|
private activeSkillNames;
|
|
@@ -19,28 +15,23 @@ export declare class SkillManager {
|
|
|
19
15
|
*/
|
|
20
16
|
clearSkills(): void;
|
|
21
17
|
/**
|
|
22
|
-
* Discovers skills from standard user and project locations.
|
|
23
|
-
*
|
|
18
|
+
* Discovers skills from standard user and project locations, as well as extensions.
|
|
19
|
+
* Precedence: Extensions (lowest) -> User -> Project (highest).
|
|
24
20
|
*/
|
|
25
|
-
discoverSkills(storage: Storage): Promise<void>;
|
|
21
|
+
discoverSkills(storage: Storage, extensions?: GeminiCLIExtension[]): Promise<void>;
|
|
26
22
|
private addSkillsWithPrecedence;
|
|
27
|
-
/**
|
|
28
|
-
* Discovered skills in the provided paths and adds them to the manager.
|
|
29
|
-
* Internal helper for tiered discovery.
|
|
30
|
-
*/
|
|
31
|
-
discoverSkillsInternal(paths: string[]): Promise<SkillMetadata[]>;
|
|
32
23
|
/**
|
|
33
24
|
* Returns the list of enabled discovered skills.
|
|
34
25
|
*/
|
|
35
|
-
getSkills():
|
|
26
|
+
getSkills(): SkillDefinition[];
|
|
36
27
|
/**
|
|
37
28
|
* Returns all discovered skills, including disabled ones.
|
|
38
29
|
*/
|
|
39
|
-
getAllSkills():
|
|
30
|
+
getAllSkills(): SkillDefinition[];
|
|
40
31
|
/**
|
|
41
32
|
* Filters discovered skills by name.
|
|
42
33
|
*/
|
|
43
|
-
filterSkills(predicate: (skill:
|
|
34
|
+
filterSkills(predicate: (skill: SkillDefinition) => boolean): void;
|
|
44
35
|
/**
|
|
45
36
|
* Sets the list of disabled skill names.
|
|
46
37
|
*/
|
|
@@ -48,7 +39,7 @@ export declare class SkillManager {
|
|
|
48
39
|
/**
|
|
49
40
|
* Reads the full content (metadata + body) of a skill by name.
|
|
50
41
|
*/
|
|
51
|
-
getSkill(name: string):
|
|
42
|
+
getSkill(name: string): SkillDefinition | null;
|
|
52
43
|
/**
|
|
53
44
|
* Activates a skill by name.
|
|
54
45
|
*/
|
|
@@ -57,5 +48,4 @@ export declare class SkillManager {
|
|
|
57
48
|
* Checks if a skill is active.
|
|
58
49
|
*/
|
|
59
50
|
isSkillActive(name: string): boolean;
|
|
60
|
-
private parseSkillFile;
|
|
61
51
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { Storage } from '../config/storage.js';
|
|
7
|
+
import { loadSkillsFromDir } from './skillLoader.js';
|
|
8
|
+
export {};
|
|
9
|
+
export class SkillManager {
|
|
10
|
+
skills = [];
|
|
11
|
+
activeSkillNames = new Set();
|
|
12
|
+
/**
|
|
13
|
+
* Clears all discovered skills.
|
|
14
|
+
*/
|
|
15
|
+
clearSkills() {
|
|
16
|
+
this.skills = [];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Discovers skills from standard user and project locations, as well as extensions.
|
|
20
|
+
* Precedence: Extensions (lowest) -> User -> Project (highest).
|
|
21
|
+
*/
|
|
22
|
+
async discoverSkills(storage, extensions = []) {
|
|
23
|
+
this.clearSkills();
|
|
24
|
+
// 1. Extension skills (lowest precedence)
|
|
25
|
+
for (const extension of extensions) {
|
|
26
|
+
if (extension.isActive && extension.skills) {
|
|
27
|
+
this.addSkillsWithPrecedence(extension.skills);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// 2. User skills
|
|
31
|
+
const userSkills = await loadSkillsFromDir(Storage.getUserSkillsDir());
|
|
32
|
+
this.addSkillsWithPrecedence(userSkills);
|
|
33
|
+
// 3. Project skills (highest precedence)
|
|
34
|
+
const projectSkills = await loadSkillsFromDir(storage.getProjectSkillsDir());
|
|
35
|
+
this.addSkillsWithPrecedence(projectSkills);
|
|
36
|
+
}
|
|
37
|
+
addSkillsWithPrecedence(newSkills) {
|
|
38
|
+
const skillMap = new Map();
|
|
39
|
+
for (const skill of [...this.skills, ...newSkills]) {
|
|
40
|
+
skillMap.set(skill.name, skill);
|
|
41
|
+
}
|
|
42
|
+
this.skills = Array.from(skillMap.values());
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Returns the list of enabled discovered skills.
|
|
46
|
+
*/
|
|
47
|
+
getSkills() {
|
|
48
|
+
return this.skills.filter((s) => !s.disabled);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Returns all discovered skills, including disabled ones.
|
|
52
|
+
*/
|
|
53
|
+
getAllSkills() {
|
|
54
|
+
return this.skills;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Filters discovered skills by name.
|
|
58
|
+
*/
|
|
59
|
+
filterSkills(predicate) {
|
|
60
|
+
this.skills = this.skills.filter(predicate);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Sets the list of disabled skill names.
|
|
64
|
+
*/
|
|
65
|
+
setDisabledSkills(disabledNames) {
|
|
66
|
+
for (const skill of this.skills) {
|
|
67
|
+
skill.disabled = disabledNames.includes(skill.name);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Reads the full content (metadata + body) of a skill by name.
|
|
72
|
+
*/
|
|
73
|
+
getSkill(name) {
|
|
74
|
+
return this.skills.find((s) => s.name === name) ?? null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Activates a skill by name.
|
|
78
|
+
*/
|
|
79
|
+
activateSkill(name) {
|
|
80
|
+
this.activeSkillNames.add(name);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Checks if a skill is active.
|
|
84
|
+
*/
|
|
85
|
+
isSkillActive(name) {
|
|
86
|
+
return this.activeSkillNames.has(name);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=skillManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skillManager.js","sourceRoot":"","sources":["../../../src/skills/skillManager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAwB,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG3E,OAAO,EAAwB,CAAC;AAEhC,MAAM,OAAO,YAAY;IACf,MAAM,GAAsB,EAAE,CAAC;IAC/B,gBAAgB,GAAgB,IAAI,GAAG,EAAE,CAAC;IAElD;;OAEG;IACH,WAAW;QACT,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAClB,OAAgB,EAChB,aAAmC,EAAE;QAErC,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,0CAA0C;QAC1C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,SAAS,CAAC,QAAQ,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;gBAC3C,IAAI,CAAC,uBAAuB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QAED,iBAAiB;QACjB,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC;QAEzC,yCAAyC;QACzC,MAAM,aAAa,GAAG,MAAM,iBAAiB,CAC3C,OAAO,CAAC,mBAAmB,EAAE,CAC9B,CAAC;QACF,IAAI,CAAC,uBAAuB,CAAC,aAAa,CAAC,CAAC;IAC9C,CAAC;IAEO,uBAAuB,CAAC,SAA4B;QAC1D,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;QACpD,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC;YACnD,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,SAA8C;QACzD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,aAAuB;QACvC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,KAAK,CAAC,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,IAAY;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC;IAC1D,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,IAAY;QACxB,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,IAAY;QACxB,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;CACF"}
|