nova-terminal-assistant 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nova-terminal-assistant might be problematic. Click here for more details.
- package/README.md +358 -0
- package/bin/nova +38 -0
- package/bin/nova.js +12 -0
- package/package.json +67 -0
- package/src/cli/commands/SmartCompletion.ts +458 -0
- package/src/cli/index.ts +5 -0
- package/src/cli/startup/IFlowRepl.ts +212 -0
- package/src/cli/startup/InkBasedRepl.ts +1056 -0
- package/src/cli/startup/InteractiveRepl.ts +2833 -0
- package/src/cli/startup/NovaApp.ts +1861 -0
- package/src/cli/startup/index.ts +4 -0
- package/src/cli/startup/parseArgs.ts +293 -0
- package/src/cli/test-modules.ts +27 -0
- package/src/cli/ui/IFlowDropdown.ts +425 -0
- package/src/cli/ui/ModernReplUI.ts +276 -0
- package/src/cli/ui/SimpleSelector2.ts +215 -0
- package/src/cli/ui/components/ConfirmDialog.ts +176 -0
- package/src/cli/ui/components/ErrorPanel.ts +364 -0
- package/src/cli/ui/components/InkAppRunner.tsx +67 -0
- package/src/cli/ui/components/InkComponents.tsx +613 -0
- package/src/cli/ui/components/NovaInkApp.tsx +312 -0
- package/src/cli/ui/components/ProgressBar.ts +177 -0
- package/src/cli/ui/components/ProgressIndicator.ts +298 -0
- package/src/cli/ui/components/QuickActions.ts +396 -0
- package/src/cli/ui/components/SimpleErrorPanel.ts +231 -0
- package/src/cli/ui/components/StatusBar.ts +194 -0
- package/src/cli/ui/components/ThinkingBlockRenderer.ts +401 -0
- package/src/cli/ui/components/index.ts +27 -0
- package/src/cli/ui/ink-prototype.tsx +347 -0
- package/src/cli/utils/CliUI.ts +336 -0
- package/src/cli/utils/CompletionHelper.ts +388 -0
- package/src/cli/utils/EnhancedCompleter.test.ts +226 -0
- package/src/cli/utils/EnhancedCompleter.ts +513 -0
- package/src/cli/utils/ErrorEnhancer.ts +429 -0
- package/src/cli/utils/OutputFormatter.ts +193 -0
- package/src/cli/utils/index.ts +9 -0
- package/src/core/agents/AgentOrchestrator.ts +515 -0
- package/src/core/agents/index.ts +17 -0
- package/src/core/audit/AuditLogger.ts +509 -0
- package/src/core/audit/index.ts +11 -0
- package/src/core/auth/AuthManager.d.ts.map +1 -0
- package/src/core/auth/AuthManager.ts +138 -0
- package/src/core/auth/index.d.ts.map +1 -0
- package/src/core/auth/index.ts +2 -0
- package/src/core/config/ConfigManager.d.ts.map +1 -0
- package/src/core/config/ConfigManager.test.ts +183 -0
- package/src/core/config/ConfigManager.ts +1219 -0
- package/src/core/config/index.d.ts.map +1 -0
- package/src/core/config/index.ts +1 -0
- package/src/core/context/ContextBuilder.d.ts.map +1 -0
- package/src/core/context/ContextBuilder.ts +171 -0
- package/src/core/context/ContextCompressor.d.ts.map +1 -0
- package/src/core/context/ContextCompressor.ts +642 -0
- package/src/core/context/LayeredMemoryManager.ts +657 -0
- package/src/core/context/MemoryDiscovery.d.ts.map +1 -0
- package/src/core/context/MemoryDiscovery.ts +175 -0
- package/src/core/context/defaultSystemPrompt.d.ts.map +1 -0
- package/src/core/context/defaultSystemPrompt.ts +35 -0
- package/src/core/context/index.d.ts.map +1 -0
- package/src/core/context/index.ts +22 -0
- package/src/core/extensions/SkillGenerator.ts +421 -0
- package/src/core/extensions/SkillInstaller.d.ts.map +1 -0
- package/src/core/extensions/SkillInstaller.ts +257 -0
- package/src/core/extensions/SkillRegistry.d.ts.map +1 -0
- package/src/core/extensions/SkillRegistry.ts +361 -0
- package/src/core/extensions/SkillValidator.ts +525 -0
- package/src/core/extensions/index.ts +15 -0
- package/src/core/index.d.ts.map +1 -0
- package/src/core/index.ts +42 -0
- package/src/core/mcp/McpManager.d.ts.map +1 -0
- package/src/core/mcp/McpManager.ts +632 -0
- package/src/core/mcp/index.d.ts.map +1 -0
- package/src/core/mcp/index.ts +2 -0
- package/src/core/model/ModelClient.d.ts.map +1 -0
- package/src/core/model/ModelClient.ts +217 -0
- package/src/core/model/ModelConnectionTester.ts +363 -0
- package/src/core/model/ModelValidator.ts +348 -0
- package/src/core/model/index.d.ts.map +1 -0
- package/src/core/model/index.ts +6 -0
- package/src/core/model/providers/AnthropicProvider.d.ts.map +1 -0
- package/src/core/model/providers/AnthropicProvider.ts +279 -0
- package/src/core/model/providers/CodingPlanProvider.d.ts.map +1 -0
- package/src/core/model/providers/CodingPlanProvider.ts +210 -0
- package/src/core/model/providers/OllamaCloudProvider.d.ts.map +1 -0
- package/src/core/model/providers/OllamaCloudProvider.ts +405 -0
- package/src/core/model/providers/OllamaManager.d.ts.map +1 -0
- package/src/core/model/providers/OllamaManager.ts +201 -0
- package/src/core/model/providers/OllamaProvider.d.ts.map +1 -0
- package/src/core/model/providers/OllamaProvider.ts +73 -0
- package/src/core/model/providers/OpenAICompatibleProvider.d.ts.map +1 -0
- package/src/core/model/providers/OpenAICompatibleProvider.ts +327 -0
- package/src/core/model/providers/OpenAIProvider.d.ts.map +1 -0
- package/src/core/model/providers/OpenAIProvider.ts +29 -0
- package/src/core/model/providers/index.d.ts.map +1 -0
- package/src/core/model/providers/index.ts +12 -0
- package/src/core/model/types.d.ts.map +1 -0
- package/src/core/model/types.ts +77 -0
- package/src/core/security/ApprovalManager.d.ts.map +1 -0
- package/src/core/security/ApprovalManager.ts +174 -0
- package/src/core/security/FileFilter.d.ts.map +1 -0
- package/src/core/security/FileFilter.ts +141 -0
- package/src/core/security/HookExecutor.d.ts.map +1 -0
- package/src/core/security/HookExecutor.ts +178 -0
- package/src/core/security/SandboxExecutor.ts +447 -0
- package/src/core/security/index.d.ts.map +1 -0
- package/src/core/security/index.ts +8 -0
- package/src/core/session/AgentLoop.d.ts.map +1 -0
- package/src/core/session/AgentLoop.ts +501 -0
- package/src/core/session/SessionManager.d.ts.map +1 -0
- package/src/core/session/SessionManager.test.ts +183 -0
- package/src/core/session/SessionManager.ts +460 -0
- package/src/core/session/index.d.ts.map +1 -0
- package/src/core/session/index.ts +3 -0
- package/src/core/telemetry/Telemetry.d.ts.map +1 -0
- package/src/core/telemetry/Telemetry.ts +90 -0
- package/src/core/telemetry/TelemetryService.ts +531 -0
- package/src/core/telemetry/index.d.ts.map +1 -0
- package/src/core/telemetry/index.ts +12 -0
- package/src/core/testing/AutoFixer.ts +385 -0
- package/src/core/testing/ErrorAnalyzer.ts +499 -0
- package/src/core/testing/TestRunner.ts +265 -0
- package/src/core/testing/agent-cli-tests.ts +538 -0
- package/src/core/testing/index.ts +11 -0
- package/src/core/tools/ToolRegistry.d.ts.map +1 -0
- package/src/core/tools/ToolRegistry.test.ts +206 -0
- package/src/core/tools/ToolRegistry.ts +260 -0
- package/src/core/tools/impl/EditFileTool.d.ts.map +1 -0
- package/src/core/tools/impl/EditFileTool.ts +97 -0
- package/src/core/tools/impl/ListDirectoryTool.d.ts.map +1 -0
- package/src/core/tools/impl/ListDirectoryTool.ts +142 -0
- package/src/core/tools/impl/MemoryTool.d.ts.map +1 -0
- package/src/core/tools/impl/MemoryTool.ts +102 -0
- package/src/core/tools/impl/ReadFileTool.d.ts.map +1 -0
- package/src/core/tools/impl/ReadFileTool.ts +58 -0
- package/src/core/tools/impl/SearchContentTool.d.ts.map +1 -0
- package/src/core/tools/impl/SearchContentTool.ts +94 -0
- package/src/core/tools/impl/SearchFileTool.d.ts.map +1 -0
- package/src/core/tools/impl/SearchFileTool.ts +61 -0
- package/src/core/tools/impl/ShellTool.d.ts.map +1 -0
- package/src/core/tools/impl/ShellTool.ts +118 -0
- package/src/core/tools/impl/TaskTool.d.ts.map +1 -0
- package/src/core/tools/impl/TaskTool.ts +207 -0
- package/src/core/tools/impl/TodoTool.d.ts.map +1 -0
- package/src/core/tools/impl/TodoTool.ts +122 -0
- package/src/core/tools/impl/WebFetchTool.d.ts.map +1 -0
- package/src/core/tools/impl/WebFetchTool.ts +103 -0
- package/src/core/tools/impl/WebSearchTool.d.ts.map +1 -0
- package/src/core/tools/impl/WebSearchTool.ts +89 -0
- package/src/core/tools/impl/WriteFileTool.d.ts.map +1 -0
- package/src/core/tools/impl/WriteFileTool.ts +49 -0
- package/src/core/tools/impl/index.d.ts.map +1 -0
- package/src/core/tools/impl/index.ts +16 -0
- package/src/core/tools/index.d.ts.map +1 -0
- package/src/core/tools/index.ts +7 -0
- package/src/core/tools/schemas/execution.d.ts.map +1 -0
- package/src/core/tools/schemas/execution.ts +42 -0
- package/src/core/tools/schemas/file.d.ts.map +1 -0
- package/src/core/tools/schemas/file.ts +119 -0
- package/src/core/tools/schemas/index.d.ts.map +1 -0
- package/src/core/tools/schemas/index.ts +11 -0
- package/src/core/tools/schemas/memory.d.ts.map +1 -0
- package/src/core/tools/schemas/memory.ts +52 -0
- package/src/core/tools/schemas/orchestration.d.ts.map +1 -0
- package/src/core/tools/schemas/orchestration.ts +44 -0
- package/src/core/tools/schemas/search.d.ts.map +1 -0
- package/src/core/tools/schemas/search.ts +112 -0
- package/src/core/tools/schemas/todo.d.ts.map +1 -0
- package/src/core/tools/schemas/todo.ts +32 -0
- package/src/core/tools/schemas/web.d.ts.map +1 -0
- package/src/core/tools/schemas/web.ts +86 -0
- package/src/core/types/config.d.ts.map +1 -0
- package/src/core/types/config.ts +200 -0
- package/src/core/types/errors.d.ts.map +1 -0
- package/src/core/types/errors.ts +204 -0
- package/src/core/types/index.d.ts.map +1 -0
- package/src/core/types/index.ts +8 -0
- package/src/core/types/session.d.ts.map +1 -0
- package/src/core/types/session.ts +216 -0
- package/src/core/types/tools.d.ts.map +1 -0
- package/src/core/types/tools.ts +157 -0
- package/src/core/utils/CheckpointManager.d.ts.map +1 -0
- package/src/core/utils/CheckpointManager.ts +327 -0
- package/src/core/utils/Logger.d.ts.map +1 -0
- package/src/core/utils/Logger.ts +98 -0
- package/src/core/utils/RetryManager.ts +471 -0
- package/src/core/utils/TokenCounter.d.ts.map +1 -0
- package/src/core/utils/TokenCounter.ts +414 -0
- package/src/core/utils/VectorMemoryStore.ts +440 -0
- package/src/core/utils/helpers.d.ts.map +1 -0
- package/src/core/utils/helpers.ts +89 -0
- package/src/core/utils/index.d.ts.map +1 -0
- package/src/core/utils/index.ts +19 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Task Tool - Launch sub-agents for parallel task execution
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import type { ToolHandler, ToolHandlerInput, ToolHandlerOutput } from '../../types/tools.js';
|
|
6
|
+
import { ToolError } from '../../types/errors.js';
|
|
7
|
+
import { AgentLoop } from '../../session/AgentLoop.js';
|
|
8
|
+
import { SessionManager } from '../../session/SessionManager.js';
|
|
9
|
+
import { ToolRegistry } from '../../tools/ToolRegistry.js';
|
|
10
|
+
import { ModelClient } from '../../model/ModelClient.js';
|
|
11
|
+
import { buildSystemPrompt } from '../../context/defaultSystemPrompt.js';
|
|
12
|
+
import type { ContextCompressor } from '../../context/ContextCompressor.js';
|
|
13
|
+
|
|
14
|
+
interface TaskInput {
|
|
15
|
+
description: string;
|
|
16
|
+
prompt: string;
|
|
17
|
+
subagentType: 'code-explorer' | 'research' | 'executor';
|
|
18
|
+
maxTurns?: number;
|
|
19
|
+
mode?: 'acceptEdits' | 'bypassPermissions' | 'default' | 'plan';
|
|
20
|
+
name?: string;
|
|
21
|
+
teamName?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Task handler - launches a sub-agent to perform a specific task
|
|
26
|
+
*
|
|
27
|
+
* This enables parallel task execution and specialized agent behaviors:
|
|
28
|
+
* - code-explorer: Analyzes codebases and provides insights
|
|
29
|
+
* - research: Gathers information from web and documentation
|
|
30
|
+
* - executor: Performs actions and executes commands
|
|
31
|
+
*/
|
|
32
|
+
export const taskHandler: ToolHandler = async (input: ToolHandlerInput): Promise<ToolHandlerOutput> => {
|
|
33
|
+
// Validate required fields
|
|
34
|
+
const { description, prompt, subagentType, maxTurns = 10, mode = 'default', name } = input.params as Record<string, unknown>;
|
|
35
|
+
|
|
36
|
+
if (typeof description !== 'string' || typeof prompt !== 'string' || typeof subagentType !== 'string') {
|
|
37
|
+
throw new ToolError('Task requires description, prompt, and subagentType parameters to be strings', 'task');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!description || !prompt || !subagentType) {
|
|
41
|
+
throw new ToolError('Task requires description, prompt, and subagentType parameters', 'task');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const params: TaskInput = {
|
|
45
|
+
description,
|
|
46
|
+
prompt,
|
|
47
|
+
subagentType: subagentType as TaskInput['subagentType'],
|
|
48
|
+
maxTurns: typeof maxTurns === 'number' ? maxTurns : 10,
|
|
49
|
+
mode: typeof mode === 'string' ? mode as TaskInput['mode'] : 'default',
|
|
50
|
+
name: typeof name === 'string' ? name : undefined,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const sessionManager = input.context.sessionManager as SessionManager;
|
|
54
|
+
const toolRegistry = input.context.toolRegistry as ToolRegistry;
|
|
55
|
+
const modelClient = input.context.modelClient as ModelClient;
|
|
56
|
+
const contextCompressor = input.context.contextCompressor as ContextCompressor;
|
|
57
|
+
|
|
58
|
+
if (!sessionManager || !toolRegistry || !modelClient) {
|
|
59
|
+
throw new ToolError('Task tool requires sessionManager, toolRegistry, and modelClient in context', 'task');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Create a new session for the sub-agent
|
|
63
|
+
const subSession = sessionManager.create({
|
|
64
|
+
workingDirectory: input.context.workingDirectory,
|
|
65
|
+
model: modelClient.getModel(),
|
|
66
|
+
streaming: false,
|
|
67
|
+
parentSessionId: input.context.sessionId,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Configure approval mode based on task mode
|
|
71
|
+
let approvalMode = input.context.approvalMode || 'plan';
|
|
72
|
+
if (mode === 'acceptEdits') {
|
|
73
|
+
approvalMode = 'plan';
|
|
74
|
+
} else if (mode === 'bypassPermissions') {
|
|
75
|
+
approvalMode = 'yolo';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Build system prompt for sub-agent
|
|
79
|
+
const subSystemPrompt = buildSystemPrompt({
|
|
80
|
+
workingDirectory: input.context.workingDirectory,
|
|
81
|
+
model: modelClient.getModel(),
|
|
82
|
+
approvalMode,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Add sub-agent specialization to system prompt
|
|
86
|
+
const specializations: Record<string, string> = {
|
|
87
|
+
'code-explorer': `You are a Code Explorer agent. Your specialty is analyzing codebases, understanding architecture, identifying patterns, and providing code insights.
|
|
88
|
+
Focus on:
|
|
89
|
+
- Code structure and organization
|
|
90
|
+
- Design patterns and architecture
|
|
91
|
+
- Potential issues and improvements
|
|
92
|
+
- Dependencies and relationships
|
|
93
|
+
|
|
94
|
+
Be thorough in your analysis and provide actionable insights.`,
|
|
95
|
+
|
|
96
|
+
'research': `You are a Research agent. Your specialty is gathering information, investigating problems, and finding solutions.
|
|
97
|
+
Focus on:
|
|
98
|
+
- Searching for relevant documentation and examples
|
|
99
|
+
- Investigating error messages and issues
|
|
100
|
+
- Finding best practices and patterns
|
|
101
|
+
- Gathering context and background information
|
|
102
|
+
|
|
103
|
+
Be comprehensive in your research and cite sources when possible.`,
|
|
104
|
+
|
|
105
|
+
'executor': `You are an Executor agent. Your specialty is performing tasks, running commands, and making changes.
|
|
106
|
+
Focus on:
|
|
107
|
+
- Executing commands and scripts
|
|
108
|
+
- Modifying files and code
|
|
109
|
+
- Running tests and builds
|
|
110
|
+
- Implementing solutions
|
|
111
|
+
|
|
112
|
+
Be careful and precise in your actions, following best practices.`
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const specializedSystemPrompt = subSystemPrompt + '\n\n' + specializations[subagentType];
|
|
116
|
+
|
|
117
|
+
// Create agent loop for sub-agent
|
|
118
|
+
const agentLoop = new AgentLoop({
|
|
119
|
+
modelClient,
|
|
120
|
+
sessionManager,
|
|
121
|
+
toolRegistry,
|
|
122
|
+
systemPrompt: specializedSystemPrompt,
|
|
123
|
+
contextCompressor,
|
|
124
|
+
maxContextTokens: input.context.maxTokens * 8 || 128000,
|
|
125
|
+
onApprovalRequired: input.context.onApprovalRequired,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Run the sub-agent
|
|
129
|
+
const result = await agentLoop.run(subSession.id, prompt);
|
|
130
|
+
|
|
131
|
+
// Get all messages from the sub-session
|
|
132
|
+
const messages = sessionManager.getMessages(subSession.id);
|
|
133
|
+
const assistantMessages = messages.filter(m => m.role === 'assistant');
|
|
134
|
+
|
|
135
|
+
// Extract the final response
|
|
136
|
+
let finalResponse = '';
|
|
137
|
+
if (assistantMessages.length > 0) {
|
|
138
|
+
const lastMessage = assistantMessages[assistantMessages.length - 1];
|
|
139
|
+
const textBlocks = lastMessage.content.filter(block => block.type === 'text');
|
|
140
|
+
finalResponse = textBlocks.map(block => (block as any).text).join('\n\n');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Clean up sub-session
|
|
144
|
+
sessionManager.delete(subSession.id);
|
|
145
|
+
|
|
146
|
+
// Format the result
|
|
147
|
+
const output = `
|
|
148
|
+
### 🤖 Sub-agent Task Complete
|
|
149
|
+
|
|
150
|
+
**Task**: ${description}
|
|
151
|
+
**Type**: ${subagentType}
|
|
152
|
+
**Agent**: ${name || 'Unnamed'}
|
|
153
|
+
**Turns**: ${result.turnsCompleted}
|
|
154
|
+
**Tokens**: ${result.totalInputTokens + result.totalOutputTokens}
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
${finalResponse}
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
**Status**: ✅ Completed successfully
|
|
163
|
+
`.trim();
|
|
164
|
+
|
|
165
|
+
return { content: output };
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
export const taskSchema = {
|
|
169
|
+
type: 'object' as const,
|
|
170
|
+
properties: {
|
|
171
|
+
description: {
|
|
172
|
+
type: 'string',
|
|
173
|
+
description: 'Brief description of the task (3-5 words)',
|
|
174
|
+
},
|
|
175
|
+
prompt: {
|
|
176
|
+
type: 'string',
|
|
177
|
+
description: 'Detailed task description for the sub-agent',
|
|
178
|
+
},
|
|
179
|
+
subagentType: {
|
|
180
|
+
type: 'string',
|
|
181
|
+
description: 'Type of sub-agent to spawn',
|
|
182
|
+
enum: ['code-explorer', 'research', 'executor'],
|
|
183
|
+
default: 'research',
|
|
184
|
+
},
|
|
185
|
+
maxTurns: {
|
|
186
|
+
type: 'number',
|
|
187
|
+
description: 'Maximum number of agentic turns',
|
|
188
|
+
default: 10,
|
|
189
|
+
},
|
|
190
|
+
mode: {
|
|
191
|
+
type: 'string',
|
|
192
|
+
description: 'Permission mode for the sub-agent',
|
|
193
|
+
enum: ['acceptEdits', 'bypassPermissions', 'default', 'plan'],
|
|
194
|
+
default: 'default',
|
|
195
|
+
},
|
|
196
|
+
name: {
|
|
197
|
+
type: 'string',
|
|
198
|
+
description: 'Name for the sub-agent (enables team mode)',
|
|
199
|
+
},
|
|
200
|
+
teamName: {
|
|
201
|
+
type: 'string',
|
|
202
|
+
description: 'Team to join (enables team mode)',
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
required: ['description', 'prompt', 'subagentType'],
|
|
206
|
+
additionalProperties: false,
|
|
207
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TodoTool.d.ts","sourceRoot":"","sources":["TodoTool.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAuC,MAAM,sBAAsB,CAAC;AA6B7F,eAAO,MAAM,WAAW,EAAE,WA2DzB,CAAC;AAEF,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BtB,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Todo Tool - Task tracking and progress display
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
import type { ToolHandler, ToolHandlerInput, ToolHandlerOutput } from '../../types/tools.js';
|
|
6
|
+
import { ToolError } from '../../types/errors.js';
|
|
7
|
+
|
|
8
|
+
interface TodoItem {
|
|
9
|
+
id: string;
|
|
10
|
+
content: string;
|
|
11
|
+
status: 'pending' | 'in_progress' | 'completed';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** In-memory todo storage per session */
|
|
15
|
+
const sessionTodos = new Map<string, TodoItem[]>();
|
|
16
|
+
|
|
17
|
+
function getTodos(sessionId: string): TodoItem[] {
|
|
18
|
+
if (!sessionTodos.has(sessionId)) {
|
|
19
|
+
sessionTodos.set(sessionId, []);
|
|
20
|
+
}
|
|
21
|
+
return sessionTodos.get(sessionId)!;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function renderTodos(todos: TodoItem[]): string {
|
|
25
|
+
if (todos.length === 0) return 'No tasks tracked.';
|
|
26
|
+
const statusIcons: Record<string, string> = {
|
|
27
|
+
pending: '○',
|
|
28
|
+
in_progress: '◉',
|
|
29
|
+
completed: '●',
|
|
30
|
+
};
|
|
31
|
+
return todos.map((t) => `${statusIcons[t.status]} [${t.status.padEnd(12)}] ${t.content}`).join('\n');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const todoHandler: ToolHandler = async (input: ToolHandlerInput): Promise<ToolHandlerOutput> => {
|
|
35
|
+
const { action, items, id, content, status } = input.params as {
|
|
36
|
+
action?: string;
|
|
37
|
+
items?: string;
|
|
38
|
+
id?: string;
|
|
39
|
+
content?: string;
|
|
40
|
+
status?: string;
|
|
41
|
+
};
|
|
42
|
+
const sessionId = input.context.sessionId;
|
|
43
|
+
const todos = getTodos(sessionId);
|
|
44
|
+
|
|
45
|
+
switch (action) {
|
|
46
|
+
case 'list': {
|
|
47
|
+
return { content: renderTodos(todos) };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
case 'create': {
|
|
51
|
+
if (!items) {
|
|
52
|
+
throw new ToolError('Missing "items" parameter. Provide a JSON array of task strings.', 'todo');
|
|
53
|
+
}
|
|
54
|
+
let parsed: unknown[];
|
|
55
|
+
try {
|
|
56
|
+
parsed = JSON.parse(typeof items === 'string' ? items : JSON.stringify(items));
|
|
57
|
+
} catch {
|
|
58
|
+
parsed = [String(items)];
|
|
59
|
+
}
|
|
60
|
+
for (const item of parsed) {
|
|
61
|
+
todos.push({ id: `t${todos.length + 1}`, content: String(item), status: 'pending' });
|
|
62
|
+
}
|
|
63
|
+
return { content: `Added ${parsed.length} task(s).\n${renderTodos(todos)}` };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
case 'update': {
|
|
67
|
+
if (!id || !status) {
|
|
68
|
+
throw new ToolError('Missing "id" or "status" parameter.', 'todo');
|
|
69
|
+
}
|
|
70
|
+
const target = todos.find((t) => t.id === id || t.id === `t${id}`);
|
|
71
|
+
if (!target) {
|
|
72
|
+
throw new ToolError(`Task "${id}" not found.`, 'todo');
|
|
73
|
+
}
|
|
74
|
+
const validStatuses = ['pending', 'in_progress', 'completed'];
|
|
75
|
+
if (!validStatuses.includes(status)) {
|
|
76
|
+
throw new ToolError(`Invalid status "${status}". Use: ${validStatuses.join(', ')}`, 'todo');
|
|
77
|
+
}
|
|
78
|
+
if (content) target.content = content;
|
|
79
|
+
target.status = status as TodoItem['status'];
|
|
80
|
+
return { content: renderTodos(todos) };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
case 'clear': {
|
|
84
|
+
todos.length = 0;
|
|
85
|
+
return { content: 'All tasks cleared.' };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
default: {
|
|
89
|
+
// If no action, show current state
|
|
90
|
+
return { content: renderTodos(todos) };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const todoSchema = {
|
|
96
|
+
type: 'object' as const,
|
|
97
|
+
properties: {
|
|
98
|
+
action: {
|
|
99
|
+
type: 'string',
|
|
100
|
+
enum: ['list', 'create', 'update', 'clear'],
|
|
101
|
+
description: 'Action to perform: list (show tasks), create (add tasks), update (change status), clear (remove all)',
|
|
102
|
+
},
|
|
103
|
+
items: {
|
|
104
|
+
type: 'string',
|
|
105
|
+
description: 'JSON array of task strings to create (for action=create). Example: \'["Task 1", "Task 2"]\'',
|
|
106
|
+
},
|
|
107
|
+
id: {
|
|
108
|
+
type: 'string',
|
|
109
|
+
description: 'Task ID to update (for action=update)',
|
|
110
|
+
},
|
|
111
|
+
content: {
|
|
112
|
+
type: 'string',
|
|
113
|
+
description: 'New content for the task (for action=update)',
|
|
114
|
+
},
|
|
115
|
+
status: {
|
|
116
|
+
type: 'string',
|
|
117
|
+
enum: ['pending', 'in_progress', 'completed'],
|
|
118
|
+
description: 'New status for the task (for action=update)',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
additionalProperties: false,
|
|
122
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebFetchTool.d.ts","sourceRoot":"","sources":["WebFetchTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAuC,MAAM,sBAAsB,CAAC;AAG7F,eAAO,MAAM,eAAe,EAAE,WA+E7B,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { ToolHandler, ToolHandlerInput, ToolHandlerOutput } from '../../types/tools.js';
|
|
2
|
+
import { ToolError, TimeoutError } from '../../types/errors.js';
|
|
3
|
+
|
|
4
|
+
export const webFetchHandler: ToolHandler = async (input: ToolHandlerInput): Promise<ToolHandlerOutput> => {
|
|
5
|
+
const {
|
|
6
|
+
url,
|
|
7
|
+
method = 'GET',
|
|
8
|
+
headers: extraHeaders,
|
|
9
|
+
body,
|
|
10
|
+
timeout = 15000,
|
|
11
|
+
followRedirects = true,
|
|
12
|
+
maxLength = 50000,
|
|
13
|
+
} = input.params as {
|
|
14
|
+
url: string;
|
|
15
|
+
method?: string;
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
body?: string;
|
|
18
|
+
timeout?: number;
|
|
19
|
+
followRedirects?: boolean;
|
|
20
|
+
maxLength?: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
// Basic URL validation
|
|
25
|
+
const parsedUrl = new URL(url);
|
|
26
|
+
if (!['http:', 'https:'].includes(parsedUrl.protocol)) {
|
|
27
|
+
throw new Error(`Unsupported protocol: ${parsedUrl.protocol}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
32
|
+
|
|
33
|
+
const response = await fetch(url, {
|
|
34
|
+
method,
|
|
35
|
+
headers: {
|
|
36
|
+
'User-Agent': 'NovaCLI/0.1.0 (Research Agent)',
|
|
37
|
+
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,text/markdown;q=0.9,*/*;q=0.8',
|
|
38
|
+
...extraHeaders,
|
|
39
|
+
},
|
|
40
|
+
body: method !== 'GET' ? body : undefined,
|
|
41
|
+
signal: controller.signal,
|
|
42
|
+
redirect: followRedirects ? 'follow' : 'manual',
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const contentType = response.headers.get('content-type') || '';
|
|
52
|
+
let content = await response.text();
|
|
53
|
+
|
|
54
|
+
// Truncate if too long
|
|
55
|
+
if (content.length > maxLength) {
|
|
56
|
+
content = content.slice(0, maxLength) + `\n\n[Content truncated: showing ${maxLength} of ${content.length} characters]`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Basic HTML to text conversion
|
|
60
|
+
if (contentType.includes('text/html')) {
|
|
61
|
+
content = htmlToText(content);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
content,
|
|
66
|
+
metadata: {
|
|
67
|
+
url,
|
|
68
|
+
status: response.status,
|
|
69
|
+
contentType,
|
|
70
|
+
contentLength: content.length,
|
|
71
|
+
finalUrl: response.url,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
} catch (err) {
|
|
75
|
+
if (err instanceof DOMException && err.name === 'AbortError') {
|
|
76
|
+
throw new TimeoutError(`Fetch timed out after ${timeout}ms`, timeout);
|
|
77
|
+
}
|
|
78
|
+
if (err instanceof TypeError && (err as Error).message.includes('URL')) {
|
|
79
|
+
throw new ToolError(`Invalid URL: ${url}`, 'web_fetch');
|
|
80
|
+
}
|
|
81
|
+
throw new ToolError(`Failed to fetch URL: ${(err as Error).message}`, 'web_fetch');
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/** Basic HTML to text converter */
|
|
86
|
+
function htmlToText(html: string): string {
|
|
87
|
+
return html
|
|
88
|
+
// Remove scripts and styles
|
|
89
|
+
.replace(/<script[\s\S]*?<\/script>/gi, '')
|
|
90
|
+
.replace(/<style[\s\S]*?<\/style>/gi, '')
|
|
91
|
+
// Remove HTML tags
|
|
92
|
+
.replace(/<[^>]+>/g, ' ')
|
|
93
|
+
// Decode HTML entities
|
|
94
|
+
.replace(/&/g, '&')
|
|
95
|
+
.replace(/</g, '<')
|
|
96
|
+
.replace(/>/g, '>')
|
|
97
|
+
.replace(/"/g, '"')
|
|
98
|
+
.replace(/'/g, "'")
|
|
99
|
+
.replace(/ /g, ' ')
|
|
100
|
+
// Collapse whitespace
|
|
101
|
+
.replace(/\s+/g, ' ')
|
|
102
|
+
.trim();
|
|
103
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebSearchTool.d.ts","sourceRoot":"","sources":["WebSearchTool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAuC,MAAM,sBAAsB,CAAC;AAG7F,eAAO,MAAM,gBAAgB,EAAE,WAqF9B,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { ToolHandler, ToolHandlerInput, ToolHandlerOutput } from '../../types/tools.js';
|
|
2
|
+
import { ToolError } from '../../types/errors.js';
|
|
3
|
+
|
|
4
|
+
export const webSearchHandler: ToolHandler = async (input: ToolHandlerInput): Promise<ToolHandlerOutput> => {
|
|
5
|
+
const { query, maxResults = 10, language, region, safeSearch = true, freshness } = input.params as {
|
|
6
|
+
query: string;
|
|
7
|
+
maxResults?: number;
|
|
8
|
+
language?: string;
|
|
9
|
+
region?: string;
|
|
10
|
+
safeSearch?: boolean;
|
|
11
|
+
freshness?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// This is a placeholder implementation. In production, integrate with a search API
|
|
15
|
+
// such as Google Custom Search, Bing Web Search, or Serper API.
|
|
16
|
+
|
|
17
|
+
const apiKey = process.env.NOVA_SEARCH_API_KEY || process.env.SERPER_API_KEY;
|
|
18
|
+
|
|
19
|
+
if (!apiKey) {
|
|
20
|
+
// Fallback: provide a helpful message about configuration
|
|
21
|
+
return {
|
|
22
|
+
content: `[Web Search Placeholder]\n\nQuery: ${query}\n\nTo enable web search, configure one of:\n- NOVA_SEARCH_API_KEY: Set to a Serper.dev API key\n- SERPER_API_KEY: Alternative Serper key\n\nGet a Serper API key at: https://serper.dev/\n\nConfiguration can be set in:\n- Environment variables\n- ~/.nova/config.yaml (search.apiKey)\n- Project .nova/config.yaml`,
|
|
23
|
+
metadata: { query, configured: false },
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
// Serper.dev API integration
|
|
29
|
+
const response = await fetch('https://google.serper.dev/search', {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: {
|
|
32
|
+
'X-API-KEY': apiKey,
|
|
33
|
+
'Content-Type': 'application/json',
|
|
34
|
+
},
|
|
35
|
+
body: JSON.stringify({
|
|
36
|
+
q: query,
|
|
37
|
+
num: maxResults,
|
|
38
|
+
gl: region,
|
|
39
|
+
hl: language,
|
|
40
|
+
safe: safeSearch ? 'active' : 'off',
|
|
41
|
+
tbs: freshness ? `qdr:${freshness}` : undefined,
|
|
42
|
+
}),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
throw new Error(`Search API returned ${response.status}: ${response.statusText}`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const data = await response.json() as Record<string, unknown>;
|
|
50
|
+
const organic = (data.organic || []) as Array<{
|
|
51
|
+
title: string;
|
|
52
|
+
link: string;
|
|
53
|
+
snippet: string;
|
|
54
|
+
position: number;
|
|
55
|
+
}>;
|
|
56
|
+
|
|
57
|
+
if (organic.length === 0) {
|
|
58
|
+
return {
|
|
59
|
+
content: `No results found for: "${query}"`,
|
|
60
|
+
metadata: { query, count: 0 },
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const results = organic
|
|
65
|
+
.map((r, i) => `${i + 1}. ${r.title}\n ${r.link}\n ${r.snippet}`)
|
|
66
|
+
.join('\n\n');
|
|
67
|
+
|
|
68
|
+
const knowledgeGraph = data.knowledgeGraph as { title?: string; description?: string } | undefined;
|
|
69
|
+
let output = '';
|
|
70
|
+
if (knowledgeGraph?.title) {
|
|
71
|
+
output += `Knowledge Graph: ${knowledgeGraph.title}\n`;
|
|
72
|
+
if (knowledgeGraph.description) output += `${knowledgeGraph.description}\n`;
|
|
73
|
+
output += '\n';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
output += results;
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
content: output,
|
|
80
|
+
metadata: {
|
|
81
|
+
query,
|
|
82
|
+
count: organic.length,
|
|
83
|
+
hasKnowledgeGraph: !!knowledgeGraph,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
} catch (err) {
|
|
87
|
+
throw new ToolError(`Web search failed: ${(err as Error).message}`, 'web_search');
|
|
88
|
+
}
|
|
89
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WriteFileTool.d.ts","sourceRoot":"","sources":["WriteFileTool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAuC,MAAM,sBAAsB,CAAC;AAG7F,eAAO,MAAM,gBAAgB,EAAE,WA2C9B,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import type { ToolHandler, ToolHandlerInput, ToolHandlerOutput } from '../../types/tools.js';
|
|
4
|
+
import { ToolError } from '../../types/errors.js';
|
|
5
|
+
|
|
6
|
+
export const writeFileHandler: ToolHandler = async (input: ToolHandlerInput): Promise<ToolHandlerOutput> => {
|
|
7
|
+
const { filePath, content, createDirectories = false, encoding = 'utf-8' } = input.params as {
|
|
8
|
+
filePath: string;
|
|
9
|
+
content: string;
|
|
10
|
+
createDirectories?: boolean;
|
|
11
|
+
encoding?: BufferEncoding;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const resolvedPath = path.resolve(filePath);
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
if (createDirectories) {
|
|
18
|
+
const dir = path.dirname(resolvedPath);
|
|
19
|
+
await fs.mkdir(dir, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Verify parent directory exists
|
|
23
|
+
const dir = path.dirname(resolvedPath);
|
|
24
|
+
try {
|
|
25
|
+
await fs.access(dir, fs.constants.W_OK);
|
|
26
|
+
} catch {
|
|
27
|
+
throw new ToolError(`Cannot write to directory: ${dir}`, 'write_file');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
await fs.writeFile(resolvedPath, content, { encoding });
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
content: `Successfully wrote ${content.length} characters to ${resolvedPath}`,
|
|
34
|
+
metadata: {
|
|
35
|
+
path: resolvedPath,
|
|
36
|
+
size: Buffer.byteLength(content, encoding),
|
|
37
|
+
encoding,
|
|
38
|
+
},
|
|
39
|
+
filesAffected: [resolvedPath],
|
|
40
|
+
};
|
|
41
|
+
} catch (err) {
|
|
42
|
+
if (err instanceof ToolError) throw err;
|
|
43
|
+
const code = (err as NodeJS.ErrnoException).code;
|
|
44
|
+
if (code === 'EACCES') {
|
|
45
|
+
throw new ToolError(`Permission denied: ${filePath}`, 'write_file', undefined, { code });
|
|
46
|
+
}
|
|
47
|
+
throw new ToolError(`Failed to write file: ${(err as Error).message}`, 'write_file');
|
|
48
|
+
}
|
|
49
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Tool Implementations Barrel Export
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
export { readFileHandler } from './ReadFileTool.js';
|
|
6
|
+
export { writeFileHandler } from './WriteFileTool.js';
|
|
7
|
+
export { editFileHandler } from './EditFileTool.js';
|
|
8
|
+
export { listDirectoryHandler } from './ListDirectoryTool.js';
|
|
9
|
+
export { searchFileHandler } from './SearchFileTool.js';
|
|
10
|
+
export { searchContentHandler } from './SearchContentTool.js';
|
|
11
|
+
export { shellHandler } from './ShellTool.js';
|
|
12
|
+
export { webSearchHandler } from './WebSearchTool.js';
|
|
13
|
+
export { webFetchHandler } from './WebFetchTool.js';
|
|
14
|
+
export { memoryReadHandler, memoryWriteHandler } from './MemoryTool.js';
|
|
15
|
+
export { todoHandler } from './TodoTool.js';
|
|
16
|
+
export { taskHandler } from './TaskTool.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Tools Package Barrel Export
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
export { ToolRegistry } from './ToolRegistry.js';
|
|
6
|
+
export * from './schemas/index.js';
|
|
7
|
+
export * from './impl/index.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution.d.ts","sourceRoot":"","sources":["execution.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqChC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Execution Tool Schemas - JSON schemas for shell command execution
|
|
3
|
+
// ============================================================================
|
|
4
|
+
|
|
5
|
+
export const executeCommandSchema = {
|
|
6
|
+
type: 'object' as const,
|
|
7
|
+
properties: {
|
|
8
|
+
command: {
|
|
9
|
+
type: 'string',
|
|
10
|
+
description: 'The shell command to execute',
|
|
11
|
+
},
|
|
12
|
+
workingDirectory: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: 'Working directory for the command (overrides session default)',
|
|
15
|
+
},
|
|
16
|
+
env: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
description: 'Additional environment variables for the command',
|
|
19
|
+
additionalProperties: { type: 'string' },
|
|
20
|
+
},
|
|
21
|
+
timeout: {
|
|
22
|
+
type: 'number',
|
|
23
|
+
description: 'Timeout in milliseconds (default: 30000)',
|
|
24
|
+
default: 30000,
|
|
25
|
+
},
|
|
26
|
+
shell: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'Shell to use (e.g., "bash", "powershell", "cmd")',
|
|
29
|
+
},
|
|
30
|
+
captureStderr: {
|
|
31
|
+
type: 'boolean',
|
|
32
|
+
description: 'Whether to capture stderr separately',
|
|
33
|
+
default: true,
|
|
34
|
+
},
|
|
35
|
+
input: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
description: 'Stdin input for the command',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
required: ['command'],
|
|
41
|
+
additionalProperties: false,
|
|
42
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["file.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;CAuB1B,CAAC;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;CAwB3B,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4B1B,CAAC;AAEF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiC/B,CAAC"}
|