@friendliai/ai-provider 1.0.0-beta.1 → 1.0.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/dist/index.mjs CHANGED
@@ -17,7 +17,6 @@ import {
17
17
  import {
18
18
  combineHeaders,
19
19
  createEventSourceResponseHandler,
20
- createJsonErrorResponseHandler as createJsonErrorResponseHandler2,
21
20
  createJsonResponseHandler,
22
21
  generateId,
23
22
  isParsableJson,
@@ -27,17 +26,88 @@ import {
27
26
  import { z as z2 } from "zod/v4";
28
27
 
29
28
  // src/friendli-error.ts
30
- import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils";
29
+ import { APICallError } from "@ai-sdk/provider";
30
+ import { safeParseJSON } from "@ai-sdk/provider-utils";
31
31
  import { z } from "zod/v4";
32
- var friendliaiErrorSchema = z.object({
32
+ var friendliErrorResponseSchema = z.object({
33
33
  message: z.string(),
34
- error: z.record(z.string(), z.any())
34
+ error: z.record(z.string(), z.any()).optional()
35
35
  });
36
+ var openAIStyleErrorResponseSchema = z.object({
37
+ error: z.object({
38
+ message: z.string()
39
+ }).loose()
40
+ }).loose();
41
+ var friendliaiErrorSchema = z.union([
42
+ // OpenAI/OpenRouter style error: { "error": { "message": "..." } }
43
+ openAIStyleErrorResponseSchema,
44
+ // Friendli style error: { "message": "...", "error": { ... } }
45
+ friendliErrorResponseSchema
46
+ ]);
36
47
  var friendliaiErrorStructure = {
37
48
  errorSchema: friendliaiErrorSchema,
38
- errorToMessage: (data) => data.message
49
+ errorToMessage: (data) => {
50
+ if (typeof data === "object" && data != null && "error" in data && typeof data.error === "object" && data.error != null && "message" in data.error && typeof data.error.message === "string") {
51
+ return data.error.message;
52
+ }
53
+ if (typeof data === "object" && data != null && "message" in data && typeof data.message === "string") {
54
+ return data.message;
55
+ }
56
+ return "Unknown error";
57
+ }
58
+ };
59
+ var friendliaiFailedResponseHandler = async ({
60
+ response,
61
+ url,
62
+ requestBodyValues
63
+ }) => {
64
+ const responseBody = await response.text();
65
+ const responseHeaders = {};
66
+ response.headers.forEach((value, key) => {
67
+ responseHeaders[key] = value;
68
+ });
69
+ const baseErrorOptions = {
70
+ url,
71
+ requestBodyValues,
72
+ statusCode: response.status,
73
+ responseHeaders,
74
+ responseBody
75
+ };
76
+ const trimmedBody = responseBody.trim();
77
+ if (trimmedBody === "") {
78
+ const fallback2 = response.statusText || `Request failed with status ${response.status}`;
79
+ return {
80
+ responseHeaders,
81
+ value: new APICallError({
82
+ message: fallback2,
83
+ ...baseErrorOptions
84
+ })
85
+ };
86
+ }
87
+ const parsedError = await safeParseJSON({
88
+ text: responseBody,
89
+ schema: friendliaiErrorSchema
90
+ });
91
+ if (parsedError.success) {
92
+ return {
93
+ responseHeaders,
94
+ value: new APICallError({
95
+ message: friendliaiErrorStructure.errorToMessage(parsedError.value),
96
+ data: parsedError.value,
97
+ ...baseErrorOptions
98
+ })
99
+ };
100
+ }
101
+ const fallback = trimmedBody || response.statusText || `Request failed with status ${response.status}`;
102
+ return {
103
+ responseHeaders,
104
+ value: new APICallError({
105
+ message: fallback,
106
+ cause: parsedError.error,
107
+ ...baseErrorOptions
108
+ })
109
+ };
39
110
  };
40
- var friendliaiFailedResponseHandler = createJsonErrorResponseHandler(friendliaiErrorStructure);
41
111
 
42
112
  // src/friendli-prepare-tools.ts
43
113
  import {
@@ -57,7 +127,9 @@ function prepareTools({
57
127
  for (const tool of tools) {
58
128
  if (tool.type === "provider") {
59
129
  openaiCompatTools.push({
60
- // NOTE: It would be better to use tool.name, but since ":" is replaced with "_", the following code is used instead
130
+ // NOTE: Friendli tool-assisted API expects provider tool types like "web:search".
131
+ // We derive it from the provider tool id (e.g. "friendli.web:search" -> "web:search")
132
+ // instead of tool.name (often "web_search").
61
133
  type: (_a = tool.id.split(".")[1]) != null ? _a : "unknown"
62
134
  });
63
135
  } else {
@@ -99,6 +171,28 @@ function prepareTools({
99
171
  }
100
172
 
101
173
  // src/friendli-chat-language-model.ts
174
+ function isRecord(value) {
175
+ return typeof value === "object" && value != null;
176
+ }
177
+ function isHostedToolExecutionChunk(value) {
178
+ if (!isRecord(value)) return false;
179
+ return typeof value.status === "string" && typeof value.name === "string" && Array.isArray(value.parameters);
180
+ }
181
+ function getChunkErrorMessage(value) {
182
+ if (!isRecord(value)) return void 0;
183
+ if (typeof value.message === "string") {
184
+ return value.message;
185
+ }
186
+ const nestedError = value.error;
187
+ if (isRecord(nestedError) && typeof nestedError.message === "string") {
188
+ return nestedError.message;
189
+ }
190
+ return void 0;
191
+ }
192
+ function isOpenAIChatChunk(value) {
193
+ if (!isRecord(value)) return false;
194
+ return Array.isArray(value.choices);
195
+ }
102
196
  var FriendliAIChatLanguageModel = class {
103
197
  // type inferred via constructor
104
198
  constructor(modelId, config) {
@@ -108,7 +202,7 @@ var FriendliAIChatLanguageModel = class {
108
202
  this.config = config;
109
203
  const errorStructure = friendliaiErrorStructure;
110
204
  this.chunkSchema = createOpenAICompatibleChatChunkSchema(errorStructure.errorSchema);
111
- this.failedResponseHandler = createJsonErrorResponseHandler2(friendliaiErrorStructure);
205
+ this.failedResponseHandler = friendliaiFailedResponseHandler;
112
206
  this.supportsStructuredOutputs = (_a = config.supportsStructuredOutputs) != null ? _a : true;
113
207
  }
114
208
  get provider() {
@@ -136,14 +230,20 @@ var FriendliAIChatLanguageModel = class {
136
230
  }) {
137
231
  var _a;
138
232
  const warnings = [];
139
- if (topK != null) {
140
- warnings.push({ type: "unsupported", feature: "topK" });
141
- }
142
233
  const friendliOptions = await parseProviderOptions({
234
+ provider: "friendliai",
235
+ providerOptions,
236
+ schema: friendliProviderOptionsSchema
237
+ });
238
+ const legacyFriendliOptions = await parseProviderOptions({
143
239
  provider: "friendli",
144
240
  providerOptions,
145
241
  schema: friendliProviderOptionsSchema
146
242
  });
243
+ const options = {
244
+ ...legacyFriendliOptions,
245
+ ...friendliOptions
246
+ };
147
247
  if ((responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && !this.supportsStructuredOutputs) {
148
248
  warnings.push({
149
249
  type: "unsupported",
@@ -159,6 +259,14 @@ var FriendliAIChatLanguageModel = class {
159
259
  tools,
160
260
  toolChoice
161
261
  });
262
+ const isToolsPresent = openaiTools != null && openaiTools.length > 0;
263
+ if (isToolsPresent && (responseFormat != null || (options == null ? void 0 : options.regex) != null)) {
264
+ warnings.push({
265
+ type: "unsupported",
266
+ feature: "responseFormat",
267
+ details: "response_format is not supported when tools are present."
268
+ });
269
+ }
162
270
  return {
163
271
  args: {
164
272
  // >>> hard-coded default options >>>
@@ -170,36 +278,39 @@ var FriendliAIChatLanguageModel = class {
170
278
  max_tokens: maxOutputTokens,
171
279
  temperature,
172
280
  top_p: topP,
281
+ top_k: topK,
173
282
  frequency_penalty: frequencyPenalty,
174
283
  presence_penalty: presencePenalty,
175
- response_format: (responseFormat == null ? void 0 : responseFormat.type) === "json" ? this.supportsStructuredOutputs === true && responseFormat.schema != null ? {
284
+ response_format: isToolsPresent === false ? (responseFormat == null ? void 0 : responseFormat.type) === "json" ? this.supportsStructuredOutputs === true && responseFormat.schema != null ? {
176
285
  type: "json_schema",
177
286
  json_schema: {
178
287
  schema: responseFormat.schema,
179
288
  name: (_a = responseFormat.name) != null ? _a : "response",
180
289
  description: responseFormat.description
181
290
  }
182
- } : { type: "json_object" } : (friendliOptions == null ? void 0 : friendliOptions.regex) != null ? {
291
+ } : { type: "json_object" } : (options == null ? void 0 : options.regex) != null ? {
183
292
  type: "regex",
184
- schema: friendliOptions.regex
185
- } : void 0,
293
+ schema: options.regex
294
+ } : void 0 : void 0,
186
295
  stop: stopSequences,
187
296
  seed,
188
- ...(friendliOptions == null ? void 0 : friendliOptions.chat_template_kwargs) ? { chat_template_kwargs: friendliOptions.chat_template_kwargs } : {},
189
- // ...providerOptions?.[this.providerOptionsName],
190
- // reasoning_effort: compatibleOptions.reasoningEffort,
297
+ min_p: options == null ? void 0 : options.minP,
298
+ repetition_penalty: options == null ? void 0 : options.repetitionPenalty,
299
+ xtc_threshold: options == null ? void 0 : options.xtcThreshold,
300
+ xtc_probability: options == null ? void 0 : options.xtcProbability,
301
+ ...(options == null ? void 0 : options.chat_template_kwargs) ? { chat_template_kwargs: options.chat_template_kwargs } : {},
191
302
  // messages:
192
303
  messages: convertToOpenAICompatibleChatMessages(prompt),
193
304
  // tools:
194
305
  tools: openaiTools,
195
306
  tool_choice: openaiToolChoice,
196
- parallel_tool_calls: friendliOptions == null ? void 0 : friendliOptions.parallelToolCalls
307
+ parallel_tool_calls: options == null ? void 0 : options.parallelToolCalls
197
308
  },
198
309
  warnings: [...warnings, ...toolWarnings]
199
310
  };
200
311
  }
201
312
  async doGenerate(options) {
202
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
313
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
203
314
  const { args, warnings } = await this.getArgs({ ...options, stream: false });
204
315
  const body = JSON.stringify(args);
205
316
  const {
@@ -243,18 +354,21 @@ var FriendliAIChatLanguageModel = class {
243
354
  }
244
355
  return {
245
356
  content,
246
- finishReason: mapOpenAICompatibleFinishReason(choice.finish_reason),
357
+ finishReason: {
358
+ unified: mapOpenAICompatibleFinishReason(choice.finish_reason),
359
+ raw: (_b = choice.finish_reason) != null ? _b : void 0
360
+ },
247
361
  usage: {
248
362
  inputTokens: {
249
- total: (_c = (_b = responseBody.usage) == null ? void 0 : _b.prompt_tokens) != null ? _c : void 0,
363
+ total: (_d = (_c = responseBody.usage) == null ? void 0 : _c.prompt_tokens) != null ? _d : void 0,
250
364
  noCache: void 0,
251
- cacheRead: (_f = (_e = (_d = responseBody.usage) == null ? void 0 : _d.prompt_tokens_details) == null ? void 0 : _e.cached_tokens) != null ? _f : void 0,
365
+ cacheRead: (_g = (_f = (_e = responseBody.usage) == null ? void 0 : _e.prompt_tokens_details) == null ? void 0 : _f.cached_tokens) != null ? _g : void 0,
252
366
  cacheWrite: void 0
253
367
  },
254
368
  outputTokens: {
255
- total: (_h = (_g = responseBody.usage) == null ? void 0 : _g.completion_tokens) != null ? _h : void 0,
369
+ total: (_i = (_h = responseBody.usage) == null ? void 0 : _h.completion_tokens) != null ? _i : void 0,
256
370
  text: void 0,
257
- reasoning: (_k = (_j = (_i = responseBody.usage) == null ? void 0 : _i.completion_tokens_details) == null ? void 0 : _j.reasoning_tokens) != null ? _k : void 0
371
+ reasoning: (_l = (_k = (_j = responseBody.usage) == null ? void 0 : _j.completion_tokens_details) == null ? void 0 : _k.reasoning_tokens) != null ? _l : void 0
258
372
  }
259
373
  },
260
374
  // providerMetadata,
@@ -290,7 +404,8 @@ var FriendliAIChatLanguageModel = class {
290
404
  fetch: this.config.fetch
291
405
  });
292
406
  const toolCalls = [];
293
- let finishReason = "unknown";
407
+ let finishReason = "other";
408
+ let rawFinishReason;
294
409
  const usage = {
295
410
  completionTokens: void 0,
296
411
  completionTokensDetails: {
@@ -312,9 +427,10 @@ var FriendliAIChatLanguageModel = class {
312
427
  start(controller) {
313
428
  controller.enqueue({ type: "stream-start", warnings });
314
429
  },
315
- // TODO we lost type safety on Chunk, most likely due to the error schema. MUST FIX
430
+ // NOTE: Chunk values can contain OpenAI-compatible deltas, hosted tool events, and error events.
431
+ // We narrow with type guards for safe handling.
316
432
  transform(chunk, controller) {
317
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
433
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
318
434
  if (!chunk.success) {
319
435
  finishReason = "error";
320
436
  controller.enqueue({ type: "error", error: chunk.error });
@@ -322,7 +438,7 @@ var FriendliAIChatLanguageModel = class {
322
438
  }
323
439
  const value = chunk.value;
324
440
  metadataExtractor == null ? void 0 : metadataExtractor.processChunk(chunk.rawValue);
325
- if ("status" in value) {
441
+ if (isHostedToolExecutionChunk(value)) {
326
442
  const toolCallId = (_a2 = value.tool_call_id) != null ? _a2 : generateId();
327
443
  switch (value.status) {
328
444
  case "STARTED":
@@ -365,26 +481,36 @@ var FriendliAIChatLanguageModel = class {
365
481
  }
366
482
  return;
367
483
  }
368
- if ("error" in value) {
484
+ const chunkErrorMessage = getChunkErrorMessage(value);
485
+ if (chunkErrorMessage != null) {
369
486
  finishReason = "error";
370
- controller.enqueue({ type: "error", error: value.error.message });
487
+ controller.enqueue({ type: "error", error: chunkErrorMessage });
371
488
  return;
372
489
  }
490
+ if (!isOpenAIChatChunk(value)) {
491
+ finishReason = "error";
492
+ controller.enqueue({
493
+ type: "error",
494
+ error: new Error("Unsupported chunk shape")
495
+ });
496
+ return;
497
+ }
498
+ const chunkValue = value;
373
499
  if (isFirstChunk) {
374
500
  isFirstChunk = false;
375
501
  controller.enqueue({
376
502
  type: "response-metadata",
377
- ...getResponseMetadata(value)
503
+ ...getResponseMetadata(chunkValue)
378
504
  });
379
505
  }
380
- if (value.usage != null) {
506
+ if (chunkValue.usage != null) {
381
507
  const {
382
508
  prompt_tokens,
383
509
  completion_tokens,
384
510
  total_tokens,
385
511
  prompt_tokens_details,
386
512
  completion_tokens_details
387
- } = value.usage;
513
+ } = chunkValue.usage;
388
514
  usage.promptTokens = prompt_tokens != null ? prompt_tokens : void 0;
389
515
  usage.completionTokens = completion_tokens != null ? completion_tokens : void 0;
390
516
  usage.totalTokens = total_tokens != null ? total_tokens : void 0;
@@ -401,8 +527,9 @@ var FriendliAIChatLanguageModel = class {
401
527
  usage.promptTokensDetails.cachedTokens = prompt_tokens_details == null ? void 0 : prompt_tokens_details.cached_tokens;
402
528
  }
403
529
  }
404
- const choice = value.choices[0];
530
+ const choice = chunkValue.choices[0];
405
531
  if ((choice == null ? void 0 : choice.finish_reason) != null) {
532
+ rawFinishReason = choice.finish_reason;
406
533
  finishReason = mapOpenAICompatibleFinishReason(choice.finish_reason);
407
534
  }
408
535
  if ((choice == null ? void 0 : choice.delta) == null) {
@@ -485,12 +612,12 @@ var FriendliAIChatLanguageModel = class {
485
612
  controller.enqueue({
486
613
  type: "tool-input-delta",
487
614
  id: toolCall.id,
488
- delta: (_m = toolCallDelta.function.arguments) != null ? _m : ""
615
+ delta: (_n = (_m = toolCallDelta.function) == null ? void 0 : _m.arguments) != null ? _n : ""
489
616
  });
490
- if (((_n = toolCall.function) == null ? void 0 : _n.name) != null && ((_o = toolCall.function) == null ? void 0 : _o.arguments) != null && isParsableJson(toolCall.function.arguments)) {
617
+ if (((_o = toolCall.function) == null ? void 0 : _o.name) != null && ((_p = toolCall.function) == null ? void 0 : _p.arguments) != null && isParsableJson(toolCall.function.arguments)) {
491
618
  controller.enqueue({
492
619
  type: "tool-call",
493
- toolCallId: (_p = toolCall.id) != null ? _p : generateId(),
620
+ toolCallId: (_q = toolCall.id) != null ? _q : generateId(),
494
621
  toolName: toolCall.function.name,
495
622
  input: toolCall.function.arguments
496
623
  });
@@ -513,7 +640,10 @@ var FriendliAIChatLanguageModel = class {
513
640
  }
514
641
  controller.enqueue({
515
642
  type: "finish",
516
- finishReason,
643
+ finishReason: {
644
+ unified: finishReason,
645
+ raw: rawFinishReason
646
+ },
517
647
  usage: {
518
648
  inputTokens: {
519
649
  total: (_a2 = usage.promptTokens) != null ? _a2 : void 0,
@@ -537,86 +667,6 @@ var FriendliAIChatLanguageModel = class {
537
667
  };
538
668
  }
539
669
  };
540
- var friendliAIChatResponseSchema = z2.object({
541
- id: z2.string().nullish(),
542
- created: z2.number().nullish(),
543
- model: z2.string().nullish(),
544
- choices: z2.array(
545
- z2.object({
546
- message: z2.object({
547
- role: z2.literal("assistant").nullish(),
548
- content: z2.string().nullish(),
549
- tool_calls: z2.array(
550
- z2.object({
551
- id: z2.string().nullish(),
552
- type: z2.literal("function"),
553
- function: z2.object({
554
- name: z2.string(),
555
- arguments: z2.union([z2.string(), z2.any()]).nullish()
556
- })
557
- })
558
- ).nullish()
559
- }),
560
- finish_reason: z2.string().nullish()
561
- })
562
- ),
563
- usage: z2.object({
564
- prompt_tokens: z2.number().nullish(),
565
- completion_tokens: z2.number().nullish()
566
- }).nullish()
567
- });
568
- var friendliaiChatChunkSchema = z2.union([
569
- z2.object({
570
- id: z2.string().nullish(),
571
- created: z2.number().nullish(),
572
- model: z2.string().nullish(),
573
- choices: z2.array(
574
- z2.object({
575
- delta: z2.object({
576
- role: z2.enum(["assistant"]).nullish(),
577
- content: z2.string().nullish(),
578
- tool_calls: z2.array(
579
- z2.object({
580
- index: z2.number(),
581
- id: z2.string().nullish(),
582
- type: z2.literal("function").optional(),
583
- function: z2.object({
584
- name: z2.string().nullish(),
585
- arguments: z2.string().nullish()
586
- })
587
- })
588
- ).nullish()
589
- }).nullish(),
590
- finish_reason: z2.string().nullish()
591
- })
592
- ),
593
- usage: z2.object({
594
- prompt_tokens: z2.number().nullish(),
595
- completion_tokens: z2.number().nullish()
596
- }).nullish()
597
- }),
598
- z2.object({
599
- name: z2.string(),
600
- status: z2.enum(["ENDED", "STARTED", "ERRORED", "UPDATING"]),
601
- message: z2.null(),
602
- parameters: z2.array(
603
- z2.object({
604
- name: z2.string(),
605
- value: z2.string()
606
- })
607
- ),
608
- result: z2.string().nullable(),
609
- error: z2.object({
610
- type: z2.enum(["INVALID_PARAMETER", "UNKNOWN"]),
611
- msg: z2.string()
612
- }).nullable(),
613
- timestamp: z2.number(),
614
- usage: z2.null(),
615
- tool_call_id: z2.string().nullable()
616
- // temporary fix for "file:text" tool calls
617
- }),
618
- friendliaiErrorSchema
619
- ]);
620
670
  var openaiCompatibleTokenUsageSchema = z2.object({
621
671
  prompt_tokens: z2.number().nullish(),
622
672
  completion_tokens: z2.number().nullish(),
@@ -715,7 +765,23 @@ var friendliProviderOptionsSchema = z2.object({
715
765
  */
716
766
  // regex: z.instanceof(RegExp).nullish(),
717
767
  regex: z2.string().nullish(),
718
- chat_template_kwargs: z2.record(z2.string(), z2.any()).nullish()
768
+ chat_template_kwargs: z2.record(z2.string(), z2.any()).nullish(),
769
+ /**
770
+ * A scaling factor used to determine the minimum token probability threshold.
771
+ */
772
+ minP: z2.number().nullish(),
773
+ /**
774
+ * Penalizes tokens that have already appeared in the generated result.
775
+ */
776
+ repetitionPenalty: z2.number().nullish(),
777
+ /**
778
+ * A probability threshold used to identify “top choice” tokens for exclusion in XTC sampling.
779
+ */
780
+ xtcThreshold: z2.number().nullish(),
781
+ /**
782
+ * The probability that XTC (Exclude Top Choices) filtering will be applied for each sampling decision.
783
+ */
784
+ xtcProbability: z2.number().nullish()
719
785
  });
720
786
 
721
787
  // src/friendli-settings.ts
@@ -745,54 +811,65 @@ var FriendliAIServerlessModelIds = [
745
811
  ];
746
812
 
747
813
  // src/friendli-tools.ts
748
- import { jsonSchema } from "@ai-sdk/provider-utils";
814
+ import { createProviderToolFactoryWithOutputSchema } from "@ai-sdk/provider-utils";
815
+ import { z as z3 } from "zod/v4";
816
+ var inputSchema = z3.object({}).loose();
817
+ var outputSchema = z3.unknown();
818
+ var webSearchTool = createProviderToolFactoryWithOutputSchema({
819
+ id: "friendli.web:search",
820
+ inputSchema,
821
+ outputSchema
822
+ });
823
+ var webUrlTool = createProviderToolFactoryWithOutputSchema({
824
+ id: "friendli.web:url",
825
+ inputSchema,
826
+ outputSchema
827
+ });
828
+ var mathCalendarTool = createProviderToolFactoryWithOutputSchema({
829
+ id: "friendli.math:calendar",
830
+ inputSchema,
831
+ outputSchema
832
+ });
833
+ var mathStatisticsTool = createProviderToolFactoryWithOutputSchema({
834
+ id: "friendli.math:statistics",
835
+ inputSchema,
836
+ outputSchema
837
+ });
838
+ var mathCalculatorTool = createProviderToolFactoryWithOutputSchema({
839
+ id: "friendli.math:calculator",
840
+ inputSchema,
841
+ outputSchema
842
+ });
843
+ var codePythonInterpreterTool = createProviderToolFactoryWithOutputSchema({
844
+ id: "friendli.code:python-interpreter",
845
+ inputSchema,
846
+ outputSchema
847
+ });
848
+ var linkupSearchTool = createProviderToolFactoryWithOutputSchema({
849
+ id: "friendli.linkup:search",
850
+ inputSchema,
851
+ outputSchema
852
+ });
749
853
  function webSearch() {
750
- return {
751
- type: "provider",
752
- id: "friendli.web:search",
753
- args: {},
754
- inputSchema: jsonSchema({ type: "object", properties: {} })
755
- };
854
+ return webSearchTool({});
756
855
  }
757
856
  function webUrl() {
758
- return {
759
- type: "provider",
760
- id: "friendli.web:url",
761
- args: {},
762
- inputSchema: jsonSchema({ type: "object", properties: {} })
763
- };
857
+ return webUrlTool({});
764
858
  }
765
859
  function mathCalendar() {
766
- return {
767
- type: "provider",
768
- id: "friendli.math:calendar",
769
- args: {},
770
- inputSchema: jsonSchema({ type: "object", properties: {} })
771
- };
860
+ return mathCalendarTool({});
772
861
  }
773
862
  function mathStatistics() {
774
- return {
775
- type: "provider",
776
- id: "friendli.math:statistics",
777
- args: {},
778
- inputSchema: jsonSchema({ type: "object", properties: {} })
779
- };
863
+ return mathStatisticsTool({});
780
864
  }
781
865
  function mathCalculator() {
782
- return {
783
- type: "provider",
784
- id: "friendli.math:calculator",
785
- args: {},
786
- inputSchema: jsonSchema({ type: "object", properties: {} })
787
- };
866
+ return mathCalculatorTool({});
788
867
  }
789
868
  function codePythonInterpreter() {
790
- return {
791
- type: "provider",
792
- id: "friendli.code:python-interpreter",
793
- args: {},
794
- inputSchema: jsonSchema({ type: "object", properties: {} })
795
- };
869
+ return codePythonInterpreterTool({});
870
+ }
871
+ function linkupSearch() {
872
+ return linkupSearchTool({});
796
873
  }
797
874
  var friendliTools = {
798
875
  webSearch,
@@ -800,7 +877,8 @@ var friendliTools = {
800
877
  mathCalendar,
801
878
  mathStatistics,
802
879
  mathCalculator,
803
- codePythonInterpreter
880
+ codePythonInterpreter,
881
+ linkupSearch
804
882
  };
805
883
 
806
884
  // src/get-available-models.ts
@@ -967,7 +1045,8 @@ function createFriendli(options = {}) {
967
1045
  provider: `friendliai.${type}.chat`,
968
1046
  url: ({ path }) => `${baseURL}${path}`,
969
1047
  headers: getHeaders,
970
- fetch: options.fetch
1048
+ fetch: options.fetch,
1049
+ includeUsage: options.includeUsage
971
1050
  });
972
1051
  };
973
1052
  const createCompletionModel = (modelId) => {