@studio-foundation/runner 0.3.0-beta.1
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/ARCHITECTURE.md +53 -0
- package/LICENSE +663 -0
- package/README.md +125 -0
- package/configs/agents/analyst.agent.yaml +31 -0
- package/configs/agents/code-generator.agent.yaml +31 -0
- package/configs/agents/generic.agent.yaml +23 -0
- package/dist/__tests__/script-executor.test.d.ts +2 -0
- package/dist/__tests__/script-executor.test.d.ts.map +1 -0
- package/dist/__tests__/script-executor.test.js +173 -0
- package/dist/__tests__/script-executor.test.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/integration-loader.d.ts +20 -0
- package/dist/integrations/integration-loader.d.ts.map +1 -0
- package/dist/integrations/integration-loader.js +71 -0
- package/dist/integrations/integration-loader.js.map +1 -0
- package/dist/integrations/integration-loader.test.d.ts +2 -0
- package/dist/integrations/integration-loader.test.d.ts.map +1 -0
- package/dist/integrations/integration-loader.test.js +77 -0
- package/dist/integrations/integration-loader.test.js.map +1 -0
- package/dist/middleware/anonymization.d.ts +22 -0
- package/dist/middleware/anonymization.d.ts.map +1 -0
- package/dist/middleware/anonymization.js +37 -0
- package/dist/middleware/anonymization.js.map +1 -0
- package/dist/plugins/index.d.ts +5 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +10 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/mcp-client.d.ts +19 -0
- package/dist/plugins/mcp-client.d.ts.map +1 -0
- package/dist/plugins/mcp-client.js +126 -0
- package/dist/plugins/mcp-client.js.map +1 -0
- package/dist/plugins/mcp-client.test.d.ts +2 -0
- package/dist/plugins/mcp-client.test.d.ts.map +1 -0
- package/dist/plugins/mcp-client.test.js +160 -0
- package/dist/plugins/mcp-client.test.js.map +1 -0
- package/dist/plugins/oauth-provider.d.ts +27 -0
- package/dist/plugins/oauth-provider.d.ts.map +1 -0
- package/dist/plugins/oauth-provider.js +140 -0
- package/dist/plugins/oauth-provider.js.map +1 -0
- package/dist/plugins/oauth-provider.test.d.ts +2 -0
- package/dist/plugins/oauth-provider.test.d.ts.map +1 -0
- package/dist/plugins/oauth-provider.test.js +144 -0
- package/dist/plugins/oauth-provider.test.js.map +1 -0
- package/dist/plugins/plugin-loader.d.ts +29 -0
- package/dist/plugins/plugin-loader.d.ts.map +1 -0
- package/dist/plugins/plugin-loader.js +71 -0
- package/dist/plugins/plugin-loader.js.map +1 -0
- package/dist/plugins/plugin-loader.test.d.ts +2 -0
- package/dist/plugins/plugin-loader.test.d.ts.map +1 -0
- package/dist/plugins/plugin-loader.test.js +87 -0
- package/dist/plugins/plugin-loader.test.js.map +1 -0
- package/dist/prompt-builder.d.ts +47 -0
- package/dist/prompt-builder.d.ts.map +1 -0
- package/dist/prompt-builder.js +263 -0
- package/dist/prompt-builder.js.map +1 -0
- package/dist/prompt-builder.test.d.ts +2 -0
- package/dist/prompt-builder.test.d.ts.map +1 -0
- package/dist/prompt-builder.test.js +154 -0
- package/dist/prompt-builder.test.js.map +1 -0
- package/dist/providers/anthropic.d.ts +14 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +118 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/anthropic.test.d.ts +2 -0
- package/dist/providers/anthropic.test.d.ts.map +1 -0
- package/dist/providers/anthropic.test.js +76 -0
- package/dist/providers/anthropic.test.js.map +1 -0
- package/dist/providers/mock.d.ts +17 -0
- package/dist/providers/mock.d.ts.map +1 -0
- package/dist/providers/mock.js +39 -0
- package/dist/providers/mock.js.map +1 -0
- package/dist/providers/ollama.d.ts +18 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +155 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/ollama.test.d.ts +2 -0
- package/dist/providers/ollama.test.d.ts.map +1 -0
- package/dist/providers/ollama.test.js +123 -0
- package/dist/providers/ollama.test.js.map +1 -0
- package/dist/providers/openai-responses.d.ts +18 -0
- package/dist/providers/openai-responses.d.ts.map +1 -0
- package/dist/providers/openai-responses.js +175 -0
- package/dist/providers/openai-responses.js.map +1 -0
- package/dist/providers/openai.d.ts +16 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +132 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/openai.test.d.ts +2 -0
- package/dist/providers/openai.test.d.ts.map +1 -0
- package/dist/providers/openai.test.js +51 -0
- package/dist/providers/openai.test.js.map +1 -0
- package/dist/providers/provider.d.ts +42 -0
- package/dist/providers/provider.d.ts.map +1 -0
- package/dist/providers/provider.js +10 -0
- package/dist/providers/provider.js.map +1 -0
- package/dist/providers/registry.d.ts +42 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +65 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/runner.d.ts +46 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +324 -0
- package/dist/runner.js.map +1 -0
- package/dist/runner.test.d.ts +2 -0
- package/dist/runner.test.d.ts.map +1 -0
- package/dist/runner.test.js +280 -0
- package/dist/runner.test.js.map +1 -0
- package/dist/script-executor.d.ts +11 -0
- package/dist/script-executor.d.ts.map +1 -0
- package/dist/script-executor.js +85 -0
- package/dist/script-executor.js.map +1 -0
- package/dist/tools/builtin/git.d.ts +6 -0
- package/dist/tools/builtin/git.d.ts.map +1 -0
- package/dist/tools/builtin/git.js +294 -0
- package/dist/tools/builtin/git.js.map +1 -0
- package/dist/tools/builtin/patch.d.ts +6 -0
- package/dist/tools/builtin/patch.d.ts.map +1 -0
- package/dist/tools/builtin/patch.js +238 -0
- package/dist/tools/builtin/patch.js.map +1 -0
- package/dist/tools/builtin/repo-manager.d.ts +6 -0
- package/dist/tools/builtin/repo-manager.d.ts.map +1 -0
- package/dist/tools/builtin/repo-manager.js +171 -0
- package/dist/tools/builtin/repo-manager.js.map +1 -0
- package/dist/tools/builtin/search.d.ts +6 -0
- package/dist/tools/builtin/search.d.ts.map +1 -0
- package/dist/tools/builtin/search.js +104 -0
- package/dist/tools/builtin/search.js.map +1 -0
- package/dist/tools/builtin/shell.d.ts +6 -0
- package/dist/tools/builtin/shell.d.ts.map +1 -0
- package/dist/tools/builtin/shell.js +78 -0
- package/dist/tools/builtin/shell.js.map +1 -0
- package/dist/tools/builtin/studio-run.d.ts +12 -0
- package/dist/tools/builtin/studio-run.d.ts.map +1 -0
- package/dist/tools/builtin/studio-run.js +61 -0
- package/dist/tools/builtin/studio-run.js.map +1 -0
- package/dist/tools/builtin/web-search.d.ts +7 -0
- package/dist/tools/builtin/web-search.d.ts.map +1 -0
- package/dist/tools/builtin/web-search.js +94 -0
- package/dist/tools/builtin/web-search.js.map +1 -0
- package/dist/tools/builtin/web-search.test.d.ts +5 -0
- package/dist/tools/builtin/web-search.test.d.ts.map +1 -0
- package/dist/tools/builtin/web-search.test.js +90 -0
- package/dist/tools/builtin/web-search.test.js.map +1 -0
- package/dist/tools/errors.d.ts +4 -0
- package/dist/tools/errors.d.ts.map +1 -0
- package/dist/tools/errors.js +11 -0
- package/dist/tools/errors.js.map +1 -0
- package/dist/tools/errors.test.d.ts +2 -0
- package/dist/tools/errors.test.d.ts.map +1 -0
- package/dist/tools/errors.test.js +14 -0
- package/dist/tools/errors.test.js.map +1 -0
- package/dist/tools/plugin-loader.d.ts +31 -0
- package/dist/tools/plugin-loader.d.ts.map +1 -0
- package/dist/tools/plugin-loader.js +183 -0
- package/dist/tools/plugin-loader.js.map +1 -0
- package/dist/tools/plugin-loader.test.d.ts +2 -0
- package/dist/tools/plugin-loader.test.d.ts.map +1 -0
- package/dist/tools/plugin-loader.test.js +116 -0
- package/dist/tools/plugin-loader.test.js.map +1 -0
- package/dist/tools/skills/skill-loader.d.ts +23 -0
- package/dist/tools/skills/skill-loader.d.ts.map +1 -0
- package/dist/tools/skills/skill-loader.js +58 -0
- package/dist/tools/skills/skill-loader.js.map +1 -0
- package/dist/tools/skills/skill-loader.test.d.ts +2 -0
- package/dist/tools/skills/skill-loader.test.d.ts.map +1 -0
- package/dist/tools/skills/skill-loader.test.js +92 -0
- package/dist/tools/skills/skill-loader.test.js.map +1 -0
- package/dist/tools/tool-executor.d.ts +12 -0
- package/dist/tools/tool-executor.d.ts.map +1 -0
- package/dist/tools/tool-executor.js +76 -0
- package/dist/tools/tool-executor.js.map +1 -0
- package/dist/tools/tool-executor.test.d.ts +2 -0
- package/dist/tools/tool-executor.test.d.ts.map +1 -0
- package/dist/tools/tool-executor.test.js +83 -0
- package/dist/tools/tool-executor.test.js.map +1 -0
- package/dist/tools/tool-registry.d.ts +65 -0
- package/dist/tools/tool-registry.d.ts.map +1 -0
- package/dist/tools/tool-registry.js +112 -0
- package/dist/tools/tool-registry.js.map +1 -0
- package/dist/tools/yaml-executor.d.ts +22 -0
- package/dist/tools/yaml-executor.d.ts.map +1 -0
- package/dist/tools/yaml-executor.js +80 -0
- package/dist/tools/yaml-executor.js.map +1 -0
- package/dist/utils/race-signal.d.ts +6 -0
- package/dist/utils/race-signal.d.ts.map +1 -0
- package/dist/utils/race-signal.js +21 -0
- package/dist/utils/race-signal.js.map +1 -0
- package/dist/utils/race-signal.test.d.ts +2 -0
- package/dist/utils/race-signal.test.d.ts.map +1 -0
- package/dist/utils/race-signal.test.js +48 -0
- package/dist/utils/race-signal.test.js.map +1 -0
- package/package.json +36 -0
- package/src/__tests__/script-executor.test.ts +180 -0
- package/src/index.ts +68 -0
- package/src/integrations/integration-loader.test.ts +88 -0
- package/src/integrations/integration-loader.ts +68 -0
- package/src/middleware/anonymization.ts +38 -0
- package/src/plugins/index.ts +4 -0
- package/src/plugins/mcp-client.test.ts +148 -0
- package/src/plugins/mcp-client.ts +128 -0
- package/src/plugins/oauth-provider.test.ts +167 -0
- package/src/plugins/oauth-provider.ts +175 -0
- package/src/plugins/plugin-loader.test.ts +114 -0
- package/src/plugins/plugin-loader.ts +90 -0
- package/src/prompt-builder.test.ts +167 -0
- package/src/prompt-builder.ts +332 -0
- package/src/providers/anthropic.test.ts +101 -0
- package/src/providers/anthropic.ts +135 -0
- package/src/providers/mock.ts +57 -0
- package/src/providers/ollama.test.ts +166 -0
- package/src/providers/ollama.ts +152 -0
- package/src/providers/openai-responses.ts +212 -0
- package/src/providers/openai.test.ts +67 -0
- package/src/providers/openai.ts +139 -0
- package/src/providers/provider.ts +54 -0
- package/src/providers/registry.ts +77 -0
- package/src/runner.test.ts +343 -0
- package/src/runner.ts +396 -0
- package/src/script-executor.ts +107 -0
- package/src/tools/builtin/git.ts +311 -0
- package/src/tools/builtin/patch.ts +257 -0
- package/src/tools/builtin/repo-manager.ts +142 -0
- package/src/tools/builtin/search.ts +108 -0
- package/src/tools/builtin/shell.ts +82 -0
- package/src/tools/builtin/studio-run.ts +73 -0
- package/src/tools/builtin/web-search.test.ts +122 -0
- package/src/tools/builtin/web-search.ts +101 -0
- package/src/tools/errors.test.ts +12 -0
- package/src/tools/errors.ts +6 -0
- package/src/tools/plugin-loader.test.ts +130 -0
- package/src/tools/plugin-loader.ts +203 -0
- package/src/tools/skills/README.md +49 -0
- package/src/tools/skills/skill-loader.test.ts +106 -0
- package/src/tools/skills/skill-loader.ts +62 -0
- package/src/tools/tool-executor.test.ts +88 -0
- package/src/tools/tool-executor.ts +84 -0
- package/src/tools/tool-registry.ts +130 -0
- package/src/tools/yaml-executor.ts +120 -0
- package/src/utils/race-signal.test.ts +50 -0
- package/src/utils/race-signal.ts +17 -0
- package/templates/integrations/linear.integration.yaml +35 -0
- package/templates/integrations/slack.integration.yaml +22 -0
- package/templates/integrations/webhook.integration.yaml +17 -0
- package/templates/tools/git.tool.yaml +80 -0
- package/templates/tools/repo-manager.tool.yaml +64 -0
- package/templates/tools/search.tool.yaml +22 -0
- package/templates/tools/shell.tool.yaml +19 -0
- package/templates/tools/web-search.tool.yaml +24 -0
- package/tests/anonymization-middleware.test.ts +61 -0
- package/tests/anthropic.test.ts +87 -0
- package/tests/apply-patch.test.ts +355 -0
- package/tests/fixtures/tools/test-builtin.tool.yaml +14 -0
- package/tests/fixtures/tools/test-shell.tool.yaml +19 -0
- package/tests/mock-provider.test.ts +104 -0
- package/tests/openai.test.ts +72 -0
- package/tests/plugin-loader.test.ts +54 -0
- package/tests/prompt-builder.test.ts +468 -0
- package/tests/runner-anonymization.test.ts +89 -0
- package/tests/runner.test.ts +885 -0
- package/tests/studio-run.test.ts +94 -0
- package/tests/tool-executor.test.ts +115 -0
- package/tests/tool-registry.test.ts +84 -0
- package/tests/yaml-executor.test.ts +76 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +7 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Prompt builder - constructs messages for LLM with retry escalation
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.buildPrompt = buildPrompt;
|
|
7
|
+
/**
|
|
8
|
+
* Build prompt messages with retry escalation support
|
|
9
|
+
*/
|
|
10
|
+
function buildPrompt(config) {
|
|
11
|
+
const { agent, task, context, executionContext } = config;
|
|
12
|
+
const messages = [];
|
|
13
|
+
// Build system message
|
|
14
|
+
let systemContent = agent.system_prompt || 'You are a helpful AI assistant.';
|
|
15
|
+
// Add output format with concrete schema when available
|
|
16
|
+
const contract = config.outputContract;
|
|
17
|
+
if (contract?.schema?.required_fields?.length) {
|
|
18
|
+
const fields = contract.schema.required_fields;
|
|
19
|
+
const requiresToolCalls = (contract.tool_calls?.minimum ?? 0) > 0;
|
|
20
|
+
systemContent += `
|
|
21
|
+
|
|
22
|
+
## REQUIRED OUTPUT FORMAT
|
|
23
|
+
|
|
24
|
+
You MUST ${requiresToolCalls ? 'end with' : 'respond with'} a valid JSON object. ${requiresToolCalls ? 'Your final message (after all tool calls)' : 'Your entire response'} must be parseable JSON — no markdown, no code blocks, no explanatory text${requiresToolCalls ? ' in that final message' : ' before or after'}.
|
|
25
|
+
|
|
26
|
+
The JSON object MUST contain these fields:
|
|
27
|
+
${fields.map((f) => `- "${f}" — ${getFieldTypeHint(f)}`).join('\n')}
|
|
28
|
+
|
|
29
|
+
Example structure:
|
|
30
|
+
{
|
|
31
|
+
${fields.map((f) => ` "${f}": ${getFieldExample(f)}`).join(',\n')}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
CRITICAL: If your response is not valid JSON with ALL required fields, it will be rejected and you will be asked to retry.
|
|
35
|
+
Pay attention to field types: arrays must be arrays, objects must be objects. Do NOT flatten structured fields into plain strings.`;
|
|
36
|
+
// Inject accepted values for rejection detection fields
|
|
37
|
+
const rd = contract.post_validation?.rejection_detection;
|
|
38
|
+
if (rd?.field && rd?.approved_values?.length) {
|
|
39
|
+
systemContent += `
|
|
40
|
+
|
|
41
|
+
The "${rd.field}" field MUST be one of: ${rd.approved_values.map((v) => `"${v}"`).join(', ')}.
|
|
42
|
+
Any other value means rejection.`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else if (task.contract_name || task.expected_output) {
|
|
46
|
+
systemContent += `
|
|
47
|
+
|
|
48
|
+
## Output Format
|
|
49
|
+
|
|
50
|
+
${task.expected_output || `Provide your response according to the ${task.contract_name} contract.`}
|
|
51
|
+
`;
|
|
52
|
+
}
|
|
53
|
+
// Inject prompt snippets from active tool plugins
|
|
54
|
+
if (config.promptSnippets && config.promptSnippets.length > 0) {
|
|
55
|
+
systemContent += '\n\n' + config.promptSnippets.join('\n\n');
|
|
56
|
+
}
|
|
57
|
+
// Inject skills (.studio/skills/*.skill.md) declared by the agent
|
|
58
|
+
if (config.skills && config.skills.length > 0) {
|
|
59
|
+
const skillChunks = config.skills.map(s => `## Skill: ${s.name}\n\n${s.content}`);
|
|
60
|
+
systemContent += '\n\n' + skillChunks.join('\n\n---\n\n');
|
|
61
|
+
}
|
|
62
|
+
messages.push({
|
|
63
|
+
role: 'system',
|
|
64
|
+
content: systemContent
|
|
65
|
+
});
|
|
66
|
+
// Build user message with context
|
|
67
|
+
let userContent = '';
|
|
68
|
+
// Group feedback FIRST — must be the most prominent thing the model sees
|
|
69
|
+
if (context.group_feedback) {
|
|
70
|
+
const fb = context.group_feedback;
|
|
71
|
+
userContent += `## ⚠️ REVISION REQUIRED — Iteration ${fb.iteration + 1}/${fb.max_iterations}\n\n`;
|
|
72
|
+
userContent += `Your previous implementation was **REJECTED**. You MUST address ALL issues below before proceeding.\n\n`;
|
|
73
|
+
userContent += `**Reason:** ${fb.rejection_reason}\n\n`;
|
|
74
|
+
if (fb.rejection_details?.length) {
|
|
75
|
+
userContent += `**Issues to fix:**\n`;
|
|
76
|
+
for (const detail of fb.rejection_details) {
|
|
77
|
+
userContent += `- ${detail}\n`;
|
|
78
|
+
}
|
|
79
|
+
userContent += '\n';
|
|
80
|
+
}
|
|
81
|
+
userContent += `DO NOT repeat the same approach. Each issue above MUST be resolved in your new implementation.\n\n---\n\n`;
|
|
82
|
+
}
|
|
83
|
+
// Add previous outputs if any
|
|
84
|
+
if (context.previous_outputs && Object.keys(context.previous_outputs).length > 0) {
|
|
85
|
+
userContent += '## Previous Stage Outputs\n\n';
|
|
86
|
+
for (const [stage, output] of Object.entries(context.previous_outputs)) {
|
|
87
|
+
userContent += `### ${stage}\n\`\`\`json\n${JSON.stringify(output, null, 2)}\n\`\`\`\n\n`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Add repository context if provided
|
|
91
|
+
if (context.repo_files && context.repo_files.length > 0) {
|
|
92
|
+
userContent += `## Repository Files\n\nRelevant files:\n${context.repo_files.map(f => `- ${f}`).join('\n')}\n\n`;
|
|
93
|
+
}
|
|
94
|
+
// Add additional context
|
|
95
|
+
if (context.additional_context) {
|
|
96
|
+
userContent += `## Additional Context\n\n${context.additional_context}\n\n`;
|
|
97
|
+
}
|
|
98
|
+
// Add stage name (used in parallel groups so agents can identify their slot)
|
|
99
|
+
if (context.stage_name) {
|
|
100
|
+
userContent += `## Stage Name\n\n${context.stage_name}\n\n`;
|
|
101
|
+
}
|
|
102
|
+
// Render pipeline startup context — each key as a ### section
|
|
103
|
+
if (context.startup_context && Object.keys(context.startup_context).length > 0) {
|
|
104
|
+
userContent += '## Pipeline Startup Context\n\n';
|
|
105
|
+
for (const [key, value] of Object.entries(context.startup_context)) {
|
|
106
|
+
userContent += `### ${key}\n\`\`\`\n${value}\n\`\`\`\n\n`;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Add context packs — each as a top-level ## section, sections as ###
|
|
110
|
+
if (context.context_packs?.length) {
|
|
111
|
+
for (const pack of context.context_packs) {
|
|
112
|
+
userContent += `## ${pack.name}`;
|
|
113
|
+
if (pack.description)
|
|
114
|
+
userContent += ` — ${pack.description}`;
|
|
115
|
+
userContent += '\n\n';
|
|
116
|
+
for (const section of pack.sections) {
|
|
117
|
+
userContent += `### ${section.title}\n\n${section.content}\n\n`;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Add previous stage tool results (discoveries) — placed last before the task
|
|
122
|
+
// so they have high recency salience for the LLM
|
|
123
|
+
if (context.previous_tool_results && Object.keys(context.previous_tool_results).length > 0) {
|
|
124
|
+
userContent += renderToolResults(context.previous_tool_results);
|
|
125
|
+
}
|
|
126
|
+
// Add task description
|
|
127
|
+
userContent += `## Task\n\n${task.description}`;
|
|
128
|
+
// Add retry escalation if this is a retry attempt
|
|
129
|
+
if (executionContext && executionContext.attempt > 1) {
|
|
130
|
+
userContent += getRetryEscalationMessage(executionContext);
|
|
131
|
+
}
|
|
132
|
+
messages.push({
|
|
133
|
+
role: 'user',
|
|
134
|
+
content: userContent
|
|
135
|
+
});
|
|
136
|
+
return messages;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get retry escalation message based on attempt number
|
|
140
|
+
* Progressively stronger messaging to enforce tool usage
|
|
141
|
+
*/
|
|
142
|
+
function getRetryEscalationMessage(executionContext) {
|
|
143
|
+
const { attempt, previous_failures } = executionContext;
|
|
144
|
+
let message = '\n\n---\n\n';
|
|
145
|
+
const hasStringError = previous_failures?.some(f => f.error.includes('Expected object output, got string'));
|
|
146
|
+
const hasMissingTool = previous_failures?.some(f => f.error.includes('Required tool'));
|
|
147
|
+
if (attempt === 2) {
|
|
148
|
+
message += `⚠️ **RETRY ATTEMPT ${attempt}**
|
|
149
|
+
|
|
150
|
+
Your previous attempt failed. Please review the errors below and fix the issues:
|
|
151
|
+
|
|
152
|
+
`;
|
|
153
|
+
previous_failures?.forEach((failure, idx) => {
|
|
154
|
+
message += `Attempt ${idx + 1}: ${failure.error}\n`;
|
|
155
|
+
if (failure.tool_calls_count === 0) {
|
|
156
|
+
message += ` → Problem: No tool calls were made. You need to use the available tools.\n`;
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
if (hasStringError) {
|
|
160
|
+
message += `\n⚠️ Your response was plain text, not JSON. Your FINAL message (after all tool calls) must be ONLY a raw JSON object — no explanations, no markdown.`;
|
|
161
|
+
}
|
|
162
|
+
if (hasMissingTool) {
|
|
163
|
+
message += `\n⚠️ You must use the required tools to make the actual changes, not just read or explore.`;
|
|
164
|
+
}
|
|
165
|
+
message += `\nMake sure to use the tools available to you to complete the task.`;
|
|
166
|
+
}
|
|
167
|
+
else if (attempt === 3) {
|
|
168
|
+
message += `🚨 **CRITICAL: RETRY ATTEMPT ${attempt}**
|
|
169
|
+
|
|
170
|
+
Multiple previous attempts have failed. This is your ${attempt}rd attempt.
|
|
171
|
+
|
|
172
|
+
Previous errors:
|
|
173
|
+
`;
|
|
174
|
+
previous_failures?.forEach((failure, idx) => {
|
|
175
|
+
message += `- Attempt ${idx + 1}: ${failure.error} (tool_calls: ${failure.tool_calls_count})\n`;
|
|
176
|
+
});
|
|
177
|
+
message += `
|
|
178
|
+
**YOU MUST:**
|
|
179
|
+
1. Use the available tools to make the requested changes — reading and exploring is NOT enough
|
|
180
|
+
2. After all tool calls are done, send ONE final message that is ONLY a raw JSON object
|
|
181
|
+
3. No markdown, no explanations, no code fences — just {"summary": "...", ...}
|
|
182
|
+
|
|
183
|
+
DO NOT just provide instructions or descriptions. EXECUTE the changes, then return JSON.`;
|
|
184
|
+
}
|
|
185
|
+
else if (attempt >= 4) {
|
|
186
|
+
message += `⛔ **FINAL WARNING: RETRY ATTEMPT ${attempt}**
|
|
187
|
+
|
|
188
|
+
This is attempt ${attempt}. Previous attempts all failed:
|
|
189
|
+
|
|
190
|
+
`;
|
|
191
|
+
previous_failures?.forEach((failure, idx) => {
|
|
192
|
+
message += `Attempt ${idx + 1}:\n Error: ${failure.error}\n Tool calls made: ${failure.tool_calls_count}\n\n`;
|
|
193
|
+
});
|
|
194
|
+
message += `
|
|
195
|
+
🔴 **ABSOLUTE REQUIREMENTS:**
|
|
196
|
+
|
|
197
|
+
1. Use the required tools to make the actual changes — DO NOT just describe them
|
|
198
|
+
2. tool_calls = 0 is an AUTOMATIC FAILURE
|
|
199
|
+
3. You must make ACTUAL changes, not describe them
|
|
200
|
+
4. Read existing files before modifying them
|
|
201
|
+
5. Your FINAL message must be ONLY a JSON object
|
|
202
|
+
6. If your final message contains ANY text outside the JSON, it WILL be rejected
|
|
203
|
+
|
|
204
|
+
If you do not make real tool calls AND return valid JSON, this task will fail permanently.`;
|
|
205
|
+
}
|
|
206
|
+
return message;
|
|
207
|
+
}
|
|
208
|
+
/** Known field type hints for required_fields schema injection */
|
|
209
|
+
const FIELD_TYPE_HINTS = {
|
|
210
|
+
summary: 'string',
|
|
211
|
+
requirements: 'array of objects, each with relevant keys (e.g. {id, description, priority})',
|
|
212
|
+
acceptance_criteria: 'array of strings',
|
|
213
|
+
files_changed: 'array of objects with {path, status, changes}',
|
|
214
|
+
files_to_modify: 'array of strings (file paths)',
|
|
215
|
+
steps: 'array of strings',
|
|
216
|
+
issues: 'array of strings or objects',
|
|
217
|
+
};
|
|
218
|
+
/** Known field example values for required_fields schema injection */
|
|
219
|
+
const FIELD_EXAMPLES = {
|
|
220
|
+
summary: '"A concise summary of the result"',
|
|
221
|
+
requirements: '[{"id": "REQ-1", "description": "...", "priority": "high"}]',
|
|
222
|
+
acceptance_criteria: '["criterion 1", "criterion 2"]',
|
|
223
|
+
files_changed: '[{"path": "src/file.tsx", "status": "modified", "changes": "description of changes"}]',
|
|
224
|
+
files_to_modify: '["src/file.tsx", "src/utils/helper.ts"]',
|
|
225
|
+
steps: '["step 1", "step 2", "step 3"]',
|
|
226
|
+
issues: '["issue 1", "issue 2"]',
|
|
227
|
+
};
|
|
228
|
+
const TOOL_RESULT_MAX_CHARS = 2000;
|
|
229
|
+
function renderToolResults(previous_tool_results) {
|
|
230
|
+
let out = '';
|
|
231
|
+
for (const [stage, toolCalls] of Object.entries(previous_tool_results)) {
|
|
232
|
+
out += `## Previous Stage Discoveries (${stage})\n\n`;
|
|
233
|
+
for (const tc of toolCalls) {
|
|
234
|
+
// Use first string argument value as the display label
|
|
235
|
+
const label = Object.values(tc.arguments).find(v => typeof v === 'string') ?? JSON.stringify(tc.arguments);
|
|
236
|
+
out += `### ${tc.name}(${label})\n`;
|
|
237
|
+
if (tc.error) {
|
|
238
|
+
out += `Error: ${tc.error}\n\n`;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
// For write operations, render the content being written from arguments
|
|
242
|
+
// (the result is just {written: true} which is not useful for reviewers).
|
|
243
|
+
// For all other operations, render the result as usual.
|
|
244
|
+
const writeContent = typeof tc.arguments?.content === 'string'
|
|
245
|
+
? tc.arguments.content
|
|
246
|
+
: null;
|
|
247
|
+
const raw = writeContent ?? JSON.stringify(tc.result, null, 2);
|
|
248
|
+
const body = raw.length > TOOL_RESULT_MAX_CHARS
|
|
249
|
+
? raw.slice(0, TOOL_RESULT_MAX_CHARS) + '\n[truncated]'
|
|
250
|
+
: raw;
|
|
251
|
+
out += `\`\`\`\n${body}\n\`\`\`\n\n`;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return out;
|
|
256
|
+
}
|
|
257
|
+
function getFieldTypeHint(field) {
|
|
258
|
+
return FIELD_TYPE_HINTS[field] || 'string';
|
|
259
|
+
}
|
|
260
|
+
function getFieldExample(field) {
|
|
261
|
+
return FIELD_EXAMPLES[field] || '"..."';
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=prompt-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-builder.js","sourceRoot":"","sources":["../src/prompt-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-builder.test.d.ts","sourceRoot":"","sources":["../src/prompt-builder.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const prompt_builder_js_1 = require("./prompt-builder.js");
|
|
5
|
+
const AGENT = {
|
|
6
|
+
name: 'test-agent',
|
|
7
|
+
provider: 'anthropic',
|
|
8
|
+
model: 'claude-haiku-4-5-20251001',
|
|
9
|
+
system_prompt: 'You are a helpful assistant.',
|
|
10
|
+
};
|
|
11
|
+
const TASK = { description: 'Do the thing.' };
|
|
12
|
+
(0, vitest_1.describe)('buildPrompt — previous_tool_results', () => {
|
|
13
|
+
(0, vitest_1.it)('renders write_file content from tc.arguments.content', () => {
|
|
14
|
+
const messages = (0, prompt_builder_js_1.buildPrompt)({
|
|
15
|
+
agent: AGENT,
|
|
16
|
+
task: TASK,
|
|
17
|
+
context: {
|
|
18
|
+
previous_tool_results: {
|
|
19
|
+
'code-generation': [
|
|
20
|
+
{
|
|
21
|
+
id: '1',
|
|
22
|
+
name: 'repo_manager-write_file',
|
|
23
|
+
arguments: { path: 'src/foo.ts', content: 'const x = 1;' },
|
|
24
|
+
result: { written: true },
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
const userMsg = messages.find(m => m.role === 'user').content;
|
|
31
|
+
(0, vitest_1.expect)(userMsg).toContain('Previous Stage Discoveries (code-generation)');
|
|
32
|
+
(0, vitest_1.expect)(userMsg).toContain('const x = 1;');
|
|
33
|
+
// Should NOT show the useless {written: true} result as the body
|
|
34
|
+
(0, vitest_1.expect)(userMsg).not.toContain('"written": true');
|
|
35
|
+
});
|
|
36
|
+
(0, vitest_1.it)('renders read_file content from tc.result', () => {
|
|
37
|
+
const messages = (0, prompt_builder_js_1.buildPrompt)({
|
|
38
|
+
agent: AGENT,
|
|
39
|
+
task: TASK,
|
|
40
|
+
context: {
|
|
41
|
+
previous_tool_results: {
|
|
42
|
+
'brief-analysis': [
|
|
43
|
+
{
|
|
44
|
+
id: '1',
|
|
45
|
+
name: 'repo_manager-read_file',
|
|
46
|
+
arguments: { path: 'src/foo.ts' },
|
|
47
|
+
result: { path: 'src/foo.ts', content: 'const y = 2;' },
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
const userMsg = messages.find(m => m.role === 'user').content;
|
|
54
|
+
(0, vitest_1.expect)(userMsg).toContain('Previous Stage Discoveries (brief-analysis)');
|
|
55
|
+
(0, vitest_1.expect)(userMsg).toContain('const y = 2;');
|
|
56
|
+
});
|
|
57
|
+
(0, vitest_1.it)('omits the section when previous_tool_results is absent', () => {
|
|
58
|
+
const messages = (0, prompt_builder_js_1.buildPrompt)({ agent: AGENT, task: TASK, context: {} });
|
|
59
|
+
const userMsg = messages.find(m => m.role === 'user').content;
|
|
60
|
+
(0, vitest_1.expect)(userMsg).not.toContain('Previous Stage Discoveries');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
(0, vitest_1.describe)('buildPrompt — startup_context', () => {
|
|
64
|
+
(0, vitest_1.it)('renders each startup_context key as a ### section under ## Pipeline Startup Context', () => {
|
|
65
|
+
const messages = (0, prompt_builder_js_1.buildPrompt)({
|
|
66
|
+
agent: AGENT,
|
|
67
|
+
task: TASK,
|
|
68
|
+
context: {
|
|
69
|
+
startup_context: {
|
|
70
|
+
git_status: 'M src/foo.ts',
|
|
71
|
+
recent_commits: 'abc123 feat: stuff',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
const userMsg = messages.find(m => m.role === 'user').content;
|
|
76
|
+
(0, vitest_1.expect)(userMsg).toContain('## Pipeline Startup Context');
|
|
77
|
+
(0, vitest_1.expect)(userMsg).toContain('### git_status');
|
|
78
|
+
(0, vitest_1.expect)(userMsg).toContain('M src/foo.ts');
|
|
79
|
+
(0, vitest_1.expect)(userMsg).toContain('### recent_commits');
|
|
80
|
+
(0, vitest_1.expect)(userMsg).toContain('abc123 feat: stuff');
|
|
81
|
+
});
|
|
82
|
+
(0, vitest_1.it)('omits the section when startup_context is absent', () => {
|
|
83
|
+
const messages = (0, prompt_builder_js_1.buildPrompt)({
|
|
84
|
+
agent: AGENT,
|
|
85
|
+
task: TASK,
|
|
86
|
+
context: {},
|
|
87
|
+
});
|
|
88
|
+
const userMsg = messages.find(m => m.role === 'user').content;
|
|
89
|
+
(0, vitest_1.expect)(userMsg).not.toContain('Pipeline Startup Context');
|
|
90
|
+
});
|
|
91
|
+
(0, vitest_1.it)('omits the section when startup_context is empty', () => {
|
|
92
|
+
const messages = (0, prompt_builder_js_1.buildPrompt)({
|
|
93
|
+
agent: AGENT,
|
|
94
|
+
task: TASK,
|
|
95
|
+
context: { startup_context: {} },
|
|
96
|
+
});
|
|
97
|
+
const userMsg = messages.find(m => m.role === 'user').content;
|
|
98
|
+
(0, vitest_1.expect)(userMsg).not.toContain('Pipeline Startup Context');
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
(0, vitest_1.describe)('buildPrompt — skills injection', () => {
|
|
102
|
+
(0, vitest_1.it)('injects a single skill into the system prompt', () => {
|
|
103
|
+
const skills = [
|
|
104
|
+
{ name: 'commit-conventions', content: '# Commit Conventions\n\nUse conventional commits.' },
|
|
105
|
+
];
|
|
106
|
+
const messages = (0, prompt_builder_js_1.buildPrompt)({ agent: AGENT, task: TASK, context: {}, skills });
|
|
107
|
+
const sysMsg = messages.find(m => m.role === 'system').content;
|
|
108
|
+
(0, vitest_1.expect)(sysMsg).toContain('## Skill: commit-conventions');
|
|
109
|
+
(0, vitest_1.expect)(sysMsg).toContain('Use conventional commits.');
|
|
110
|
+
});
|
|
111
|
+
(0, vitest_1.it)('injects multiple skills separated by ---', () => {
|
|
112
|
+
const skills = [
|
|
113
|
+
{ name: 'commit-conventions', content: 'Commit content.' },
|
|
114
|
+
{ name: 'react-patterns', content: 'React content.' },
|
|
115
|
+
];
|
|
116
|
+
const messages = (0, prompt_builder_js_1.buildPrompt)({ agent: AGENT, task: TASK, context: {}, skills });
|
|
117
|
+
const sysMsg = messages.find(m => m.role === 'system').content;
|
|
118
|
+
(0, vitest_1.expect)(sysMsg).toContain('## Skill: commit-conventions');
|
|
119
|
+
(0, vitest_1.expect)(sysMsg).toContain('## Skill: react-patterns');
|
|
120
|
+
(0, vitest_1.expect)(sysMsg).toContain('---');
|
|
121
|
+
});
|
|
122
|
+
(0, vitest_1.it)('omits skill section when skills array is empty', () => {
|
|
123
|
+
const messages = (0, prompt_builder_js_1.buildPrompt)({ agent: AGENT, task: TASK, context: {}, skills: [] });
|
|
124
|
+
const sysMsg = messages.find(m => m.role === 'system').content;
|
|
125
|
+
(0, vitest_1.expect)(sysMsg).not.toContain('## Skill:');
|
|
126
|
+
});
|
|
127
|
+
(0, vitest_1.it)('omits skill section when skills is not provided', () => {
|
|
128
|
+
const messages = (0, prompt_builder_js_1.buildPrompt)({ agent: AGENT, task: TASK, context: {} });
|
|
129
|
+
const sysMsg = messages.find(m => m.role === 'system').content;
|
|
130
|
+
(0, vitest_1.expect)(sysMsg).not.toContain('## Skill:');
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
(0, vitest_1.describe)('buildPrompt — stage_name', () => {
|
|
134
|
+
(0, vitest_1.it)('renders ## Stage Name section when stage_name is provided', () => {
|
|
135
|
+
const messages = (0, prompt_builder_js_1.buildPrompt)({
|
|
136
|
+
agent: AGENT,
|
|
137
|
+
task: TASK,
|
|
138
|
+
context: { stage_name: 'recipe-1' },
|
|
139
|
+
});
|
|
140
|
+
const userMsg = messages.find(m => m.role === 'user').content;
|
|
141
|
+
(0, vitest_1.expect)(userMsg).toContain('## Stage Name');
|
|
142
|
+
(0, vitest_1.expect)(userMsg).toContain('recipe-1');
|
|
143
|
+
});
|
|
144
|
+
(0, vitest_1.it)('does not render ## Stage Name when stage_name is absent', () => {
|
|
145
|
+
const messages = (0, prompt_builder_js_1.buildPrompt)({
|
|
146
|
+
agent: AGENT,
|
|
147
|
+
task: TASK,
|
|
148
|
+
context: {},
|
|
149
|
+
});
|
|
150
|
+
const userMsg = messages.find(m => m.role === 'user').content;
|
|
151
|
+
(0, vitest_1.expect)(userMsg).not.toContain('## Stage Name');
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
//# sourceMappingURL=prompt-builder.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-builder.test.js","sourceRoot":"","sources":["../src/prompt-builder.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic provider implementation with full tool calling support
|
|
3
|
+
*/
|
|
4
|
+
import type { LLMRequest, LLMResponse } from '@studio-foundation/contracts';
|
|
5
|
+
import type { Provider } from './provider.js';
|
|
6
|
+
export declare class AnthropicProvider implements Provider {
|
|
7
|
+
readonly name = "anthropic";
|
|
8
|
+
private client;
|
|
9
|
+
constructor(apiKey?: string);
|
|
10
|
+
call(request: LLMRequest, onToken?: (token: string) => void, signal?: AbortSignal): Promise<LLMResponse>;
|
|
11
|
+
private buildParams;
|
|
12
|
+
private parseResponse;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=anthropic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAU9C,qBAAa,iBAAkB,YAAW,QAAQ;IAChD,QAAQ,CAAC,IAAI,eAAe;IAC5B,OAAO,CAAC,MAAM,CAAY;gBAEd,MAAM,CAAC,EAAE,MAAM;IAMrB,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAsB9G,OAAO,CAAC,WAAW;IAkDnB,OAAO,CAAC,aAAa;CAqCtB"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Anthropic provider implementation with full tool calling support
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.AnthropicProvider = void 0;
|
|
10
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
11
|
+
const race_signal_js_1 = require("../utils/race-signal.js");
|
|
12
|
+
class AnthropicProvider {
|
|
13
|
+
name = 'anthropic';
|
|
14
|
+
client;
|
|
15
|
+
constructor(apiKey) {
|
|
16
|
+
this.client = new sdk_1.default({
|
|
17
|
+
apiKey: apiKey || process.env.ANTHROPIC_API_KEY
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
async call(request, onToken, signal) {
|
|
21
|
+
const params = this.buildParams(request);
|
|
22
|
+
if (onToken) {
|
|
23
|
+
// Streaming path
|
|
24
|
+
const stream = this.client.messages.stream(params, { signal });
|
|
25
|
+
stream.on('text', (textDelta) => {
|
|
26
|
+
if (signal?.aborted)
|
|
27
|
+
return; // guard: don't emit after abort
|
|
28
|
+
onToken(textDelta);
|
|
29
|
+
});
|
|
30
|
+
// KEY FIX: race finalMessage() against signal abort.
|
|
31
|
+
// Without this, finalMessage() hangs forever when the HTTP connection
|
|
32
|
+
// is killed mid-stream (the stream 'end' event never fires).
|
|
33
|
+
const response = await (0, race_signal_js_1.raceSignal)(stream.finalMessage(), signal);
|
|
34
|
+
return this.parseResponse(response);
|
|
35
|
+
}
|
|
36
|
+
// Non-streaming path
|
|
37
|
+
const response = await (0, race_signal_js_1.raceSignal)(this.client.messages.create(params, { signal }), signal);
|
|
38
|
+
return this.parseResponse(response);
|
|
39
|
+
}
|
|
40
|
+
buildParams(request) {
|
|
41
|
+
// Extract system messages (Anthropic handles them separately)
|
|
42
|
+
const systemMessages = request.messages.filter(m => m.role === 'system');
|
|
43
|
+
const systemContent = systemMessages.map(m => m.content).join('\n\n');
|
|
44
|
+
// Convert remaining messages to Anthropic format
|
|
45
|
+
const anthropicMessages = request.messages
|
|
46
|
+
.filter(m => m.role !== 'system')
|
|
47
|
+
.map(msg => {
|
|
48
|
+
if (msg.role === 'user') {
|
|
49
|
+
return { role: 'user', content: msg.content };
|
|
50
|
+
}
|
|
51
|
+
if (msg.role === 'assistant') {
|
|
52
|
+
return { role: 'assistant', content: msg.content };
|
|
53
|
+
}
|
|
54
|
+
throw new Error(`Unsupported message role: ${msg.role}`);
|
|
55
|
+
});
|
|
56
|
+
// Convert tool definitions to Anthropic format
|
|
57
|
+
// Mark the last tool with cache_control so Anthropic caches system + tools block
|
|
58
|
+
const rawTools = request.tools ?? [];
|
|
59
|
+
const tools = rawTools.length > 0
|
|
60
|
+
? rawTools.map((tool, index) => ({
|
|
61
|
+
name: tool.name,
|
|
62
|
+
description: tool.description,
|
|
63
|
+
input_schema: {
|
|
64
|
+
type: 'object',
|
|
65
|
+
...tool.parameters
|
|
66
|
+
},
|
|
67
|
+
...(index === rawTools.length - 1
|
|
68
|
+
? { cache_control: { type: 'ephemeral' } }
|
|
69
|
+
: {})
|
|
70
|
+
}))
|
|
71
|
+
: undefined;
|
|
72
|
+
// Mark system prompt with cache_control — stable across retries and group iterations
|
|
73
|
+
const systemParam = systemContent
|
|
74
|
+
? [{ type: 'text', text: systemContent, cache_control: { type: 'ephemeral' } }]
|
|
75
|
+
: undefined;
|
|
76
|
+
return {
|
|
77
|
+
model: request.model,
|
|
78
|
+
max_tokens: request.max_tokens || 4096,
|
|
79
|
+
system: systemParam,
|
|
80
|
+
messages: anthropicMessages,
|
|
81
|
+
tools: tools,
|
|
82
|
+
temperature: request.temperature
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
parseResponse(response) {
|
|
86
|
+
// Parse tool calls and text content from response
|
|
87
|
+
const tool_calls = [];
|
|
88
|
+
let textContent = '';
|
|
89
|
+
for (const block of response.content) {
|
|
90
|
+
if (block.type === 'text') {
|
|
91
|
+
textContent += block.text;
|
|
92
|
+
}
|
|
93
|
+
else if (block.type === 'tool_use') {
|
|
94
|
+
tool_calls.push({
|
|
95
|
+
id: block.id,
|
|
96
|
+
name: block.name,
|
|
97
|
+
arguments: block.input
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const cachedInputTokens = response.usage.cache_read_input_tokens ?? 0;
|
|
102
|
+
const cacheCreationTokens = response.usage.cache_creation_input_tokens ?? 0;
|
|
103
|
+
return {
|
|
104
|
+
content: textContent,
|
|
105
|
+
tool_calls,
|
|
106
|
+
finish_reason: response.stop_reason || 'stop',
|
|
107
|
+
usage: {
|
|
108
|
+
prompt_tokens: response.usage.input_tokens,
|
|
109
|
+
completion_tokens: response.usage.output_tokens,
|
|
110
|
+
total_tokens: response.usage.input_tokens + response.usage.output_tokens,
|
|
111
|
+
cached_input_tokens: cachedInputTokens > 0 ? cachedInputTokens : undefined,
|
|
112
|
+
cache_creation_tokens: cacheCreationTokens > 0 ? cacheCreationTokens : undefined
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.AnthropicProvider = AnthropicProvider;
|
|
118
|
+
//# sourceMappingURL=anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.test.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.test.ts"],"names":[],"mappings":""}
|