@compilr-dev/sdk 0.1.18 → 0.1.20
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/meta-tools/registry.js +69 -5
- package/dist/provider.d.ts +1 -0
- package/dist/provider.js +11 -11
- package/package.json +1 -1
|
@@ -260,15 +260,17 @@ export function createMetaTools(registry) {
|
|
|
260
260
|
`Available tools include: ${availableTools.join(', ')}... ` +
|
|
261
261
|
`Check the Tool Index for the full list.`);
|
|
262
262
|
}
|
|
263
|
-
// 2.
|
|
264
|
-
const
|
|
263
|
+
// 2. Coerce + validate args
|
|
264
|
+
const toolSchema = tool.definition.inputSchema;
|
|
265
|
+
const coercedArgs = coerceArgs(toolSchema, args);
|
|
266
|
+
const validationError = registry.validateArgs(tool_name, coercedArgs);
|
|
265
267
|
if (validationError) {
|
|
266
268
|
return createErrorResult(`Invalid arguments for '${tool_name}': ${validationError}.\n` +
|
|
267
269
|
`Expected:\n${buildCompactSchema(tool)}`);
|
|
268
270
|
}
|
|
269
271
|
// 3. Execute the tool
|
|
270
272
|
try {
|
|
271
|
-
const result = await tool.execute(
|
|
273
|
+
const result = await tool.execute(coercedArgs);
|
|
272
274
|
// Enhance result with clear top-level message for smaller models
|
|
273
275
|
if (result.success && typeof result.result === 'object' && result.result !== null) {
|
|
274
276
|
const innerResult = result.result;
|
|
@@ -307,15 +309,18 @@ export function createMetaTools(registry) {
|
|
|
307
309
|
return createErrorResult(`Tool '${name}' is not available for this agent. ` +
|
|
308
310
|
`Available tools: ${allowedTools.slice(0, 10).join(', ')}${allowedTools.length > 10 ? '...' : ''}`);
|
|
309
311
|
}
|
|
312
|
+
// Coerce arguments before validation (handles LLM mistakes without guided decoding)
|
|
313
|
+
const toolSchema = tool.definition.inputSchema;
|
|
314
|
+
const coercedInput = coerceArgs(toolSchema, input);
|
|
310
315
|
// Validate args
|
|
311
|
-
const validationError = registry.validateArgs(name,
|
|
316
|
+
const validationError = registry.validateArgs(name, coercedInput);
|
|
312
317
|
if (validationError) {
|
|
313
318
|
return createErrorResult(`Invalid arguments for '${name}': ${validationError}. ` +
|
|
314
319
|
`Call get_tool_info("${name}") to get the exact parameter schema before retrying.`);
|
|
315
320
|
}
|
|
316
321
|
// Execute the tool
|
|
317
322
|
try {
|
|
318
|
-
return await tool.execute(
|
|
323
|
+
return await tool.execute(coercedInput);
|
|
319
324
|
}
|
|
320
325
|
catch (err) {
|
|
321
326
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
@@ -437,6 +442,26 @@ function buildCompactSchema(tool) {
|
|
|
437
442
|
detail += ' (required)';
|
|
438
443
|
}
|
|
439
444
|
paramDetails.push(detail);
|
|
445
|
+
// For array-of-objects, show item properties as indented sub-details
|
|
446
|
+
if (prop.type === 'array') {
|
|
447
|
+
const items = prop.items;
|
|
448
|
+
if (items?.type === 'object' && items.properties) {
|
|
449
|
+
const itemProps = items.properties;
|
|
450
|
+
const itemRequired = new Set(items.required ?? []);
|
|
451
|
+
for (const [itemName, itemProp] of Object.entries(itemProps)) {
|
|
452
|
+
const itemDesc = itemProp.description;
|
|
453
|
+
const itemEnum = itemProp.enum;
|
|
454
|
+
let itemDetail = ` - ${itemName}: ${resolveCompactType(itemProp)}`;
|
|
455
|
+
if (itemDesc)
|
|
456
|
+
itemDetail += ` — ${itemDesc}`;
|
|
457
|
+
if (itemEnum)
|
|
458
|
+
itemDetail += ` (${itemEnum.map((v) => `"${v}"`).join('|')})`;
|
|
459
|
+
if (itemRequired.has(itemName))
|
|
460
|
+
itemDetail += ' (required)';
|
|
461
|
+
paramDetails.push(itemDetail);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
440
465
|
}
|
|
441
466
|
}
|
|
442
467
|
const paramsStr = params.join(', ');
|
|
@@ -447,6 +472,45 @@ function buildCompactSchema(tool) {
|
|
|
447
472
|
}
|
|
448
473
|
return lines.join('\n');
|
|
449
474
|
}
|
|
475
|
+
/**
|
|
476
|
+
* Attempt to coerce arguments to match the tool schema.
|
|
477
|
+
* Handles common LLM mistakes when calling tools without guided decoding:
|
|
478
|
+
* - Single object where array expected → wraps in array
|
|
479
|
+
* - JSON string where array expected → parses it
|
|
480
|
+
*/
|
|
481
|
+
function coerceArgs(schema, args) {
|
|
482
|
+
const properties = schema.properties;
|
|
483
|
+
if (!properties)
|
|
484
|
+
return args;
|
|
485
|
+
let changed = false;
|
|
486
|
+
const coerced = { ...args };
|
|
487
|
+
for (const [name, prop] of Object.entries(properties)) {
|
|
488
|
+
if (prop.type === 'array' && name in coerced && !Array.isArray(coerced[name])) {
|
|
489
|
+
const value = coerced[name];
|
|
490
|
+
if (value !== null && value !== undefined) {
|
|
491
|
+
if (typeof value === 'object') {
|
|
492
|
+
// Single object → wrap in array
|
|
493
|
+
coerced[name] = [value];
|
|
494
|
+
changed = true;
|
|
495
|
+
}
|
|
496
|
+
else if (typeof value === 'string') {
|
|
497
|
+
// JSON string → try parsing
|
|
498
|
+
try {
|
|
499
|
+
const parsed = JSON.parse(value);
|
|
500
|
+
if (Array.isArray(parsed)) {
|
|
501
|
+
coerced[name] = parsed;
|
|
502
|
+
changed = true;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
catch {
|
|
506
|
+
// Leave as-is, will fail validation
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return changed ? coerced : args;
|
|
513
|
+
}
|
|
450
514
|
/**
|
|
451
515
|
* Format AJV validation errors into a readable string.
|
|
452
516
|
*/
|
package/dist/provider.d.ts
CHANGED
package/dist/provider.js
CHANGED
|
@@ -32,29 +32,29 @@ export function detectProviderFromEnv() {
|
|
|
32
32
|
* Create an LLM provider from a provider type string.
|
|
33
33
|
*/
|
|
34
34
|
export function createProviderFromType(type, options) {
|
|
35
|
-
const { model, apiKey, baseUrl, siteName } = options ?? {};
|
|
35
|
+
const { model, apiKey, baseUrl, siteName, estimateTokens } = options ?? {};
|
|
36
36
|
switch (type) {
|
|
37
37
|
case 'claude':
|
|
38
|
-
return createClaudeProvider({ model, apiKey });
|
|
38
|
+
return createClaudeProvider({ model, apiKey, estimateTokens });
|
|
39
39
|
case 'openai':
|
|
40
|
-
return createOpenAIProvider({ model, apiKey });
|
|
40
|
+
return createOpenAIProvider({ model, apiKey, estimateTokens });
|
|
41
41
|
case 'gemini':
|
|
42
|
-
return createGeminiNativeProvider({ model, apiKey });
|
|
42
|
+
return createGeminiNativeProvider({ model, apiKey, estimateTokens });
|
|
43
43
|
case 'ollama':
|
|
44
|
-
return createOllamaProvider({ model, baseUrl });
|
|
44
|
+
return createOllamaProvider({ model, baseUrl, estimateTokens });
|
|
45
45
|
case 'together':
|
|
46
|
-
return createTogetherProvider({ model, apiKey });
|
|
46
|
+
return createTogetherProvider({ model, apiKey, estimateTokens });
|
|
47
47
|
case 'groq':
|
|
48
|
-
return createGroqProvider({ model, apiKey });
|
|
48
|
+
return createGroqProvider({ model, apiKey, estimateTokens });
|
|
49
49
|
case 'fireworks':
|
|
50
|
-
return createFireworksProvider({ model, apiKey });
|
|
50
|
+
return createFireworksProvider({ model, apiKey, estimateTokens });
|
|
51
51
|
case 'perplexity':
|
|
52
|
-
return createPerplexityProvider({ model, apiKey });
|
|
52
|
+
return createPerplexityProvider({ model, apiKey, estimateTokens });
|
|
53
53
|
case 'openrouter':
|
|
54
|
-
return createOpenRouterProvider({ model, apiKey, siteName });
|
|
54
|
+
return createOpenRouterProvider({ model, apiKey, siteName, estimateTokens });
|
|
55
55
|
case 'custom':
|
|
56
56
|
// Custom endpoints use OpenAI-compatible format
|
|
57
|
-
return createOpenAIProvider({ model, apiKey });
|
|
57
|
+
return createOpenAIProvider({ model, apiKey, estimateTokens });
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
/**
|