@qduc/term2 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.lite-mode.test.d.ts +2 -0
- package/dist/agent.lite-mode.test.d.ts.map +1 -0
- package/dist/agent.lite-mode.test.js +39 -0
- package/dist/agent.lite-mode.test.js.map +1 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +3 -1
- package/dist/app.js.map +1 -1
- package/dist/components/ApprovalPrompt.d.ts.map +1 -1
- package/dist/components/ApprovalPrompt.js +20 -0
- package/dist/components/ApprovalPrompt.js.map +1 -1
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +2 -7
- package/dist/components/InputBox.js.map +1 -1
- package/dist/components/TextInput.d.ts.map +1 -1
- package/dist/components/TextInput.js +2 -1
- package/dist/components/TextInput.js.map +1 -1
- package/dist/components/TextInput.test.js.map +1 -1
- package/dist/debug_ask_mentor.d.ts +2 -0
- package/dist/debug_ask_mentor.d.ts.map +1 -0
- package/dist/debug_ask_mentor.js +73 -0
- package/dist/debug_ask_mentor.js.map +1 -0
- package/dist/hooks/use-model-selection.d.ts.map +1 -1
- package/dist/hooks/use-model-selection.js +7 -3
- package/dist/hooks/use-model-selection.js.map +1 -1
- package/dist/hooks/use-settings-completion.d.ts.map +1 -1
- package/dist/hooks/use-settings-completion.js +3 -0
- package/dist/hooks/use-settings-completion.js.map +1 -1
- package/dist/hooks/use-settings-completion.test.js +6 -0
- package/dist/hooks/use-settings-completion.test.js.map +1 -1
- package/dist/lib/openai-agent-client.d.ts.map +1 -1
- package/dist/lib/openai-agent-client.js +35 -15
- package/dist/lib/openai-agent-client.js.map +1 -1
- package/dist/lib/tool-invoke.test.js +1 -1
- package/dist/lib/tool-invoke.test.js.map +1 -1
- package/dist/modes/companion/command-index.d.ts +26 -0
- package/dist/modes/companion/command-index.d.ts.map +1 -0
- package/dist/modes/companion/command-index.js +50 -0
- package/dist/modes/companion/command-index.js.map +1 -0
- package/dist/modes/companion/command-index.test.d.ts +2 -0
- package/dist/modes/companion/command-index.test.d.ts.map +1 -0
- package/dist/modes/companion/command-index.test.js +86 -0
- package/dist/modes/companion/command-index.test.js.map +1 -0
- package/dist/modes/companion/companion-app.d.ts +12 -0
- package/dist/modes/companion/companion-app.d.ts.map +1 -0
- package/dist/modes/companion/companion-app.js +297 -0
- package/dist/modes/companion/companion-app.js.map +1 -0
- package/dist/modes/companion/companion-session.d.ts +63 -0
- package/dist/modes/companion/companion-session.d.ts.map +1 -0
- package/dist/modes/companion/companion-session.js +146 -0
- package/dist/modes/companion/companion-session.js.map +1 -0
- package/dist/modes/companion/companion-session.test.d.ts +2 -0
- package/dist/modes/companion/companion-session.test.d.ts.map +1 -0
- package/dist/modes/companion/companion-session.test.js +28 -0
- package/dist/modes/companion/companion-session.test.js.map +1 -0
- package/dist/modes/companion/components/status-bar.d.ts +13 -0
- package/dist/modes/companion/components/status-bar.d.ts.map +1 -0
- package/dist/modes/companion/components/status-bar.js +26 -0
- package/dist/modes/companion/components/status-bar.js.map +1 -0
- package/dist/modes/companion/context-buffer.d.ts +65 -0
- package/dist/modes/companion/context-buffer.d.ts.map +1 -0
- package/dist/modes/companion/context-buffer.js +156 -0
- package/dist/modes/companion/context-buffer.js.map +1 -0
- package/dist/modes/companion/context-buffer.test.d.ts +2 -0
- package/dist/modes/companion/context-buffer.test.d.ts.map +1 -0
- package/dist/modes/companion/context-buffer.test.js +154 -0
- package/dist/modes/companion/context-buffer.test.js.map +1 -0
- package/dist/modes/companion/event-detector.d.ts +46 -0
- package/dist/modes/companion/event-detector.d.ts.map +1 -0
- package/dist/modes/companion/event-detector.js +169 -0
- package/dist/modes/companion/event-detector.js.map +1 -0
- package/dist/modes/companion/event-detector.test.d.ts +2 -0
- package/dist/modes/companion/event-detector.test.d.ts.map +1 -0
- package/dist/modes/companion/event-detector.test.js +121 -0
- package/dist/modes/companion/event-detector.test.js.map +1 -0
- package/dist/modes/companion/index.d.ts +33 -0
- package/dist/modes/companion/index.d.ts.map +1 -0
- package/dist/modes/companion/index.js +21 -0
- package/dist/modes/companion/index.js.map +1 -0
- package/dist/modes/companion/input-key-mapper.d.ts +3 -0
- package/dist/modes/companion/input-key-mapper.d.ts.map +1 -0
- package/dist/modes/companion/input-key-mapper.js +31 -0
- package/dist/modes/companion/input-key-mapper.js.map +1 -0
- package/dist/modes/companion/input-key-mapper.test.d.ts +2 -0
- package/dist/modes/companion/input-key-mapper.test.d.ts.map +1 -0
- package/dist/modes/companion/input-key-mapper.test.js +26 -0
- package/dist/modes/companion/input-key-mapper.test.js.map +1 -0
- package/dist/modes/companion/input-parser.d.ts +53 -0
- package/dist/modes/companion/input-parser.d.ts.map +1 -0
- package/dist/modes/companion/input-parser.js +114 -0
- package/dist/modes/companion/input-parser.js.map +1 -0
- package/dist/modes/companion/input-parser.test.d.ts +2 -0
- package/dist/modes/companion/input-parser.test.d.ts.map +1 -0
- package/dist/modes/companion/input-parser.test.js +123 -0
- package/dist/modes/companion/input-parser.test.js.map +1 -0
- package/dist/modes/companion/mode-manager.d.ts +41 -0
- package/dist/modes/companion/mode-manager.d.ts.map +1 -0
- package/dist/modes/companion/mode-manager.js +56 -0
- package/dist/modes/companion/mode-manager.js.map +1 -0
- package/dist/modes/companion/mode-manager.test.d.ts +2 -0
- package/dist/modes/companion/mode-manager.test.d.ts.map +1 -0
- package/dist/modes/companion/mode-manager.test.js +65 -0
- package/dist/modes/companion/mode-manager.test.js.map +1 -0
- package/dist/modes/companion/output-classifier.d.ts +15 -0
- package/dist/modes/companion/output-classifier.d.ts.map +1 -0
- package/dist/modes/companion/output-classifier.js +77 -0
- package/dist/modes/companion/output-classifier.js.map +1 -0
- package/dist/modes/companion/output-classifier.test.d.ts +2 -0
- package/dist/modes/companion/output-classifier.test.d.ts.map +1 -0
- package/dist/modes/companion/output-classifier.test.js +133 -0
- package/dist/modes/companion/output-classifier.test.js.map +1 -0
- package/dist/modes/companion/pty-wrapper.d.ts +46 -0
- package/dist/modes/companion/pty-wrapper.d.ts.map +1 -0
- package/dist/modes/companion/pty-wrapper.js +143 -0
- package/dist/modes/companion/pty-wrapper.js.map +1 -0
- package/dist/modes/companion/safety-classifier.d.ts +31 -0
- package/dist/modes/companion/safety-classifier.d.ts.map +1 -0
- package/dist/modes/companion/safety-classifier.js +140 -0
- package/dist/modes/companion/safety-classifier.js.map +1 -0
- package/dist/modes/companion/safety-classifier.test.d.ts +2 -0
- package/dist/modes/companion/safety-classifier.test.d.ts.map +1 -0
- package/dist/modes/companion/safety-classifier.test.js +151 -0
- package/dist/modes/companion/safety-classifier.test.js.map +1 -0
- package/dist/modes/companion/summarizer.d.ts +24 -0
- package/dist/modes/companion/summarizer.d.ts.map +1 -0
- package/dist/modes/companion/summarizer.js +132 -0
- package/dist/modes/companion/summarizer.js.map +1 -0
- package/dist/modes/companion/terminal-history.d.ts +27 -0
- package/dist/modes/companion/terminal-history.d.ts.map +1 -0
- package/dist/modes/companion/terminal-history.js +142 -0
- package/dist/modes/companion/terminal-history.js.map +1 -0
- package/dist/prompts/simple-mentor.md +8 -0
- package/dist/providers/openai-compatible/model.d.ts.map +1 -1
- package/dist/providers/openai-compatible/model.js +13 -2
- package/dist/providers/openai-compatible/model.js.map +1 -1
- package/dist/providers/openai-compatible/reasoning-content.test.js +2 -2
- package/dist/providers/openai-compatible/reasoning-content.test.js.map +1 -1
- package/dist/providers/openrouter/reasoning-content.test.js +2 -2
- package/dist/providers/openrouter/reasoning-content.test.js.map +1 -1
- package/dist/providers/openrouter.test.js +30 -21
- package/dist/providers/openrouter.test.js.map +1 -1
- package/dist/services/check_mock.d.ts +2 -0
- package/dist/services/check_mock.d.ts.map +1 -0
- package/dist/services/check_mock.js +22 -0
- package/dist/services/check_mock.js.map +1 -0
- package/dist/services/conversation-service.test.d.ts +2 -0
- package/dist/services/conversation-service.test.d.ts.map +1 -0
- package/dist/services/conversation-service.test.js +149 -183
- package/dist/services/conversation-service.test.js.map +1 -0
- package/dist/services/conversation-store.test.js +12 -11
- package/dist/services/conversation-store.test.js.map +1 -1
- package/dist/services/settings-service.d.ts +5 -2
- package/dist/services/settings-service.d.ts.map +1 -1
- package/dist/services/settings-service.js +12 -0
- package/dist/services/settings-service.js.map +1 -1
- package/dist/tools/ask-mentor.d.ts +1 -1
- package/dist/tools/ask-mentor.d.ts.map +1 -1
- package/dist/tools/ask-mentor.js +1 -0
- package/dist/tools/ask-mentor.js.map +1 -1
- package/dist/tools/find-files.d.ts +2 -2
- package/dist/tools/find-files.d.ts.map +1 -1
- package/dist/tools/find-files.js +2 -0
- package/dist/tools/find-files.js.map +1 -1
- package/dist/tools/grep.d.ts +1 -1
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +1 -0
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +10 -9
- package/dist/tools/read-file.js.map +1 -1
- package/dist/tools/read-file.test.js +24 -19
- package/dist/tools/read-file.test.js.map +1 -1
- package/dist/tools/search-replace.d.ts +1 -1
- package/dist/tools/search-replace.d.ts.map +1 -1
- package/dist/tools/search-replace.js +129 -1
- package/dist/tools/search-replace.js.map +1 -1
- package/dist/tools/search-replace.test.js +18 -0
- package/dist/tools/search-replace.test.js.map +1 -1
- package/dist/tools/search.d.ts +4 -4
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +4 -0
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/shell.d.ts +2 -2
- package/dist/tools/shell.d.ts.map +1 -1
- package/dist/tools/shell.js +2 -0
- package/dist/tools/shell.js.map +1 -1
- package/dist/tools/types.d.ts +2 -2
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/utils/command-safety.d.ts.map +1 -1
- package/dist/utils/command-safety.devnull.test.d.ts +2 -0
- package/dist/utils/command-safety.devnull.test.d.ts.map +1 -0
- package/dist/utils/command-safety.devnull.test.js +13 -0
- package/dist/utils/command-safety.devnull.test.js.map +1 -0
- package/dist/utils/command-safety.js +10 -364
- package/dist/utils/command-safety.js.map +1 -1
- package/dist/utils/extract-command-messages.test.d.ts +2 -0
- package/dist/utils/extract-command-messages.test.d.ts.map +1 -0
- package/dist/utils/extract-command-messages.test.js +58 -51
- package/dist/utils/extract-command-messages.test.js.map +1 -0
- package/dist/utils/settings-command.d.ts.map +1 -1
- package/dist/utils/settings-command.js +13 -4
- package/dist/utils/settings-command.js.map +1 -1
- package/package.json +2 -2
- package/dist/app.model-command-feedback.test.d.ts +0 -2
- package/dist/app.model-command-feedback.test.d.ts.map +0 -1
- package/dist/app.model-command-feedback.test.js +0 -19
- package/dist/app.model-command-feedback.test.js.map +0 -1
- package/dist/components/MentorMode.test.d.ts +0 -2
- package/dist/components/MentorMode.test.d.ts.map +0 -1
- package/dist/components/MentorMode.test.js.map +0 -1
- package/dist/debug-schema.d.ts +0 -2
- package/dist/debug-schema.d.ts.map +0 -1
- package/dist/debug-schema.js +0 -22
- package/dist/debug-schema.js.map +0 -1
- package/dist/hooks/use-model-selection.test.d.ts +0 -2
- package/dist/hooks/use-model-selection.test.d.ts.map +0 -1
- package/dist/hooks/use-model-selection.test.js +0 -28
- package/dist/hooks/use-model-selection.test.js.map +0 -1
- package/dist/hooks/use-path-completion.test.d.ts +0 -2
- package/dist/hooks/use-path-completion.test.d.ts.map +0 -1
- package/dist/hooks/use-path-completion.test.js +0 -29
- package/dist/hooks/use-path-completion.test.js.map +0 -1
- package/dist/prompts/default.md.bak +0 -77
- package/dist/providers/openrouter.history.test.d.ts +0 -2
- package/dist/providers/openrouter.history.test.d.ts.map +0 -1
- package/dist/providers/openrouter.history.test.js +0 -533
- package/dist/providers/openrouter.history.test.js.map +0 -1
- package/dist/test-search-tool.d.ts +0 -2
- package/dist/test-search-tool.d.ts.map +0 -1
- package/dist/test-search-tool.js +0 -36
- package/dist/test-search-tool.js.map +0 -1
- package/dist/utils/extract-command-messages.repro.test.d.ts +0 -2
- package/dist/utils/extract-command-messages.repro.test.d.ts.map +0 -1
- package/dist/utils/extract-command-messages.repro.test.js +0 -31
- package/dist/utils/extract-command-messages.repro.test.js.map +0 -1
- /package/{README.md → readme.md} +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safety classifier for companion mode Auto commands.
|
|
3
|
+
*
|
|
4
|
+
* Classifies commands into safety levels:
|
|
5
|
+
* - GREEN: Safe, auto-approve
|
|
6
|
+
* - YELLOW: Potentially risky, show for confirmation
|
|
7
|
+
* - RED: Dangerous, block or require explicit approval
|
|
8
|
+
*/
|
|
9
|
+
export type SafetyLevel = 'green' | 'yellow' | 'red';
|
|
10
|
+
export interface SafetyClassification {
|
|
11
|
+
level: SafetyLevel;
|
|
12
|
+
reason: string;
|
|
13
|
+
command: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Classify a command's safety level.
|
|
17
|
+
*/
|
|
18
|
+
export declare function classifyCommandSafety(command: string): SafetyClassification;
|
|
19
|
+
/**
|
|
20
|
+
* Check if a command should be auto-approved.
|
|
21
|
+
*/
|
|
22
|
+
export declare function shouldAutoApprove(classification: SafetyClassification): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Check if a command should be blocked.
|
|
25
|
+
*/
|
|
26
|
+
export declare function shouldBlock(classification: SafetyClassification): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Get user-friendly description of safety level.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getSafetyDescription(level: SafetyLevel): string;
|
|
31
|
+
//# sourceMappingURL=safety-classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety-classifier.d.ts","sourceRoot":"","sources":["../../../source/modes/companion/safety-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAErD,MAAM,WAAW,oBAAoB;IACjC,KAAK,EAAE,WAAW,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACnB;AAoFD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB,CA2B3E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,CAE/E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,cAAc,EAAE,oBAAoB,GAAG,OAAO,CAEzE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAS/D"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safety classifier for companion mode Auto commands.
|
|
3
|
+
*
|
|
4
|
+
* Classifies commands into safety levels:
|
|
5
|
+
* - GREEN: Safe, auto-approve
|
|
6
|
+
* - YELLOW: Potentially risky, show for confirmation
|
|
7
|
+
* - RED: Dangerous, block or require explicit approval
|
|
8
|
+
*/
|
|
9
|
+
// Patterns for dangerous operations (RED)
|
|
10
|
+
const DANGEROUS_PATTERNS = [
|
|
11
|
+
{ pattern: /\brm\s+(-rf?|--recursive)?\s*\/\s*$/i, reason: 'Recursive delete of root' },
|
|
12
|
+
{ pattern: /\brm\s+(-rf?|--recursive)?\s*~\s*$/i, reason: 'Recursive delete of home' },
|
|
13
|
+
{ pattern: /\brm\s+(-rf?|--recursive)?\s*\.\s*$/i, reason: 'Recursive delete of current directory' },
|
|
14
|
+
{ pattern: /\bsudo\s+rm\b/i, reason: 'Sudo delete operation' },
|
|
15
|
+
{ pattern: /\bsudo\s+dd\b/i, reason: 'Sudo disk write operation' },
|
|
16
|
+
{ pattern: /\bmkfs\b/i, reason: 'Filesystem creation' },
|
|
17
|
+
{ pattern: /\bformat\s+[a-z]:/i, reason: 'Drive format' },
|
|
18
|
+
{ pattern: /\bshutdown\b/i, reason: 'System shutdown' },
|
|
19
|
+
{ pattern: /\breboot\b/i, reason: 'System reboot' },
|
|
20
|
+
{ pattern: /\bsystemctl\s+(stop|disable|mask)\b/i, reason: 'System service modification' },
|
|
21
|
+
{ pattern: /\bchmod\s+777\b/i, reason: 'Overly permissive chmod' },
|
|
22
|
+
{ pattern: /\bchown\s+-R\s+root\b/i, reason: 'Recursive chown to root' },
|
|
23
|
+
{ pattern: />\s*\/dev\/(sd[a-z]|nvme|hd[a-z])/i, reason: 'Direct disk write' },
|
|
24
|
+
{ pattern: /\bcurl\b.*\|\s*(bash|sh)\b/i, reason: 'Pipe remote script to shell' },
|
|
25
|
+
{ pattern: /\bwget\b.*\|\s*(bash|sh)\b/i, reason: 'Pipe remote script to shell' },
|
|
26
|
+
{ pattern: /\beval\s+.*\$\(/i, reason: 'Eval with command substitution' },
|
|
27
|
+
{ pattern: /\bkill\s+-9\s+1\b/i, reason: 'Kill init process' },
|
|
28
|
+
{ pattern: /\b:()\s*{\s*:\s*\|\s*:\s*&\s*}\s*;\s*:/i, reason: 'Fork bomb' },
|
|
29
|
+
];
|
|
30
|
+
// Patterns for risky operations (YELLOW)
|
|
31
|
+
const RISKY_PATTERNS = [
|
|
32
|
+
{ pattern: /\brm\s+(-r|-f|-rf)/i, reason: 'Recursive or forced delete' },
|
|
33
|
+
{ pattern: /\bsudo\b/i, reason: 'Sudo command' },
|
|
34
|
+
{ pattern: /\bgit\s+(push|force-push|reset\s+--hard)/i, reason: 'Git destructive operation' },
|
|
35
|
+
{ pattern: /\bgit\s+checkout\s+--\s*\./i, reason: 'Git discard all changes' },
|
|
36
|
+
{ pattern: /\bnpm\s+(publish|unpublish)/i, reason: 'npm publish operation' },
|
|
37
|
+
{ pattern: /\bdocker\s+(rm|rmi|stop|kill)/i, reason: 'Docker destructive operation' },
|
|
38
|
+
{ pattern: /\bchmod\s+[0-7]{3}/i, reason: 'Permission change' },
|
|
39
|
+
{ pattern: /\bchown\b/i, reason: 'Ownership change' },
|
|
40
|
+
{ pattern: />\s*[^|&]/i, reason: 'File overwrite redirection' },
|
|
41
|
+
{ pattern: /\bmv\b.*\//i, reason: 'File move operation' },
|
|
42
|
+
{ pattern: /\bcp\s+-r/i, reason: 'Recursive copy' },
|
|
43
|
+
{ pattern: /\btar\s+.*-x/i, reason: 'Archive extraction' },
|
|
44
|
+
{ pattern: /\bunzip\b/i, reason: 'Archive extraction' },
|
|
45
|
+
{ pattern: /\bpip\s+install\b(?!.*--user)/i, reason: 'System-wide pip install' },
|
|
46
|
+
{ pattern: /\bnpm\s+install\s+-g/i, reason: 'Global npm install' },
|
|
47
|
+
{ pattern: /\bapt\s+(install|remove|purge)/i, reason: 'System package operation' },
|
|
48
|
+
{ pattern: /\bbrew\s+(install|uninstall|remove)/i, reason: 'Homebrew package operation' },
|
|
49
|
+
];
|
|
50
|
+
// Patterns for safe operations (GREEN)
|
|
51
|
+
const SAFE_PATTERNS = [
|
|
52
|
+
{ pattern: /^\s*(ls|ll|la|dir)\b/i, reason: 'List files' },
|
|
53
|
+
{ pattern: /^\s*cd\b/i, reason: 'Change directory' },
|
|
54
|
+
{ pattern: /^\s*pwd\b/i, reason: 'Print working directory' },
|
|
55
|
+
{ pattern: /^\s*echo\b/i, reason: 'Echo output' },
|
|
56
|
+
{ pattern: /^\s*cat\b/i, reason: 'View file' },
|
|
57
|
+
{ pattern: /^\s*head\b/i, reason: 'View file head' },
|
|
58
|
+
{ pattern: /^\s*tail\b/i, reason: 'View file tail' },
|
|
59
|
+
{ pattern: /^\s*less\b/i, reason: 'View file with pager' },
|
|
60
|
+
{ pattern: /^\s*more\b/i, reason: 'View file with pager' },
|
|
61
|
+
{ pattern: /^\s*grep\b/i, reason: 'Search text' },
|
|
62
|
+
{ pattern: /^\s*find\b/i, reason: 'Find files' },
|
|
63
|
+
{ pattern: /^\s*which\b/i, reason: 'Locate command' },
|
|
64
|
+
{ pattern: /^\s*whereis\b/i, reason: 'Locate command' },
|
|
65
|
+
{ pattern: /^\s*type\b/i, reason: 'Describe command' },
|
|
66
|
+
{ pattern: /^\s*whoami\b/i, reason: 'Show current user' },
|
|
67
|
+
{ pattern: /^\s*hostname\b/i, reason: 'Show hostname' },
|
|
68
|
+
{ pattern: /^\s*date\b/i, reason: 'Show date' },
|
|
69
|
+
{ pattern: /^\s*uptime\b/i, reason: 'Show uptime' },
|
|
70
|
+
{ pattern: /^\s*df\b/i, reason: 'Show disk usage' },
|
|
71
|
+
{ pattern: /^\s*du\b/i, reason: 'Show directory usage' },
|
|
72
|
+
{ pattern: /^\s*free\b/i, reason: 'Show memory usage' },
|
|
73
|
+
{ pattern: /^\s*top\b/i, reason: 'Show processes' },
|
|
74
|
+
{ pattern: /^\s*ps\b/i, reason: 'Show processes' },
|
|
75
|
+
{ pattern: /^\s*git\s+(status|log|diff|branch|show|stash\s+list)\b/i, reason: 'Git read-only' },
|
|
76
|
+
{ pattern: /^\s*npm\s+(ls|list|outdated|audit|view|info)\b/i, reason: 'npm read-only' },
|
|
77
|
+
{ pattern: /^\s*node\s+--version/i, reason: 'Version check' },
|
|
78
|
+
{ pattern: /^\s*npm\s+--version/i, reason: 'Version check' },
|
|
79
|
+
{ pattern: /^\s*python\s+--version/i, reason: 'Version check' },
|
|
80
|
+
{ pattern: /^\s*npm\s+test\b/i, reason: 'Run tests' },
|
|
81
|
+
{ pattern: /^\s*npm\s+run\s+(test|lint|check|build)\b/i, reason: 'Run npm script' },
|
|
82
|
+
{ pattern: /^\s*npm\s+install\b(?!.*-g)/i, reason: 'Local npm install' },
|
|
83
|
+
{ pattern: /^\s*yarn\s+(install|add)\b(?!.*--global)/i, reason: 'Local yarn install' },
|
|
84
|
+
{ pattern: /^\s*pnpm\s+(install|add)\b(?!.*--global)/i, reason: 'Local pnpm install' },
|
|
85
|
+
{ pattern: /^\s*pip\s+install\s+--user\b/i, reason: 'User pip install' },
|
|
86
|
+
{ pattern: /^\s*pip\s+list\b/i, reason: 'pip read-only' },
|
|
87
|
+
];
|
|
88
|
+
/**
|
|
89
|
+
* Classify a command's safety level.
|
|
90
|
+
*/
|
|
91
|
+
export function classifyCommandSafety(command) {
|
|
92
|
+
const trimmed = command.trim();
|
|
93
|
+
// Check for dangerous patterns first (RED) - always takes precedence
|
|
94
|
+
for (const { pattern, reason } of DANGEROUS_PATTERNS) {
|
|
95
|
+
if (pattern.test(trimmed)) {
|
|
96
|
+
return { level: 'red', reason, command: trimmed };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Check for risky patterns (YELLOW) - before safe patterns
|
|
100
|
+
// This ensures operations like redirects are caught even with safe base commands
|
|
101
|
+
for (const { pattern, reason } of RISKY_PATTERNS) {
|
|
102
|
+
if (pattern.test(trimmed)) {
|
|
103
|
+
return { level: 'yellow', reason, command: trimmed };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Check for safe patterns (GREEN)
|
|
107
|
+
for (const { pattern, reason } of SAFE_PATTERNS) {
|
|
108
|
+
if (pattern.test(trimmed)) {
|
|
109
|
+
return { level: 'green', reason, command: trimmed };
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Default to YELLOW for unknown commands
|
|
113
|
+
return { level: 'yellow', reason: 'Unknown command', command: trimmed };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Check if a command should be auto-approved.
|
|
117
|
+
*/
|
|
118
|
+
export function shouldAutoApprove(classification) {
|
|
119
|
+
return classification.level === 'green';
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Check if a command should be blocked.
|
|
123
|
+
*/
|
|
124
|
+
export function shouldBlock(classification) {
|
|
125
|
+
return classification.level === 'red';
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get user-friendly description of safety level.
|
|
129
|
+
*/
|
|
130
|
+
export function getSafetyDescription(level) {
|
|
131
|
+
switch (level) {
|
|
132
|
+
case 'green':
|
|
133
|
+
return 'Safe - will auto-execute';
|
|
134
|
+
case 'yellow':
|
|
135
|
+
return 'Needs confirmation';
|
|
136
|
+
case 'red':
|
|
137
|
+
return 'Blocked - potentially dangerous';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=safety-classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety-classifier.js","sourceRoot":"","sources":["../../../source/modes/companion/safety-classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety-classifier.test.d.ts","sourceRoot":"","sources":["../../../source/modes/companion/safety-classifier.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { classifyCommandSafety, shouldAutoApprove, shouldBlock, getSafetyDescription, } from './safety-classifier.js';
|
|
3
|
+
// GREEN (safe) commands
|
|
4
|
+
test('classifies ls as green', t => {
|
|
5
|
+
const result = classifyCommandSafety('ls -la');
|
|
6
|
+
t.is(result.level, 'green');
|
|
7
|
+
});
|
|
8
|
+
test('classifies cd as green', t => {
|
|
9
|
+
const result = classifyCommandSafety('cd /path/to/dir');
|
|
10
|
+
t.is(result.level, 'green');
|
|
11
|
+
});
|
|
12
|
+
test('classifies git status as green', t => {
|
|
13
|
+
const result = classifyCommandSafety('git status');
|
|
14
|
+
t.is(result.level, 'green');
|
|
15
|
+
});
|
|
16
|
+
test('classifies git log as green', t => {
|
|
17
|
+
const result = classifyCommandSafety('git log --oneline');
|
|
18
|
+
t.is(result.level, 'green');
|
|
19
|
+
});
|
|
20
|
+
test('classifies npm test as green', t => {
|
|
21
|
+
const result = classifyCommandSafety('npm test');
|
|
22
|
+
t.is(result.level, 'green');
|
|
23
|
+
});
|
|
24
|
+
test('classifies npm install (local) as green', t => {
|
|
25
|
+
const result = classifyCommandSafety('npm install lodash');
|
|
26
|
+
t.is(result.level, 'green');
|
|
27
|
+
});
|
|
28
|
+
test('classifies cat as green', t => {
|
|
29
|
+
const result = classifyCommandSafety('cat file.txt');
|
|
30
|
+
t.is(result.level, 'green');
|
|
31
|
+
});
|
|
32
|
+
test('classifies grep as green', t => {
|
|
33
|
+
const result = classifyCommandSafety('grep -r "pattern" .');
|
|
34
|
+
t.is(result.level, 'green');
|
|
35
|
+
});
|
|
36
|
+
// YELLOW (risky) commands
|
|
37
|
+
test('classifies rm -r as yellow', t => {
|
|
38
|
+
const result = classifyCommandSafety('rm -r directory');
|
|
39
|
+
t.is(result.level, 'yellow');
|
|
40
|
+
});
|
|
41
|
+
test('classifies sudo as yellow', t => {
|
|
42
|
+
const result = classifyCommandSafety('sudo apt update');
|
|
43
|
+
t.is(result.level, 'yellow');
|
|
44
|
+
});
|
|
45
|
+
test('classifies git push as yellow', t => {
|
|
46
|
+
const result = classifyCommandSafety('git push origin main');
|
|
47
|
+
t.is(result.level, 'yellow');
|
|
48
|
+
});
|
|
49
|
+
test('classifies npm install -g as yellow', t => {
|
|
50
|
+
const result = classifyCommandSafety('npm install -g typescript');
|
|
51
|
+
t.is(result.level, 'yellow');
|
|
52
|
+
});
|
|
53
|
+
test('classifies file overwrite redirect as yellow', t => {
|
|
54
|
+
const result = classifyCommandSafety('echo "test" > file.txt');
|
|
55
|
+
t.is(result.level, 'yellow');
|
|
56
|
+
});
|
|
57
|
+
test('classifies chmod as yellow', t => {
|
|
58
|
+
const result = classifyCommandSafety('chmod 644 file.txt');
|
|
59
|
+
t.is(result.level, 'yellow');
|
|
60
|
+
});
|
|
61
|
+
test('classifies unknown command as yellow', t => {
|
|
62
|
+
const result = classifyCommandSafety('someunknowncommand --flag');
|
|
63
|
+
t.is(result.level, 'yellow');
|
|
64
|
+
t.is(result.reason, 'Unknown command');
|
|
65
|
+
});
|
|
66
|
+
// RED (dangerous) commands
|
|
67
|
+
test('classifies rm -rf / as red', t => {
|
|
68
|
+
const result = classifyCommandSafety('rm -rf /');
|
|
69
|
+
t.is(result.level, 'red');
|
|
70
|
+
});
|
|
71
|
+
test('classifies rm -rf ~ as red', t => {
|
|
72
|
+
const result = classifyCommandSafety('rm -rf ~');
|
|
73
|
+
t.is(result.level, 'red');
|
|
74
|
+
});
|
|
75
|
+
test('classifies sudo rm as red', t => {
|
|
76
|
+
const result = classifyCommandSafety('sudo rm -rf /var');
|
|
77
|
+
t.is(result.level, 'red');
|
|
78
|
+
});
|
|
79
|
+
test('classifies curl pipe to bash as red', t => {
|
|
80
|
+
const result = classifyCommandSafety('curl http://example.com/script.sh | bash');
|
|
81
|
+
t.is(result.level, 'red');
|
|
82
|
+
});
|
|
83
|
+
test('classifies wget pipe to sh as red', t => {
|
|
84
|
+
const result = classifyCommandSafety('wget -qO- http://example.com/script.sh | sh');
|
|
85
|
+
t.is(result.level, 'red');
|
|
86
|
+
});
|
|
87
|
+
test('classifies chmod 777 as red', t => {
|
|
88
|
+
const result = classifyCommandSafety('chmod 777 /etc/passwd');
|
|
89
|
+
t.is(result.level, 'red');
|
|
90
|
+
});
|
|
91
|
+
test('classifies direct disk write as red', t => {
|
|
92
|
+
const result = classifyCommandSafety('dd if=/dev/zero > /dev/sda');
|
|
93
|
+
t.is(result.level, 'red');
|
|
94
|
+
});
|
|
95
|
+
test('classifies mkfs as red', t => {
|
|
96
|
+
const result = classifyCommandSafety('mkfs.ext4 /dev/sdb1');
|
|
97
|
+
t.is(result.level, 'red');
|
|
98
|
+
});
|
|
99
|
+
// Helper functions
|
|
100
|
+
test('shouldAutoApprove returns true for green', t => {
|
|
101
|
+
const result = classifyCommandSafety('ls');
|
|
102
|
+
t.true(shouldAutoApprove(result));
|
|
103
|
+
});
|
|
104
|
+
test('shouldAutoApprove returns false for yellow', t => {
|
|
105
|
+
const result = classifyCommandSafety('rm -r dir');
|
|
106
|
+
t.false(shouldAutoApprove(result));
|
|
107
|
+
});
|
|
108
|
+
test('shouldAutoApprove returns false for red', t => {
|
|
109
|
+
const result = classifyCommandSafety('rm -rf /');
|
|
110
|
+
t.false(shouldAutoApprove(result));
|
|
111
|
+
});
|
|
112
|
+
test('shouldBlock returns false for green', t => {
|
|
113
|
+
const result = classifyCommandSafety('ls');
|
|
114
|
+
t.false(shouldBlock(result));
|
|
115
|
+
});
|
|
116
|
+
test('shouldBlock returns false for yellow', t => {
|
|
117
|
+
const result = classifyCommandSafety('rm -r dir');
|
|
118
|
+
t.false(shouldBlock(result));
|
|
119
|
+
});
|
|
120
|
+
test('shouldBlock returns true for red', t => {
|
|
121
|
+
const result = classifyCommandSafety('rm -rf /');
|
|
122
|
+
t.true(shouldBlock(result));
|
|
123
|
+
});
|
|
124
|
+
test('getSafetyDescription returns correct text for green', t => {
|
|
125
|
+
t.is(getSafetyDescription('green'), 'Safe - will auto-execute');
|
|
126
|
+
});
|
|
127
|
+
test('getSafetyDescription returns correct text for yellow', t => {
|
|
128
|
+
t.is(getSafetyDescription('yellow'), 'Needs confirmation');
|
|
129
|
+
});
|
|
130
|
+
test('getSafetyDescription returns correct text for red', t => {
|
|
131
|
+
t.is(getSafetyDescription('red'), 'Blocked - potentially dangerous');
|
|
132
|
+
});
|
|
133
|
+
// Edge cases
|
|
134
|
+
test('handles empty command', t => {
|
|
135
|
+
const result = classifyCommandSafety('');
|
|
136
|
+
t.is(result.level, 'yellow');
|
|
137
|
+
});
|
|
138
|
+
test('handles whitespace-only command', t => {
|
|
139
|
+
const result = classifyCommandSafety(' ');
|
|
140
|
+
t.is(result.level, 'yellow');
|
|
141
|
+
});
|
|
142
|
+
test('is case insensitive for patterns', t => {
|
|
143
|
+
const result1 = classifyCommandSafety('LS -LA');
|
|
144
|
+
const result2 = classifyCommandSafety('ls -la');
|
|
145
|
+
t.is(result1.level, result2.level);
|
|
146
|
+
});
|
|
147
|
+
test('trims command before classification', t => {
|
|
148
|
+
const result = classifyCommandSafety(' ls ');
|
|
149
|
+
t.is(result.level, 'green');
|
|
150
|
+
});
|
|
151
|
+
//# sourceMappingURL=safety-classifier.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety-classifier.test.js","sourceRoot":"","sources":["../../../source/modes/companion/safety-classifier.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ISettingsService, ILoggingService } from '../../services/service-interfaces.js';
|
|
2
|
+
import type { CommandEntry } from './context-buffer.js';
|
|
3
|
+
export interface SummarizerDeps {
|
|
4
|
+
settings: ISettingsService;
|
|
5
|
+
logger: ILoggingService;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Summarizer for command outputs using a small, fast LLM.
|
|
9
|
+
* Caches summaries to avoid reprocessing.
|
|
10
|
+
*/
|
|
11
|
+
export declare class Summarizer {
|
|
12
|
+
#private;
|
|
13
|
+
constructor(deps: SummarizerDeps);
|
|
14
|
+
/**
|
|
15
|
+
* Summarize command output.
|
|
16
|
+
* Returns the original output if summarization is not needed or fails.
|
|
17
|
+
*/
|
|
18
|
+
summarize(entry: CommandEntry, detail: 'summary' | 'errors_only'): Promise<string>;
|
|
19
|
+
/**
|
|
20
|
+
* Clear the summary cache.
|
|
21
|
+
*/
|
|
22
|
+
clearCache(): void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=summarizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarizer.d.ts","sourceRoot":"","sources":["../../../source/modes/companion/summarizer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,gBAAgB,EAAE,eAAe,EAAC,MAAM,sCAAsC,CAAC;AAC5F,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,qBAAqB,CAAC;AAGtD,MAAM,WAAW,cAAc;IAC3B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,eAAe,CAAC;CAC3B;AASD;;;GAGG;AACH,qBAAa,UAAU;;gBAMP,IAAI,EAAE,cAAc;IAKhC;;;OAGG;IACG,SAAS,CACX,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,SAAS,GAAG,aAAa,GAClC,OAAO,CAAC,MAAM,CAAC;IAkDlB;;OAEG;IACH,UAAU,IAAI,IAAI;CAsFrB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import { classifyOutputType, getSummarizationPrompt, shouldSummarize } from './output-classifier.js';
|
|
3
|
+
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
4
|
+
/**
|
|
5
|
+
* Summarizer for command outputs using a small, fast LLM.
|
|
6
|
+
* Caches summaries to avoid reprocessing.
|
|
7
|
+
*/
|
|
8
|
+
export class Summarizer {
|
|
9
|
+
#client = null;
|
|
10
|
+
#settings;
|
|
11
|
+
#logger;
|
|
12
|
+
#cache = new Map();
|
|
13
|
+
constructor(deps) {
|
|
14
|
+
this.#settings = deps.settings;
|
|
15
|
+
this.#logger = deps.logger;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Summarize command output.
|
|
19
|
+
* Returns the original output if summarization is not needed or fails.
|
|
20
|
+
*/
|
|
21
|
+
async summarize(entry, detail) {
|
|
22
|
+
// Check if summarization is needed
|
|
23
|
+
if (!shouldSummarize(entry)) {
|
|
24
|
+
return entry.output;
|
|
25
|
+
}
|
|
26
|
+
// Check cache
|
|
27
|
+
const cacheKey = this.#getCacheKey(entry, detail);
|
|
28
|
+
const cached = this.#cache.get(cacheKey);
|
|
29
|
+
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
|
|
30
|
+
return cached.summary;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const client = await this.#getClient();
|
|
34
|
+
const model = this.#settings.get('companion.summarizerModel') || 'gpt-4o-mini';
|
|
35
|
+
const maxTokens = this.#settings.get('companion.summarizerMaxTokens') || 500;
|
|
36
|
+
const outputType = classifyOutputType(entry);
|
|
37
|
+
const prompt = this.#buildPrompt(entry, detail, outputType);
|
|
38
|
+
const response = await client.chat.completions.create({
|
|
39
|
+
model,
|
|
40
|
+
max_tokens: maxTokens,
|
|
41
|
+
messages: [
|
|
42
|
+
{
|
|
43
|
+
role: 'system',
|
|
44
|
+
content: 'You are a concise technical summarizer. Extract key information only.',
|
|
45
|
+
},
|
|
46
|
+
{ role: 'user', content: prompt },
|
|
47
|
+
],
|
|
48
|
+
});
|
|
49
|
+
const summary = response.choices[0]?.message?.content || entry.output;
|
|
50
|
+
// Cache result
|
|
51
|
+
this.#cache.set(cacheKey, { summary, timestamp: Date.now() });
|
|
52
|
+
return summary;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
this.#logger.warn('Summarization failed, using fallback', {
|
|
56
|
+
error: error instanceof Error ? error.message : String(error),
|
|
57
|
+
command: entry.command.slice(0, 50),
|
|
58
|
+
});
|
|
59
|
+
// Fallback: smart truncation
|
|
60
|
+
return this.#fallbackSummarize(entry, detail);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Clear the summary cache.
|
|
65
|
+
*/
|
|
66
|
+
clearCache() {
|
|
67
|
+
this.#cache.clear();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get or create OpenAI client.
|
|
71
|
+
*/
|
|
72
|
+
async #getClient() {
|
|
73
|
+
if (this.#client) {
|
|
74
|
+
return this.#client;
|
|
75
|
+
}
|
|
76
|
+
const provider = this.#settings.get('companion.summarizerProvider') || 'openai';
|
|
77
|
+
// Use OpenAI API key from environment
|
|
78
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
79
|
+
// For non-OpenAI providers, get baseURL from settings
|
|
80
|
+
const baseURL = provider === 'openai'
|
|
81
|
+
? undefined
|
|
82
|
+
: this.#settings.get(`agent.${provider}.baseUrl`);
|
|
83
|
+
if (!apiKey) {
|
|
84
|
+
throw new Error('OPENAI_API_KEY not set');
|
|
85
|
+
}
|
|
86
|
+
this.#client = new OpenAI({ apiKey, baseURL });
|
|
87
|
+
return this.#client;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Build the summarization prompt.
|
|
91
|
+
*/
|
|
92
|
+
#buildPrompt(entry, detail, outputType) {
|
|
93
|
+
const basePrompt = getSummarizationPrompt(outputType);
|
|
94
|
+
return `Command: ${entry.command}
|
|
95
|
+
Exit code: ${entry.exitCode}
|
|
96
|
+
|
|
97
|
+
Output:
|
|
98
|
+
\`\`\`
|
|
99
|
+
${entry.output}
|
|
100
|
+
\`\`\`
|
|
101
|
+
|
|
102
|
+
${detail === 'errors_only' ? getSummarizationPrompt('error_output') : basePrompt}`;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Fallback summarization without LLM.
|
|
106
|
+
*/
|
|
107
|
+
#fallbackSummarize(entry, detail) {
|
|
108
|
+
const lines = entry.output.split('\n');
|
|
109
|
+
if (detail === 'errors_only') {
|
|
110
|
+
// Extract lines containing common error patterns
|
|
111
|
+
const errorPatterns = /error|fail|exception|fatal|critical|warning/i;
|
|
112
|
+
const errorLines = lines.filter(l => errorPatterns.test(l));
|
|
113
|
+
return errorLines.slice(0, 20).join('\n') || 'No obvious errors found';
|
|
114
|
+
}
|
|
115
|
+
// Default: first and last N lines
|
|
116
|
+
if (lines.length <= 30) {
|
|
117
|
+
return entry.output;
|
|
118
|
+
}
|
|
119
|
+
return [
|
|
120
|
+
...lines.slice(0, 15),
|
|
121
|
+
`... (${lines.length - 30} lines omitted)`,
|
|
122
|
+
...lines.slice(-15),
|
|
123
|
+
].join('\n');
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Generate cache key for an entry.
|
|
127
|
+
*/
|
|
128
|
+
#getCacheKey(entry, detail) {
|
|
129
|
+
return `${entry.command}:${entry.timestamp}:${detail}`;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=summarizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../../../source/modes/companion/summarizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ToolDefinition } from '../../tools/types.js';
|
|
3
|
+
import type { ContextBuffer } from './context-buffer.js';
|
|
4
|
+
import type { Summarizer } from './summarizer.js';
|
|
5
|
+
declare const TerminalHistoryParamsSchema: z.ZodObject<{
|
|
6
|
+
index: z.ZodOptional<z.ZodNumber>;
|
|
7
|
+
lastN: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
search: z.ZodOptional<z.ZodString>;
|
|
9
|
+
detail: z.ZodEnum<{
|
|
10
|
+
summary: "summary";
|
|
11
|
+
errors_only: "errors_only";
|
|
12
|
+
full: "full";
|
|
13
|
+
}>;
|
|
14
|
+
maxLines: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
}, z.core.$strip>;
|
|
16
|
+
export type TerminalHistoryParams = z.infer<typeof TerminalHistoryParamsSchema>;
|
|
17
|
+
interface TerminalHistoryDeps {
|
|
18
|
+
contextBuffer: ContextBuffer;
|
|
19
|
+
summarizer: Summarizer;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create the terminal_history tool definition for companion mode.
|
|
23
|
+
* This tool allows the AI to query command history and outputs on-demand.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createTerminalHistoryToolDefinition(deps: TerminalHistoryDeps): ToolDefinition<TerminalHistoryParams>;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=terminal-history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-history.d.ts","sourceRoot":"","sources":["../../../source/modes/companion/terminal-history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,KAAK,EAAC,cAAc,EAAiB,MAAM,sBAAsB,CAAC;AACzE,OAAO,KAAK,EAAC,aAAa,EAAe,MAAM,qBAAqB,CAAC;AACrE,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAIhD,QAAA,MAAM,2BAA2B;;;;;;;;;;iBA2B/B,CAAC;AAEH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAShF,UAAU,mBAAmB;IACzB,aAAa,EAAE,aAAa,CAAC;IAC7B,UAAU,EAAE,UAAU,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CAC/C,IAAI,EAAE,mBAAmB,GAC1B,cAAc,CAAC,qBAAqB,CAAC,CA8HvC"}
|