@compilr-dev/agents 0.3.21 → 0.3.23
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/providers/claude.d.ts +20 -0
- package/dist/providers/claude.js +25 -6
- package/dist/providers/fireworks.d.ts +2 -0
- package/dist/providers/fireworks.js +1 -0
- package/dist/providers/gemini-native.d.ts +7 -0
- package/dist/providers/gemini-native.js +8 -4
- package/dist/providers/groq.d.ts +2 -0
- package/dist/providers/groq.js +1 -0
- package/dist/providers/ollama.d.ts +2 -0
- package/dist/providers/ollama.js +1 -0
- package/dist/providers/openai-compatible.d.ts +17 -0
- package/dist/providers/openai-compatible.js +50 -7
- package/dist/providers/openai.d.ts +2 -0
- package/dist/providers/openai.js +1 -0
- package/dist/providers/openrouter.d.ts +2 -0
- package/dist/providers/openrouter.js +1 -0
- package/dist/providers/perplexity.d.ts +2 -0
- package/dist/providers/perplexity.js +1 -0
- package/dist/providers/together.d.ts +2 -0
- package/dist/providers/together.js +1 -0
- package/dist/providers/types.d.ts +4 -4
- package/package.json +1 -1
|
@@ -45,6 +45,19 @@ export interface ClaudeProviderConfig {
|
|
|
45
45
|
* @default true
|
|
46
46
|
*/
|
|
47
47
|
enablePromptCaching?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Enable token-efficient tool use (Anthropic beta).
|
|
50
|
+
* Sends compact tool representation, reducing input tokens.
|
|
51
|
+
* No-op for Claude 4+ (already default).
|
|
52
|
+
* @default true
|
|
53
|
+
*/
|
|
54
|
+
enableTokenEfficientTools?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Optional token estimator function (e.g., tiktoken).
|
|
57
|
+
* When provided, debug payload reports token counts instead of char-based estimates.
|
|
58
|
+
* Fallback: Math.ceil(text.length / 4)
|
|
59
|
+
*/
|
|
60
|
+
estimateTokens?: (text: string) => number;
|
|
48
61
|
}
|
|
49
62
|
/**
|
|
50
63
|
* ClaudeProvider implements LLMProvider for Anthropic's Claude API
|
|
@@ -55,6 +68,8 @@ export declare class ClaudeProvider implements LLMProvider {
|
|
|
55
68
|
private readonly defaultModel;
|
|
56
69
|
private readonly defaultMaxTokens;
|
|
57
70
|
private readonly enablePromptCaching;
|
|
71
|
+
private readonly enableTokenEfficientTools;
|
|
72
|
+
private readonly estimateTokensFn;
|
|
58
73
|
constructor(config: ClaudeProviderConfig);
|
|
59
74
|
/**
|
|
60
75
|
* Send messages and stream the response
|
|
@@ -64,6 +79,11 @@ export declare class ClaudeProvider implements LLMProvider {
|
|
|
64
79
|
* Count tokens in messages using tiktoken (cl100k_base encoding)
|
|
65
80
|
*/
|
|
66
81
|
countTokens(messages: Message[]): Promise<number>;
|
|
82
|
+
/**
|
|
83
|
+
* Build request options with optional abort signal and beta header.
|
|
84
|
+
* The token-efficient tools beta reduces schema tokenization for older models.
|
|
85
|
+
*/
|
|
86
|
+
private buildRequestOptions;
|
|
67
87
|
/**
|
|
68
88
|
* Convert our Message format to Anthropic's format
|
|
69
89
|
*/
|
package/dist/providers/claude.js
CHANGED
|
@@ -30,6 +30,8 @@ export class ClaudeProvider {
|
|
|
30
30
|
defaultModel;
|
|
31
31
|
defaultMaxTokens;
|
|
32
32
|
enablePromptCaching;
|
|
33
|
+
enableTokenEfficientTools;
|
|
34
|
+
estimateTokensFn;
|
|
33
35
|
constructor(config) {
|
|
34
36
|
this.client = new Anthropic({
|
|
35
37
|
apiKey: config.apiKey,
|
|
@@ -38,6 +40,9 @@ export class ClaudeProvider {
|
|
|
38
40
|
this.defaultModel = config.model ?? DEFAULT_MODEL;
|
|
39
41
|
this.defaultMaxTokens = config.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
40
42
|
this.enablePromptCaching = config.enablePromptCaching ?? true;
|
|
43
|
+
this.enableTokenEfficientTools = config.enableTokenEfficientTools ?? true;
|
|
44
|
+
this.estimateTokensFn =
|
|
45
|
+
config.estimateTokens ?? ((s) => Math.ceil(s.length / 4));
|
|
41
46
|
}
|
|
42
47
|
/**
|
|
43
48
|
* Send messages and stream the response
|
|
@@ -46,11 +51,12 @@ export class ClaudeProvider {
|
|
|
46
51
|
const { systemPrompt, anthropicMessages } = this.convertMessages(messages);
|
|
47
52
|
const tools = this.convertTools(options?.tools);
|
|
48
53
|
const thinking = this.convertThinking(options?.thinking);
|
|
49
|
-
// Calculate payload sizes for debugging (
|
|
54
|
+
// Calculate payload sizes for debugging (token estimates)
|
|
55
|
+
const estimate = this.estimateTokensFn;
|
|
50
56
|
const debugPayload = {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
systemTokens: estimate(systemPrompt),
|
|
58
|
+
contentsTokens: estimate(JSON.stringify(anthropicMessages)),
|
|
59
|
+
toolsTokens: estimate(JSON.stringify(tools)),
|
|
54
60
|
};
|
|
55
61
|
try {
|
|
56
62
|
// Determine if prompt caching is enabled
|
|
@@ -74,8 +80,8 @@ export class ClaudeProvider {
|
|
|
74
80
|
if (thinking) {
|
|
75
81
|
Object.assign(params, { thinking });
|
|
76
82
|
}
|
|
77
|
-
// Pass abort signal
|
|
78
|
-
const requestOptions = options?.signal
|
|
83
|
+
// Pass abort signal and optional beta header to SDK
|
|
84
|
+
const requestOptions = this.buildRequestOptions(options?.signal, tools.length > 0);
|
|
79
85
|
const stream = this.client.messages.stream(params, requestOptions);
|
|
80
86
|
const model = options?.model ?? this.defaultModel;
|
|
81
87
|
let currentToolId = '';
|
|
@@ -130,6 +136,19 @@ export class ClaudeProvider {
|
|
|
130
136
|
countTokens(messages) {
|
|
131
137
|
return Promise.resolve(countMessageTokens(messages));
|
|
132
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Build request options with optional abort signal and beta header.
|
|
141
|
+
* The token-efficient tools beta reduces schema tokenization for older models.
|
|
142
|
+
*/
|
|
143
|
+
buildRequestOptions(signal, hasTools) {
|
|
144
|
+
const needsBeta = this.enableTokenEfficientTools && hasTools;
|
|
145
|
+
if (!signal && !needsBeta)
|
|
146
|
+
return undefined;
|
|
147
|
+
return {
|
|
148
|
+
...(signal ? { signal } : {}),
|
|
149
|
+
...(needsBeta ? { headers: { 'anthropic-beta': 'token-efficient-tools-2025-02-19' } } : {}),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
133
152
|
/**
|
|
134
153
|
* Convert our Message format to Anthropic's format
|
|
135
154
|
*/
|
|
@@ -34,6 +34,8 @@ export interface FireworksProviderConfig {
|
|
|
34
34
|
maxTokens?: number;
|
|
35
35
|
/** Request timeout in milliseconds (default: 120000) */
|
|
36
36
|
timeout?: number;
|
|
37
|
+
/** Optional token estimator (e.g., tiktoken) for debug payload */
|
|
38
|
+
estimateTokens?: (text: string) => number;
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
41
|
* Fireworks AI LLM Provider
|
|
@@ -32,6 +32,12 @@ export interface GeminiNativeProviderConfig {
|
|
|
32
32
|
* @default 4096
|
|
33
33
|
*/
|
|
34
34
|
maxTokens?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Optional token estimator function (e.g., tiktoken).
|
|
37
|
+
* When provided, debug payload reports token counts instead of char-based estimates.
|
|
38
|
+
* Fallback: Math.ceil(text.length / 4)
|
|
39
|
+
*/
|
|
40
|
+
estimateTokens?: (text: string) => number;
|
|
35
41
|
}
|
|
36
42
|
/**
|
|
37
43
|
* GeminiNativeProvider implements LLMProvider using the native Google Gen AI SDK
|
|
@@ -46,6 +52,7 @@ export declare class GeminiNativeProvider implements LLMProvider {
|
|
|
46
52
|
private readonly client;
|
|
47
53
|
private readonly defaultModel;
|
|
48
54
|
private readonly defaultMaxTokens;
|
|
55
|
+
private readonly estimateTokensFn;
|
|
49
56
|
constructor(config: GeminiNativeProviderConfig);
|
|
50
57
|
/**
|
|
51
58
|
* Send messages and stream the response
|
|
@@ -37,10 +37,13 @@ export class GeminiNativeProvider {
|
|
|
37
37
|
client;
|
|
38
38
|
defaultModel;
|
|
39
39
|
defaultMaxTokens;
|
|
40
|
+
estimateTokensFn;
|
|
40
41
|
constructor(config) {
|
|
41
42
|
this.client = new GoogleGenAI({ apiKey: config.apiKey });
|
|
42
43
|
this.defaultModel = config.model ?? DEFAULT_MODEL;
|
|
43
44
|
this.defaultMaxTokens = config.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
45
|
+
this.estimateTokensFn =
|
|
46
|
+
config.estimateTokens ?? ((s) => Math.ceil(s.length / 4));
|
|
44
47
|
}
|
|
45
48
|
/**
|
|
46
49
|
* Send messages and stream the response
|
|
@@ -49,11 +52,12 @@ export class GeminiNativeProvider {
|
|
|
49
52
|
const { systemInstruction, contents } = this.convertMessages(messages);
|
|
50
53
|
const tools = this.convertTools(options?.tools);
|
|
51
54
|
const model = options?.model ?? this.defaultModel;
|
|
52
|
-
// Calculate payload sizes for debugging
|
|
55
|
+
// Calculate payload sizes for debugging (token estimates)
|
|
56
|
+
const estimate = this.estimateTokensFn;
|
|
53
57
|
const debugPayload = {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
systemTokens: estimate(systemInstruction ?? ''),
|
|
59
|
+
contentsTokens: estimate(JSON.stringify(contents)),
|
|
60
|
+
toolsTokens: estimate(JSON.stringify(tools)),
|
|
57
61
|
};
|
|
58
62
|
try {
|
|
59
63
|
// Build config
|
package/dist/providers/groq.d.ts
CHANGED
|
@@ -34,6 +34,8 @@ export interface GroqProviderConfig {
|
|
|
34
34
|
maxTokens?: number;
|
|
35
35
|
/** Request timeout in milliseconds (default: 120000) */
|
|
36
36
|
timeout?: number;
|
|
37
|
+
/** Optional token estimator (e.g., tiktoken) for debug payload */
|
|
38
|
+
estimateTokens?: (text: string) => number;
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
41
|
* Groq LLM Provider
|
package/dist/providers/groq.js
CHANGED
|
@@ -34,6 +34,8 @@ export interface OllamaProviderConfig {
|
|
|
34
34
|
timeout?: number;
|
|
35
35
|
/** Keep alive duration for model in memory (default: '5m') */
|
|
36
36
|
keepAlive?: string;
|
|
37
|
+
/** Optional token estimator (e.g., tiktoken) for debug payload */
|
|
38
|
+
estimateTokens?: (text: string) => number;
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
41
|
* Ollama LLM Provider
|
package/dist/providers/ollama.js
CHANGED
|
@@ -37,6 +37,7 @@ export class OllamaProvider extends OpenAICompatibleProvider {
|
|
|
37
37
|
model: config.model ?? DEFAULT_MODEL,
|
|
38
38
|
maxTokens: config.maxTokens,
|
|
39
39
|
timeout: config.timeout,
|
|
40
|
+
estimateTokens: config.estimateTokens,
|
|
40
41
|
};
|
|
41
42
|
super(baseConfig);
|
|
42
43
|
this.keepAlive = config.keepAlive ?? '5m';
|
|
@@ -102,6 +102,12 @@ export interface OpenAICompatibleConfig {
|
|
|
102
102
|
maxTokens?: number;
|
|
103
103
|
/** Request timeout in milliseconds (default: 120000) */
|
|
104
104
|
timeout?: number;
|
|
105
|
+
/**
|
|
106
|
+
* Optional token estimator function (e.g., tiktoken).
|
|
107
|
+
* When provided, debug payload reports token counts instead of char-based estimates.
|
|
108
|
+
* Fallback: Math.ceil(text.length / 4)
|
|
109
|
+
*/
|
|
110
|
+
estimateTokens?: (text: string) => number;
|
|
105
111
|
}
|
|
106
112
|
/**
|
|
107
113
|
* Abstract base class for OpenAI-compatible LLM providers
|
|
@@ -118,6 +124,7 @@ export declare abstract class OpenAICompatibleProvider implements LLMProvider {
|
|
|
118
124
|
protected readonly defaultModel: string;
|
|
119
125
|
protected readonly defaultMaxTokens: number;
|
|
120
126
|
protected readonly timeout: number;
|
|
127
|
+
protected readonly estimateTokensFn: (text: string) => number;
|
|
121
128
|
constructor(config: OpenAICompatibleConfig);
|
|
122
129
|
/**
|
|
123
130
|
* Get authentication headers for API requests
|
|
@@ -169,6 +176,16 @@ export declare abstract class OpenAICompatibleProvider implements LLMProvider {
|
|
|
169
176
|
* Convert library messages to OpenAI format
|
|
170
177
|
*/
|
|
171
178
|
protected convertMessages(messages: Message[]): OpenAIMessage[];
|
|
179
|
+
/**
|
|
180
|
+
* Ensure every assistant tool_call has a matching tool response message.
|
|
181
|
+
*
|
|
182
|
+
* OpenAI strictly requires that each tool_call_id in an assistant message
|
|
183
|
+
* is followed by a tool-role response before the next non-tool message.
|
|
184
|
+
* This can break after ToolLoopError (partial results) or context
|
|
185
|
+
* compaction (message reordering). We add synthetic error responses
|
|
186
|
+
* for any orphaned tool_calls.
|
|
187
|
+
*/
|
|
188
|
+
protected repairOpenAIToolPairing(messages: OpenAIMessage[]): OpenAIMessage[];
|
|
172
189
|
/**
|
|
173
190
|
* Map library role to OpenAI role
|
|
174
191
|
*/
|
|
@@ -37,11 +37,14 @@ export class OpenAICompatibleProvider {
|
|
|
37
37
|
defaultModel;
|
|
38
38
|
defaultMaxTokens;
|
|
39
39
|
timeout;
|
|
40
|
+
estimateTokensFn;
|
|
40
41
|
constructor(config) {
|
|
41
42
|
this.baseUrl = config.baseUrl;
|
|
42
43
|
this.defaultModel = config.model;
|
|
43
44
|
this.defaultMaxTokens = config.maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
44
45
|
this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
46
|
+
this.estimateTokensFn =
|
|
47
|
+
config.estimateTokens ?? ((s) => Math.ceil(s.length / 4));
|
|
45
48
|
}
|
|
46
49
|
/**
|
|
47
50
|
* Extract cache statistics from response headers.
|
|
@@ -67,14 +70,14 @@ export class OpenAICompatibleProvider {
|
|
|
67
70
|
const openaiMessages = this.convertMessages(messages);
|
|
68
71
|
// Convert tools if provided
|
|
69
72
|
const tools = options?.tools ? this.convertTools(options.tools) : undefined;
|
|
70
|
-
// Calculate payload sizes for debugging
|
|
71
|
-
|
|
73
|
+
// Calculate payload sizes for debugging (token estimates)
|
|
74
|
+
const estimate = this.estimateTokensFn;
|
|
72
75
|
const systemMsg = openaiMessages.find((m) => m.role === 'system');
|
|
73
|
-
const
|
|
76
|
+
const systemTokens = systemMsg && typeof systemMsg.content === 'string' ? estimate(systemMsg.content) : 0;
|
|
74
77
|
const debugPayload = {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
systemTokens,
|
|
79
|
+
contentsTokens: estimate(JSON.stringify(openaiMessages)),
|
|
80
|
+
toolsTokens: tools ? estimate(JSON.stringify(tools)) : 0,
|
|
78
81
|
};
|
|
79
82
|
// Build request body
|
|
80
83
|
const body = {
|
|
@@ -271,7 +274,47 @@ export class OpenAICompatibleProvider {
|
|
|
271
274
|
}
|
|
272
275
|
}
|
|
273
276
|
}
|
|
274
|
-
return result;
|
|
277
|
+
return this.repairOpenAIToolPairing(result);
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Ensure every assistant tool_call has a matching tool response message.
|
|
281
|
+
*
|
|
282
|
+
* OpenAI strictly requires that each tool_call_id in an assistant message
|
|
283
|
+
* is followed by a tool-role response before the next non-tool message.
|
|
284
|
+
* This can break after ToolLoopError (partial results) or context
|
|
285
|
+
* compaction (message reordering). We add synthetic error responses
|
|
286
|
+
* for any orphaned tool_calls.
|
|
287
|
+
*/
|
|
288
|
+
repairOpenAIToolPairing(messages) {
|
|
289
|
+
const repaired = [];
|
|
290
|
+
for (let i = 0; i < messages.length; i++) {
|
|
291
|
+
const msg = messages[i];
|
|
292
|
+
repaired.push(msg);
|
|
293
|
+
// Only check assistant messages with tool_calls
|
|
294
|
+
if (msg.role !== 'assistant' || !msg.tool_calls || msg.tool_calls.length === 0) {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
// Collect expected tool_call_ids
|
|
298
|
+
const expectedIds = new Set(msg.tool_calls.map((tc) => tc.id));
|
|
299
|
+
// Push all consecutive tool messages first, tracking which IDs are satisfied
|
|
300
|
+
while (i + 1 < messages.length && messages[i + 1].role === 'tool') {
|
|
301
|
+
i++;
|
|
302
|
+
const toolMsg = messages[i];
|
|
303
|
+
repaired.push(toolMsg);
|
|
304
|
+
if (toolMsg.tool_call_id) {
|
|
305
|
+
expectedIds.delete(toolMsg.tool_call_id);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// Add synthetic responses for any missing tool_call_ids
|
|
309
|
+
for (const missingId of expectedIds) {
|
|
310
|
+
repaired.push({
|
|
311
|
+
role: 'tool',
|
|
312
|
+
tool_call_id: missingId,
|
|
313
|
+
content: '[Error: Tool execution was interrupted]',
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return repaired;
|
|
275
318
|
}
|
|
276
319
|
/**
|
|
277
320
|
* Map library role to OpenAI role
|
|
@@ -36,6 +36,8 @@ export interface OpenAIProviderConfig {
|
|
|
36
36
|
timeout?: number;
|
|
37
37
|
/** OpenAI organization ID (optional) */
|
|
38
38
|
organization?: string;
|
|
39
|
+
/** Optional token estimator (e.g., tiktoken) for debug payload */
|
|
40
|
+
estimateTokens?: (text: string) => number;
|
|
39
41
|
}
|
|
40
42
|
/**
|
|
41
43
|
* OpenAI LLM Provider
|
package/dist/providers/openai.js
CHANGED
|
@@ -39,6 +39,8 @@ export interface OpenRouterProviderConfig {
|
|
|
39
39
|
siteUrl?: string;
|
|
40
40
|
/** Site name for OpenRouter rankings (optional) */
|
|
41
41
|
siteName?: string;
|
|
42
|
+
/** Optional token estimator (e.g., tiktoken) for debug payload */
|
|
43
|
+
estimateTokens?: (text: string) => number;
|
|
42
44
|
}
|
|
43
45
|
/**
|
|
44
46
|
* OpenRouter LLM Provider
|
|
@@ -44,6 +44,7 @@ export class OpenRouterProvider extends OpenAICompatibleProvider {
|
|
|
44
44
|
model: config.model ?? DEFAULT_MODEL,
|
|
45
45
|
maxTokens: config.maxTokens,
|
|
46
46
|
timeout: config.timeout,
|
|
47
|
+
estimateTokens: config.estimateTokens,
|
|
47
48
|
};
|
|
48
49
|
super(baseConfig);
|
|
49
50
|
this.apiKey = apiKey;
|
|
@@ -34,6 +34,8 @@ export interface PerplexityProviderConfig {
|
|
|
34
34
|
maxTokens?: number;
|
|
35
35
|
/** Request timeout in milliseconds (default: 120000) */
|
|
36
36
|
timeout?: number;
|
|
37
|
+
/** Optional token estimator (e.g., tiktoken) for debug payload */
|
|
38
|
+
estimateTokens?: (text: string) => number;
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
41
|
* Perplexity LLM Provider
|
|
@@ -41,6 +41,7 @@ export class PerplexityProvider extends OpenAICompatibleProvider {
|
|
|
41
41
|
model: config.model ?? DEFAULT_MODEL,
|
|
42
42
|
maxTokens: config.maxTokens,
|
|
43
43
|
timeout: config.timeout,
|
|
44
|
+
estimateTokens: config.estimateTokens,
|
|
44
45
|
};
|
|
45
46
|
super(baseConfig);
|
|
46
47
|
this.apiKey = apiKey;
|
|
@@ -34,6 +34,8 @@ export interface TogetherProviderConfig {
|
|
|
34
34
|
maxTokens?: number;
|
|
35
35
|
/** Request timeout in milliseconds (default: 120000) */
|
|
36
36
|
timeout?: number;
|
|
37
|
+
/** Optional token estimator (e.g., tiktoken) for debug payload */
|
|
38
|
+
estimateTokens?: (text: string) => number;
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
41
|
* Together AI LLM Provider
|
|
@@ -72,11 +72,11 @@ export interface LLMUsage {
|
|
|
72
72
|
cacheCreationTokens?: number;
|
|
73
73
|
/** Thinking tokens (Gemini 2.5+ models with thinking) */
|
|
74
74
|
thinkingTokens?: number;
|
|
75
|
-
/** Debug payload info - estimated
|
|
75
|
+
/** Debug payload info - estimated token counts before sending to provider */
|
|
76
76
|
debugPayload?: {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
systemTokens: number;
|
|
78
|
+
contentsTokens: number;
|
|
79
|
+
toolsTokens: number;
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
/**
|