@compilr-dev/sdk 0.1.5 → 0.1.6
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/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/meta-tools/index.d.ts +16 -0
- package/dist/meta-tools/index.js +16 -0
- package/dist/meta-tools/registry.d.ts +94 -0
- package/dist/meta-tools/registry.js +406 -0
- package/package.json +4 -1
package/dist/index.d.ts
CHANGED
|
@@ -43,6 +43,8 @@ export { resolveProvider, detectProviderFromEnv, createProviderFromType } from '
|
|
|
43
43
|
export { DEFAULT_MODELS, getContextWindow, DEFAULT_CONTEXT_WINDOW } from './models.js';
|
|
44
44
|
export { type ModelTier, type TierInfo, type ProviderModelMap, MODEL_TIERS, TIER_INFO, isValidTier, type ThinkingFormat, type ModelStatus, type ModelInfo, MODEL_REGISTRY, getModelsForProvider, getModelsSortedForDisplay, getModelInfo, isKnownModel, isModelSupported, getThinkingFormat, getStatusIndicator, getStatusLabel, getDefaultModelForTier, areThinkingFormatsCompatible, shouldClearHistoryOnModelChange, getModelContextWindow, getModelDisplayName, getModelDescription, getModelForTier, getTierMappings, getTierDisplayName, getShortModelName, getDefaultTierMappings, type ProviderMetadata, type OthersProviderModel, PROVIDER_METADATA, TOGETHER_MODELS, GROQ_MODELS, FIREWORKS_MODELS, PERPLEXITY_MODELS, OPENROUTER_MODELS, getModelsForOthersProvider, getOthersProviders, getProviderMetadata, isOthersProvider, } from './models/index.js';
|
|
45
45
|
export { assembleTools, deduplicateTools } from './tools.js';
|
|
46
|
+
export { MetaToolsRegistry, createMetaTools, META_TOOLS_SYSTEM_PROMPT_PREFIX, } from './meta-tools/index.js';
|
|
47
|
+
export type { MetaToolStats, MetaTools } from './meta-tools/index.js';
|
|
46
48
|
export { SystemPromptBuilder, buildSystemPrompt, detectGitRepository, getModuleStats, ALL_MODULES, IDENTITY_MODULE, STYLE_MODULE, TASK_EXECUTION_MODULE, TODO_MANAGEMENT_MODULE, TOOL_USAGE_DIRECT_MODULE, TOOL_USAGE_META_MODULE, DELEGATION_MODULE, GIT_SAFETY_MODULE, SUGGEST_MODULE, IMPORTANT_RULES_MODULE, ENVIRONMENT_MODULE, shouldIncludeModule, getEstimatedTokensForConditions, getTotalEstimatedTokens, } from './system-prompt/index.js';
|
|
47
49
|
export type { SystemPromptContext, BuildResult, SystemPromptModule, ModuleConditions, } from './system-prompt/index.js';
|
|
48
50
|
export { defineTool, createSuccessResult, createErrorResult, mergeHooks, createLoggingHooks, createClaudeProvider, createOpenAIProvider, createGeminiNativeProvider, createOllamaProvider, createTogetherProvider, createGroqProvider, createFireworksProvider, createPerplexityProvider, createOpenRouterProvider, createMockProvider, MockProvider, Agent, ContextManager, DEFAULT_CONTEXT_CONFIG, createTaskTool, createSuggestTool, defaultAgentTypes, TOOL_SETS, BUILTIN_GUARDRAILS, TOOL_NAMES, getDefaultShellManager, builtinSkills, AnchorManager, MCPManager, AgentError, ProviderError, ToolError, ToolTimeoutError, MaxIterationsError, AbortError, } from '@compilr-dev/agents';
|
package/dist/index.js
CHANGED
|
@@ -61,6 +61,10 @@ getModelForTier, getTierMappings, getTierDisplayName, getShortModelName, getDefa
|
|
|
61
61
|
// =============================================================================
|
|
62
62
|
export { assembleTools, deduplicateTools } from './tools.js';
|
|
63
63
|
// =============================================================================
|
|
64
|
+
// Meta-Tools Registry (dynamic tool loading for token reduction)
|
|
65
|
+
// =============================================================================
|
|
66
|
+
export { MetaToolsRegistry, createMetaTools, META_TOOLS_SYSTEM_PROMPT_PREFIX, } from './meta-tools/index.js';
|
|
67
|
+
// =============================================================================
|
|
64
68
|
// System Prompt Builder
|
|
65
69
|
// =============================================================================
|
|
66
70
|
export {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meta-tools — Dynamic tool loading for token reduction.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { MetaToolsRegistry, createMetaTools } from '@compilr-dev/sdk';
|
|
7
|
+
*
|
|
8
|
+
* const registry = new MetaToolsRegistry();
|
|
9
|
+
* registry.initialize(myTools);
|
|
10
|
+
*
|
|
11
|
+
* const metaTools = createMetaTools(registry);
|
|
12
|
+
* // Use metaTools.getToolInfoTool as a direct tool
|
|
13
|
+
* // Use metaTools.createFallback() for transparent routing
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export { MetaToolsRegistry, createMetaTools, META_TOOLS_SYSTEM_PROMPT_PREFIX, type MetaToolStats, type MetaTools, } from './registry.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meta-tools — Dynamic tool loading for token reduction.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { MetaToolsRegistry, createMetaTools } from '@compilr-dev/sdk';
|
|
7
|
+
*
|
|
8
|
+
* const registry = new MetaToolsRegistry();
|
|
9
|
+
* registry.initialize(myTools);
|
|
10
|
+
*
|
|
11
|
+
* const metaTools = createMetaTools(registry);
|
|
12
|
+
* // Use metaTools.getToolInfoTool as a direct tool
|
|
13
|
+
* // Use metaTools.createFallback() for transparent routing
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export { MetaToolsRegistry, createMetaTools, META_TOOLS_SYSTEM_PROMPT_PREFIX, } from './registry.js';
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetaToolsRegistry — Instance-based meta-tools for SDK consumers.
|
|
3
|
+
*
|
|
4
|
+
* Replaces full tool declarations (~15K tokens for 49 tools) with:
|
|
5
|
+
* 1. A compact tool index in the system prompt (~800 tokens)
|
|
6
|
+
* 2. Three meta-tools: list_tools, get_tool_info, use_tool
|
|
7
|
+
* 3. A transparent fallback handler for direct tool calls
|
|
8
|
+
*
|
|
9
|
+
* Each agent gets its own registry instance, enabling multi-agent
|
|
10
|
+
* scenarios where each agent has a different tool set.
|
|
11
|
+
*/
|
|
12
|
+
import { type Tool, type ToolExecutionResult } from '@compilr-dev/agents';
|
|
13
|
+
/**
|
|
14
|
+
* Statistics about the meta-tools registry.
|
|
15
|
+
*/
|
|
16
|
+
export interface MetaToolStats {
|
|
17
|
+
/** Total tools in the registry */
|
|
18
|
+
registeredTools: number;
|
|
19
|
+
/** Tools allowed by the current filter (or all if no filter) */
|
|
20
|
+
allowedTools: number;
|
|
21
|
+
/** Estimated token savings vs declaring all tools directly */
|
|
22
|
+
estimatedTokenSavings: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The set of meta-tools and fallback handler returned by createMetaTools().
|
|
26
|
+
*/
|
|
27
|
+
export interface MetaTools {
|
|
28
|
+
/** Lists available tools by category */
|
|
29
|
+
listToolsTool: Tool;
|
|
30
|
+
/** Returns the JSON schema for a tool's parameters */
|
|
31
|
+
getToolInfoTool: Tool;
|
|
32
|
+
/** Executes any registered tool by name */
|
|
33
|
+
useToolTool: Tool;
|
|
34
|
+
/** Creates a fallback handler for transparent tool routing */
|
|
35
|
+
createFallback: () => (name: string, input: Record<string, unknown>) => Promise<ToolExecutionResult | null>;
|
|
36
|
+
}
|
|
37
|
+
export declare class MetaToolsRegistry {
|
|
38
|
+
private readonly toolRegistry;
|
|
39
|
+
private readonly ajv;
|
|
40
|
+
private currentFilter;
|
|
41
|
+
/**
|
|
42
|
+
* Populate the registry with available tools.
|
|
43
|
+
* Call this once at startup with all tools that should be available via meta-tools.
|
|
44
|
+
*/
|
|
45
|
+
initialize(tools: Tool[]): void;
|
|
46
|
+
/**
|
|
47
|
+
* Set the current tool filter for meta-registry access.
|
|
48
|
+
* Pass null or undefined to allow all tools.
|
|
49
|
+
*/
|
|
50
|
+
setFilter(filter: string[] | null | undefined): void;
|
|
51
|
+
/**
|
|
52
|
+
* Get the current tool filter.
|
|
53
|
+
*/
|
|
54
|
+
getFilter(): Set<string> | null;
|
|
55
|
+
/**
|
|
56
|
+
* Check if a tool is allowed by the current filter.
|
|
57
|
+
*/
|
|
58
|
+
isToolAllowed(name: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Get all registered tools.
|
|
61
|
+
*/
|
|
62
|
+
getRegisteredTools(): Tool[];
|
|
63
|
+
/**
|
|
64
|
+
* Get a tool by name from the registry.
|
|
65
|
+
*/
|
|
66
|
+
getTool(name: string): Tool | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Get count of registered tools.
|
|
69
|
+
*/
|
|
70
|
+
getToolCount(): number;
|
|
71
|
+
/**
|
|
72
|
+
* Generate tool index for the system prompt.
|
|
73
|
+
* Groups tools by category and shows signatures.
|
|
74
|
+
*/
|
|
75
|
+
generateToolIndex(): string;
|
|
76
|
+
/**
|
|
77
|
+
* Get the full system prompt section (prefix + index).
|
|
78
|
+
*/
|
|
79
|
+
getToolIndexForSystemPrompt(): string;
|
|
80
|
+
/**
|
|
81
|
+
* Get registry statistics.
|
|
82
|
+
*/
|
|
83
|
+
getStats(): MetaToolStats;
|
|
84
|
+
/**
|
|
85
|
+
* Validate arguments against a tool's schema.
|
|
86
|
+
* Returns null if valid, or an error message string.
|
|
87
|
+
*/
|
|
88
|
+
validateArgs(toolName: string, args: Record<string, unknown>): string | null;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Create the three meta-tools + fallback handler, all bound to a registry instance.
|
|
92
|
+
*/
|
|
93
|
+
export declare function createMetaTools(registry: MetaToolsRegistry): MetaTools;
|
|
94
|
+
export declare const META_TOOLS_SYSTEM_PROMPT_PREFIX = "\n## Tool Index (Specialized Tools)\n\nThese tools are called **exactly like direct tools** \u2014 just use the tool name with parameters. No special syntax or wrapper needed. The system routes them automatically.\n\n**IMPORTANT \u2014 These are CLI system tools, NOT your project's backend. Never use localhost/curl to access them.**\n\n**Parameter Rules:**\n- For **zero-parameter calls**: call the tool directly (e.g., `workitem_query()`, `git_status()`).\n- For **calls WITH parameters**: you MUST call `get_tool_info(\"tool_name\")` first to get the exact JSON schema. The signatures below are summaries only \u2014 do NOT guess parameter structure from them.\n- After a failed tool call, always call `get_tool_info()` before retrying.\n\n";
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MetaToolsRegistry — Instance-based meta-tools for SDK consumers.
|
|
3
|
+
*
|
|
4
|
+
* Replaces full tool declarations (~15K tokens for 49 tools) with:
|
|
5
|
+
* 1. A compact tool index in the system prompt (~800 tokens)
|
|
6
|
+
* 2. Three meta-tools: list_tools, get_tool_info, use_tool
|
|
7
|
+
* 3. A transparent fallback handler for direct tool calls
|
|
8
|
+
*
|
|
9
|
+
* Each agent gets its own registry instance, enabling multi-agent
|
|
10
|
+
* scenarios where each agent has a different tool set.
|
|
11
|
+
*/
|
|
12
|
+
import Ajv from 'ajv';
|
|
13
|
+
import { defineTool, createSuccessResult, createErrorResult, } from '@compilr-dev/agents';
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// MetaToolsRegistry class
|
|
16
|
+
// =============================================================================
|
|
17
|
+
export class MetaToolsRegistry {
|
|
18
|
+
toolRegistry = new Map();
|
|
19
|
+
ajv = new Ajv({ allErrors: true });
|
|
20
|
+
currentFilter = null;
|
|
21
|
+
/**
|
|
22
|
+
* Populate the registry with available tools.
|
|
23
|
+
* Call this once at startup with all tools that should be available via meta-tools.
|
|
24
|
+
*/
|
|
25
|
+
initialize(tools) {
|
|
26
|
+
this.toolRegistry.clear();
|
|
27
|
+
for (const tool of tools) {
|
|
28
|
+
this.toolRegistry.set(tool.definition.name, tool);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Set the current tool filter for meta-registry access.
|
|
33
|
+
* Pass null or undefined to allow all tools.
|
|
34
|
+
*/
|
|
35
|
+
setFilter(filter) {
|
|
36
|
+
this.currentFilter = filter ? new Set(filter) : null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get the current tool filter.
|
|
40
|
+
*/
|
|
41
|
+
getFilter() {
|
|
42
|
+
return this.currentFilter;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if a tool is allowed by the current filter.
|
|
46
|
+
*/
|
|
47
|
+
isToolAllowed(name) {
|
|
48
|
+
if (!this.currentFilter) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return this.currentFilter.has(name);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get all registered tools.
|
|
55
|
+
*/
|
|
56
|
+
getRegisteredTools() {
|
|
57
|
+
return Array.from(this.toolRegistry.values());
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get a tool by name from the registry.
|
|
61
|
+
*/
|
|
62
|
+
getTool(name) {
|
|
63
|
+
return this.toolRegistry.get(name);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get count of registered tools.
|
|
67
|
+
*/
|
|
68
|
+
getToolCount() {
|
|
69
|
+
return this.toolRegistry.size;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Generate tool index for the system prompt.
|
|
73
|
+
* Groups tools by category and shows signatures.
|
|
74
|
+
*/
|
|
75
|
+
generateToolIndex() {
|
|
76
|
+
const tools = this.getRegisteredTools();
|
|
77
|
+
if (tools.length === 0) {
|
|
78
|
+
return '(No tools registered in meta-tool registry)';
|
|
79
|
+
}
|
|
80
|
+
// Filter by allowed tools
|
|
81
|
+
const allowedTools = tools.filter((t) => this.isToolAllowed(t.definition.name));
|
|
82
|
+
// Group tools by prefix
|
|
83
|
+
const groups = {};
|
|
84
|
+
for (const tool of allowedTools) {
|
|
85
|
+
const prefix = tool.definition.name.split('_')[0];
|
|
86
|
+
const category = getCategoryName(prefix);
|
|
87
|
+
groups[category] = groups[category] ?? [];
|
|
88
|
+
groups[category].push(tool);
|
|
89
|
+
}
|
|
90
|
+
// Build index with signatures
|
|
91
|
+
const lines = [];
|
|
92
|
+
for (const [category, categoryTools] of Object.entries(groups).sort()) {
|
|
93
|
+
lines.push(`### ${category}`);
|
|
94
|
+
for (const tool of categoryTools) {
|
|
95
|
+
const signature = buildToolSignature(tool);
|
|
96
|
+
lines.push(`- ${signature}`);
|
|
97
|
+
}
|
|
98
|
+
lines.push('');
|
|
99
|
+
}
|
|
100
|
+
return lines.join('\n');
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get the full system prompt section (prefix + index).
|
|
104
|
+
*/
|
|
105
|
+
getToolIndexForSystemPrompt() {
|
|
106
|
+
return META_TOOLS_SYSTEM_PROMPT_PREFIX + this.generateToolIndex();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get registry statistics.
|
|
110
|
+
*/
|
|
111
|
+
getStats() {
|
|
112
|
+
const registeredTools = this.toolRegistry.size;
|
|
113
|
+
const allowedTools = this.getRegisteredTools().filter((t) => this.isToolAllowed(t.definition.name)).length;
|
|
114
|
+
// ~300 tokens per full tool definition, ~800 tokens for the index
|
|
115
|
+
const tokensPerTool = 300;
|
|
116
|
+
const estimatedTokenSavings = registeredTools * tokensPerTool - 800;
|
|
117
|
+
return {
|
|
118
|
+
registeredTools,
|
|
119
|
+
allowedTools,
|
|
120
|
+
estimatedTokenSavings: Math.max(0, estimatedTokenSavings),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Validate arguments against a tool's schema.
|
|
125
|
+
* Returns null if valid, or an error message string.
|
|
126
|
+
*/
|
|
127
|
+
validateArgs(toolName, args) {
|
|
128
|
+
const tool = this.toolRegistry.get(toolName);
|
|
129
|
+
if (!tool) {
|
|
130
|
+
return `Unknown tool: '${toolName}'`;
|
|
131
|
+
}
|
|
132
|
+
const schema = tool.definition.inputSchema;
|
|
133
|
+
const validate = this.ajv.compile(schema);
|
|
134
|
+
const valid = validate(args);
|
|
135
|
+
if (!valid) {
|
|
136
|
+
return formatValidationErrors(validate.errors);
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// =============================================================================
|
|
142
|
+
// Meta-tool factory
|
|
143
|
+
// =============================================================================
|
|
144
|
+
/**
|
|
145
|
+
* Create the three meta-tools + fallback handler, all bound to a registry instance.
|
|
146
|
+
*/
|
|
147
|
+
export function createMetaTools(registry) {
|
|
148
|
+
// -------------------------------------------------------------------------
|
|
149
|
+
// list_tools
|
|
150
|
+
// -------------------------------------------------------------------------
|
|
151
|
+
const listToolsTool = defineTool({
|
|
152
|
+
name: 'list_tools',
|
|
153
|
+
description: 'List all available specialized tools. Call this first to see what tools are available ' +
|
|
154
|
+
'before using use_tool. Optionally filter by category.',
|
|
155
|
+
inputSchema: {
|
|
156
|
+
type: 'object',
|
|
157
|
+
properties: {
|
|
158
|
+
category: {
|
|
159
|
+
type: 'string',
|
|
160
|
+
description: 'Optional category filter (e.g., "git", "project", "workitem", "plan", "anchor")',
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
required: [],
|
|
164
|
+
},
|
|
165
|
+
execute: ({ category }) => {
|
|
166
|
+
const tools = registry.getRegisteredTools();
|
|
167
|
+
// Filter by allowed tools
|
|
168
|
+
let filteredTools = tools.filter((t) => registry.isToolAllowed(t.definition.name));
|
|
169
|
+
// Filter by category if specified
|
|
170
|
+
if (category) {
|
|
171
|
+
const prefix = category.toLowerCase();
|
|
172
|
+
filteredTools = filteredTools.filter((t) => t.definition.name.toLowerCase().startsWith(prefix));
|
|
173
|
+
}
|
|
174
|
+
const toolList = filteredTools.map((t) => ({
|
|
175
|
+
name: t.definition.name,
|
|
176
|
+
description: t.definition.description.split('.')[0],
|
|
177
|
+
}));
|
|
178
|
+
return Promise.resolve(createSuccessResult({
|
|
179
|
+
count: toolList.length,
|
|
180
|
+
tools: toolList,
|
|
181
|
+
hint: 'Use get_tool_info("tool_name") to see full parameter details for any tool.',
|
|
182
|
+
}));
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
// -------------------------------------------------------------------------
|
|
186
|
+
// get_tool_info
|
|
187
|
+
// -------------------------------------------------------------------------
|
|
188
|
+
const getToolInfoTool = defineTool({
|
|
189
|
+
name: 'get_tool_info',
|
|
190
|
+
description: "Get the exact JSON schema for a tool's parameters. " +
|
|
191
|
+
'MUST be called before passing any parameters to a Tool Index tool. ' +
|
|
192
|
+
'Zero-parameter calls do not need this.',
|
|
193
|
+
inputSchema: {
|
|
194
|
+
type: 'object',
|
|
195
|
+
properties: {
|
|
196
|
+
tool_name: {
|
|
197
|
+
type: 'string',
|
|
198
|
+
description: 'Name of the tool from the Tool Index',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
required: ['tool_name'],
|
|
202
|
+
},
|
|
203
|
+
execute: ({ tool_name }) => {
|
|
204
|
+
const tool = registry.getTool(tool_name);
|
|
205
|
+
if (!tool) {
|
|
206
|
+
const availableTools = registry
|
|
207
|
+
.getRegisteredTools()
|
|
208
|
+
.map((t) => t.definition.name)
|
|
209
|
+
.slice(0, 10);
|
|
210
|
+
return Promise.resolve(createErrorResult(`Unknown tool: '${tool_name}'. ` +
|
|
211
|
+
`Available tools include: ${availableTools.join(', ')}... ` +
|
|
212
|
+
`Check the Tool Index for the full list.`));
|
|
213
|
+
}
|
|
214
|
+
return Promise.resolve(createSuccessResult({
|
|
215
|
+
name: tool.definition.name,
|
|
216
|
+
description: tool.definition.description,
|
|
217
|
+
parameters: tool.definition.inputSchema,
|
|
218
|
+
}));
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
// -------------------------------------------------------------------------
|
|
222
|
+
// use_tool
|
|
223
|
+
// -------------------------------------------------------------------------
|
|
224
|
+
const useToolTool = defineTool({
|
|
225
|
+
name: 'use_tool',
|
|
226
|
+
description: 'Execute any tool from the Tool Index. Check the Tool Index for ' +
|
|
227
|
+
'available tools and their parameters. For complex parameters, ' +
|
|
228
|
+
'call get_tool_info first.',
|
|
229
|
+
inputSchema: {
|
|
230
|
+
type: 'object',
|
|
231
|
+
properties: {
|
|
232
|
+
tool_name: {
|
|
233
|
+
type: 'string',
|
|
234
|
+
description: 'Name of the tool to execute (from Tool Index)',
|
|
235
|
+
},
|
|
236
|
+
args: {
|
|
237
|
+
type: 'object',
|
|
238
|
+
description: 'Arguments to pass to the tool. Must match the tool schema.',
|
|
239
|
+
additionalProperties: true,
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
required: ['tool_name', 'args'],
|
|
243
|
+
},
|
|
244
|
+
execute: async ({ tool_name, args }) => {
|
|
245
|
+
// 0. Check tool filter
|
|
246
|
+
if (!registry.isToolAllowed(tool_name)) {
|
|
247
|
+
const filter = registry.getFilter();
|
|
248
|
+
const allowedTools = filter
|
|
249
|
+
? Array.from(filter).filter((t) => registry.getTool(t) !== undefined)
|
|
250
|
+
: [];
|
|
251
|
+
return createErrorResult(`Tool '${tool_name}' is not available for this agent. ` +
|
|
252
|
+
`Your available meta-registry tools: ${allowedTools.slice(0, 10).join(', ')}${allowedTools.length > 10 ? '...' : ''} ` +
|
|
253
|
+
`Call list_tools() to see all available tools.`);
|
|
254
|
+
}
|
|
255
|
+
// 1. Find the tool
|
|
256
|
+
const tool = registry.getTool(tool_name);
|
|
257
|
+
if (!tool) {
|
|
258
|
+
const availableTools = registry
|
|
259
|
+
.getRegisteredTools()
|
|
260
|
+
.filter((t) => registry.isToolAllowed(t.definition.name))
|
|
261
|
+
.map((t) => t.definition.name)
|
|
262
|
+
.slice(0, 10);
|
|
263
|
+
return createErrorResult(`Unknown tool: '${tool_name}'. ` +
|
|
264
|
+
`Available tools include: ${availableTools.join(', ')}... ` +
|
|
265
|
+
`Check the Tool Index for the full list.`);
|
|
266
|
+
}
|
|
267
|
+
// 2. Validate args
|
|
268
|
+
const validationError = registry.validateArgs(tool_name, args);
|
|
269
|
+
if (validationError) {
|
|
270
|
+
return createErrorResult(`Invalid arguments for '${tool_name}': ${validationError}. ` +
|
|
271
|
+
`Expected schema: ${JSON.stringify(tool.definition.inputSchema, null, 2)}. ` +
|
|
272
|
+
`Hint: Call get_tool_info("${tool_name}") to see full parameter details.`);
|
|
273
|
+
}
|
|
274
|
+
// 3. Execute the tool
|
|
275
|
+
try {
|
|
276
|
+
const result = await tool.execute(args);
|
|
277
|
+
// Enhance result with clear top-level message for smaller models
|
|
278
|
+
if (result.success && typeof result.result === 'object' && result.result !== null) {
|
|
279
|
+
const innerResult = result.result;
|
|
280
|
+
const innerMessage = typeof innerResult.message === 'string' ? innerResult.message : null;
|
|
281
|
+
return createSuccessResult({
|
|
282
|
+
tool: tool_name,
|
|
283
|
+
status: 'completed',
|
|
284
|
+
message: innerMessage ?? `Tool '${tool_name}' executed successfully.`,
|
|
285
|
+
result: innerResult,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
290
|
+
catch (err) {
|
|
291
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
292
|
+
return createErrorResult(`Tool '${tool_name}' execution failed: ${errorMessage}`);
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
});
|
|
296
|
+
// -------------------------------------------------------------------------
|
|
297
|
+
// Fallback handler factory
|
|
298
|
+
// -------------------------------------------------------------------------
|
|
299
|
+
function createFallback() {
|
|
300
|
+
return async (name, input) => {
|
|
301
|
+
// Check if tool exists in registry
|
|
302
|
+
const tool = registry.getTool(name);
|
|
303
|
+
if (!tool) {
|
|
304
|
+
return null; // Not in registry — let default "not found" error through
|
|
305
|
+
}
|
|
306
|
+
// Check tool filter
|
|
307
|
+
if (!registry.isToolAllowed(name)) {
|
|
308
|
+
const filter = registry.getFilter();
|
|
309
|
+
const allowedTools = filter
|
|
310
|
+
? Array.from(filter).filter((t) => registry.getTool(t) !== undefined)
|
|
311
|
+
: [];
|
|
312
|
+
return createErrorResult(`Tool '${name}' is not available for this agent. ` +
|
|
313
|
+
`Available tools: ${allowedTools.slice(0, 10).join(', ')}${allowedTools.length > 10 ? '...' : ''}`);
|
|
314
|
+
}
|
|
315
|
+
// Validate args
|
|
316
|
+
const validationError = registry.validateArgs(name, input);
|
|
317
|
+
if (validationError) {
|
|
318
|
+
return createErrorResult(`Invalid arguments for '${name}': ${validationError}. ` +
|
|
319
|
+
`Call get_tool_info("${name}") to get the exact parameter schema before retrying.`);
|
|
320
|
+
}
|
|
321
|
+
// Execute the tool
|
|
322
|
+
try {
|
|
323
|
+
return await tool.execute(input);
|
|
324
|
+
}
|
|
325
|
+
catch (err) {
|
|
326
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
327
|
+
return createErrorResult(`Tool '${name}' execution failed: ${errorMessage}`);
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
listToolsTool: listToolsTool,
|
|
333
|
+
getToolInfoTool: getToolInfoTool,
|
|
334
|
+
useToolTool: useToolTool,
|
|
335
|
+
createFallback,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
// =============================================================================
|
|
339
|
+
// System prompt constant
|
|
340
|
+
// =============================================================================
|
|
341
|
+
export const META_TOOLS_SYSTEM_PROMPT_PREFIX = `
|
|
342
|
+
## Tool Index (Specialized Tools)
|
|
343
|
+
|
|
344
|
+
These tools are called **exactly like direct tools** — just use the tool name with parameters. No special syntax or wrapper needed. The system routes them automatically.
|
|
345
|
+
|
|
346
|
+
**IMPORTANT — These are CLI system tools, NOT your project's backend. Never use localhost/curl to access them.**
|
|
347
|
+
|
|
348
|
+
**Parameter Rules:**
|
|
349
|
+
- For **zero-parameter calls**: call the tool directly (e.g., \`workitem_query()\`, \`git_status()\`).
|
|
350
|
+
- For **calls WITH parameters**: you MUST call \`get_tool_info("tool_name")\` first to get the exact JSON schema. The signatures below are summaries only — do NOT guess parameter structure from them.
|
|
351
|
+
- After a failed tool call, always call \`get_tool_info()\` before retrying.
|
|
352
|
+
|
|
353
|
+
`;
|
|
354
|
+
// =============================================================================
|
|
355
|
+
// Helpers (internal)
|
|
356
|
+
// =============================================================================
|
|
357
|
+
/**
|
|
358
|
+
* Map tool prefix to category name.
|
|
359
|
+
*/
|
|
360
|
+
function getCategoryName(prefix) {
|
|
361
|
+
const categoryMap = {
|
|
362
|
+
git: 'Git Operations',
|
|
363
|
+
project: 'Project Management',
|
|
364
|
+
workitem: 'Work Items',
|
|
365
|
+
plan: 'Planning',
|
|
366
|
+
document: 'Documents',
|
|
367
|
+
anchor: 'Context Anchors',
|
|
368
|
+
backlog: 'Backlog',
|
|
369
|
+
detect: 'Analysis',
|
|
370
|
+
find: 'Analysis',
|
|
371
|
+
run: 'Runners',
|
|
372
|
+
};
|
|
373
|
+
return categoryMap[prefix] ?? 'Other';
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Build a concise signature for a tool.
|
|
377
|
+
* e.g., "git_commit(message: string, files?: string[]) - Create a commit"
|
|
378
|
+
*/
|
|
379
|
+
function buildToolSignature(tool) {
|
|
380
|
+
const schema = tool.definition.inputSchema;
|
|
381
|
+
const params = [];
|
|
382
|
+
if (schema.properties) {
|
|
383
|
+
const required = new Set(schema.required ?? []);
|
|
384
|
+
for (const [name, prop] of Object.entries(schema.properties)) {
|
|
385
|
+
const isRequired = required.has(name);
|
|
386
|
+
const type = prop.type ?? 'any';
|
|
387
|
+
params.push(isRequired ? `${name}: ${type}` : `${name}?: ${type}`);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
const paramsStr = params.length > 0 ? params.join(', ') : '';
|
|
391
|
+
const desc = tool.definition.description.split('.')[0]; // First sentence
|
|
392
|
+
return `${tool.definition.name}(${paramsStr}) - ${desc}`;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Format AJV validation errors into a readable string.
|
|
396
|
+
*/
|
|
397
|
+
function formatValidationErrors(errors) {
|
|
398
|
+
if (!errors || errors.length === 0) {
|
|
399
|
+
return 'Unknown validation error';
|
|
400
|
+
}
|
|
401
|
+
const messages = errors.map((e) => {
|
|
402
|
+
const path = e.dataPath ? e.dataPath.replace(/^\./, '') : 'args';
|
|
403
|
+
return `${path}: ${e.message ?? 'validation failed'}`;
|
|
404
|
+
});
|
|
405
|
+
return messages.join('; ');
|
|
406
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@compilr-dev/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Universal agent runtime for building AI-powered applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -52,6 +52,9 @@
|
|
|
52
52
|
"engines": {
|
|
53
53
|
"node": ">=18.0.0"
|
|
54
54
|
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"ajv": "^6.14.0"
|
|
57
|
+
},
|
|
55
58
|
"peerDependencies": {
|
|
56
59
|
"@compilr-dev/agents": "^0.3.14",
|
|
57
60
|
"@compilr-dev/agents-coding": "^1.0.2"
|