@purista/harness-anthropic 1.2.0 → 1.2.2

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.
Files changed (2) hide show
  1. package/dist/index.js +25 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -85,9 +85,11 @@ class AnthropicModelProvider extends BaseModelProvider {
85
85
  req.signal.throwIfAborted();
86
86
  const response = await createMessage(this.client, req, false, true);
87
87
  const toolUse = response.content?.find((block) => block.type === 'tool_use' && block.name === 'harness_response');
88
+ const toolCalls = withoutObjectTool(extractToolCalls(response, req, 'object'));
88
89
  const object = (toolUse?.input ?? parseJson(response.content?.filter((block) => block.type === 'text').map((block) => block.text).join('') || '{}', req, 'object'));
89
90
  return {
90
91
  object,
92
+ ...(toolCalls ? { toolCalls } : {}),
91
93
  usage: toUsage(response.usage?.input_tokens, response.usage?.output_tokens),
92
94
  finishReason: toFinishReason(response.stop_reason),
93
95
  raw: response
@@ -136,23 +138,35 @@ async function createMessage(client, req, stream, forceObject = false) {
136
138
  ...(req.defaults?.providerOptions ?? {}),
137
139
  ...(req.call?.providerOptions ?? {})
138
140
  };
139
- const { requestOptions, ...bodyOptions } = providerOptions;
141
+ const { requestOptions, tool_choice: providerToolChoice, ...bodyOptions } = providerOptions;
140
142
  const { system, messages } = toAnthropicMessages(req.messages);
141
- const tools = forceObject ? [toObjectTool(req)] : toTools(req.tools);
143
+ const modelTools = toTools(req.tools) ?? [];
144
+ const tools = forceObject ? [...modelTools, toObjectTool(req)] : modelTools;
145
+ const forceObjectTool = forceObject && modelTools.length === 0;
146
+ const toolChoice = anthropicToolChoice(providerToolChoice, forceObjectTool, req.call?.parallelToolCalls ?? req.defaults?.parallelToolCalls);
142
147
  return client.messages.create({
143
148
  model: req.model,
144
149
  messages,
145
150
  stream,
146
151
  max_tokens: req.call?.maxTokens ?? req.defaults?.maxTokens ?? 1024,
147
152
  ...(system ? { system } : {}),
148
- ...(tools ? { tools } : {}),
149
- ...(forceObject ? { tool_choice: { type: 'tool', name: 'harness_response' } } : {}),
150
- ...(req.call?.temperature ?? req.defaults?.temperature !== undefined ? { temperature: req.call?.temperature ?? req.defaults?.temperature } : {}),
151
- ...(req.call?.topP ?? req.defaults?.topP !== undefined ? { top_p: req.call?.topP ?? req.defaults?.topP } : {}),
152
- ...(req.call?.stopSequences ?? req.defaults?.stopSequences ? { stop_sequences: req.call?.stopSequences ?? req.defaults?.stopSequences } : {}),
153
+ ...(tools.length > 0 ? { tools } : {}),
154
+ ...(toolChoice ? { tool_choice: toolChoice } : {}),
155
+ ...((req.call?.temperature ?? req.defaults?.temperature) !== undefined ? { temperature: req.call?.temperature ?? req.defaults?.temperature } : {}),
156
+ ...((req.call?.topP ?? req.defaults?.topP) !== undefined ? { top_p: req.call?.topP ?? req.defaults?.topP } : {}),
157
+ ...((req.call?.stopSequences ?? req.defaults?.stopSequences) !== undefined ? { stop_sequences: req.call?.stopSequences ?? req.defaults?.stopSequences } : {}),
153
158
  ...bodyOptions
154
159
  }, { ...requestOptions, signal: req.signal });
155
160
  }
161
+ function anthropicToolChoice(providerToolChoice, forceObjectTool, parallelToolCalls) {
162
+ if (providerToolChoice !== undefined)
163
+ return providerToolChoice;
164
+ if (forceObjectTool)
165
+ return { type: 'tool', name: 'harness_response' };
166
+ if (parallelToolCalls === false)
167
+ return { type: 'auto', disable_parallel_tool_use: true };
168
+ return undefined;
169
+ }
156
170
  function toAnthropicMessages(messages) {
157
171
  const system = messages.filter((message) => message.role === 'system').map((message) => message.content).join('\n\n');
158
172
  const converted = messages.filter((message) => message.role !== 'system').map((message) => {
@@ -218,6 +232,10 @@ function extractToolCalls(response, req, method) {
218
232
  arguments: typeof call.input === 'string' ? parseJson(call.input, req, method) : call.input ?? {}
219
233
  }));
220
234
  }
235
+ function withoutObjectTool(calls) {
236
+ const filtered = calls?.filter((call) => call.name !== 'harness_response');
237
+ return filtered && filtered.length > 0 ? filtered : undefined;
238
+ }
221
239
  function parseJson(content, req, method) {
222
240
  try {
223
241
  return JSON.parse(content);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@purista/harness-anthropic",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Anthropic model provider adapter for @purista/harness.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",