mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-08-02 21:21:09 -07:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e4d1c07294 | |||
| 99bc45b689 | |||
| 903c9f79b3 | |||
| c6ff82944f |
@@ -11,6 +11,50 @@ Enter to submit · Esc to cancel
|
|||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`AskUserDialog > Choice question placeholder > uses default placeholder when not provided 2`] = `
|
||||||
|
"
|
||||||
|
ERROR Cannot read properties of undefined (reading '$$typeof')
|
||||||
|
|
||||||
|
/Users/spencertang/Workspace/gemini-cli/node_modules/react/cjs/react.developme
|
||||||
|
nt.js:1208:15
|
||||||
|
|
||||||
|
1205: };
|
||||||
|
1206: exports.useContext = function (Context) {
|
||||||
|
1207: var dispatcher = resolveDispatcher();
|
||||||
|
1208: Context.$$typeof === REACT_CONSUMER_TYPE &&
|
||||||
|
1209: console.error(
|
||||||
|
1210 "Calling useContext(Context.Consumer) is not supported and will
|
||||||
|
: cause bugs. Did you mean to call useContext(Context) instead?"
|
||||||
|
1211: );
|
||||||
|
|
||||||
|
-process.env.NODE_ENV.expo
|
||||||
|
ts.useContext (/Users/spencertang/Workspace/gemini-cli/node_module
|
||||||
|
s/react/cjs/react.development.js:1208:15)
|
||||||
|
- useTerminalCapabilities (src/ui/hooks/useTerminalCapabilities.ts:15:19)
|
||||||
|
- useAlternateBuffer (src/ui/hooks/useAlternateBuffer.ts:15:24)
|
||||||
|
- ChoiceQuestionView (src/ui/components/AskUserDialog.tsx:484:29)
|
||||||
|
-Object.react-stack-bot
|
||||||
|
om-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/r
|
||||||
|
eact-reconciler/cjs/react-reconciler.development.js:158
|
||||||
|
59:20)
|
||||||
|
-renderWithHo
|
||||||
|
ks (/Users/spencertang/Workspace/gemini-cli/node_modules/react-recon
|
||||||
|
ciler/cjs/react-reconciler.development.js:3221:22)
|
||||||
|
-updateFunctionCom
|
||||||
|
onent (/Users/spencertang/Workspace/gemini-cli/node_modules/react-
|
||||||
|
reconciler/cjs/react-reconciler.development.js:6475:19)
|
||||||
|
-beginWor
|
||||||
|
(/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconcile
|
||||||
|
r/cjs/react-reconciler.development.js:8009:18)
|
||||||
|
-runWithFiberIn
|
||||||
|
EV (/Users/spencertang/Workspace/gemini-cli/node_modules/react-rec
|
||||||
|
onciler/cjs/react-reconciler.development.js:1738:13)
|
||||||
|
-performUnitOfW
|
||||||
|
rk (/Users/spencertang/Workspace/gemini-cli/node_modules/react-rec
|
||||||
|
onciler/cjs/react-reconciler.development.js:12834:22)
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`AskUserDialog > Choice question placeholder > uses placeholder for "Other" option when provided 1`] = `
|
exports[`AskUserDialog > Choice question placeholder > uses placeholder for "Other" option when provided 1`] = `
|
||||||
"Select your preferred language:
|
"Select your preferred language:
|
||||||
|
|
||||||
@@ -22,6 +66,50 @@ Enter to submit · Esc to cancel
|
|||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`AskUserDialog > Choice question placeholder > uses placeholder for "Other" option when provided 2`] = `
|
||||||
|
"
|
||||||
|
ERROR Cannot read properties of undefined (reading '$$typeof')
|
||||||
|
|
||||||
|
/Users/spencertang/Workspace/gemini-cli/node_modules/react/cjs/react.developme
|
||||||
|
nt.js:1208:15
|
||||||
|
|
||||||
|
1205: };
|
||||||
|
1206: exports.useContext = function (Context) {
|
||||||
|
1207: var dispatcher = resolveDispatcher();
|
||||||
|
1208: Context.$$typeof === REACT_CONSUMER_TYPE &&
|
||||||
|
1209: console.error(
|
||||||
|
1210 "Calling useContext(Context.Consumer) is not supported and will
|
||||||
|
: cause bugs. Did you mean to call useContext(Context) instead?"
|
||||||
|
1211: );
|
||||||
|
|
||||||
|
-process.env.NODE_ENV.expo
|
||||||
|
ts.useContext (/Users/spencertang/Workspace/gemini-cli/node_module
|
||||||
|
s/react/cjs/react.development.js:1208:15)
|
||||||
|
- useTerminalCapabilities (src/ui/hooks/useTerminalCapabilities.ts:15:19)
|
||||||
|
- useAlternateBuffer (src/ui/hooks/useAlternateBuffer.ts:15:24)
|
||||||
|
- ChoiceQuestionView (src/ui/components/AskUserDialog.tsx:484:29)
|
||||||
|
-Object.react-stack-bot
|
||||||
|
om-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/r
|
||||||
|
eact-reconciler/cjs/react-reconciler.development.js:158
|
||||||
|
59:20)
|
||||||
|
-renderWithHo
|
||||||
|
ks (/Users/spencertang/Workspace/gemini-cli/node_modules/react-recon
|
||||||
|
ciler/cjs/react-reconciler.development.js:3221:22)
|
||||||
|
-updateFunctionCom
|
||||||
|
onent (/Users/spencertang/Workspace/gemini-cli/node_modules/react-
|
||||||
|
reconciler/cjs/react-reconciler.development.js:6475:19)
|
||||||
|
-beginWor
|
||||||
|
(/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconcile
|
||||||
|
r/cjs/react-reconciler.development.js:8009:18)
|
||||||
|
-runWithFiberIn
|
||||||
|
EV (/Users/spencertang/Workspace/gemini-cli/node_modules/react-rec
|
||||||
|
onciler/cjs/react-reconciler.development.js:1738:13)
|
||||||
|
-performUnitOfW
|
||||||
|
rk (/Users/spencertang/Workspace/gemini-cli/node_modules/react-rec
|
||||||
|
onciler/cjs/react-reconciler.development.js:12834:22)
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: false) > shows scroll arrows correctly when useAlternateBuffer is false 1`] = `
|
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: false) > shows scroll arrows correctly when useAlternateBuffer is false 1`] = `
|
||||||
"Choose an option
|
"Choose an option
|
||||||
|
|
||||||
@@ -75,6 +163,48 @@ Enter to select · ↑/↓ to navigate · Esc to cancel
|
|||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: true) > shows scroll arrows correctly when useAlternateBuffer is true 2`] = `
|
||||||
|
"
|
||||||
|
ERROR Cannot read properties of undefined (reading '$$typeof')
|
||||||
|
|
||||||
|
/Users/spencertang/Workspace/gemini-cli/node_modules/react/cjs/react.development.js:1208:15
|
||||||
|
|
||||||
|
1205: };
|
||||||
|
1206: exports.useContext = function (Context) {
|
||||||
|
1207: var dispatcher = resolveDispatcher();
|
||||||
|
1208: Context.$$typeof === REACT_CONSUMER_TYPE &&
|
||||||
|
1209: console.error(
|
||||||
|
1210 "Calling useContext(Context.Consumer) is not supported and will cause bugs. Did you
|
||||||
|
: mean to call useContext(Context) instead?"
|
||||||
|
1211: );
|
||||||
|
|
||||||
|
-process.env.NODE_ENV.exports
|
||||||
|
useContext (/Users/spencertang/Workspace/gemini-cli/node_modules/react/cjs/react
|
||||||
|
.development.js:1208:15)
|
||||||
|
- useTerminalCapabilities (src/ui/hooks/useTerminalCapabilities.ts:15:19)
|
||||||
|
- useAlternateBuffer (src/ui/hooks/useAlternateBuffer.ts:15:24)
|
||||||
|
- ChoiceQuestionView (src/ui/components/AskUserDialog.tsx:484:29)
|
||||||
|
-Object.react-stack-bott
|
||||||
|
m-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs
|
||||||
|
/react-reconciler.development.js:15859:20)
|
||||||
|
-renderWithHoo
|
||||||
|
s (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-rec
|
||||||
|
onciler.development.js:3221:22)
|
||||||
|
-updateFunctionComp
|
||||||
|
nent (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/reac
|
||||||
|
t-reconciler.development.js:6475:19)
|
||||||
|
-beginWor
|
||||||
|
(/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconcil
|
||||||
|
er.development.js:8009:18)
|
||||||
|
-runWithFiberIn
|
||||||
|
EV (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-re
|
||||||
|
conciler.development.js:1738:13)
|
||||||
|
-performUnitOfW
|
||||||
|
rk (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-re
|
||||||
|
conciler.development.js:12834:22)
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`AskUserDialog > Text type questions > renders text input for type: "text" 1`] = `
|
exports[`AskUserDialog > Text type questions > renders text input for type: "text" 1`] = `
|
||||||
"What should we name this component?
|
"What should we name this component?
|
||||||
|
|
||||||
@@ -201,3 +331,45 @@ README → (not answered)
|
|||||||
Enter to submit · Tab/Shift+Tab to edit answers · Esc to cancel
|
Enter to submit · Tab/Shift+Tab to edit answers · Esc to cancel
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`AskUserDialog > shows warning for unanswered questions on Review tab 2`] = `
|
||||||
|
"
|
||||||
|
ERROR Cannot read properties of undefined (reading '$$typeof')
|
||||||
|
|
||||||
|
/Users/spencertang/Workspace/gemini-cli/node_modules/react/cjs/react.development.js:1208:15
|
||||||
|
|
||||||
|
1205: };
|
||||||
|
1206: exports.useContext = function (Context) {
|
||||||
|
1207: var dispatcher = resolveDispatcher();
|
||||||
|
1208: Context.$$typeof === REACT_CONSUMER_TYPE &&
|
||||||
|
1209: console.error(
|
||||||
|
1210: "Calling useContext(Context.Consumer) is not supported and will cause bugs. Did you mean to call
|
||||||
|
useContext(Context) instead?"
|
||||||
|
1211: );
|
||||||
|
|
||||||
|
-process.env.NODE_ENV.exports.useCo
|
||||||
|
text (/Users/spencertang/Workspace/gemini-cli/node_modules/react/cjs/react.development.j
|
||||||
|
s:1208:15)
|
||||||
|
- useTerminalCapabilities (src/ui/hooks/useTerminalCapabilities.ts:15:19)
|
||||||
|
- useAlternateBuffer (src/ui/hooks/useAlternateBuffer.ts:15:24)
|
||||||
|
- ChoiceQuestionView (src/ui/components/AskUserDialog.tsx:484:29)
|
||||||
|
-Object.react-stack-botto
|
||||||
|
-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconciler.d
|
||||||
|
evelopment.js:15859:20)
|
||||||
|
-renderWithHook
|
||||||
|
(/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconciler.development
|
||||||
|
.js:3221:22)
|
||||||
|
-updateFunctionCompo
|
||||||
|
ent (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconciler.develo
|
||||||
|
pment.js:6475:19)
|
||||||
|
-beginWork
|
||||||
|
(/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconciler.development.js:8
|
||||||
|
009:18)
|
||||||
|
-runWithFiberInD
|
||||||
|
V (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconciler.developmen
|
||||||
|
t.js:1738:13)
|
||||||
|
-performUnitOfWo
|
||||||
|
k (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconciler.developmen
|
||||||
|
t.js:12834:22)
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|||||||
@@ -6,6 +6,51 @@ Spinner Initializing...
|
|||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`ConfigInitDisplay > handles empty clients map 2`] = `
|
||||||
|
"
|
||||||
|
ERROR Cannot read properties of undefined (reading 'isKittyProtocolEnabled')
|
||||||
|
|
||||||
|
src/ui/contexts/KeypressContext.tsx:797:36
|
||||||
|
|
||||||
|
794: process.stdin.setEncoding('utf8'); // Make data events emit strings
|
||||||
|
795:
|
||||||
|
796: let processor = nonKeyboardEventFilter(broadcast);
|
||||||
|
797: if (!terminalCapabilityManager.isKittyProtocolEnabled()) {
|
||||||
|
798: processor = bufferFastReturn(processor);
|
||||||
|
799: }
|
||||||
|
800: processor = bufferBackslashEnter(processor);
|
||||||
|
|
||||||
|
- (src/ui/contexts/KeypressContext.tsx:797:36)
|
||||||
|
-Object.react-stack-bott
|
||||||
|
m-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs
|
||||||
|
/react-reconciler.development.js:15945:20)
|
||||||
|
-runWithFiberIn
|
||||||
|
EV (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-re
|
||||||
|
conciler.development.js:1738:13)
|
||||||
|
-commitHookEffectList
|
||||||
|
ount (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
|
||||||
|
act-reconciler.development.js:9516:29)
|
||||||
|
-commitHookPassiveMount
|
||||||
|
ffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/
|
||||||
|
react-reconciler.development.js:9639:11)
|
||||||
|
-commitPassiveMountOn
|
||||||
|
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
|
||||||
|
act-reconciler.development.js:11364:13)
|
||||||
|
-recursivelyTraversePassiveM
|
||||||
|
untEffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler
|
||||||
|
/cjs/react-reconciler.development.js:11338:11)
|
||||||
|
-commitPassiveMountOn
|
||||||
|
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
|
||||||
|
act-reconciler.development.js:11479:11)
|
||||||
|
-recursivelyTraversePassiveM
|
||||||
|
untEffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler
|
||||||
|
/cjs/react-reconciler.development.js:11338:11)
|
||||||
|
-commitPassiveMountOn
|
||||||
|
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
|
||||||
|
act-reconciler.development.js:11357:11)
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`ConfigInitDisplay > renders initial state 1`] = `
|
exports[`ConfigInitDisplay > renders initial state 1`] = `
|
||||||
"
|
"
|
||||||
Spinner Initializing...
|
Spinner Initializing...
|
||||||
@@ -18,8 +63,98 @@ Spinner Connecting to MCP servers... (0/5) - Waiting for: s1, s2, s3, +2 more
|
|||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`ConfigInitDisplay > truncates list of waiting servers if too many 2`] = `
|
||||||
|
"
|
||||||
|
ERROR Cannot read properties of undefined (reading 'isKittyProtocolEnabled')
|
||||||
|
|
||||||
|
src/ui/contexts/KeypressContext.tsx:797:36
|
||||||
|
|
||||||
|
794: process.stdin.setEncoding('utf8'); // Make data events emit strings
|
||||||
|
795:
|
||||||
|
796: let processor = nonKeyboardEventFilter(broadcast);
|
||||||
|
797: if (!terminalCapabilityManager.isKittyProtocolEnabled()) {
|
||||||
|
798: processor = bufferFastReturn(processor);
|
||||||
|
799: }
|
||||||
|
800: processor = bufferBackslashEnter(processor);
|
||||||
|
|
||||||
|
- (src/ui/contexts/KeypressContext.tsx:797:36)
|
||||||
|
-Object.react-stack-bott
|
||||||
|
m-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs
|
||||||
|
/react-reconciler.development.js:15945:20)
|
||||||
|
-runWithFiberIn
|
||||||
|
EV (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-re
|
||||||
|
conciler.development.js:1738:13)
|
||||||
|
-commitHookEffectList
|
||||||
|
ount (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
|
||||||
|
act-reconciler.development.js:9516:29)
|
||||||
|
-commitHookPassiveMount
|
||||||
|
ffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/
|
||||||
|
react-reconciler.development.js:9639:11)
|
||||||
|
-commitPassiveMountOn
|
||||||
|
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
|
||||||
|
act-reconciler.development.js:11364:13)
|
||||||
|
-recursivelyTraversePassiveM
|
||||||
|
untEffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler
|
||||||
|
/cjs/react-reconciler.development.js:11338:11)
|
||||||
|
-commitPassiveMountOn
|
||||||
|
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
|
||||||
|
act-reconciler.development.js:11479:11)
|
||||||
|
-recursivelyTraversePassiveM
|
||||||
|
untEffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler
|
||||||
|
/cjs/react-reconciler.development.js:11338:11)
|
||||||
|
-commitPassiveMountOn
|
||||||
|
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
|
||||||
|
act-reconciler.development.js:11357:11)
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`ConfigInitDisplay > updates message on McpClientUpdate event 1`] = `
|
exports[`ConfigInitDisplay > updates message on McpClientUpdate event 1`] = `
|
||||||
"
|
"
|
||||||
Spinner Connecting to MCP servers... (1/2) - Waiting for: server2
|
Spinner Connecting to MCP servers... (1/2) - Waiting for: server2
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`ConfigInitDisplay > updates message on McpClientUpdate event 2`] = `
|
||||||
|
"
|
||||||
|
ERROR Cannot read properties of undefined (reading 'isKittyProtocolEnabled')
|
||||||
|
|
||||||
|
src/ui/contexts/KeypressContext.tsx:797:36
|
||||||
|
|
||||||
|
794: process.stdin.setEncoding('utf8'); // Make data events emit strings
|
||||||
|
795:
|
||||||
|
796: let processor = nonKeyboardEventFilter(broadcast);
|
||||||
|
797: if (!terminalCapabilityManager.isKittyProtocolEnabled()) {
|
||||||
|
798: processor = bufferFastReturn(processor);
|
||||||
|
799: }
|
||||||
|
800: processor = bufferBackslashEnter(processor);
|
||||||
|
|
||||||
|
- (src/ui/contexts/KeypressContext.tsx:797:36)
|
||||||
|
-Object.react-stack-bott
|
||||||
|
m-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs
|
||||||
|
/react-reconciler.development.js:15945:20)
|
||||||
|
-runWithFiberIn
|
||||||
|
EV (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-re
|
||||||
|
conciler.development.js:1738:13)
|
||||||
|
-commitHookEffectList
|
||||||
|
ount (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
|
||||||
|
act-reconciler.development.js:9516:29)
|
||||||
|
-commitHookPassiveMount
|
||||||
|
ffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/
|
||||||
|
react-reconciler.development.js:9639:11)
|
||||||
|
-commitPassiveMountOn
|
||||||
|
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
|
||||||
|
act-reconciler.development.js:11364:13)
|
||||||
|
-recursivelyTraversePassiveM
|
||||||
|
untEffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler
|
||||||
|
/cjs/react-reconciler.development.js:11338:11)
|
||||||
|
-commitPassiveMountOn
|
||||||
|
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
|
||||||
|
act-reconciler.development.js:11479:11)
|
||||||
|
-recursivelyTraversePassiveM
|
||||||
|
untEffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler
|
||||||
|
/cjs/react-reconciler.development.js:11338:11)
|
||||||
|
-commitPassiveMountOn
|
||||||
|
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
|
||||||
|
act-reconciler.development.js:11357:11)
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,378 +0,0 @@
|
|||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright 2025 Google LLC
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
||||||
import { TerminalCapabilityManager } from './terminalCapabilityManager.js';
|
|
||||||
import { EventEmitter } from 'node:events';
|
|
||||||
import {
|
|
||||||
enableKittyKeyboardProtocol,
|
|
||||||
enableModifyOtherKeys,
|
|
||||||
} from '@google/gemini-cli-core';
|
|
||||||
import * as fs from 'node:fs';
|
|
||||||
|
|
||||||
// Mock fs
|
|
||||||
vi.mock('node:fs', () => ({
|
|
||||||
writeSync: vi.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Mock core
|
|
||||||
vi.mock('@google/gemini-cli-core', () => ({
|
|
||||||
debugLogger: {
|
|
||||||
log: vi.fn(),
|
|
||||||
warn: vi.fn(),
|
|
||||||
},
|
|
||||||
enableKittyKeyboardProtocol: vi.fn(),
|
|
||||||
disableKittyKeyboardProtocol: vi.fn(),
|
|
||||||
enableModifyOtherKeys: vi.fn(),
|
|
||||||
disableModifyOtherKeys: vi.fn(),
|
|
||||||
enableBracketedPasteMode: vi.fn(),
|
|
||||||
disableBracketedPasteMode: vi.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('TerminalCapabilityManager', () => {
|
|
||||||
let stdin: EventEmitter & {
|
|
||||||
isTTY?: boolean;
|
|
||||||
isRaw?: boolean;
|
|
||||||
setRawMode?: (mode: boolean) => void;
|
|
||||||
removeListener?: (
|
|
||||||
event: string,
|
|
||||||
listener: (...args: unknown[]) => void,
|
|
||||||
) => void;
|
|
||||||
};
|
|
||||||
let stdout: { isTTY?: boolean; fd?: number };
|
|
||||||
// Save original process properties
|
|
||||||
const originalStdin = process.stdin;
|
|
||||||
const originalStdout = process.stdout;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
vi.resetAllMocks();
|
|
||||||
|
|
||||||
// Reset singleton
|
|
||||||
TerminalCapabilityManager.resetInstanceForTesting();
|
|
||||||
|
|
||||||
// Setup process mocks
|
|
||||||
stdin = new EventEmitter();
|
|
||||||
stdin.isTTY = true;
|
|
||||||
stdin.isRaw = false;
|
|
||||||
stdin.setRawMode = vi.fn();
|
|
||||||
stdin.removeListener = vi.fn();
|
|
||||||
|
|
||||||
stdout = { isTTY: true, fd: 1 };
|
|
||||||
|
|
||||||
// Use defineProperty to mock process.stdin/stdout
|
|
||||||
Object.defineProperty(process, 'stdin', {
|
|
||||||
value: stdin,
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
Object.defineProperty(process, 'stdout', {
|
|
||||||
value: stdout,
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
vi.useFakeTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
vi.useRealTimers();
|
|
||||||
// Restore original process properties
|
|
||||||
Object.defineProperty(process, 'stdin', {
|
|
||||||
value: originalStdin,
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
Object.defineProperty(process, 'stdout', {
|
|
||||||
value: originalStdout,
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should detect Kitty support when u response is received', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
// Simulate Kitty response: \x1b[?1u
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?1u'));
|
|
||||||
// Complete detection with DA1
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
expect(manager.isKittyProtocolEnabled()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should detect Background Color', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
// Simulate OSC 11 response
|
|
||||||
// \x1b]11;rgb:0000/ff00/0000\x1b\
|
|
||||||
// RGB: 0, 255, 0 -> #00ff00
|
|
||||||
stdin.emit('data', Buffer.from('\x1b]11;rgb:0000/ffff/0000\x1b\\'));
|
|
||||||
// Complete detection with DA1
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
expect(manager.getTerminalBackgroundColor()).toBe('#00ff00');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should detect Terminal Name', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
// Simulate Terminal Name response
|
|
||||||
stdin.emit('data', Buffer.from('\x1bP>|WezTerm 20240203\x1b\\'));
|
|
||||||
// Complete detection with DA1
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
expect(manager.getTerminalName()).toBe('WezTerm 20240203');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should complete early if sentinel (DA1) is found', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?1u'));
|
|
||||||
stdin.emit('data', Buffer.from('\x1b]11;rgb:0000/0000/0000\x1b\\'));
|
|
||||||
// Sentinel
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
// Should resolve without waiting for timeout
|
|
||||||
await promise;
|
|
||||||
|
|
||||||
expect(manager.isKittyProtocolEnabled()).toBe(true);
|
|
||||||
expect(manager.getTerminalBackgroundColor()).toBe('#000000');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should timeout if no DA1 (c) is received', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
// Simulate only Kitty response
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?1u'));
|
|
||||||
|
|
||||||
// Advance to timeout
|
|
||||||
vi.advanceTimersByTime(1000);
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
expect(manager.isKittyProtocolEnabled()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not detect Kitty if only DA1 (c) is received', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
// Simulate DA1 response only: \x1b[?62;c
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
expect(manager.isKittyProtocolEnabled()).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle split chunks', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
// Split response: \x1b[? 1u
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?'));
|
|
||||||
stdin.emit('data', Buffer.from('1u'));
|
|
||||||
// Complete with DA1
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
expect(manager.isKittyProtocolEnabled()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('modifyOtherKeys detection', () => {
|
|
||||||
it('should detect modifyOtherKeys support (level 2)', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
// Simulate modifyOtherKeys level 2 response: \x1b[>4;2m
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[>4;2m'));
|
|
||||||
// Complete detection with DA1
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
|
|
||||||
expect(enableModifyOtherKeys).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not enable modifyOtherKeys for level 0', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
// Simulate modifyOtherKeys level 0 response: \x1b[>4;0m
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[>4;0m'));
|
|
||||||
// Complete detection with DA1
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
|
|
||||||
expect(enableModifyOtherKeys).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should prefer Kitty over modifyOtherKeys', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
// Simulate both Kitty and modifyOtherKeys responses
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?1u'));
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[>4;2m'));
|
|
||||||
// Complete detection with DA1
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
expect(manager.isKittyProtocolEnabled()).toBe(true);
|
|
||||||
|
|
||||||
expect(enableKittyKeyboardProtocol).toHaveBeenCalled();
|
|
||||||
expect(enableModifyOtherKeys).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should enable modifyOtherKeys when Kitty not supported', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
// Simulate only modifyOtherKeys response (no Kitty)
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[>4;2m'));
|
|
||||||
// Complete detection with DA1
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
|
|
||||||
expect(manager.isKittyProtocolEnabled()).toBe(false);
|
|
||||||
expect(enableModifyOtherKeys).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle split modifyOtherKeys response chunks', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
// Split response: \x1b[>4;2m
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[>4;'));
|
|
||||||
stdin.emit('data', Buffer.from('2m'));
|
|
||||||
// Complete detection with DA1
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
|
|
||||||
expect(enableModifyOtherKeys).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should detect modifyOtherKeys with other capabilities', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
stdin.emit('data', Buffer.from('\x1b]11;rgb:1a1a/1a1a/1a1a\x1b\\')); // background color
|
|
||||||
stdin.emit('data', Buffer.from('\x1bP>|tmux\x1b\\')); // Terminal name
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[>4;2m')); // modifyOtherKeys
|
|
||||||
// Complete detection with DA1
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
|
|
||||||
expect(manager.getTerminalBackgroundColor()).toBe('#1a1a1a');
|
|
||||||
expect(manager.getTerminalName()).toBe('tmux');
|
|
||||||
|
|
||||||
expect(enableModifyOtherKeys).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not enable modifyOtherKeys without explicit response', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
const promise = manager.detectCapabilities();
|
|
||||||
|
|
||||||
// Simulate only DA1 response (no specific MOK or Kitty response)
|
|
||||||
stdin.emit('data', Buffer.from('\x1b[?62c'));
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
|
|
||||||
expect(manager.isKittyProtocolEnabled()).toBe(false);
|
|
||||||
expect(enableModifyOtherKeys).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should wrap queries in hidden/clear sequence', async () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
void manager.detectCapabilities();
|
|
||||||
|
|
||||||
expect(fs.writeSync).toHaveBeenCalledWith(
|
|
||||||
expect.anything(),
|
|
||||||
// eslint-disable-next-line no-control-regex
|
|
||||||
expect.stringMatching(/^\x1b\[8m.*\x1b\[2K\r\x1b\[0m$/s),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('supportsOsc9Notifications', () => {
|
|
||||||
const manager = TerminalCapabilityManager.getInstance();
|
|
||||||
|
|
||||||
it.each([
|
|
||||||
{
|
|
||||||
name: 'WezTerm (terminal name)',
|
|
||||||
terminalName: 'WezTerm',
|
|
||||||
env: {},
|
|
||||||
expected: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'iTerm.app (terminal name)',
|
|
||||||
terminalName: 'iTerm.app',
|
|
||||||
env: {},
|
|
||||||
expected: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'ghostty (terminal name)',
|
|
||||||
terminalName: 'ghostty',
|
|
||||||
env: {},
|
|
||||||
expected: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'kitty (terminal name)',
|
|
||||||
terminalName: 'kitty',
|
|
||||||
env: {},
|
|
||||||
expected: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'some-other-term (terminal name)',
|
|
||||||
terminalName: 'some-other-term',
|
|
||||||
env: {},
|
|
||||||
expected: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'iTerm.app (TERM_PROGRAM)',
|
|
||||||
terminalName: undefined,
|
|
||||||
env: { TERM_PROGRAM: 'iTerm.app' },
|
|
||||||
expected: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'vscode (TERM_PROGRAM)',
|
|
||||||
terminalName: undefined,
|
|
||||||
env: { TERM_PROGRAM: 'vscode' },
|
|
||||||
expected: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'xterm-kitty (TERM)',
|
|
||||||
terminalName: undefined,
|
|
||||||
env: { TERM: 'xterm-kitty' },
|
|
||||||
expected: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'xterm-256color (TERM)',
|
|
||||||
terminalName: undefined,
|
|
||||||
env: { TERM: 'xterm-256color' },
|
|
||||||
expected: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Windows Terminal (WT_SESSION)',
|
|
||||||
terminalName: 'iTerm.app',
|
|
||||||
env: { WT_SESSION: 'some-guid' },
|
|
||||||
expected: false,
|
|
||||||
},
|
|
||||||
])(
|
|
||||||
'should return $expected for $name',
|
|
||||||
({ terminalName, env, expected }) => {
|
|
||||||
vi.spyOn(manager, 'getTerminalName').mockReturnValue(terminalName);
|
|
||||||
expect(manager.supportsOsc9Notifications(env)).toBe(expected);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -84,6 +84,7 @@ describe('SubAgentInvocation', () => {
|
|||||||
params: {},
|
params: {},
|
||||||
getDescription: vi.fn(),
|
getDescription: vi.fn(),
|
||||||
toolLocations: vi.fn(),
|
toolLocations: vi.fn(),
|
||||||
|
isSensitive: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
MockSubagentToolWrapper.prototype.build = vi
|
MockSubagentToolWrapper.prototype.build = vi
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ export interface UpdatePolicy {
|
|||||||
argsPattern?: string;
|
argsPattern?: string;
|
||||||
commandPrefix?: string | string[];
|
commandPrefix?: string | string[];
|
||||||
mcpName?: string;
|
mcpName?: string;
|
||||||
|
isSensitive?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ToolPolicyRejection {
|
export interface ToolPolicyRejection {
|
||||||
|
|||||||
@@ -43,7 +43,15 @@ class ActivateSkillToolInvocation extends BaseToolInvocation<
|
|||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, _toolName, _toolDisplayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
_toolName,
|
||||||
|
_toolDisplayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true, // ActivateSkill is always sensitive
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getDescription(): string {
|
getDescription(): string {
|
||||||
@@ -185,13 +193,14 @@ export class ActivateSkillTool extends BaseDeclarativeTool<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
_isSensitive?: boolean,
|
||||||
): ToolInvocation<ActivateSkillToolParams, ToolResult> {
|
): ToolInvocation<ActivateSkillToolParams, ToolResult> {
|
||||||
return new ActivateSkillToolInvocation(
|
return new ActivateSkillToolInvocation(
|
||||||
this.config,
|
this.config,
|
||||||
params,
|
params,
|
||||||
messageBus,
|
messageBus,
|
||||||
_toolName,
|
_toolName,
|
||||||
_toolDisplayName ?? 'Activate Skill',
|
_toolDisplayName,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -293,6 +293,7 @@ describe('AskUserTool', () => {
|
|||||||
getDescription: vi.fn().mockReturnValue(''),
|
getDescription: vi.fn().mockReturnValue(''),
|
||||||
toolLocations: vi.fn().mockReturnValue([]),
|
toolLocations: vi.fn().mockReturnValue([]),
|
||||||
shouldConfirmExecute: vi.fn().mockResolvedValue(false),
|
shouldConfirmExecute: vi.fn().mockResolvedValue(false),
|
||||||
|
isSensitive: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildSpy = vi.spyOn(tool, 'build').mockReturnValue(mockInvocation);
|
const buildSpy = vi.spyOn(tool, 'build').mockReturnValue(mockInvocation);
|
||||||
|
|||||||
@@ -202,6 +202,21 @@ describe('EditTool', () => {
|
|||||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be marked as sensitive and pass the flag to its invocations', () => {
|
||||||
|
// Check the tool definition itself
|
||||||
|
expect(tool.isSensitive).toBe(true);
|
||||||
|
|
||||||
|
// Build an invocation and check the instance
|
||||||
|
const params: EditToolParams = {
|
||||||
|
file_path: path.join(rootDir, 'test.txt'),
|
||||||
|
instruction: 'An instruction',
|
||||||
|
old_string: 'old',
|
||||||
|
new_string: 'new',
|
||||||
|
};
|
||||||
|
const invocation = tool.build(params);
|
||||||
|
expect(invocation.isSensitive).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
describe('applyReplacement', () => {
|
describe('applyReplacement', () => {
|
||||||
it('should return newString if isNewFile is true', () => {
|
it('should return newString if isNewFile is true', () => {
|
||||||
expect(applyReplacement(null, 'old', 'new', true)).toBe('new');
|
expect(applyReplacement(null, 'old', 'new', true)).toBe('new');
|
||||||
|
|||||||
@@ -434,8 +434,17 @@ class EditToolInvocation
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
toolName?: string,
|
toolName?: string,
|
||||||
displayName?: string,
|
displayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, toolName, displayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
toolName,
|
||||||
|
displayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
override toolLocations(): ToolLocation[] {
|
override toolLocations(): ToolLocation[] {
|
||||||
@@ -956,6 +965,9 @@ export class EditTool
|
|||||||
messageBus,
|
messageBus,
|
||||||
true, // isOutputMarkdown
|
true, // isOutputMarkdown
|
||||||
false, // canUpdateOutput
|
false, // canUpdateOutput
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1001,6 +1013,9 @@ export class EditTool
|
|||||||
protected createInvocation(
|
protected createInvocation(
|
||||||
params: EditToolParams,
|
params: EditToolParams,
|
||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
|
_toolName?: string,
|
||||||
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<EditToolParams, ToolResult> {
|
): ToolInvocation<EditToolParams, ToolResult> {
|
||||||
return new EditToolInvocation(
|
return new EditToolInvocation(
|
||||||
this.config,
|
this.config,
|
||||||
@@ -1008,6 +1023,7 @@ export class EditTool
|
|||||||
messageBus,
|
messageBus,
|
||||||
this.name,
|
this.name,
|
||||||
this.displayName,
|
this.displayName,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,8 +79,17 @@ class GetInternalDocsInvocation extends BaseToolInvocation<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, _toolName, _toolDisplayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
_toolName,
|
||||||
|
_toolDisplayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
override async shouldConfirmExecute(
|
override async shouldConfirmExecute(
|
||||||
@@ -165,6 +174,9 @@ export class GetInternalDocsTool extends BaseDeclarativeTool<
|
|||||||
messageBus,
|
messageBus,
|
||||||
/* isOutputMarkdown */ true,
|
/* isOutputMarkdown */ true,
|
||||||
/* canUpdateOutput */ false,
|
/* canUpdateOutput */ false,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,12 +185,14 @@ export class GetInternalDocsTool extends BaseDeclarativeTool<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<GetInternalDocsParams, ToolResult> {
|
): ToolInvocation<GetInternalDocsParams, ToolResult> {
|
||||||
return new GetInternalDocsInvocation(
|
return new GetInternalDocsInvocation(
|
||||||
params,
|
params,
|
||||||
messageBus,
|
messageBus,
|
||||||
_toolName ?? GetInternalDocsTool.Name,
|
_toolName ?? GetInternalDocsTool.Name,
|
||||||
_toolDisplayName,
|
_toolDisplayName,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,8 +96,17 @@ class GlobToolInvocation extends BaseToolInvocation<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, _toolName, _toolDisplayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
_toolName,
|
||||||
|
_toolDisplayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getDescription(): string {
|
getDescription(): string {
|
||||||
@@ -278,6 +287,9 @@ export class GlobTool extends BaseDeclarativeTool<GlobToolParams, ToolResult> {
|
|||||||
messageBus,
|
messageBus,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,6 +340,7 @@ export class GlobTool extends BaseDeclarativeTool<GlobToolParams, ToolResult> {
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<GlobToolParams, ToolResult> {
|
): ToolInvocation<GlobToolParams, ToolResult> {
|
||||||
return new GlobToolInvocation(
|
return new GlobToolInvocation(
|
||||||
this.config,
|
this.config,
|
||||||
@@ -335,6 +348,7 @@ export class GlobTool extends BaseDeclarativeTool<GlobToolParams, ToolResult> {
|
|||||||
messageBus,
|
messageBus,
|
||||||
_toolName,
|
_toolName,
|
||||||
_toolDisplayName,
|
_toolDisplayName,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,8 +83,17 @@ class GrepToolInvocation extends BaseToolInvocation<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, _toolName, _toolDisplayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
_toolName,
|
||||||
|
_toolDisplayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
this.fileExclusions = config.getFileExclusions();
|
this.fileExclusions = config.getFileExclusions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,6 +610,9 @@ export class GrepTool extends BaseDeclarativeTool<GrepToolParams, ToolResult> {
|
|||||||
messageBus,
|
messageBus,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,6 +688,7 @@ export class GrepTool extends BaseDeclarativeTool<GrepToolParams, ToolResult> {
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<GrepToolParams, ToolResult> {
|
): ToolInvocation<GrepToolParams, ToolResult> {
|
||||||
return new GrepToolInvocation(
|
return new GrepToolInvocation(
|
||||||
this.config,
|
this.config,
|
||||||
@@ -683,6 +696,7 @@ export class GrepTool extends BaseDeclarativeTool<GrepToolParams, ToolResult> {
|
|||||||
messageBus,
|
messageBus,
|
||||||
_toolName,
|
_toolName,
|
||||||
_toolDisplayName,
|
_toolDisplayName,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,8 +78,17 @@ class LSToolInvocation extends BaseToolInvocation<LSToolParams, ToolResult> {
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, _toolName, _toolDisplayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
_toolName,
|
||||||
|
_toolDisplayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -293,6 +302,9 @@ export class LSTool extends BaseDeclarativeTool<LSToolParams, ToolResult> {
|
|||||||
messageBus,
|
messageBus,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,13 +328,15 @@ export class LSTool extends BaseDeclarativeTool<LSToolParams, ToolResult> {
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<LSToolParams, ToolResult> {
|
): ToolInvocation<LSToolParams, ToolResult> {
|
||||||
return new LSToolInvocation(
|
return new LSToolInvocation(
|
||||||
this.config,
|
this.config,
|
||||||
params,
|
params,
|
||||||
messageBus ?? this.messageBus,
|
messageBus,
|
||||||
_toolName,
|
_toolName,
|
||||||
_toolDisplayName,
|
_toolDisplayName,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ export class DiscoveredMCPToolInvocation extends BaseToolInvocation<
|
|||||||
private readonly toolDescription?: string,
|
private readonly toolDescription?: string,
|
||||||
private readonly toolParameterSchema?: unknown,
|
private readonly toolParameterSchema?: unknown,
|
||||||
toolAnnotationsData?: Record<string, unknown>,
|
toolAnnotationsData?: Record<string, unknown>,
|
||||||
|
isSensitive: boolean = false,
|
||||||
) {
|
) {
|
||||||
// Use composite format for policy checks: serverName__toolName
|
// Use composite format for policy checks: serverName__toolName
|
||||||
// This enables server wildcards (e.g., "google-workspace__*")
|
// This enables server wildcards (e.g., "google-workspace__*")
|
||||||
@@ -105,6 +106,7 @@ export class DiscoveredMCPToolInvocation extends BaseToolInvocation<
|
|||||||
displayName,
|
displayName,
|
||||||
serverName,
|
serverName,
|
||||||
toolAnnotationsData,
|
toolAnnotationsData,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,6 +285,7 @@ export class DiscoveredMCPTool extends BaseDeclarativeTool<
|
|||||||
false, // canUpdateOutput,
|
false, // canUpdateOutput,
|
||||||
extensionName,
|
extensionName,
|
||||||
extensionId,
|
extensionId,
|
||||||
|
true, // isSensitive
|
||||||
);
|
);
|
||||||
this._isReadOnly = isReadOnly;
|
this._isReadOnly = isReadOnly;
|
||||||
}
|
}
|
||||||
@@ -331,6 +334,7 @@ export class DiscoveredMCPTool extends BaseDeclarativeTool<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_displayName?: string,
|
_displayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<ToolParams, ToolResult> {
|
): ToolInvocation<ToolParams, ToolResult> {
|
||||||
return new DiscoveredMCPToolInvocation(
|
return new DiscoveredMCPToolInvocation(
|
||||||
this.mcpTool,
|
this.mcpTool,
|
||||||
@@ -344,6 +348,7 @@ export class DiscoveredMCPTool extends BaseDeclarativeTool<
|
|||||||
this.description,
|
this.description,
|
||||||
this.parameterSchema,
|
this.parameterSchema,
|
||||||
this._toolAnnotations,
|
this._toolAnnotations,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,6 +285,9 @@ export class MemoryTool
|
|||||||
messageBus,
|
messageBus,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,8 +114,17 @@ class ReadManyFilesToolInvocation extends BaseToolInvocation<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, _toolName, _toolDisplayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
_toolName,
|
||||||
|
_toolDisplayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getDescription(): string {
|
getDescription(): string {
|
||||||
@@ -474,6 +483,9 @@ export class ReadManyFilesTool extends BaseDeclarativeTool<
|
|||||||
messageBus,
|
messageBus,
|
||||||
true, // isOutputMarkdown
|
true, // isOutputMarkdown
|
||||||
false, // canUpdateOutput
|
false, // canUpdateOutput
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,6 +494,7 @@ export class ReadManyFilesTool extends BaseDeclarativeTool<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<ReadManyFilesParams, ToolResult> {
|
): ToolInvocation<ReadManyFilesParams, ToolResult> {
|
||||||
return new ReadManyFilesToolInvocation(
|
return new ReadManyFilesToolInvocation(
|
||||||
this.config,
|
this.config,
|
||||||
@@ -489,6 +502,7 @@ export class ReadManyFilesTool extends BaseDeclarativeTool<
|
|||||||
messageBus,
|
messageBus,
|
||||||
_toolName,
|
_toolName,
|
||||||
_toolDisplayName,
|
_toolDisplayName,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,8 +167,17 @@ class GrepToolInvocation extends BaseToolInvocation<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, _toolName, _toolDisplayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
_toolName,
|
||||||
|
_toolDisplayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute(signal: AbortSignal): Promise<ToolResult> {
|
async execute(signal: AbortSignal): Promise<ToolResult> {
|
||||||
@@ -584,6 +593,9 @@ export class RipGrepTool extends BaseDeclarativeTool<
|
|||||||
messageBus,
|
messageBus,
|
||||||
true, // isOutputMarkdown
|
true, // isOutputMarkdown
|
||||||
false, // canUpdateOutput
|
false, // canUpdateOutput
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
this.fileDiscoveryService = new FileDiscoveryService(
|
this.fileDiscoveryService = new FileDiscoveryService(
|
||||||
config.getTargetDir(),
|
config.getTargetDir(),
|
||||||
@@ -665,14 +677,16 @@ export class RipGrepTool extends BaseDeclarativeTool<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<RipGrepToolParams, ToolResult> {
|
): ToolInvocation<RipGrepToolParams, ToolResult> {
|
||||||
return new GrepToolInvocation(
|
return new GrepToolInvocation(
|
||||||
this.config,
|
this.config,
|
||||||
this.fileDiscoveryService,
|
this.fileDiscoveryService,
|
||||||
params,
|
params,
|
||||||
messageBus ?? this.messageBus,
|
messageBus,
|
||||||
_toolName,
|
_toolName,
|
||||||
_toolDisplayName,
|
_toolDisplayName,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,8 +68,17 @@ export class ShellToolInvocation extends BaseToolInvocation<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, _toolName, _toolDisplayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
_toolName,
|
||||||
|
_toolDisplayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getDescription(): string {
|
getDescription(): string {
|
||||||
@@ -479,6 +488,9 @@ export class ShellTool extends BaseDeclarativeTool<
|
|||||||
messageBus,
|
messageBus,
|
||||||
false, // output is not markdown
|
false, // output is not markdown
|
||||||
true, // output can be updated
|
true, // output can be updated
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,6 +516,7 @@ export class ShellTool extends BaseDeclarativeTool<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<ShellToolParams, ToolResult> {
|
): ToolInvocation<ShellToolParams, ToolResult> {
|
||||||
return new ShellToolInvocation(
|
return new ShellToolInvocation(
|
||||||
this.config,
|
this.config,
|
||||||
@@ -511,6 +524,7 @@ export class ShellTool extends BaseDeclarativeTool<
|
|||||||
messageBus,
|
messageBus,
|
||||||
_toolName,
|
_toolName,
|
||||||
_toolDisplayName,
|
_toolDisplayName,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class TestToolInvocation implements ToolInvocation<object, ToolResult> {
|
|||||||
constructor(
|
constructor(
|
||||||
readonly params: object,
|
readonly params: object,
|
||||||
private readonly executeFn: () => Promise<ToolResult>,
|
private readonly executeFn: () => Promise<ToolResult>,
|
||||||
|
readonly isSensitive: boolean = false,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getDescription(): string {
|
getDescription(): string {
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ export interface ToolInvocation<
|
|||||||
*/
|
*/
|
||||||
params: TParams;
|
params: TParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the tool is sensitive and requires specific policy approvals.
|
||||||
|
*/
|
||||||
|
isSensitive: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a pre-execution description of the tool operation.
|
* Gets a pre-execution description of the tool operation.
|
||||||
*
|
*
|
||||||
@@ -75,6 +80,7 @@ export interface ToolInvocation<
|
|||||||
export interface PolicyUpdateOptions {
|
export interface PolicyUpdateOptions {
|
||||||
commandPrefix?: string | string[];
|
commandPrefix?: string | string[];
|
||||||
mcpName?: string;
|
mcpName?: string;
|
||||||
|
argsPattern?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,6 +98,7 @@ export abstract class BaseToolInvocation<
|
|||||||
readonly _toolDisplayName?: string,
|
readonly _toolDisplayName?: string,
|
||||||
readonly _serverName?: string,
|
readonly _serverName?: string,
|
||||||
readonly _toolAnnotations?: Record<string, unknown>,
|
readonly _toolAnnotations?: Record<string, unknown>,
|
||||||
|
readonly isSensitive: boolean = false,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
abstract getDescription(): string;
|
abstract getDescription(): string;
|
||||||
@@ -152,6 +159,7 @@ export abstract class BaseToolInvocation<
|
|||||||
type: MessageBusType.UPDATE_POLICY,
|
type: MessageBusType.UPDATE_POLICY,
|
||||||
toolName: this._toolName,
|
toolName: this._toolName,
|
||||||
persist: outcome === ToolConfirmationOutcome.ProceedAlwaysAndSave,
|
persist: outcome === ToolConfirmationOutcome.ProceedAlwaysAndSave,
|
||||||
|
isSensitive: this.isSensitive,
|
||||||
...options,
|
...options,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -340,6 +348,11 @@ export interface ToolBuilder<
|
|||||||
*/
|
*/
|
||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the tool is sensitive and requires specific policy approvals.
|
||||||
|
*/
|
||||||
|
isSensitive: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates raw parameters and builds a ready-to-execute invocation.
|
* Validates raw parameters and builds a ready-to-execute invocation.
|
||||||
* @param params The raw, untrusted parameters from the model.
|
* @param params The raw, untrusted parameters from the model.
|
||||||
@@ -368,6 +381,7 @@ export abstract class DeclarativeTool<
|
|||||||
readonly canUpdateOutput: boolean = false,
|
readonly canUpdateOutput: boolean = false,
|
||||||
readonly extensionName?: string,
|
readonly extensionName?: string,
|
||||||
readonly extensionId?: string,
|
readonly extensionId?: string,
|
||||||
|
readonly isSensitive: boolean = false,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
get isReadOnly(): boolean {
|
get isReadOnly(): boolean {
|
||||||
@@ -498,6 +512,34 @@ export abstract class BaseDeclarativeTool<
|
|||||||
TParams extends object,
|
TParams extends object,
|
||||||
TResult extends ToolResult,
|
TResult extends ToolResult,
|
||||||
> extends DeclarativeTool<TParams, TResult> {
|
> extends DeclarativeTool<TParams, TResult> {
|
||||||
|
constructor(
|
||||||
|
name: string,
|
||||||
|
displayName: string,
|
||||||
|
description: string,
|
||||||
|
kind: Kind,
|
||||||
|
parameterSchema: unknown,
|
||||||
|
messageBus: MessageBus,
|
||||||
|
isOutputMarkdown: boolean = true,
|
||||||
|
canUpdateOutput: boolean = false,
|
||||||
|
extensionName?: string,
|
||||||
|
extensionId?: string,
|
||||||
|
isSensitive: boolean = false,
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
name,
|
||||||
|
displayName,
|
||||||
|
description,
|
||||||
|
kind,
|
||||||
|
parameterSchema,
|
||||||
|
messageBus,
|
||||||
|
isOutputMarkdown,
|
||||||
|
canUpdateOutput,
|
||||||
|
extensionName,
|
||||||
|
extensionId,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
build(params: TParams): ToolInvocation<TParams, TResult> {
|
build(params: TParams): ToolInvocation<TParams, TResult> {
|
||||||
const validationError = this.validateToolParams(params);
|
const validationError = this.validateToolParams(params);
|
||||||
if (validationError) {
|
if (validationError) {
|
||||||
@@ -508,6 +550,7 @@ export abstract class BaseDeclarativeTool<
|
|||||||
this.messageBus,
|
this.messageBus,
|
||||||
this.name,
|
this.name,
|
||||||
this.displayName,
|
this.displayName,
|
||||||
|
this.isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,6 +576,7 @@ export abstract class BaseDeclarativeTool<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<TParams, TResult>;
|
): ToolInvocation<TParams, TResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,6 +870,7 @@ export enum ToolConfirmationOutcome {
|
|||||||
|
|
||||||
export enum Kind {
|
export enum Kind {
|
||||||
Read = 'read',
|
Read = 'read',
|
||||||
|
Write = 'write',
|
||||||
Edit = 'edit',
|
Edit = 'edit',
|
||||||
Delete = 'delete',
|
Delete = 'delete',
|
||||||
Move = 'move',
|
Move = 'move',
|
||||||
@@ -842,6 +887,7 @@ export enum Kind {
|
|||||||
|
|
||||||
// Function kinds that have side effects
|
// Function kinds that have side effects
|
||||||
export const MUTATOR_KINDS: Kind[] = [
|
export const MUTATOR_KINDS: Kind[] = [
|
||||||
|
Kind.Write,
|
||||||
Kind.Edit,
|
Kind.Edit,
|
||||||
Kind.Delete,
|
Kind.Delete,
|
||||||
Kind.Move,
|
Kind.Move,
|
||||||
|
|||||||
@@ -178,8 +178,17 @@ class WebFetchToolInvocation extends BaseToolInvocation<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, _toolName, _toolDisplayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
_toolName,
|
||||||
|
_toolDisplayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async executeFallback(signal: AbortSignal): Promise<ToolResult> {
|
private async executeFallback(signal: AbortSignal): Promise<ToolResult> {
|
||||||
@@ -689,6 +698,9 @@ export class WebFetchTool extends BaseDeclarativeTool<
|
|||||||
messageBus,
|
messageBus,
|
||||||
true, // isOutputMarkdown
|
true, // isOutputMarkdown
|
||||||
false, // canUpdateOutput
|
false, // canUpdateOutput
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,6 +741,7 @@ export class WebFetchTool extends BaseDeclarativeTool<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<WebFetchToolParams, ToolResult> {
|
): ToolInvocation<WebFetchToolParams, ToolResult> {
|
||||||
return new WebFetchToolInvocation(
|
return new WebFetchToolInvocation(
|
||||||
this.config,
|
this.config,
|
||||||
@@ -736,6 +749,7 @@ export class WebFetchTool extends BaseDeclarativeTool<
|
|||||||
messageBus,
|
messageBus,
|
||||||
_toolName,
|
_toolName,
|
||||||
_toolDisplayName,
|
_toolDisplayName,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,8 +71,17 @@ class WebSearchToolInvocation extends BaseToolInvocation<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, _toolName, _toolDisplayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
_toolName,
|
||||||
|
_toolDisplayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
override getDescription(): string {
|
override getDescription(): string {
|
||||||
@@ -208,6 +217,9 @@ export class WebSearchTool extends BaseDeclarativeTool<
|
|||||||
messageBus,
|
messageBus,
|
||||||
true, // isOutputMarkdown
|
true, // isOutputMarkdown
|
||||||
false, // canUpdateOutput
|
false, // canUpdateOutput
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +242,7 @@ export class WebSearchTool extends BaseDeclarativeTool<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<WebSearchToolParams, WebSearchToolResult> {
|
): ToolInvocation<WebSearchToolParams, WebSearchToolResult> {
|
||||||
return new WebSearchToolInvocation(
|
return new WebSearchToolInvocation(
|
||||||
this.config,
|
this.config,
|
||||||
@@ -237,6 +250,7 @@ export class WebSearchTool extends BaseDeclarativeTool<
|
|||||||
messageBus ?? this.messageBus,
|
messageBus ?? this.messageBus,
|
||||||
_toolName,
|
_toolName,
|
||||||
_toolDisplayName,
|
_toolDisplayName,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -136,8 +136,17 @@ class WriteFileToolInvocation extends BaseToolInvocation<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
toolName?: string,
|
toolName?: string,
|
||||||
displayName?: string,
|
displayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, toolName, displayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
toolName,
|
||||||
|
displayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
this.resolvedPath = path.resolve(
|
this.resolvedPath = path.resolve(
|
||||||
this.config.getTargetDir(),
|
this.config.getTargetDir(),
|
||||||
this.params.file_path,
|
this.params.file_path,
|
||||||
@@ -429,11 +438,14 @@ export class WriteFileTool
|
|||||||
WriteFileTool.Name,
|
WriteFileTool.Name,
|
||||||
WRITE_FILE_DISPLAY_NAME,
|
WRITE_FILE_DISPLAY_NAME,
|
||||||
WRITE_FILE_DEFINITION.base.description!,
|
WRITE_FILE_DEFINITION.base.description!,
|
||||||
Kind.Edit,
|
Kind.Write,
|
||||||
WRITE_FILE_DEFINITION.base.parametersJsonSchema,
|
WRITE_FILE_DEFINITION.base.parametersJsonSchema,
|
||||||
messageBus,
|
messageBus,
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,6 +489,9 @@ export class WriteFileTool
|
|||||||
protected createInvocation(
|
protected createInvocation(
|
||||||
params: WriteFileToolParams,
|
params: WriteFileToolParams,
|
||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
|
_toolName?: string,
|
||||||
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<WriteFileToolParams, ToolResult> {
|
): ToolInvocation<WriteFileToolParams, ToolResult> {
|
||||||
return new WriteFileToolInvocation(
|
return new WriteFileToolInvocation(
|
||||||
this.config,
|
this.config,
|
||||||
@@ -484,6 +499,7 @@ export class WriteFileTool
|
|||||||
messageBus ?? this.messageBus,
|
messageBus ?? this.messageBus,
|
||||||
this.name,
|
this.name,
|
||||||
this.displayName,
|
this.displayName,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,17 @@ class WriteTodosToolInvocation extends BaseToolInvocation<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_toolDisplayName?: string,
|
_toolDisplayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
) {
|
) {
|
||||||
super(params, messageBus, _toolName, _toolDisplayName);
|
super(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
_toolName,
|
||||||
|
_toolDisplayName,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
isSensitive,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getDescription(): string {
|
getDescription(): string {
|
||||||
@@ -85,6 +94,9 @@ export class WriteTodosTool extends BaseDeclarativeTool<
|
|||||||
messageBus,
|
messageBus,
|
||||||
true, // isOutputMarkdown
|
true, // isOutputMarkdown
|
||||||
false, // canUpdateOutput
|
false, // canUpdateOutput
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,12 +140,14 @@ export class WriteTodosTool extends BaseDeclarativeTool<
|
|||||||
messageBus: MessageBus,
|
messageBus: MessageBus,
|
||||||
_toolName?: string,
|
_toolName?: string,
|
||||||
_displayName?: string,
|
_displayName?: string,
|
||||||
|
isSensitive?: boolean,
|
||||||
): ToolInvocation<WriteTodosToolParams, ToolResult> {
|
): ToolInvocation<WriteTodosToolParams, ToolResult> {
|
||||||
return new WriteTodosToolInvocation(
|
return new WriteTodosToolInvocation(
|
||||||
params,
|
params,
|
||||||
messageBus,
|
messageBus,
|
||||||
_toolName,
|
_toolName,
|
||||||
_displayName,
|
_displayName,
|
||||||
|
isSensitive,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user