skimpyclaw 0.3.14 → 0.4.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/README.md +47 -37
- package/dist/__tests__/adapter-types.test.d.ts +4 -0
- package/dist/__tests__/adapter-types.test.js +63 -0
- package/dist/__tests__/anthropic-adapter.test.d.ts +4 -0
- package/dist/__tests__/anthropic-adapter.test.js +264 -0
- package/dist/__tests__/api.test.js +0 -1
- package/dist/__tests__/cli.integration.test.js +2 -4
- package/dist/__tests__/cli.test.js +0 -1
- package/dist/__tests__/code-agents-notifications.test.js +137 -0
- package/dist/__tests__/code-agents-parser.test.js +19 -1
- package/dist/__tests__/code-agents-preflight.test.js +3 -28
- package/dist/__tests__/code-agents-utils.test.js +34 -9
- package/dist/__tests__/code-agents-worktrees.test.js +116 -0
- package/dist/__tests__/codex-adapter.test.js +184 -0
- package/dist/__tests__/codex-auth.test.js +66 -0
- package/dist/__tests__/codex-provider-gating.test.js +35 -0
- package/dist/__tests__/codex-unified-loop.test.js +111 -0
- package/dist/__tests__/config-security.test.js +127 -0
- package/dist/__tests__/config.test.js +23 -0
- package/dist/__tests__/context-manager.test.js +243 -164
- package/dist/__tests__/cron-run.test.js +250 -0
- package/dist/__tests__/cron.test.js +12 -38
- package/dist/__tests__/digests.test.js +67 -0
- package/dist/__tests__/discord-attachments.test.js +211 -0
- package/dist/__tests__/discord-docs.test.d.ts +1 -0
- package/dist/__tests__/discord-docs.test.js +27 -0
- package/dist/__tests__/discord-thread-agents.test.d.ts +1 -0
- package/dist/__tests__/discord-thread-agents.test.js +115 -0
- package/dist/__tests__/discord-thread-context.test.d.ts +1 -0
- package/dist/__tests__/discord-thread-context.test.js +42 -0
- package/dist/__tests__/doctor.formatters.test.js +4 -4
- package/dist/__tests__/doctor.index.test.js +1 -1
- package/dist/__tests__/doctor.runner.test.js +3 -15
- package/dist/__tests__/env-sanitizer.test.d.ts +1 -0
- package/dist/__tests__/env-sanitizer.test.js +45 -0
- package/dist/__tests__/exec-approval.test.js +61 -0
- package/dist/__tests__/fetch-tool.test.d.ts +1 -0
- package/dist/__tests__/fetch-tool.test.js +85 -0
- package/dist/__tests__/gateway-status-auth.test.d.ts +1 -0
- package/dist/__tests__/gateway-status-auth.test.js +72 -0
- package/dist/__tests__/heartbeat.test.js +3 -3
- package/dist/__tests__/interactive-sessions.test.d.ts +1 -0
- package/dist/__tests__/interactive-sessions.test.js +96 -0
- package/dist/__tests__/langfuse.test.js +6 -18
- package/dist/__tests__/model-selection.test.js +3 -4
- package/dist/__tests__/providers-init.test.js +2 -8
- package/dist/__tests__/providers-routing.test.js +1 -1
- package/dist/__tests__/providers-utils.test.js +13 -3
- package/dist/__tests__/sessions.test.js +14 -10
- package/dist/__tests__/setup.test.js +12 -29
- package/dist/__tests__/skills.test.js +10 -7
- package/dist/__tests__/stream-formatter.test.d.ts +1 -0
- package/dist/__tests__/stream-formatter.test.js +114 -0
- package/dist/__tests__/token-efficiency.test.js +131 -15
- package/dist/__tests__/tool-loop.test.d.ts +4 -0
- package/dist/__tests__/tool-loop.test.js +505 -0
- package/dist/__tests__/tools.test.js +101 -276
- package/dist/__tests__/utils.test.d.ts +1 -0
- package/dist/__tests__/utils.test.js +14 -0
- package/dist/__tests__/voice.test.js +21 -0
- package/dist/agent.js +35 -4
- package/dist/api.js +113 -37
- package/dist/channels/discord/attachments.d.ts +50 -0
- package/dist/channels/discord/attachments.js +137 -0
- package/dist/channels/discord/delegation.d.ts +5 -0
- package/dist/channels/discord/delegation.js +136 -0
- package/dist/channels/discord/handlers.js +694 -7
- package/dist/channels/discord/index.d.ts +16 -1
- package/dist/channels/discord/index.js +64 -1
- package/dist/channels/discord/thread-agents.d.ts +54 -0
- package/dist/channels/discord/thread-agents.js +323 -0
- package/dist/channels/discord/threads.d.ts +58 -0
- package/dist/channels/discord/threads.js +192 -0
- package/dist/channels/discord/types.js +4 -2
- package/dist/channels/discord/utils.d.ts +16 -0
- package/dist/channels/discord/utils.js +86 -6
- package/dist/channels/telegram/index.d.ts +1 -1
- package/dist/channels/telegram/types.js +1 -1
- package/dist/channels/telegram/utils.js +9 -3
- package/dist/channels.d.ts +1 -1
- package/dist/cli.js +20 -400
- package/dist/code-agents/executor.d.ts +1 -1
- package/dist/code-agents/executor.js +101 -45
- package/dist/code-agents/index.d.ts +2 -7
- package/dist/code-agents/index.js +111 -80
- package/dist/code-agents/interactive-resume.d.ts +6 -0
- package/dist/code-agents/interactive-resume.js +98 -0
- package/dist/code-agents/interactive-sessions.d.ts +20 -0
- package/dist/code-agents/interactive-sessions.js +132 -0
- package/dist/code-agents/parser.js +5 -1
- package/dist/code-agents/registry.d.ts +7 -1
- package/dist/code-agents/registry.js +11 -23
- package/dist/code-agents/stream-formatter.d.ts +8 -0
- package/dist/code-agents/stream-formatter.js +92 -0
- package/dist/code-agents/types.d.ts +16 -24
- package/dist/code-agents/utils.d.ts +35 -11
- package/dist/code-agents/utils.js +349 -95
- package/dist/code-agents/worktrees.d.ts +37 -0
- package/dist/code-agents/worktrees.js +116 -0
- package/dist/config.d.ts +2 -4
- package/dist/config.js +123 -23
- package/dist/cron.d.ts +1 -6
- package/dist/cron.js +175 -82
- package/dist/dashboard/assets/index-B345aOO-.js +65 -0
- package/dist/dashboard/assets/index-ZWK4dalJ.css +1 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/digests.d.ts +1 -0
- package/dist/digests.js +132 -42
- package/dist/doctor/checks.d.ts +0 -3
- package/dist/doctor/checks.js +1 -108
- package/dist/doctor/runner.js +1 -4
- package/dist/env-sanitizer.d.ts +2 -0
- package/dist/env-sanitizer.js +61 -0
- package/dist/exec-approval.d.ts +11 -1
- package/dist/exec-approval.js +17 -4
- package/dist/gateway.d.ts +3 -1
- package/dist/gateway.js +17 -7
- package/dist/heartbeat.js +1 -6
- package/dist/langfuse.js +3 -29
- package/dist/model-selection.js +3 -1
- package/dist/providers/adapter.d.ts +118 -0
- package/dist/providers/adapter.js +6 -0
- package/dist/providers/adapters/anthropic-adapter.d.ts +22 -0
- package/dist/providers/adapters/anthropic-adapter.js +204 -0
- package/dist/providers/adapters/codex-adapter.d.ts +26 -0
- package/dist/providers/adapters/codex-adapter.js +203 -0
- package/dist/providers/anthropic.d.ts +1 -0
- package/dist/providers/anthropic.js +10 -272
- package/dist/providers/codex.d.ts +21 -0
- package/dist/providers/codex.js +149 -330
- package/dist/providers/content.d.ts +1 -1
- package/dist/providers/content.js +2 -2
- package/dist/providers/context-manager.d.ts +18 -6
- package/dist/providers/context-manager.js +199 -223
- package/dist/providers/index.d.ts +9 -1
- package/dist/providers/index.js +73 -64
- package/dist/providers/loop-utils.d.ts +20 -0
- package/dist/providers/loop-utils.js +30 -0
- package/dist/providers/tool-loop.d.ts +12 -0
- package/dist/providers/tool-loop.js +251 -0
- package/dist/providers/utils.d.ts +19 -3
- package/dist/providers/utils.js +100 -29
- package/dist/secure-store.d.ts +8 -0
- package/dist/secure-store.js +80 -0
- package/dist/service.js +3 -28
- package/dist/sessions.d.ts +3 -0
- package/dist/sessions.js +147 -18
- package/dist/setup-templates.js +13 -25
- package/dist/setup.d.ts +10 -6
- package/dist/setup.js +84 -292
- package/dist/skills.js +3 -11
- package/dist/tools/agent-delegation.d.ts +19 -0
- package/dist/tools/agent-delegation.js +49 -0
- package/dist/tools/bash-tool.js +89 -34
- package/dist/tools/definitions.d.ts +199 -302
- package/dist/tools/definitions.js +70 -123
- package/dist/tools/execute-context.d.ts +13 -4
- package/dist/tools/fetch-tool.js +109 -13
- package/dist/tools/file-tools.js +7 -1
- package/dist/tools.d.ts +7 -7
- package/dist/tools.js +133 -151
- package/dist/types.d.ts +37 -30
- package/dist/utils.js +4 -6
- package/dist/voice.d.ts +1 -1
- package/dist/voice.js +17 -4
- package/package.json +33 -23
- package/templates/TOOLS.md +0 -27
- package/dist/__tests__/audit.test.js +0 -122
- package/dist/__tests__/code-agents-orchestrator.test.js +0 -216
- package/dist/__tests__/code-agents-sandbox.test.js +0 -163
- package/dist/__tests__/orchestrator.test.js +0 -425
- package/dist/__tests__/sandbox-bridge.test.js +0 -116
- package/dist/__tests__/sandbox-manager.test.js +0 -144
- package/dist/__tests__/sandbox-mount-security.test.js +0 -139
- package/dist/__tests__/sandbox-runtime.test.js +0 -176
- package/dist/__tests__/subagent.test.js +0 -240
- package/dist/__tests__/telegram.test.js +0 -42
- package/dist/code-agents/orchestrator.d.ts +0 -29
- package/dist/code-agents/orchestrator.js +0 -694
- package/dist/code-agents/worktree.d.ts +0 -40
- package/dist/code-agents/worktree.js +0 -215
- package/dist/dashboard/assets/index-BoTHPby4.js +0 -65
- package/dist/dashboard/assets/index-D4mufvBg.css +0 -1
- package/dist/dashboard.d.ts +0 -8
- package/dist/dashboard.js +0 -4071
- package/dist/discord.d.ts +0 -8
- package/dist/discord.js +0 -792
- package/dist/mcp-context-a8c.d.ts +0 -13
- package/dist/mcp-context-a8c.js +0 -34
- package/dist/orchestrator.d.ts +0 -15
- package/dist/orchestrator.js +0 -676
- package/dist/providers/openai.d.ts +0 -10
- package/dist/providers/openai.js +0 -355
- package/dist/sandbox/bridge.d.ts +0 -5
- package/dist/sandbox/bridge.js +0 -63
- package/dist/sandbox/index.d.ts +0 -5
- package/dist/sandbox/index.js +0 -4
- package/dist/sandbox/manager.d.ts +0 -7
- package/dist/sandbox/manager.js +0 -100
- package/dist/sandbox/mount-security.d.ts +0 -12
- package/dist/sandbox/mount-security.js +0 -122
- package/dist/sandbox/runtime.d.ts +0 -39
- package/dist/sandbox/runtime.js +0 -192
- package/dist/sandbox-utils.d.ts +0 -6
- package/dist/sandbox-utils.js +0 -36
- package/dist/subagent.d.ts +0 -19
- package/dist/subagent.js +0 -407
- package/dist/telegram.d.ts +0 -2
- package/dist/telegram.js +0 -11
- package/dist/tools/browser-tool.d.ts +0 -3
- package/dist/tools/browser-tool.js +0 -266
- package/sandbox/Dockerfile +0 -40
- /package/dist/__tests__/{audit.test.d.ts → code-agents-notifications.test.d.ts} +0 -0
- /package/dist/__tests__/{code-agents-orchestrator.test.d.ts → code-agents-worktrees.test.d.ts} +0 -0
- /package/dist/__tests__/{code-agents-sandbox.test.d.ts → codex-adapter.test.d.ts} +0 -0
- /package/dist/__tests__/{orchestrator.test.d.ts → codex-auth.test.d.ts} +0 -0
- /package/dist/__tests__/{sandbox-bridge.test.d.ts → codex-provider-gating.test.d.ts} +0 -0
- /package/dist/__tests__/{sandbox-manager.test.d.ts → codex-unified-loop.test.d.ts} +0 -0
- /package/dist/__tests__/{sandbox-mount-security.test.d.ts → config-security.test.d.ts} +0 -0
- /package/dist/__tests__/{sandbox-runtime.test.d.ts → cron-run.test.d.ts} +0 -0
- /package/dist/__tests__/{subagent.test.d.ts → digests.test.d.ts} +0 -0
- /package/dist/__tests__/{telegram.test.d.ts → discord-attachments.test.d.ts} +0 -0
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
// Anthropic Provider
|
|
2
|
-
import {
|
|
3
|
-
import { buildSystemParam, addToolCacheBreakpoint, contentToText, stripProvider, buildThinkingConfig, truncateToolResult } from './utils.js';
|
|
4
|
-
import { compactAnthropicMessages } from './context-manager.js';
|
|
5
|
-
import { toAnthropicUsageDetails, toCostDetails } from './observability.js';
|
|
6
|
-
import { getToolDefinitions, executeTool } from '../tools.js';
|
|
7
|
-
import { ToolCallGuard } from './tool-guard.js';
|
|
8
|
-
import { toErrorMessage } from '../utils.js';
|
|
9
|
-
import { startTrace, addEvent } from '../audit.js';
|
|
2
|
+
import { toCostDetails } from './observability.js';
|
|
10
3
|
import { buildUsageRecord, recordUsage } from '../usage.js';
|
|
11
4
|
let anthropicClient = null;
|
|
12
5
|
export function setAnthropicClient(client) {
|
|
@@ -46,276 +39,21 @@ async function startGenerationObservation(name, attributes) {
|
|
|
46
39
|
if (!isLangfuseEnabled())
|
|
47
40
|
return null;
|
|
48
41
|
attributes.metadata = { app: LANGFUSE_APP_NAME, ...attributes.metadata };
|
|
42
|
+
const { startObservation } = await import('@langfuse/tracing');
|
|
49
43
|
return startObservation(name, attributes, { asType: 'generation' });
|
|
50
44
|
}
|
|
45
|
+
/** @deprecated Use adapter.chat() via the provider registry instead. */
|
|
51
46
|
export async function chatAnthropic(params) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const { messages, options, config } = params;
|
|
56
|
-
const modelId = stripProvider(options.model);
|
|
57
|
-
const systemMessage = messages.find(m => m.role === 'system');
|
|
58
|
-
const chatMessages = messages
|
|
59
|
-
.filter(m => m.role !== 'system')
|
|
60
|
-
.map(m => ({
|
|
61
|
-
role: m.role,
|
|
62
|
-
content: m.content,
|
|
63
|
-
}));
|
|
64
|
-
// Build request parameters
|
|
65
|
-
const cacheEnabled = config.models?.promptCaching !== false;
|
|
66
|
-
const anthropicParams = {
|
|
67
|
-
model: modelId,
|
|
68
|
-
max_tokens: options.maxTokens || 4096,
|
|
69
|
-
messages: chatMessages,
|
|
70
|
-
};
|
|
71
|
-
const systemParam = buildSystemParam(contentToText(systemMessage?.content || ''), cacheEnabled);
|
|
72
|
-
if (systemParam) {
|
|
73
|
-
anthropicParams.system = systemParam;
|
|
74
|
-
}
|
|
75
|
-
// Add extended thinking if requested
|
|
76
|
-
const thinkingConfig = buildThinkingConfig(options.thinking);
|
|
77
|
-
if (thinkingConfig) {
|
|
78
|
-
anthropicParams.thinking = {
|
|
79
|
-
type: 'enabled',
|
|
80
|
-
budget_tokens: thinkingConfig.budget,
|
|
81
|
-
};
|
|
82
|
-
anthropicParams.max_tokens = Math.max(anthropicParams.max_tokens, thinkingConfig.maxTokens);
|
|
83
|
-
}
|
|
84
|
-
const genObs = await startGenerationObservation(`anthropic:${modelId}`, {
|
|
85
|
-
input: { system: systemMessage?.content, messages: chatMessages },
|
|
86
|
-
model: modelId,
|
|
87
|
-
modelParameters: {
|
|
88
|
-
max_tokens: anthropicParams.max_tokens,
|
|
89
|
-
...(options.thinking && options.thinking !== 'none' ? { thinking: options.thinking } : {}),
|
|
90
|
-
},
|
|
91
|
-
metadata: { provider: 'anthropic' },
|
|
92
|
-
});
|
|
93
|
-
try {
|
|
94
|
-
const response = await anthropicClient.messages.create(anthropicParams);
|
|
95
|
-
const usage = response.usage;
|
|
96
|
-
// Log cache metrics
|
|
97
|
-
if (usage?.cache_read_input_tokens > 0 || usage?.cache_creation_input_tokens > 0) {
|
|
98
|
-
console.log(`[cache] read=${usage.cache_read_input_tokens || 0} created=${usage.cache_creation_input_tokens || 0}`);
|
|
99
|
-
}
|
|
100
|
-
recordAnthropicUsage({ model: modelId, usage, trigger: 'api' });
|
|
101
|
-
// Extract text content
|
|
102
|
-
const textContent = response.content.find(c => c.type === 'text');
|
|
103
|
-
const text = textContent?.text || '';
|
|
104
|
-
genObs?.update({
|
|
105
|
-
output: { text },
|
|
106
|
-
usageDetails: toAnthropicUsageDetails(usage),
|
|
107
|
-
costDetails: toCostDetails(modelId, usage),
|
|
108
|
-
});
|
|
109
|
-
genObs?.end();
|
|
110
|
-
return text;
|
|
111
|
-
}
|
|
112
|
-
catch (err) {
|
|
113
|
-
const errorMessage = toErrorMessage(err);
|
|
114
|
-
genObs?.update({ level: 'ERROR', statusMessage: errorMessage, output: { error: errorMessage } });
|
|
115
|
-
genObs?.end();
|
|
116
|
-
throw err;
|
|
117
|
-
}
|
|
47
|
+
const { AnthropicAdapter } = await import('./adapters/anthropic-adapter.js');
|
|
48
|
+
const adapter = new AnthropicAdapter();
|
|
49
|
+
return adapter.chat(params.messages, params.options, params.config);
|
|
118
50
|
}
|
|
119
51
|
export async function chatWithToolsAnthropic(params) {
|
|
120
52
|
if (!anthropicClient) {
|
|
121
53
|
throw new Error('Anthropic client not initialized');
|
|
122
54
|
}
|
|
123
|
-
const {
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
const includeSpawn = !!(toolContext?.fullConfig && (toolContext?.chatId || toolContext?.isCronJob));
|
|
128
|
-
const toolDefs = await getToolDefinitions(toolConfig, { includeAgentTools: includeSpawn, projects: toolContext?.fullConfig?.projects });
|
|
129
|
-
// Enable prompt caching for system + tools
|
|
130
|
-
const cacheEnabled = config.models?.promptCaching !== false;
|
|
131
|
-
if (cacheEnabled)
|
|
132
|
-
addToolCacheBreakpoint(toolDefs);
|
|
133
|
-
// Build system param with OAuth identity guard
|
|
134
|
-
const systemMessage = messages.find(m => m.role === 'system');
|
|
135
|
-
const systemParam = buildSystemParam(contentToText(systemMessage?.content || ''), cacheEnabled);
|
|
136
|
-
// Build initial messages (exclude system)
|
|
137
|
-
const apiMessages = messages
|
|
138
|
-
.filter(m => m.role !== 'system')
|
|
139
|
-
.map(m => ({ role: m.role, content: m.content }));
|
|
140
|
-
// Track tool calls for logging
|
|
141
|
-
const toolLog = [];
|
|
142
|
-
// Guard: spin detection, no-progress detection, token budget
|
|
143
|
-
const guard = new ToolCallGuard(toolConfig.maxTurnTokens);
|
|
144
|
-
// Start audit trace
|
|
145
|
-
const auditTraceId = toolContext?.auditTraceId || startTrace((toolContext?.trigger || 'api'));
|
|
146
|
-
for (let i = 0; i < maxIterations; i++) {
|
|
147
|
-
// Check abort signal before each iteration
|
|
148
|
-
if (toolContext?.abortSignal?.aborted) {
|
|
149
|
-
return {
|
|
150
|
-
response: `[Cancelled after ${toolLog.length} tool calls]`,
|
|
151
|
-
toolCalls: toolLog,
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
// Compact old tool results if context is growing large
|
|
155
|
-
const compactionResult = await compactAnthropicMessages(apiMessages, toolConfig.contextManagement, i + 1, config);
|
|
156
|
-
const messagesForApi = compactionResult.messages;
|
|
157
|
-
if (compactionResult.compacted) {
|
|
158
|
-
const method = compactionResult.method === 'llm' ? 'LLM summary' : 'truncation';
|
|
159
|
-
const detail = `~${Math.round((compactionResult.tokensBefore || 0) / 1000)}k → ~${Math.round((compactionResult.tokensAfter || 0) / 1000)}k tokens`;
|
|
160
|
-
toolLog.push(`[context compacted via ${method}: ${detail}]`);
|
|
161
|
-
}
|
|
162
|
-
const anthropicParams = {
|
|
163
|
-
model: modelId,
|
|
164
|
-
max_tokens: options.maxTokens || 16384,
|
|
165
|
-
messages: messagesForApi,
|
|
166
|
-
tools: toolDefs,
|
|
167
|
-
};
|
|
168
|
-
if (systemParam) {
|
|
169
|
-
anthropicParams.system = systemParam;
|
|
170
|
-
}
|
|
171
|
-
// Add thinking if configured
|
|
172
|
-
const thinkingConfig = buildThinkingConfig(options.thinking);
|
|
173
|
-
if (thinkingConfig) {
|
|
174
|
-
anthropicParams.thinking = { type: 'enabled', budget_tokens: thinkingConfig.budget };
|
|
175
|
-
anthropicParams.max_tokens = Math.max(anthropicParams.max_tokens, thinkingConfig.maxTokens);
|
|
176
|
-
}
|
|
177
|
-
console.log(`[agent:tools] Iteration ${i + 1}/${maxIterations}`);
|
|
178
|
-
const genObs = await startGenerationObservation(`anthropic:${modelId}`, {
|
|
179
|
-
input: { messages: apiMessages },
|
|
180
|
-
model: modelId,
|
|
181
|
-
modelParameters: { max_tokens: anthropicParams.max_tokens },
|
|
182
|
-
metadata: { provider: 'anthropic', iteration: i + 1 },
|
|
183
|
-
});
|
|
184
|
-
let response;
|
|
185
|
-
try {
|
|
186
|
-
response = await anthropicClient.messages.create(anthropicParams);
|
|
187
|
-
const usage = response.usage;
|
|
188
|
-
// Log cache metrics
|
|
189
|
-
if (usage?.cache_read_input_tokens > 0 || usage?.cache_creation_input_tokens > 0) {
|
|
190
|
-
console.log(`[cache] read=${usage.cache_read_input_tokens || 0} created=${usage.cache_creation_input_tokens || 0}`);
|
|
191
|
-
}
|
|
192
|
-
recordAnthropicUsage({
|
|
193
|
-
model: modelId,
|
|
194
|
-
usage,
|
|
195
|
-
trigger: toolContext?.trigger || 'api',
|
|
196
|
-
agentId: toolContext?.agentId,
|
|
197
|
-
});
|
|
198
|
-
genObs?.update({
|
|
199
|
-
output: response.content,
|
|
200
|
-
usageDetails: toAnthropicUsageDetails(usage),
|
|
201
|
-
costDetails: toCostDetails(modelId, usage),
|
|
202
|
-
});
|
|
203
|
-
genObs?.end();
|
|
204
|
-
// Guard: track token usage (stats only, no enforcement)
|
|
205
|
-
guard.recordTokens(response.usage?.input_tokens ?? 0, response.usage?.output_tokens ?? 0);
|
|
206
|
-
}
|
|
207
|
-
catch (err) {
|
|
208
|
-
const errorMessage = toErrorMessage(err);
|
|
209
|
-
genObs?.update({ level: 'ERROR', statusMessage: errorMessage, output: { error: errorMessage } });
|
|
210
|
-
genObs?.end();
|
|
211
|
-
throw err;
|
|
212
|
-
}
|
|
213
|
-
// If no tool use, we're done — extract text
|
|
214
|
-
if (response.stop_reason !== 'tool_use') {
|
|
215
|
-
const textBlocks = response.content.filter((c) => c.type === 'text');
|
|
216
|
-
let responseText = textBlocks.map((b) => b.text).join('\n') || '';
|
|
217
|
-
// Fallback when model did tool work but returned no text summary
|
|
218
|
-
if (!responseText && toolLog.length > 0) {
|
|
219
|
-
responseText = `[Completed with ${toolLog.length} tool calls, no text response]`;
|
|
220
|
-
}
|
|
221
|
-
const usage = response.usage;
|
|
222
|
-
return {
|
|
223
|
-
response: responseText,
|
|
224
|
-
toolCalls: toolLog,
|
|
225
|
-
usage: {
|
|
226
|
-
prompt_tokens: usage?.input_tokens ?? 0,
|
|
227
|
-
completion_tokens: usage?.output_tokens ?? 0,
|
|
228
|
-
total_tokens: (usage?.input_tokens ?? 0) + (usage?.output_tokens ?? 0),
|
|
229
|
-
},
|
|
230
|
-
cost: toCostDetails(modelId, usage),
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
// Add assistant response (full content including tool_use blocks)
|
|
234
|
-
apiMessages.push({ role: 'assistant', content: response.content });
|
|
235
|
-
// Execute each tool_use block
|
|
236
|
-
const toolResults = [];
|
|
237
|
-
for (const block of response.content) {
|
|
238
|
-
if (block.type !== 'tool_use')
|
|
239
|
-
continue;
|
|
240
|
-
const inputStr = JSON.stringify(block.input).slice(0, 200);
|
|
241
|
-
console.log(`[agent:tools] -> ${block.name}(${inputStr})`);
|
|
242
|
-
// Dynamic import to avoid circular dependency
|
|
243
|
-
const { isLangfuseEnabled } = await import('../langfuse.js');
|
|
244
|
-
const { startObservation } = await import('@langfuse/tracing');
|
|
245
|
-
const toolObs = isLangfuseEnabled()
|
|
246
|
-
? startObservation(`tool:${block.name}`, { input: block.input, metadata: { app: LANGFUSE_APP_NAME, tool: block.name } }, { asType: 'tool' })
|
|
247
|
-
: null;
|
|
248
|
-
// Guard: spin detection
|
|
249
|
-
const guardResult = guard.recordCall(block.name, block.input);
|
|
250
|
-
if (guardResult.warning)
|
|
251
|
-
console.warn(`[agent:tools:guard] ${guardResult.warning}`);
|
|
252
|
-
if (guardResult.blocked) {
|
|
253
|
-
toolResults.push({
|
|
254
|
-
type: 'tool_result',
|
|
255
|
-
tool_use_id: block.id,
|
|
256
|
-
content: guardResult.warning || 'Blocked: repeated identical call',
|
|
257
|
-
is_error: true,
|
|
258
|
-
});
|
|
259
|
-
toolLog.push(`${block.name} [BLOCKED: spin detected]`);
|
|
260
|
-
continue;
|
|
261
|
-
}
|
|
262
|
-
const toolStart = Date.now();
|
|
263
|
-
try {
|
|
264
|
-
const result = await executeTool(block.name, block.input, toolConfig, toolContext);
|
|
265
|
-
const truncatedResult = truncateToolResult(result);
|
|
266
|
-
const resultPreview = result.slice(0, 200) + (result.length > 200 ? '...' : '');
|
|
267
|
-
console.log(`[agent:tools] <- ${resultPreview}`);
|
|
268
|
-
toolLog.push(`${block.name}(${inputStr}) → ${resultPreview}`);
|
|
269
|
-
toolObs?.update({ output: result });
|
|
270
|
-
toolObs?.end();
|
|
271
|
-
// Record audit event
|
|
272
|
-
if (toolContext?.auditTraceId) {
|
|
273
|
-
addEvent(toolContext.auditTraceId, {
|
|
274
|
-
type: 'tool_use',
|
|
275
|
-
summary: `${block.name}(${inputStr})`,
|
|
276
|
-
durationMs: Date.now() - toolStart,
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
toolResults.push({
|
|
280
|
-
type: 'tool_result',
|
|
281
|
-
tool_use_id: block.id,
|
|
282
|
-
content: truncatedResult,
|
|
283
|
-
});
|
|
284
|
-
// Guard: no-progress detection
|
|
285
|
-
const progressResult = guard.recordResult(result);
|
|
286
|
-
if (progressResult.nudge) {
|
|
287
|
-
console.warn(`[agent:tools:guard] ${progressResult.nudge}`);
|
|
288
|
-
toolResults[toolResults.length - 1].content += `\n\n[System: ${progressResult.nudge}]`;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
catch (err) {
|
|
292
|
-
const errorMessage = toErrorMessage(err);
|
|
293
|
-
toolObs?.update({ level: 'ERROR', statusMessage: errorMessage, output: { error: errorMessage } });
|
|
294
|
-
toolObs?.end();
|
|
295
|
-
if (toolContext?.auditTraceId) {
|
|
296
|
-
addEvent(toolContext.auditTraceId, {
|
|
297
|
-
type: 'tool_error',
|
|
298
|
-
summary: `${block.name} error: ${errorMessage.slice(0, 150)}`,
|
|
299
|
-
durationMs: Date.now() - toolStart,
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
throw err;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
// Send tool results back
|
|
306
|
-
apiMessages.push({ role: 'user', content: toolResults });
|
|
307
|
-
}
|
|
308
|
-
console.warn(`[agent:tools] Max iterations (${maxIterations}) reached`);
|
|
309
|
-
return {
|
|
310
|
-
response: '[Tool use loop reached maximum iterations]',
|
|
311
|
-
toolCalls: toolLog,
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
/** Build UsageDetails from Anthropic usage response */
|
|
315
|
-
function buildUsageDetails(usage) {
|
|
316
|
-
return {
|
|
317
|
-
prompt_tokens: usage?.input_tokens ?? 0,
|
|
318
|
-
completion_tokens: usage?.output_tokens ?? 0,
|
|
319
|
-
total_tokens: (usage?.input_tokens ?? 0) + (usage?.output_tokens ?? 0),
|
|
320
|
-
};
|
|
55
|
+
const { runToolLoop } = await import('./tool-loop.js');
|
|
56
|
+
const { AnthropicAdapter } = await import('./adapters/anthropic-adapter.js');
|
|
57
|
+
const adapter = new AnthropicAdapter();
|
|
58
|
+
return runToolLoop(adapter, params.messages, params.options, params.config, params.toolConfig, params.toolContext);
|
|
321
59
|
}
|
|
@@ -8,10 +8,31 @@ interface CodexAuth {
|
|
|
8
8
|
accessToken: string;
|
|
9
9
|
accountId: string;
|
|
10
10
|
}
|
|
11
|
+
export declare function resolveCodexAuthPath(authPath?: string): string;
|
|
11
12
|
export declare function loadCodexAuth(authPath?: string): CodexAuth | null;
|
|
12
13
|
export declare function initCodexAuth(path?: string, baseUrl?: string): boolean;
|
|
13
14
|
export declare function getCodexAuth(): CodexAuth | null;
|
|
14
15
|
export declare function isCodexAvailable(): boolean;
|
|
16
|
+
export declare function recordCodexUsage(params: {
|
|
17
|
+
model: string;
|
|
18
|
+
usage: any;
|
|
19
|
+
trigger?: string;
|
|
20
|
+
agentId?: string;
|
|
21
|
+
}): void;
|
|
22
|
+
/**
|
|
23
|
+
* Make a single Codex API call. Returns raw SSE text.
|
|
24
|
+
*/
|
|
25
|
+
export declare function codexFetch(body: any, timeoutMs?: number): Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Parse an SSE response from the Codex backend.
|
|
28
|
+
* Extracts function calls from the completed response object.
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseCodexSSE(text: string): {
|
|
31
|
+
outputText: string;
|
|
32
|
+
functionCalls: any[];
|
|
33
|
+
response: any | null;
|
|
34
|
+
};
|
|
35
|
+
/** @deprecated Use adapter.chat() via the provider registry instead. */
|
|
15
36
|
export declare function chatCodex(params: ProviderChatParams): Promise<string>;
|
|
16
37
|
export declare function chatWithToolsCodex(params: ProviderToolChatParams): Promise<ToolChatResult>;
|
|
17
38
|
export {};
|