@4onstudios/iris-agent 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.
- package/LICENSE +21 -0
- package/README.md +690 -0
- package/dist/api/acp/acpServer.d.ts +23 -0
- package/dist/api/acp/acpServer.js +814 -0
- package/dist/api/acp/index.d.ts +2 -0
- package/dist/api/acp/index.js +2 -0
- package/dist/api/acp/irisClient.d.ts +58 -0
- package/dist/api/acp/irisClient.js +214 -0
- package/dist/api/agent.d.ts +14 -0
- package/dist/api/agent.js +4171 -0
- package/dist/api/backendService.d.ts +4 -0
- package/dist/api/backendService.js +14 -0
- package/dist/api/core/agent/host/AgentContract.d.ts +82 -0
- package/dist/api/core/agent/host/AgentContract.js +1 -0
- package/dist/api/core/agent/host/AgentRegistry.d.ts +24 -0
- package/dist/api/core/agent/host/AgentRegistry.js +125 -0
- package/dist/api/core/agent/host/defaultRegistry.d.ts +15 -0
- package/dist/api/core/agent/host/defaultRegistry.js +46 -0
- package/dist/api/core/agent/host/externalAgentLifecycle.d.ts +65 -0
- package/dist/api/core/agent/host/externalAgentLifecycle.js +117 -0
- package/dist/api/core/agent/host/hostSessionManager.d.ts +111 -0
- package/dist/api/core/agent/host/hostSessionManager.js +352 -0
- package/dist/api/core/agent/host/index.d.ts +5 -0
- package/dist/api/core/agent/host/index.js +5 -0
- package/dist/api/core/agent/index.d.ts +87 -0
- package/dist/api/core/agent/index.js +1024 -0
- package/dist/api/core/agent/publicContracts.d.ts +35 -0
- package/dist/api/core/agent/publicContracts.js +103 -0
- package/dist/api/core/agent/tools/applyDiff.d.ts +51 -0
- package/dist/api/core/agent/tools/applyDiff.js +131 -0
- package/dist/api/core/agent/tools/backgroundTasks.d.ts +240 -0
- package/dist/api/core/agent/tools/backgroundTasks.js +313 -0
- package/dist/api/core/agent/tools/createDirectory.d.ts +43 -0
- package/dist/api/core/agent/tools/createDirectory.js +77 -0
- package/dist/api/core/agent/tools/deleteFile.d.ts +37 -0
- package/dist/api/core/agent/tools/deleteFile.js +66 -0
- package/dist/api/core/agent/tools/editFile.d.ts +73 -0
- package/dist/api/core/agent/tools/editFile.js +173 -0
- package/dist/api/core/agent/tools/executeCommand.d.ts +59 -0
- package/dist/api/core/agent/tools/executeCommand.js +250 -0
- package/dist/api/core/agent/tools/fileContent.d.ts +54 -0
- package/dist/api/core/agent/tools/fileContent.js +227 -0
- package/dist/api/core/agent/tools/findDefinition.d.ts +72 -0
- package/dist/api/core/agent/tools/findDefinition.js +109 -0
- package/dist/api/core/agent/tools/findReferences.d.ts +86 -0
- package/dist/api/core/agent/tools/findReferences.js +135 -0
- package/dist/api/core/agent/tools/formatDocument.d.ts +67 -0
- package/dist/api/core/agent/tools/formatDocument.js +90 -0
- package/dist/api/core/agent/tools/getCodeActions.d.ts +77 -0
- package/dist/api/core/agent/tools/getCodeActions.js +97 -0
- package/dist/api/core/agent/tools/getCodeCompletion.d.ts +77 -0
- package/dist/api/core/agent/tools/getCodeCompletion.js +174 -0
- package/dist/api/core/agent/tools/getCodeContext.d.ts +14 -0
- package/dist/api/core/agent/tools/getCodeContext.js +282 -0
- package/dist/api/core/agent/tools/getSignatureHelp.d.ts +61 -0
- package/dist/api/core/agent/tools/getSignatureHelp.js +85 -0
- package/dist/api/core/agent/tools/getSymbols.d.ts +50 -0
- package/dist/api/core/agent/tools/getSymbols.js +164 -0
- package/dist/api/core/agent/tools/getSymbolsLSP.d.ts +58 -0
- package/dist/api/core/agent/tools/getSymbolsLSP.js +147 -0
- package/dist/api/core/agent/tools/getTypeInfo.d.ts +70 -0
- package/dist/api/core/agent/tools/getTypeInfo.js +84 -0
- package/dist/api/core/agent/tools/getWorkspaceInfo.d.ts +80 -0
- package/dist/api/core/agent/tools/getWorkspaceInfo.js +281 -0
- package/dist/api/core/agent/tools/getWorkspaceSymbols.d.ts +53 -0
- package/dist/api/core/agent/tools/getWorkspaceSymbols.js +97 -0
- package/dist/api/core/agent/tools/grepSearch.d.ts +100 -0
- package/dist/api/core/agent/tools/grepSearch.js +211 -0
- package/dist/api/core/agent/tools/languageModelToolsIntegration.d.ts +13 -0
- package/dist/api/core/agent/tools/languageModelToolsIntegration.js +22 -0
- package/dist/api/core/agent/tools/listDirectory.d.ts +66 -0
- package/dist/api/core/agent/tools/listDirectory.js +161 -0
- package/dist/api/core/agent/tools/mcpTools.d.ts +48 -0
- package/dist/api/core/agent/tools/mcpTools.js +442 -0
- package/dist/api/core/agent/tools/queryKnowledgeGraph.d.ts +120 -0
- package/dist/api/core/agent/tools/queryKnowledgeGraph.js +306 -0
- package/dist/api/core/agent/tools/readFile.d.ts +92 -0
- package/dist/api/core/agent/tools/readFile.js +337 -0
- package/dist/api/core/agent/tools/renameFile.d.ts +49 -0
- package/dist/api/core/agent/tools/renameFile.js +86 -0
- package/dist/api/core/agent/tools/renameSymbol.d.ts +70 -0
- package/dist/api/core/agent/tools/renameSymbol.js +106 -0
- package/dist/api/core/agent/tools/runTerminalCommand.d.ts +72 -0
- package/dist/api/core/agent/tools/runTerminalCommand.js +69 -0
- package/dist/api/core/agent/tools/searchFiles.d.ts +82 -0
- package/dist/api/core/agent/tools/searchFiles.js +280 -0
- package/dist/api/core/agent/tools/terminalAutoApprove.d.ts +3 -0
- package/dist/api/core/agent/tools/terminalAutoApprove.js +676 -0
- package/dist/api/core/agent/tools/treeTraversal.d.ts +60 -0
- package/dist/api/core/agent/tools/treeTraversal.js +217 -0
- package/dist/api/core/agent/tools/webSearch.d.ts +37 -0
- package/dist/api/core/agent/tools/webSearch.js +80 -0
- package/dist/api/core/agent/tools/writeFile.d.ts +59 -0
- package/dist/api/core/agent/tools/writeFile.js +97 -0
- package/dist/api/core/agent/utils/capturedWorkspaceMutationBridge.d.ts +12 -0
- package/dist/api/core/agent/utils/capturedWorkspaceMutationBridge.js +67 -0
- package/dist/api/core/agent/utils/diffUtils.d.ts +14 -0
- package/dist/api/core/agent/utils/diffUtils.js +39 -0
- package/dist/api/core/agent/utils/environmentSnapshot.d.ts +42 -0
- package/dist/api/core/agent/utils/environmentSnapshot.js +213 -0
- package/dist/api/core/agent/utils/errorRecovery.d.ts +49 -0
- package/dist/api/core/agent/utils/errorRecovery.js +229 -0
- package/dist/api/core/agent/utils/multimodalTokenLimiter.d.ts +8 -0
- package/dist/api/core/agent/utils/multimodalTokenLimiter.js +238 -0
- package/dist/api/core/agent/utils/openRouterModelSettings.d.ts +12 -0
- package/dist/api/core/agent/utils/openRouterModelSettings.js +34 -0
- package/dist/api/core/agent/utils/pathRecovery.d.ts +1 -0
- package/dist/api/core/agent/utils/pathRecovery.js +29 -0
- package/dist/api/core/agent/utils/repoMapIndex.d.ts +3 -0
- package/dist/api/core/agent/utils/repoMapIndex.js +197 -0
- package/dist/api/core/agent/utils/skillsDiscovery.d.ts +10 -0
- package/dist/api/core/agent/utils/skillsDiscovery.js +50 -0
- package/dist/api/core/agent/utils/toolCallBudget.d.ts +9 -0
- package/dist/api/core/agent/utils/toolCallBudget.js +55 -0
- package/dist/api/core/agent/utils/toolLifecycle.d.ts +30 -0
- package/dist/api/core/agent/utils/toolLifecycle.js +361 -0
- package/dist/api/core/agent/utils/toolResultSafetyProcessor.d.ts +12 -0
- package/dist/api/core/agent/utils/toolResultSafetyProcessor.js +57 -0
- package/dist/api/core/agent/utils/workspaceMutationBridge.d.ts +13 -0
- package/dist/api/core/agent/utils/workspaceMutationBridge.js +149 -0
- package/dist/api/core/agent/utils/workspacePathGuard.d.ts +7 -0
- package/dist/api/core/agent/utils/workspacePathGuard.js +79 -0
- package/dist/api/core/containers/chat/toolResultSerialization.d.ts +8 -0
- package/dist/api/core/containers/chat/toolResultSerialization.js +71 -0
- package/dist/api/core/library/BrowserManager.d.ts +11 -0
- package/dist/api/core/library/BrowserManager.js +66 -0
- package/dist/api/core/library/desktopWorkspace.d.ts +1 -0
- package/dist/api/core/library/desktopWorkspace.js +3 -0
- package/dist/api/core/library/extensionManager.d.ts +10 -0
- package/dist/api/core/library/extensionManager.js +27 -0
- package/dist/api/core/library/knowledgeGraph.d.ts +268 -0
- package/dist/api/core/library/knowledgeGraph.js +989 -0
- package/dist/api/core/library/languageModelTools.d.ts +141 -0
- package/dist/api/core/library/languageModelTools.js +207 -0
- package/dist/api/core/library/localRuntime.d.ts +23 -0
- package/dist/api/core/library/localRuntime.js +144 -0
- package/dist/api/core/library/lsp/coreLsp.d.ts +367 -0
- package/dist/api/core/library/lsp/coreLsp.js +2076 -0
- package/dist/api/core/library/lsp/protocol.d.ts +25 -0
- package/dist/api/core/library/lsp/protocol.js +1 -0
- package/dist/api/core/library/lsp/serverManager.d.ts +37 -0
- package/dist/api/core/library/lsp/serverManager.js +427 -0
- package/dist/api/core/library/mcpServerProvider.d.ts +69 -0
- package/dist/api/core/library/mcpServerProvider.js +152 -0
- package/dist/api/core/library/mcpSettings.d.ts +20 -0
- package/dist/api/core/library/mcpSettings.js +131 -0
- package/dist/api/core/library/patternMatcher.d.ts +66 -0
- package/dist/api/core/library/patternMatcher.js +284 -0
- package/dist/api/core/library/regexEscape.d.ts +4 -0
- package/dist/api/core/library/regexEscape.js +4 -0
- package/dist/api/core/library/runtimeEventBus.d.ts +27 -0
- package/dist/api/core/library/runtimeEventBus.js +78 -0
- package/dist/api/core/library/safetyMiddleware.d.ts +98 -0
- package/dist/api/core/library/safetyMiddleware.js +215 -0
- package/dist/api/core/library/tauri.d.ts +71 -0
- package/dist/api/core/library/tauri.js +222 -0
- package/dist/api/core/library/tauriImport.d.ts +5 -0
- package/dist/api/core/library/tauriImport.js +7 -0
- package/dist/api/core/library/terminalAutoApproveSettings.d.ts +32 -0
- package/dist/api/core/library/terminalAutoApproveSettings.js +529 -0
- package/dist/api/core/library/workspaceIdentity.d.ts +10 -0
- package/dist/api/core/library/workspaceIdentity.js +49 -0
- package/dist/api/core/library/workspaceSummary.d.ts +19 -0
- package/dist/api/core/library/workspaceSummary.js +35 -0
- package/dist/api/core/skills/agent-customization/SKILL.md +27 -0
- package/dist/api/core/skills/bug-fix/SKILL.md +21 -0
- package/dist/api/core/skills/create-pr/SKILL.md +32 -0
- package/dist/api/core/skills/dev-server/SKILL.md +20 -0
- package/dist/api/core/skills/fix-suggestions/SKILL.md +21 -0
- package/dist/api/core/skills/github-search/SKILL.md +21 -0
- package/dist/api/core/skills/github-summary/SKILL.md +25 -0
- package/dist/api/core/skills/integration-tests/SKILL.md +29 -0
- package/dist/api/core/skills/pr-comments/SKILL.md +23 -0
- package/dist/api/core/skills/project-setup/SKILL.md +20 -0
- package/dist/api/core/skills/search-integration/SKILL.md +19 -0
- package/dist/api/core/skills/search-results/SKILL.md +19 -0
- package/dist/api/core/skills/typescript-upgrade/SKILL.md +21 -0
- package/dist/api/data/runStore.d.ts +46 -0
- package/dist/api/data/runStore.js +244 -0
- package/dist/api/helpers/agentUtils.d.ts +11 -0
- package/dist/api/helpers/agentUtils.js +23 -0
- package/dist/api/helpers/modelTokenLimits.d.ts +2 -0
- package/dist/api/helpers/modelTokenLimits.js +158 -0
- package/dist/api/helpers/observationalMemory.d.ts +10 -0
- package/dist/api/helpers/observationalMemory.js +36 -0
- package/dist/api/helpers/promptBudget.d.ts +30 -0
- package/dist/api/helpers/promptBudget.js +216 -0
- package/dist/api/helpers/resolveImageMessageParts.d.ts +9 -0
- package/dist/api/helpers/resolveImageMessageParts.js +140 -0
- package/dist/api/helpers/slashCommands.d.ts +31 -0
- package/dist/api/helpers/slashCommands.js +129 -0
- package/dist/api/helpers/tokenUsage.d.ts +19 -0
- package/dist/api/helpers/tokenUsage.js +81 -0
- package/dist/api/routes/fileRoutes.d.ts +2 -0
- package/dist/api/routes/fileRoutes.js +108 -0
- package/dist/api/routes/lspDocumentRoutes.d.ts +4 -0
- package/dist/api/routes/lspDocumentRoutes.js +84 -0
- package/dist/api/routes/lspHierarchyRoutes.d.ts +4 -0
- package/dist/api/routes/lspHierarchyRoutes.js +122 -0
- package/dist/api/routes/lspPositionRoutes.d.ts +4 -0
- package/dist/api/routes/lspPositionRoutes.js +263 -0
- package/dist/api/routes/lspQueryRoutes.d.ts +4 -0
- package/dist/api/routes/lspQueryRoutes.js +679 -0
- package/dist/api/routes/lspResolveRoutes.d.ts +4 -0
- package/dist/api/routes/lspResolveRoutes.js +143 -0
- package/dist/api/routes/lspSemanticDocumentRoutes.d.ts +4 -0
- package/dist/api/routes/lspSemanticDocumentRoutes.js +98 -0
- package/dist/api/routes/semanticRoutes.d.ts +2 -0
- package/dist/api/routes/semanticRoutes.js +126 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +160 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +38 -0
- package/package.json +100 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language Model Tools API
|
|
3
|
+
* VS Code-compatible API for registering and managing language model tools
|
|
4
|
+
*/
|
|
5
|
+
import { EventEmitter } from "events";
|
|
6
|
+
import type { McpServerConfig } from "./mcpSettings.js";
|
|
7
|
+
/**
|
|
8
|
+
* Represents a tool that can be invoked by a language model
|
|
9
|
+
*/
|
|
10
|
+
export interface LanguageModelToolInformation {
|
|
11
|
+
/** Unique tool name */
|
|
12
|
+
readonly name: string;
|
|
13
|
+
/** Description for language model */
|
|
14
|
+
readonly description: string;
|
|
15
|
+
/** JSON schema for input validation */
|
|
16
|
+
readonly inputSchema?: object;
|
|
17
|
+
/** Tags for categorization */
|
|
18
|
+
readonly tags: readonly string[];
|
|
19
|
+
/** Source of the tool (mcp, native, etc.) */
|
|
20
|
+
readonly source: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Options for tool invocation
|
|
24
|
+
*/
|
|
25
|
+
export interface LanguageModelToolInvocationOptions<T = unknown> {
|
|
26
|
+
/** Tool input matching the schema */
|
|
27
|
+
input: T;
|
|
28
|
+
/** Optional token budget hints */
|
|
29
|
+
tokenizationOptions?: {
|
|
30
|
+
tokenBudget: number;
|
|
31
|
+
countTokens: (text: string) => Promise<number>;
|
|
32
|
+
};
|
|
33
|
+
/** Context from chat request (for UI integration) */
|
|
34
|
+
toolInvocationToken?: unknown;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Result from tool invocation
|
|
38
|
+
*/
|
|
39
|
+
export interface LanguageModelToolResult {
|
|
40
|
+
/** Content parts from the tool */
|
|
41
|
+
content: Array<{
|
|
42
|
+
type: "text" | "data" | "error";
|
|
43
|
+
value: string;
|
|
44
|
+
mimeType?: string;
|
|
45
|
+
}>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* A tool that can be registered and invoked
|
|
49
|
+
*/
|
|
50
|
+
export interface LanguageModelTool<T = unknown> {
|
|
51
|
+
/**
|
|
52
|
+
* Invoke the tool with the given input
|
|
53
|
+
*/
|
|
54
|
+
invoke(options: LanguageModelToolInvocationOptions<T>, signal?: AbortSignal): Promise<LanguageModelToolResult>;
|
|
55
|
+
/**
|
|
56
|
+
* Optional preparation before invocation (for progress/confirmation)
|
|
57
|
+
*/
|
|
58
|
+
prepareInvocation?(options: {
|
|
59
|
+
input: T;
|
|
60
|
+
}, signal?: AbortSignal): Promise<{
|
|
61
|
+
invocationMessage?: string;
|
|
62
|
+
confirmationMessages?: {
|
|
63
|
+
title: string;
|
|
64
|
+
message: string;
|
|
65
|
+
};
|
|
66
|
+
}>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* MCP Server Definition Provider
|
|
70
|
+
* Provides available MCP servers dynamically
|
|
71
|
+
*/
|
|
72
|
+
export interface McpServerDefinitionProvider {
|
|
73
|
+
/**
|
|
74
|
+
* Provide available MCP servers
|
|
75
|
+
*/
|
|
76
|
+
provideMcpServerDefinitions(signal?: AbortSignal): Promise<McpServerConfig[]>;
|
|
77
|
+
/**
|
|
78
|
+
* Optional: resolve server before starting (e.g., for authentication)
|
|
79
|
+
*/
|
|
80
|
+
resolveMcpServerDefinition?(server: McpServerConfig, signal?: AbortSignal): Promise<McpServerConfig>;
|
|
81
|
+
/**
|
|
82
|
+
* Optional: event when servers change
|
|
83
|
+
*/
|
|
84
|
+
onDidChangeMcpServerDefinitions?: (listener: () => void) => () => void;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Disposable pattern for cleanup
|
|
88
|
+
*/
|
|
89
|
+
export interface Disposable {
|
|
90
|
+
dispose(): void;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Language Model Tools Manager
|
|
94
|
+
* Manages tool registration and discovery
|
|
95
|
+
*/
|
|
96
|
+
export declare class LanguageModelToolsManager extends EventEmitter {
|
|
97
|
+
private tools;
|
|
98
|
+
private toolInfo;
|
|
99
|
+
private mcpProviders;
|
|
100
|
+
private mcpServerCache;
|
|
101
|
+
private workspacePath;
|
|
102
|
+
constructor();
|
|
103
|
+
/**
|
|
104
|
+
* Set workspace path for MCP servers
|
|
105
|
+
*/
|
|
106
|
+
setWorkspacePath(path: string | null): void;
|
|
107
|
+
/**
|
|
108
|
+
* Register a native tool
|
|
109
|
+
*/
|
|
110
|
+
registerTool<T = unknown>(name: string, tool: LanguageModelTool<T>, info: Omit<LanguageModelToolInformation, "name" | "source">): Disposable;
|
|
111
|
+
/**
|
|
112
|
+
* Register an MCP server definition provider
|
|
113
|
+
*/
|
|
114
|
+
registerMcpServerDefinitionProvider(id: string, provider: McpServerDefinitionProvider): Disposable;
|
|
115
|
+
/**
|
|
116
|
+
* Get all available tools (native + MCP)
|
|
117
|
+
*/
|
|
118
|
+
getAvailableTools(signal?: AbortSignal): Promise<LanguageModelToolInformation[]>;
|
|
119
|
+
/**
|
|
120
|
+
* Invoke a tool by name
|
|
121
|
+
*/
|
|
122
|
+
invokeTool(name: string, options: LanguageModelToolInvocationOptions, signal?: AbortSignal): Promise<LanguageModelToolResult>;
|
|
123
|
+
/**
|
|
124
|
+
* Invoke an MCP tool
|
|
125
|
+
*/
|
|
126
|
+
private invokeMcpTool;
|
|
127
|
+
/**
|
|
128
|
+
* Get all MCP servers from all providers
|
|
129
|
+
*/
|
|
130
|
+
private getAllMcpServers;
|
|
131
|
+
/**
|
|
132
|
+
* Generate MCP tool key (matches mcpTools.ts format)
|
|
133
|
+
*/
|
|
134
|
+
private getMcpToolKey;
|
|
135
|
+
/**
|
|
136
|
+
* Listen for tool changes
|
|
137
|
+
*/
|
|
138
|
+
onDidChangeTools(listener: () => void): Disposable;
|
|
139
|
+
}
|
|
140
|
+
export declare const languageModelTools: LanguageModelToolsManager;
|
|
141
|
+
export default LanguageModelToolsManager;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language Model Tools API
|
|
3
|
+
* VS Code-compatible API for registering and managing language model tools
|
|
4
|
+
*/
|
|
5
|
+
import { EventEmitter } from "events";
|
|
6
|
+
import { listMcpServerTools, executeMcpToolByKey } from "../agent/tools/mcpTools.js";
|
|
7
|
+
/**
|
|
8
|
+
* Language Model Tools Manager
|
|
9
|
+
* Manages tool registration and discovery
|
|
10
|
+
*/
|
|
11
|
+
export class LanguageModelToolsManager extends EventEmitter {
|
|
12
|
+
tools = new Map();
|
|
13
|
+
toolInfo = new Map();
|
|
14
|
+
mcpProviders = new Map();
|
|
15
|
+
mcpServerCache = new Map();
|
|
16
|
+
workspacePath = null;
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Set workspace path for MCP servers
|
|
22
|
+
*/
|
|
23
|
+
setWorkspacePath(path) {
|
|
24
|
+
this.workspacePath = path;
|
|
25
|
+
// Clear cache when workspace changes
|
|
26
|
+
this.mcpServerCache.clear();
|
|
27
|
+
this.emit("toolsChanged");
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Register a native tool
|
|
31
|
+
*/
|
|
32
|
+
registerTool(name, tool, info) {
|
|
33
|
+
this.tools.set(name, tool);
|
|
34
|
+
this.toolInfo.set(name, {
|
|
35
|
+
name,
|
|
36
|
+
description: info.description,
|
|
37
|
+
inputSchema: info.inputSchema,
|
|
38
|
+
tags: info.tags,
|
|
39
|
+
source: "native",
|
|
40
|
+
});
|
|
41
|
+
this.emit("toolsChanged");
|
|
42
|
+
return {
|
|
43
|
+
dispose: () => {
|
|
44
|
+
this.tools.delete(name);
|
|
45
|
+
this.toolInfo.delete(name);
|
|
46
|
+
this.emit("toolsChanged");
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Register an MCP server definition provider
|
|
52
|
+
*/
|
|
53
|
+
registerMcpServerDefinitionProvider(id, provider) {
|
|
54
|
+
this.mcpProviders.set(id, provider);
|
|
55
|
+
// Listen for changes if provider supports it
|
|
56
|
+
let unsubscribe;
|
|
57
|
+
if (provider.onDidChangeMcpServerDefinitions) {
|
|
58
|
+
unsubscribe = provider.onDidChangeMcpServerDefinitions(() => {
|
|
59
|
+
this.mcpServerCache.delete(id);
|
|
60
|
+
this.emit("toolsChanged");
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
this.emit("toolsChanged");
|
|
64
|
+
return {
|
|
65
|
+
dispose: () => {
|
|
66
|
+
this.mcpProviders.delete(id);
|
|
67
|
+
this.mcpServerCache.delete(id);
|
|
68
|
+
if (unsubscribe)
|
|
69
|
+
unsubscribe();
|
|
70
|
+
this.emit("toolsChanged");
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get all available tools (native + MCP)
|
|
76
|
+
*/
|
|
77
|
+
async getAvailableTools(signal) {
|
|
78
|
+
const tools = [];
|
|
79
|
+
// Add native tools
|
|
80
|
+
tools.push(...Array.from(this.toolInfo.values()));
|
|
81
|
+
// Add MCP tools from all providers
|
|
82
|
+
const mcpServers = await this.getAllMcpServers(signal);
|
|
83
|
+
const workspacePath = this.workspacePath || process.cwd();
|
|
84
|
+
for (const server of mcpServers) {
|
|
85
|
+
if (!server.enabled)
|
|
86
|
+
continue;
|
|
87
|
+
try {
|
|
88
|
+
const serverTools = await listMcpServerTools(server, workspacePath);
|
|
89
|
+
for (const tool of serverTools) {
|
|
90
|
+
const toolKey = this.getMcpToolKey(server.name, tool.name);
|
|
91
|
+
tools.push({
|
|
92
|
+
name: toolKey,
|
|
93
|
+
description: tool.description || `MCP tool: ${tool.name}`,
|
|
94
|
+
inputSchema: tool.inputSchema,
|
|
95
|
+
tags: ["mcp", server.name],
|
|
96
|
+
source: `mcp:${server.name}`,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error(`Failed to list tools from ${server.name}:`, error);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return tools;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Invoke a tool by name
|
|
108
|
+
*/
|
|
109
|
+
async invokeTool(name, options, signal) {
|
|
110
|
+
// Check if it's a native tool
|
|
111
|
+
const nativeTool = this.tools.get(name);
|
|
112
|
+
if (nativeTool) {
|
|
113
|
+
return nativeTool.invoke(options, signal);
|
|
114
|
+
}
|
|
115
|
+
// Check if it's an MCP tool
|
|
116
|
+
if (name.startsWith("mcp_")) {
|
|
117
|
+
return this.invokeMcpTool(name, options, signal);
|
|
118
|
+
}
|
|
119
|
+
throw new Error(`Tool '${name}' not found`);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Invoke an MCP tool
|
|
123
|
+
*/
|
|
124
|
+
async invokeMcpTool(toolKey, options, signal) {
|
|
125
|
+
const mcpServers = await this.getAllMcpServers(signal);
|
|
126
|
+
const workspacePath = this.workspacePath || process.cwd();
|
|
127
|
+
const result = await executeMcpToolByKey(mcpServers, workspacePath, toolKey, options.input);
|
|
128
|
+
if (!result.success) {
|
|
129
|
+
return {
|
|
130
|
+
content: [
|
|
131
|
+
{
|
|
132
|
+
type: "error",
|
|
133
|
+
value: result.error || "MCP tool execution failed",
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// At this point, result.success is true, so we can safely access optional content
|
|
139
|
+
// TypeScript can't narrow the union type properly, so we explicitly cast
|
|
140
|
+
const successResult = result;
|
|
141
|
+
// Convert MCP result to LanguageModelToolResult format
|
|
142
|
+
const content = [];
|
|
143
|
+
if (Array.isArray(successResult.content)) {
|
|
144
|
+
for (const item of successResult.content) {
|
|
145
|
+
if (typeof item === "object" && item !== null) {
|
|
146
|
+
const mcpItem = item;
|
|
147
|
+
if (mcpItem.text) {
|
|
148
|
+
content.push({
|
|
149
|
+
type: "text",
|
|
150
|
+
value: mcpItem.text,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
else if (mcpItem.message) {
|
|
154
|
+
content.push({
|
|
155
|
+
type: "text",
|
|
156
|
+
value: mcpItem.message,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (content.length === 0 && successResult.content !== undefined) {
|
|
163
|
+
content.push({
|
|
164
|
+
type: "text",
|
|
165
|
+
value: JSON.stringify(successResult.content, null, 2),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return { content };
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Get all MCP servers from all providers
|
|
172
|
+
*/
|
|
173
|
+
async getAllMcpServers(signal) {
|
|
174
|
+
const allServers = [];
|
|
175
|
+
for (const [id, provider] of this.mcpProviders.entries()) {
|
|
176
|
+
// Check cache first
|
|
177
|
+
let servers = this.mcpServerCache.get(id);
|
|
178
|
+
if (!servers) {
|
|
179
|
+
servers = await provider.provideMcpServerDefinitions(signal);
|
|
180
|
+
this.mcpServerCache.set(id, servers);
|
|
181
|
+
}
|
|
182
|
+
allServers.push(...servers);
|
|
183
|
+
}
|
|
184
|
+
return allServers;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Generate MCP tool key (matches mcpTools.ts format)
|
|
188
|
+
*/
|
|
189
|
+
getMcpToolKey(serverName, toolName) {
|
|
190
|
+
const safeToken = (value) => value.replace(/[^a-zA-Z0-9_]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 80);
|
|
191
|
+
return `mcp_${safeToken(serverName)}_${safeToken(toolName)}`;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Listen for tool changes
|
|
195
|
+
*/
|
|
196
|
+
onDidChangeTools(listener) {
|
|
197
|
+
this.on("toolsChanged", listener);
|
|
198
|
+
return {
|
|
199
|
+
dispose: () => {
|
|
200
|
+
this.off("toolsChanged", listener);
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Singleton instance
|
|
206
|
+
export const languageModelTools = new LanguageModelToolsManager();
|
|
207
|
+
export default LanguageModelToolsManager;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const API_KEYS_STORAGE_KEY = "settings.apiKeys";
|
|
2
|
+
export declare const DEFAULT_LOCAL_RUNTIME_BASE_URL = "http://127.0.0.1:11434/v1";
|
|
3
|
+
export declare const DEFAULT_LOCAL_RUNTIME_API_KEY = "ollama";
|
|
4
|
+
export type LocalRuntimeHealthResult = {
|
|
5
|
+
ok: boolean;
|
|
6
|
+
message: string;
|
|
7
|
+
probeUrl: string;
|
|
8
|
+
/** True when the probe was aborted due to timeout (as opposed to a hard connection error). */
|
|
9
|
+
timedOut?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare const isLocalModelId: (modelId: string) => boolean;
|
|
12
|
+
export declare const getLocalRuntimeConfigFromStorage: () => {
|
|
13
|
+
baseUrl: string;
|
|
14
|
+
apiKey: string;
|
|
15
|
+
};
|
|
16
|
+
export declare const checkLocalRuntimeConnection: (baseUrl: string, apiKey?: string, timeoutMs?: number) => Promise<LocalRuntimeHealthResult>;
|
|
17
|
+
/**
|
|
18
|
+
* Check local runtime connection with built-in caching to avoid repeated probes.
|
|
19
|
+
* Uses a short TTL (60s for successful, 5s for failed) to prevent latency regressions
|
|
20
|
+
* during repeated chat invocations while still allowing quick error recovery.
|
|
21
|
+
* All probes use HEALTH_CHECK_TIMEOUT_MS regardless of host.
|
|
22
|
+
*/
|
|
23
|
+
export declare const checkLocalRuntimeConnectionCached: (baseUrl: string, apiKey?: string) => Promise<LocalRuntimeHealthResult>;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
export const API_KEYS_STORAGE_KEY = "settings.apiKeys";
|
|
2
|
+
export const DEFAULT_LOCAL_RUNTIME_BASE_URL = "http://127.0.0.1:11434/v1";
|
|
3
|
+
export const DEFAULT_LOCAL_RUNTIME_API_KEY = "ollama";
|
|
4
|
+
// Cache for health check results to avoid repeated probes.
|
|
5
|
+
// Keyed by normalized baseUrl + a non-reversible fingerprint of apiKey.
|
|
6
|
+
// This avoids storing raw secrets in memory while preventing cache collisions
|
|
7
|
+
// across different keys for the same endpoint.
|
|
8
|
+
const HEALTH_CHECK_CACHE = new Map();
|
|
9
|
+
const HEALTH_CHECK_CACHE_MAX_SIZE = 8; // evict oldest entry when exceeded
|
|
10
|
+
const HEALTH_CHECK_TTL_MS = 60000; // Cache for 60 seconds
|
|
11
|
+
const HEALTH_CHECK_FAILED_TTL_MS = 5000; // Cache failures for 5 seconds only
|
|
12
|
+
const HEALTH_CHECK_TIMEOUT_MS = 1500; // 1500ms balances cold-start tolerance vs. latency
|
|
13
|
+
export const isLocalModelId = (modelId) => modelId.startsWith("ollama/") || modelId.startsWith("local/");
|
|
14
|
+
const trimTrailingSlash = (value) => value.replace(/\/$/, "");
|
|
15
|
+
// Produces a short, non-reversible fingerprint of the API key so that cache
|
|
16
|
+
// entries for different keys on the same baseUrl are not conflated, without
|
|
17
|
+
// retaining the raw secret in the Map key.
|
|
18
|
+
const fingerprintApiKey = (apiKey) => {
|
|
19
|
+
if (!apiKey)
|
|
20
|
+
return "";
|
|
21
|
+
let hash = 5381;
|
|
22
|
+
for (let i = 0; i < apiKey.length; i++) {
|
|
23
|
+
hash = (((hash << 5) + hash) ^ apiKey.charCodeAt(i)) >>> 0;
|
|
24
|
+
}
|
|
25
|
+
return hash.toString(36);
|
|
26
|
+
};
|
|
27
|
+
const normalizeBaseUrl = (value) => {
|
|
28
|
+
const trimmed = (value || "").trim();
|
|
29
|
+
if (!trimmed)
|
|
30
|
+
return DEFAULT_LOCAL_RUNTIME_BASE_URL;
|
|
31
|
+
const candidate = trimTrailingSlash(trimmed);
|
|
32
|
+
try {
|
|
33
|
+
const parsed = new URL(candidate);
|
|
34
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
35
|
+
return DEFAULT_LOCAL_RUNTIME_BASE_URL;
|
|
36
|
+
}
|
|
37
|
+
return candidate;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return DEFAULT_LOCAL_RUNTIME_BASE_URL;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const buildProbeUrl = (baseUrl) => {
|
|
44
|
+
const normalized = normalizeBaseUrl(baseUrl);
|
|
45
|
+
return `${normalized}/models`;
|
|
46
|
+
};
|
|
47
|
+
export const getLocalRuntimeConfigFromStorage = () => {
|
|
48
|
+
if (typeof window === "undefined") {
|
|
49
|
+
return {
|
|
50
|
+
baseUrl: DEFAULT_LOCAL_RUNTIME_BASE_URL,
|
|
51
|
+
apiKey: DEFAULT_LOCAL_RUNTIME_API_KEY,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const raw = localStorage.getItem(API_KEYS_STORAGE_KEY);
|
|
56
|
+
const parsed = raw ? JSON.parse(raw) : {};
|
|
57
|
+
return {
|
|
58
|
+
baseUrl: normalizeBaseUrl(parsed?.OLLAMA_BASE_URL),
|
|
59
|
+
apiKey: (parsed?.OLLAMA_API_KEY || DEFAULT_LOCAL_RUNTIME_API_KEY).trim(),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return {
|
|
64
|
+
baseUrl: DEFAULT_LOCAL_RUNTIME_BASE_URL,
|
|
65
|
+
apiKey: DEFAULT_LOCAL_RUNTIME_API_KEY,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
export const checkLocalRuntimeConnection = async (baseUrl, apiKey, timeoutMs = 3000) => {
|
|
70
|
+
const probeUrl = buildProbeUrl(baseUrl);
|
|
71
|
+
const controller = new AbortController();
|
|
72
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
73
|
+
try {
|
|
74
|
+
const headers = {};
|
|
75
|
+
if (apiKey && apiKey.trim().length > 0) {
|
|
76
|
+
headers.Authorization = `Bearer ${apiKey.trim()}`;
|
|
77
|
+
}
|
|
78
|
+
const res = await fetch(probeUrl, {
|
|
79
|
+
method: "GET",
|
|
80
|
+
headers,
|
|
81
|
+
signal: controller.signal,
|
|
82
|
+
});
|
|
83
|
+
if (!res.ok) {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
message: `Runtime responded with HTTP ${res.status}`,
|
|
87
|
+
probeUrl,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const payload = (await res.json().catch(() => ({})));
|
|
91
|
+
const modelCount = Array.isArray(payload?.data) ? payload.data.length : undefined;
|
|
92
|
+
return {
|
|
93
|
+
ok: true,
|
|
94
|
+
message: modelCount !== undefined ? `Connected (${modelCount} model${modelCount === 1 ? "" : "s"} available)` : "Connected",
|
|
95
|
+
probeUrl,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
const timedOut = err instanceof Error && err.name === "AbortError";
|
|
100
|
+
const message = timedOut ? "Connection timed out" : err instanceof Error ? err.message : "Connection failed";
|
|
101
|
+
return {
|
|
102
|
+
ok: false,
|
|
103
|
+
message,
|
|
104
|
+
probeUrl,
|
|
105
|
+
timedOut,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
clearTimeout(timeout);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Check local runtime connection with built-in caching to avoid repeated probes.
|
|
114
|
+
* Uses a short TTL (60s for successful, 5s for failed) to prevent latency regressions
|
|
115
|
+
* during repeated chat invocations while still allowing quick error recovery.
|
|
116
|
+
* All probes use HEALTH_CHECK_TIMEOUT_MS regardless of host.
|
|
117
|
+
*/
|
|
118
|
+
export const checkLocalRuntimeConnectionCached = async (baseUrl, apiKey) => {
|
|
119
|
+
const cacheKey = `${normalizeBaseUrl(baseUrl)}:${fingerprintApiKey(apiKey)}`;
|
|
120
|
+
const cached = HEALTH_CHECK_CACHE.get(cacheKey);
|
|
121
|
+
// Return cached result if still valid
|
|
122
|
+
if (cached) {
|
|
123
|
+
const age = Date.now() - cached.timestamp;
|
|
124
|
+
const ttl = cached.result.ok ? HEALTH_CHECK_TTL_MS : HEALTH_CHECK_FAILED_TTL_MS;
|
|
125
|
+
if (age < ttl) {
|
|
126
|
+
return cached.result;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Cache miss or expired - perform fresh check
|
|
130
|
+
const result = await checkLocalRuntimeConnection(baseUrl, apiKey, HEALTH_CHECK_TIMEOUT_MS);
|
|
131
|
+
// Don't cache timeout failures — the runtime may just be slow to start;
|
|
132
|
+
// the next invocation should retry immediately rather than hitting a stale negative.
|
|
133
|
+
if (!result.timedOut) {
|
|
134
|
+
// Evict the oldest entry before inserting when the cache is at capacity.
|
|
135
|
+
if (!HEALTH_CHECK_CACHE.has(cacheKey) && HEALTH_CHECK_CACHE.size >= HEALTH_CHECK_CACHE_MAX_SIZE) {
|
|
136
|
+
const oldestKey = HEALTH_CHECK_CACHE.keys().next().value;
|
|
137
|
+
if (oldestKey !== undefined) {
|
|
138
|
+
HEALTH_CHECK_CACHE.delete(oldestKey);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
HEALTH_CHECK_CACHE.set(cacheKey, { result, timestamp: Date.now() });
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
};
|