@google/gemini-cli-core 0.15.0-preview.3 → 0.16.0-nightly.20251113.ad1f0d99

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.
Files changed (144) hide show
  1. package/dist/google-gemini-cli-core-0.16.0-nightly.20251112.c961f274.tgz +0 -0
  2. package/dist/src/agents/codebase-investigator.test.d.ts +6 -0
  3. package/dist/src/agents/codebase-investigator.test.js +35 -0
  4. package/dist/src/agents/codebase-investigator.test.js.map +1 -0
  5. package/dist/src/agents/executor.test.js +181 -1
  6. package/dist/src/agents/executor.test.js.map +1 -1
  7. package/dist/src/code_assist/codeAssist.test.d.ts +6 -0
  8. package/dist/src/code_assist/codeAssist.test.js +99 -0
  9. package/dist/src/code_assist/codeAssist.test.js.map +1 -0
  10. package/dist/src/code_assist/experiments/client_metadata.js +2 -1
  11. package/dist/src/code_assist/experiments/client_metadata.js.map +1 -1
  12. package/dist/src/code_assist/experiments/client_metadata.test.d.ts +6 -0
  13. package/dist/src/code_assist/experiments/client_metadata.test.js +99 -0
  14. package/dist/src/code_assist/experiments/client_metadata.test.js.map +1 -0
  15. package/dist/src/code_assist/experiments/experiments.test.d.ts +6 -0
  16. package/dist/src/code_assist/experiments/experiments.test.js +92 -0
  17. package/dist/src/code_assist/experiments/experiments.test.js.map +1 -0
  18. package/dist/src/code_assist/oauth-credential-storage.test.js +49 -0
  19. package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -1
  20. package/dist/src/code_assist/server.js +5 -8
  21. package/dist/src/code_assist/server.js.map +1 -1
  22. package/dist/src/code_assist/server.test.js +109 -28
  23. package/dist/src/code_assist/server.test.js.map +1 -1
  24. package/dist/src/config/defaultModelConfigs.js +6 -0
  25. package/dist/src/config/defaultModelConfigs.js.map +1 -1
  26. package/dist/src/confirmation-bus/message-bus.d.ts +1 -1
  27. package/dist/src/confirmation-bus/message-bus.js +2 -2
  28. package/dist/src/confirmation-bus/message-bus.js.map +1 -1
  29. package/dist/src/confirmation-bus/message-bus.test.js +30 -24
  30. package/dist/src/confirmation-bus/message-bus.test.js.map +1 -1
  31. package/dist/src/core/loggingContentGenerator.test.d.ts +6 -0
  32. package/dist/src/core/loggingContentGenerator.test.js +180 -0
  33. package/dist/src/core/loggingContentGenerator.test.js.map +1 -0
  34. package/dist/src/core/tokenLimits.test.d.ts +6 -0
  35. package/dist/src/core/tokenLimits.test.js +26 -0
  36. package/dist/src/core/tokenLimits.test.js.map +1 -0
  37. package/dist/src/generated/git-commit.d.ts +2 -2
  38. package/dist/src/generated/git-commit.js +2 -2
  39. package/dist/src/generated/git-commit.js.map +1 -1
  40. package/dist/src/hooks/hookAggregator.d.ts +68 -0
  41. package/dist/src/hooks/hookAggregator.js +262 -0
  42. package/dist/src/hooks/hookAggregator.js.map +1 -0
  43. package/dist/src/hooks/hookAggregator.test.d.ts +6 -0
  44. package/dist/src/hooks/hookAggregator.test.js +387 -0
  45. package/dist/src/hooks/hookAggregator.test.js.map +1 -0
  46. package/dist/src/hooks/types.js +1 -1
  47. package/dist/src/hooks/types.js.map +1 -1
  48. package/dist/src/hooks/types.test.js +280 -2
  49. package/dist/src/hooks/types.test.js.map +1 -1
  50. package/dist/src/ide/ide-client.test.js +159 -0
  51. package/dist/src/ide/ide-client.test.js.map +1 -1
  52. package/dist/src/mcp/oauth-provider.test.js +177 -0
  53. package/dist/src/mcp/oauth-provider.test.js.map +1 -1
  54. package/dist/src/policy/config.js +3 -1
  55. package/dist/src/policy/config.js.map +1 -1
  56. package/dist/src/policy/config.test.js +118 -1
  57. package/dist/src/policy/config.test.js.map +1 -1
  58. package/dist/src/policy/policies/write.toml +10 -0
  59. package/dist/src/policy/policy-engine.d.ts +12 -3
  60. package/dist/src/policy/policy-engine.js +61 -7
  61. package/dist/src/policy/policy-engine.js.map +1 -1
  62. package/dist/src/policy/policy-engine.test.js +422 -86
  63. package/dist/src/policy/policy-engine.test.js.map +1 -1
  64. package/dist/src/policy/toml-loader.d.ts +2 -1
  65. package/dist/src/policy/toml-loader.js +103 -6
  66. package/dist/src/policy/toml-loader.js.map +1 -1
  67. package/dist/src/policy/toml-loader.test.js +32 -88
  68. package/dist/src/policy/toml-loader.test.js.map +1 -1
  69. package/dist/src/policy/types.d.ts +65 -0
  70. package/dist/src/policy/types.js +4 -0
  71. package/dist/src/policy/types.js.map +1 -1
  72. package/dist/src/prompts/mcp-prompts.test.d.ts +6 -0
  73. package/dist/src/prompts/mcp-prompts.test.js +40 -0
  74. package/dist/src/prompts/mcp-prompts.test.js.map +1 -0
  75. package/dist/src/prompts/prompt-registry.test.d.ts +6 -0
  76. package/dist/src/prompts/prompt-registry.test.js +111 -0
  77. package/dist/src/prompts/prompt-registry.test.js.map +1 -0
  78. package/dist/src/safety/built-in.d.ts +21 -0
  79. package/dist/src/safety/built-in.js +106 -0
  80. package/dist/src/safety/built-in.js.map +1 -0
  81. package/dist/src/safety/built-in.test.d.ts +6 -0
  82. package/dist/src/safety/built-in.test.js +199 -0
  83. package/dist/src/safety/built-in.test.js.map +1 -0
  84. package/dist/src/safety/checker-runner.d.ts +48 -0
  85. package/dist/src/safety/checker-runner.js +208 -0
  86. package/dist/src/safety/checker-runner.js.map +1 -0
  87. package/dist/src/safety/checker-runner.test.d.ts +6 -0
  88. package/dist/src/safety/checker-runner.test.js +238 -0
  89. package/dist/src/safety/checker-runner.test.js.map +1 -0
  90. package/dist/src/safety/context-builder.d.ts +23 -0
  91. package/dist/src/safety/context-builder.js +47 -0
  92. package/dist/src/safety/context-builder.js.map +1 -0
  93. package/dist/src/safety/context-builder.test.d.ts +6 -0
  94. package/dist/src/safety/context-builder.test.js +49 -0
  95. package/dist/src/safety/context-builder.test.js.map +1 -0
  96. package/dist/src/safety/protocol.d.ts +88 -0
  97. package/dist/src/safety/protocol.js +15 -0
  98. package/dist/src/safety/protocol.js.map +1 -0
  99. package/dist/src/safety/registry.d.ts +26 -0
  100. package/dist/src/safety/registry.js +65 -0
  101. package/dist/src/safety/registry.js.map +1 -0
  102. package/dist/src/safety/registry.test.d.ts +6 -0
  103. package/dist/src/safety/registry.test.js +31 -0
  104. package/dist/src/safety/registry.test.js.map +1 -0
  105. package/dist/src/services/loopDetectionService.d.ts +3 -0
  106. package/dist/src/services/loopDetectionService.js +81 -41
  107. package/dist/src/services/loopDetectionService.js.map +1 -1
  108. package/dist/src/services/loopDetectionService.test.js +96 -4
  109. package/dist/src/services/loopDetectionService.test.js.map +1 -1
  110. package/dist/src/services/test-data/resolved-aliases.golden.json +7 -0
  111. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +4 -2
  112. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +29 -0
  113. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  114. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +31 -0
  115. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
  116. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +5 -1
  117. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +12 -1
  118. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  119. package/dist/src/telemetry/loggers.d.ts +2 -1
  120. package/dist/src/telemetry/loggers.js +11 -0
  121. package/dist/src/telemetry/loggers.js.map +1 -1
  122. package/dist/src/telemetry/types.d.ts +15 -2
  123. package/dist/src/telemetry/types.js +42 -3
  124. package/dist/src/telemetry/types.js.map +1 -1
  125. package/dist/src/tools/base-tool-invocation.test.js +2 -2
  126. package/dist/src/tools/base-tool-invocation.test.js.map +1 -1
  127. package/dist/src/tools/memoryTool.js +1 -1
  128. package/dist/src/tools/memoryTool.js.map +1 -1
  129. package/dist/src/tools/memoryTool.test.js +1 -1
  130. package/dist/src/tools/memoryTool.test.js.map +1 -1
  131. package/dist/src/tools/ripGrep.d.ts +24 -7
  132. package/dist/src/tools/ripGrep.js +125 -145
  133. package/dist/src/tools/ripGrep.js.map +1 -1
  134. package/dist/src/tools/ripGrep.test.js +144 -20
  135. package/dist/src/tools/ripGrep.test.js.map +1 -1
  136. package/dist/src/tools/tools.js +1 -1
  137. package/dist/src/tools/tools.js.map +1 -1
  138. package/dist/src/tools/write-todos.js +1 -1
  139. package/dist/src/tools/write-todos.js.map +1 -1
  140. package/dist/src/utils/llm-edit-fixer.test.js +8 -1
  141. package/dist/src/utils/llm-edit-fixer.test.js.map +1 -1
  142. package/dist/tsconfig.tsbuildinfo +1 -1
  143. package/package.json +1 -1
  144. package/dist/google-gemini-cli-core-0.15.0-preview.2.tgz +0 -0
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { FunctionCall } from '@google/genai';
7
+ import type { SafetyCheckerConfig } from '../policy/types.js';
8
+ import type { SafetyCheckResult } from './protocol.js';
9
+ import type { CheckerRegistry } from './registry.js';
10
+ import type { ContextBuilder } from './context-builder.js';
11
+ /**
12
+ * Configuration for the checker runner.
13
+ */
14
+ export interface CheckerRunnerConfig {
15
+ /**
16
+ * Maximum time (in milliseconds) to wait for a checker to complete.
17
+ * Default: 5000 (5 seconds)
18
+ */
19
+ timeout?: number;
20
+ /**
21
+ * Path to the directory containing external checkers.
22
+ */
23
+ checkersPath: string;
24
+ }
25
+ /**
26
+ * Service for executing safety checker processes.
27
+ */
28
+ export declare class CheckerRunner {
29
+ private static readonly DEFAULT_TIMEOUT;
30
+ private readonly registry;
31
+ private readonly contextBuilder;
32
+ private readonly timeout;
33
+ constructor(contextBuilder: ContextBuilder, registry: CheckerRegistry, config: CheckerRunnerConfig);
34
+ /**
35
+ * Runs a safety checker and returns the result.
36
+ */
37
+ runChecker(toolCall: FunctionCall, checkerConfig: SafetyCheckerConfig): Promise<SafetyCheckResult>;
38
+ private runInProcessChecker;
39
+ private runExternalChecker;
40
+ /**
41
+ * Executes an external checker process and handles its lifecycle.
42
+ */
43
+ private executeCheckerProcess;
44
+ /**
45
+ * Executes a promise with a timeout.
46
+ */
47
+ private executeWithTimeout;
48
+ }
@@ -0,0 +1,208 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { spawn } from 'node:child_process';
7
+ import { SafetyCheckDecision } from './protocol.js';
8
+ /**
9
+ * Service for executing safety checker processes.
10
+ */
11
+ export class CheckerRunner {
12
+ static DEFAULT_TIMEOUT = 5000; // 5 seconds
13
+ registry;
14
+ contextBuilder;
15
+ timeout;
16
+ constructor(contextBuilder, registry, config) {
17
+ this.contextBuilder = contextBuilder;
18
+ this.registry = registry;
19
+ this.timeout = config.timeout ?? CheckerRunner.DEFAULT_TIMEOUT;
20
+ }
21
+ /**
22
+ * Runs a safety checker and returns the result.
23
+ */
24
+ async runChecker(toolCall, checkerConfig) {
25
+ if (checkerConfig.type === 'in-process') {
26
+ return this.runInProcessChecker(toolCall, checkerConfig);
27
+ }
28
+ return this.runExternalChecker(toolCall, checkerConfig);
29
+ }
30
+ async runInProcessChecker(toolCall, checkerConfig) {
31
+ try {
32
+ const checker = this.registry.resolveInProcess(checkerConfig.name);
33
+ const context = checkerConfig.required_context
34
+ ? this.contextBuilder.buildMinimalContext(checkerConfig.required_context)
35
+ : this.contextBuilder.buildFullContext();
36
+ const input = {
37
+ protocolVersion: '1.0.0',
38
+ toolCall,
39
+ context,
40
+ config: checkerConfig.config,
41
+ };
42
+ // In-process checkers can be async, but we'll also apply a timeout
43
+ // for safety, in case of infinite loops or unexpected delays.
44
+ return await this.executeWithTimeout(checker.check(input));
45
+ }
46
+ catch (error) {
47
+ return {
48
+ decision: SafetyCheckDecision.DENY,
49
+ reason: `Failed to run in-process checker "${checkerConfig.name}": ${error instanceof Error ? error.message : String(error)}`,
50
+ };
51
+ }
52
+ }
53
+ async runExternalChecker(toolCall, checkerConfig) {
54
+ try {
55
+ // Resolve the checker executable path
56
+ const checkerPath = this.registry.resolveExternal(checkerConfig.name);
57
+ // Build the appropriate context
58
+ const context = checkerConfig.required_context
59
+ ? this.contextBuilder.buildMinimalContext(checkerConfig.required_context)
60
+ : this.contextBuilder.buildFullContext();
61
+ // Create the input payload
62
+ const input = {
63
+ protocolVersion: '1.0.0',
64
+ toolCall,
65
+ context,
66
+ config: checkerConfig.config,
67
+ };
68
+ // Run the checker process
69
+ return await this.executeCheckerProcess(checkerPath, input, checkerConfig.name);
70
+ }
71
+ catch (error) {
72
+ // If anything goes wrong, deny the operation
73
+ return {
74
+ decision: SafetyCheckDecision.DENY,
75
+ reason: `Failed to run safety checker "${checkerConfig.name}": ${error instanceof Error ? error.message : String(error)}`,
76
+ };
77
+ }
78
+ }
79
+ /**
80
+ * Executes an external checker process and handles its lifecycle.
81
+ */
82
+ executeCheckerProcess(checkerPath, input, checkerName) {
83
+ return new Promise((resolve) => {
84
+ const child = spawn(checkerPath, [], {
85
+ stdio: ['pipe', 'pipe', 'pipe'],
86
+ });
87
+ let stdout = '';
88
+ let stderr = '';
89
+ let timeoutHandle = null;
90
+ let killed = false;
91
+ let exited = false;
92
+ // Set up timeout
93
+ timeoutHandle = setTimeout(() => {
94
+ killed = true;
95
+ child.kill('SIGTERM');
96
+ resolve({
97
+ decision: SafetyCheckDecision.DENY,
98
+ reason: `Safety checker "${checkerName}" timed out after ${this.timeout}ms`,
99
+ });
100
+ // Fallback: if process doesn't exit after 5s, force kill
101
+ setTimeout(() => {
102
+ if (!exited) {
103
+ child.kill('SIGKILL');
104
+ }
105
+ }, 5000).unref();
106
+ }, this.timeout);
107
+ // Collect output
108
+ if (child.stdout) {
109
+ child.stdout.on('data', (data) => {
110
+ stdout += data.toString();
111
+ });
112
+ }
113
+ if (child.stderr) {
114
+ child.stderr.on('data', (data) => {
115
+ stderr += data.toString();
116
+ });
117
+ }
118
+ // Handle process completion
119
+ child.on('close', (code) => {
120
+ exited = true;
121
+ if (timeoutHandle) {
122
+ clearTimeout(timeoutHandle);
123
+ }
124
+ // If we already killed it due to timeout, don't process the result
125
+ if (killed) {
126
+ return;
127
+ }
128
+ // Non-zero exit code is a failure
129
+ if (code !== 0) {
130
+ resolve({
131
+ decision: SafetyCheckDecision.DENY,
132
+ reason: `Safety checker "${checkerName}" exited with code ${code}${stderr ? `: ${stderr}` : ''}`,
133
+ });
134
+ return;
135
+ }
136
+ // Try to parse the output
137
+ try {
138
+ const result = JSON.parse(stdout);
139
+ // Validate the result structure
140
+ if (!result.decision ||
141
+ !Object.values(SafetyCheckDecision).includes(result.decision)) {
142
+ throw new Error('Invalid result: missing or invalid "decision" field');
143
+ }
144
+ resolve(result);
145
+ }
146
+ catch (parseError) {
147
+ resolve({
148
+ decision: SafetyCheckDecision.DENY,
149
+ reason: `Failed to parse output from safety checker "${checkerName}": ${parseError instanceof Error
150
+ ? parseError.message
151
+ : String(parseError)}`,
152
+ });
153
+ }
154
+ });
155
+ // Handle process errors
156
+ child.on('error', (error) => {
157
+ if (timeoutHandle) {
158
+ clearTimeout(timeoutHandle);
159
+ }
160
+ if (!killed) {
161
+ resolve({
162
+ decision: SafetyCheckDecision.DENY,
163
+ reason: `Failed to spawn safety checker "${checkerName}": ${error.message}`,
164
+ });
165
+ }
166
+ });
167
+ // Send input to the checker
168
+ try {
169
+ if (child.stdin) {
170
+ child.stdin.write(JSON.stringify(input));
171
+ child.stdin.end();
172
+ }
173
+ else {
174
+ throw new Error('Failed to open stdin for checker process');
175
+ }
176
+ }
177
+ catch (writeError) {
178
+ if (timeoutHandle) {
179
+ clearTimeout(timeoutHandle);
180
+ }
181
+ child.kill();
182
+ resolve({
183
+ decision: SafetyCheckDecision.DENY,
184
+ reason: `Failed to write to stdin of safety checker "${checkerName}": ${writeError instanceof Error
185
+ ? writeError.message
186
+ : String(writeError)}`,
187
+ });
188
+ }
189
+ });
190
+ }
191
+ /**
192
+ * Executes a promise with a timeout.
193
+ */
194
+ executeWithTimeout(promise) {
195
+ return new Promise((resolve, reject) => {
196
+ const timeoutHandle = setTimeout(() => {
197
+ reject(new Error(`Checker timed out after ${this.timeout}ms`));
198
+ }, this.timeout);
199
+ promise
200
+ .then(resolve)
201
+ .catch(reject)
202
+ .finally(() => {
203
+ clearTimeout(timeoutHandle);
204
+ });
205
+ });
206
+ }
207
+ }
208
+ //# sourceMappingURL=checker-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checker-runner.js","sourceRoot":"","sources":["../../../src/safety/checker-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,238 @@
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 { spawn } from 'node:child_process';
8
+ import { CheckerRunner } from './checker-runner.js';
9
+ import { ContextBuilder } from './context-builder.js';
10
+ import { CheckerRegistry } from './registry.js';
11
+ import { InProcessCheckerType, } from '../policy/types.js';
12
+ import { SafetyCheckDecision } from './protocol.js';
13
+ // Mock dependencies
14
+ vi.mock('./registry.js');
15
+ vi.mock('./context-builder.js');
16
+ vi.mock('node:child_process');
17
+ describe('CheckerRunner', () => {
18
+ let runner;
19
+ let mockContextBuilder;
20
+ let mockRegistry;
21
+ const mockToolCall = { name: 'test_tool', args: {} };
22
+ const mockInProcessConfig = {
23
+ type: 'in-process',
24
+ name: InProcessCheckerType.ALLOWED_PATH,
25
+ };
26
+ beforeEach(() => {
27
+ mockContextBuilder = new ContextBuilder({});
28
+ mockRegistry = new CheckerRegistry('/mock/dist');
29
+ CheckerRegistry.prototype.resolveInProcess = vi.fn();
30
+ runner = new CheckerRunner(mockContextBuilder, mockRegistry, {
31
+ checkersPath: '/mock/dist',
32
+ });
33
+ });
34
+ afterEach(() => {
35
+ vi.restoreAllMocks();
36
+ });
37
+ it('should run in-process checker successfully', async () => {
38
+ const mockResult = {
39
+ decision: SafetyCheckDecision.ALLOW,
40
+ };
41
+ const mockChecker = {
42
+ check: vi.fn().mockResolvedValue(mockResult),
43
+ };
44
+ vi.mocked(mockRegistry.resolveInProcess).mockReturnValue(mockChecker);
45
+ vi.mocked(mockContextBuilder.buildFullContext).mockReturnValue({
46
+ environment: { cwd: '/tmp', workspaces: [] },
47
+ });
48
+ const result = await runner.runChecker(mockToolCall, mockInProcessConfig);
49
+ expect(result).toEqual(mockResult);
50
+ expect(mockRegistry.resolveInProcess).toHaveBeenCalledWith(InProcessCheckerType.ALLOWED_PATH);
51
+ expect(mockChecker.check).toHaveBeenCalled();
52
+ });
53
+ it('should handle in-process checker errors', async () => {
54
+ const mockChecker = {
55
+ check: vi.fn().mockRejectedValue(new Error('Checker failed')),
56
+ };
57
+ vi.mocked(mockRegistry.resolveInProcess).mockReturnValue(mockChecker);
58
+ vi.mocked(mockContextBuilder.buildFullContext).mockReturnValue({
59
+ environment: { cwd: '/tmp', workspaces: [] },
60
+ });
61
+ const result = await runner.runChecker(mockToolCall, mockInProcessConfig);
62
+ expect(result.decision).toBe(SafetyCheckDecision.DENY);
63
+ expect(result.reason).toContain('Failed to run in-process checker');
64
+ expect(result.reason).toContain('Checker failed');
65
+ });
66
+ it('should respect timeout for in-process checkers', async () => {
67
+ vi.useFakeTimers();
68
+ const mockChecker = {
69
+ check: vi.fn().mockImplementation(async () => {
70
+ await new Promise((resolve) => setTimeout(resolve, 6000)); // Longer than default 5s timeout
71
+ return { decision: SafetyCheckDecision.ALLOW };
72
+ }),
73
+ };
74
+ vi.mocked(mockRegistry.resolveInProcess).mockReturnValue(mockChecker);
75
+ vi.mocked(mockContextBuilder.buildFullContext).mockReturnValue({
76
+ environment: { cwd: '/tmp', workspaces: [] },
77
+ });
78
+ const runPromise = runner.runChecker(mockToolCall, mockInProcessConfig);
79
+ vi.advanceTimersByTime(5001);
80
+ const result = await runPromise;
81
+ expect(result.decision).toBe(SafetyCheckDecision.DENY);
82
+ expect(result.reason).toContain('timed out');
83
+ vi.useRealTimers();
84
+ });
85
+ it('should use minimal context when requested', async () => {
86
+ const configWithContext = {
87
+ ...mockInProcessConfig,
88
+ required_context: ['environment'],
89
+ };
90
+ const mockChecker = {
91
+ check: vi.fn().mockResolvedValue({ decision: SafetyCheckDecision.ALLOW }),
92
+ };
93
+ vi.mocked(mockRegistry.resolveInProcess).mockReturnValue(mockChecker);
94
+ vi.mocked(mockContextBuilder.buildMinimalContext).mockReturnValue({
95
+ environment: { cwd: '/tmp', workspaces: [] },
96
+ });
97
+ await runner.runChecker(mockToolCall, configWithContext);
98
+ expect(mockContextBuilder.buildMinimalContext).toHaveBeenCalledWith([
99
+ 'environment',
100
+ ]);
101
+ expect(mockContextBuilder.buildFullContext).not.toHaveBeenCalled();
102
+ });
103
+ it('should pass config to in-process checker via toolCall', async () => {
104
+ const mockConfig = { included_args: ['foo'] };
105
+ const configWithConfig = {
106
+ ...mockInProcessConfig,
107
+ config: mockConfig,
108
+ };
109
+ const mockResult = {
110
+ decision: SafetyCheckDecision.ALLOW,
111
+ };
112
+ const mockChecker = {
113
+ check: vi.fn().mockResolvedValue(mockResult),
114
+ };
115
+ vi.mocked(mockRegistry.resolveInProcess).mockReturnValue(mockChecker);
116
+ vi.mocked(mockContextBuilder.buildFullContext).mockReturnValue({
117
+ environment: { cwd: '/tmp', workspaces: [] },
118
+ });
119
+ await runner.runChecker(mockToolCall, configWithConfig);
120
+ expect(mockChecker.check).toHaveBeenCalledWith(expect.objectContaining({
121
+ toolCall: mockToolCall,
122
+ config: mockConfig,
123
+ }));
124
+ });
125
+ describe('External Checkers', () => {
126
+ const mockExternalConfig = {
127
+ type: 'external',
128
+ name: 'python-checker',
129
+ };
130
+ it('should spawn external checker directly', async () => {
131
+ const mockCheckerPath = '/mock/dist/python-checker';
132
+ vi.mocked(mockRegistry.resolveExternal).mockReturnValue(mockCheckerPath);
133
+ vi.mocked(mockContextBuilder.buildFullContext).mockReturnValue({
134
+ environment: { cwd: '/tmp', workspaces: [] },
135
+ });
136
+ const mockStdout = {
137
+ on: vi.fn().mockImplementation((event, callback) => {
138
+ if (event === 'data') {
139
+ callback(Buffer.from(JSON.stringify({ decision: SafetyCheckDecision.ALLOW })));
140
+ }
141
+ }),
142
+ };
143
+ const mockChildProcess = {
144
+ stdin: { write: vi.fn(), end: vi.fn() },
145
+ stdout: mockStdout,
146
+ stderr: { on: vi.fn() },
147
+ on: vi.fn().mockImplementation((event, callback) => {
148
+ if (event === 'close') {
149
+ // Defer the close callback slightly to allow stdout 'data' to be registered
150
+ setTimeout(() => callback(0), 0);
151
+ }
152
+ }),
153
+ kill: vi.fn(),
154
+ };
155
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
156
+ vi.mocked(spawn).mockReturnValue(mockChildProcess);
157
+ const result = await runner.runChecker(mockToolCall, mockExternalConfig);
158
+ expect(result.decision).toBe(SafetyCheckDecision.ALLOW);
159
+ expect(spawn).toHaveBeenCalledWith(mockCheckerPath, [], expect.anything());
160
+ });
161
+ it('should include checker name in timeout error message', async () => {
162
+ vi.useFakeTimers();
163
+ const mockCheckerPath = '/mock/dist/python-checker';
164
+ vi.mocked(mockRegistry.resolveExternal).mockReturnValue(mockCheckerPath);
165
+ vi.mocked(mockContextBuilder.buildFullContext).mockReturnValue({
166
+ environment: { cwd: '/tmp', workspaces: [] },
167
+ });
168
+ const mockChildProcess = {
169
+ stdin: { write: vi.fn(), end: vi.fn() },
170
+ stdout: { on: vi.fn() },
171
+ stderr: { on: vi.fn() },
172
+ on: vi.fn(), // Never calls 'close'
173
+ kill: vi.fn(),
174
+ };
175
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
176
+ vi.mocked(spawn).mockReturnValue(mockChildProcess);
177
+ const runPromise = runner.runChecker(mockToolCall, mockExternalConfig);
178
+ vi.advanceTimersByTime(5001);
179
+ const result = await runPromise;
180
+ expect(result.decision).toBe(SafetyCheckDecision.DENY);
181
+ expect(result.reason).toContain('Safety checker "python-checker" timed out');
182
+ vi.useRealTimers();
183
+ });
184
+ it('should send SIGKILL if process ignores SIGTERM', async () => {
185
+ vi.useFakeTimers();
186
+ const mockCheckerPath = '/mock/dist/python-checker';
187
+ vi.mocked(mockRegistry.resolveExternal).mockReturnValue(mockCheckerPath);
188
+ vi.mocked(mockContextBuilder.buildFullContext).mockReturnValue({
189
+ environment: { cwd: '/tmp', workspaces: [] },
190
+ });
191
+ const mockChildProcess = {
192
+ stdin: { write: vi.fn(), end: vi.fn() },
193
+ stdout: { on: vi.fn() },
194
+ stderr: { on: vi.fn() },
195
+ on: vi.fn(), // Never calls 'close' automatically
196
+ kill: vi.fn(),
197
+ };
198
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
199
+ vi.mocked(spawn).mockReturnValue(mockChildProcess);
200
+ const runPromise = runner.runChecker(mockToolCall, mockExternalConfig);
201
+ // Trigger main timeout
202
+ vi.advanceTimersByTime(5001);
203
+ // Should have sent SIGTERM
204
+ expect(mockChildProcess.kill).toHaveBeenCalledWith('SIGTERM');
205
+ // Advance past cleanup timeout (5000ms)
206
+ vi.advanceTimersByTime(5000);
207
+ // Should have sent SIGKILL
208
+ expect(mockChildProcess.kill).toHaveBeenCalledWith('SIGKILL');
209
+ // Clean up promise
210
+ await runPromise;
211
+ vi.useRealTimers();
212
+ });
213
+ it('should include checker name in non-zero exit code error message', async () => {
214
+ const mockCheckerPath = '/mock/dist/python-checker';
215
+ vi.mocked(mockRegistry.resolveExternal).mockReturnValue(mockCheckerPath);
216
+ vi.mocked(mockContextBuilder.buildFullContext).mockReturnValue({
217
+ environment: { cwd: '/tmp', workspaces: [] },
218
+ });
219
+ const mockChildProcess = {
220
+ stdin: { write: vi.fn(), end: vi.fn() },
221
+ stdout: { on: vi.fn() },
222
+ stderr: { on: vi.fn() },
223
+ on: vi.fn().mockImplementation((event, callback) => {
224
+ if (event === 'close') {
225
+ callback(1); // Exit code 1
226
+ }
227
+ }),
228
+ kill: vi.fn(),
229
+ };
230
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
231
+ vi.mocked(spawn).mockReturnValue(mockChildProcess);
232
+ const result = await runner.runChecker(mockToolCall, mockExternalConfig);
233
+ expect(result.decision).toBe(SafetyCheckDecision.DENY);
234
+ expect(result.reason).toContain('Safety checker "python-checker" exited with code 1');
235
+ });
236
+ });
237
+ });
238
+ //# sourceMappingURL=checker-runner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checker-runner.test.js","sourceRoot":"","sources":["../../../src/safety/checker-runner.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { SafetyCheckInput, ConversationTurn } from './protocol.js';
7
+ import type { Config } from '../config/config.js';
8
+ /**
9
+ * Builds context objects for safety checkers, ensuring sensitive data is filtered.
10
+ */
11
+ export declare class ContextBuilder {
12
+ private readonly config;
13
+ private readonly conversationHistory;
14
+ constructor(config: Config, conversationHistory?: ConversationTurn[]);
15
+ /**
16
+ * Builds the full context object with all available data.
17
+ */
18
+ buildFullContext(): SafetyCheckInput['context'];
19
+ /**
20
+ * Builds a minimal context with only the specified keys.
21
+ */
22
+ buildMinimalContext(requiredKeys: Array<keyof SafetyCheckInput['context']>): SafetyCheckInput['context'];
23
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Builds context objects for safety checkers, ensuring sensitive data is filtered.
8
+ */
9
+ export class ContextBuilder {
10
+ config;
11
+ conversationHistory;
12
+ constructor(config, conversationHistory = []) {
13
+ this.config = config;
14
+ this.conversationHistory = conversationHistory;
15
+ }
16
+ /**
17
+ * Builds the full context object with all available data.
18
+ */
19
+ buildFullContext() {
20
+ return {
21
+ environment: {
22
+ cwd: process.cwd(),
23
+ workspaces: this.config
24
+ .getWorkspaceContext()
25
+ .getDirectories(),
26
+ },
27
+ history: {
28
+ turns: this.conversationHistory,
29
+ },
30
+ };
31
+ }
32
+ /**
33
+ * Builds a minimal context with only the specified keys.
34
+ */
35
+ buildMinimalContext(requiredKeys) {
36
+ const fullContext = this.buildFullContext();
37
+ const minimalContext = {};
38
+ for (const key of requiredKeys) {
39
+ if (key in fullContext) {
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
+ minimalContext[key] = fullContext[key];
42
+ }
43
+ }
44
+ return minimalContext;
45
+ }
46
+ }
47
+ //# sourceMappingURL=context-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-builder.js","sourceRoot":"","sources":["../../../src/safety/context-builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;GAEG;AACH,MAAM,OAAO,cAAc;IAEN;IACA;IAFnB,YACmB,MAAc,EACd,sBAA0C,EAAE;QAD5C,WAAM,GAAN,MAAM,CAAQ;QACd,wBAAmB,GAAnB,mBAAmB,CAAyB;IAC5D,CAAC;IAEJ;;OAEG;IACH,gBAAgB;QACd,OAAO;YACL,WAAW,EAAE;gBACX,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;gBAClB,UAAU,EAAE,IAAI,CAAC,MAAM;qBACpB,mBAAmB,EAAE;qBACrB,cAAc,EAAc;aAChC;YACD,OAAO,EAAE;gBACP,KAAK,EAAE,IAAI,CAAC,mBAAmB;aAChC;SACF,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,mBAAmB,CACjB,YAAsD;QAEtD,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC5C,MAAM,cAAc,GAAyC,EAAE,CAAC;QAEhE,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAC/B,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC;gBACvB,8DAA8D;gBAC7D,cAAsB,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QAED,OAAO,cAA6C,CAAC;IACvD,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
7
+ import { ContextBuilder } from './context-builder.js';
8
+ describe('ContextBuilder', () => {
9
+ let contextBuilder;
10
+ let mockConfig;
11
+ const mockHistory = [
12
+ { user: { text: 'hello' }, model: { text: 'hi' } },
13
+ ];
14
+ const mockCwd = '/home/user/project';
15
+ const mockWorkspaces = ['/home/user/project'];
16
+ beforeEach(() => {
17
+ vi.spyOn(process, 'cwd').mockReturnValue(mockCwd);
18
+ mockConfig = {
19
+ getWorkspaceContext: vi.fn().mockReturnValue({
20
+ getDirectories: vi.fn().mockReturnValue(mockWorkspaces),
21
+ }),
22
+ apiKey: 'secret-api-key',
23
+ somePublicConfig: 'public-value',
24
+ nested: {
25
+ secretToken: 'hidden',
26
+ public: 'visible',
27
+ },
28
+ };
29
+ contextBuilder = new ContextBuilder(mockConfig, mockHistory);
30
+ });
31
+ it('should build full context with all fields', () => {
32
+ const context = contextBuilder.buildFullContext();
33
+ expect(context.environment.cwd).toBe(mockCwd);
34
+ expect(context.environment.workspaces).toEqual(mockWorkspaces);
35
+ expect(context.history?.turns).toEqual(mockHistory);
36
+ });
37
+ it('should build minimal context with only required keys', () => {
38
+ const context = contextBuilder.buildMinimalContext(['environment']);
39
+ expect(context).toHaveProperty('environment');
40
+ expect(context).not.toHaveProperty('config');
41
+ expect(context).not.toHaveProperty('history');
42
+ });
43
+ it('should handle missing history', () => {
44
+ contextBuilder = new ContextBuilder(mockConfig);
45
+ const context = contextBuilder.buildFullContext();
46
+ expect(context.history?.turns).toEqual([]);
47
+ });
48
+ });
49
+ //# sourceMappingURL=context-builder.test.js.map