@threaded/ai 1.0.2 → 1.0.3

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.js CHANGED
@@ -1,29 +1,14 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
1
  // src/schema.ts
2
+ import { z } from "zod";
9
3
  var isStandardSchema = (schema) => {
10
4
  return schema && typeof schema === "object" && "~standard" in schema;
11
5
  };
12
6
  var convertStandardSchemaToJsonSchema = (standardSchema, name = "Schema") => {
13
- try {
14
- const zodModule = __require("zod");
15
- if (zodModule && typeof zodModule.toJSONSchema === "function") {
16
- const jsonSchema = zodModule.toJSONSchema(standardSchema);
17
- return {
18
- name,
19
- schema: jsonSchema
20
- };
21
- }
22
- } catch (error) {
23
- }
24
- throw new Error(
25
- "Standard Schema conversion requires zod v4+ with toJSONSchema support. Please install zod@^4.0.0 or provide a JsonSchema object instead."
26
- );
7
+ const jsonSchema = z.toJSONSchema(standardSchema);
8
+ return {
9
+ name,
10
+ schema: jsonSchema
11
+ };
27
12
  };
28
13
  var convertMCPSchemaToToolSchema = (mcpSchema) => {
29
14
  if (!mcpSchema?.properties) return {};
@@ -44,6 +29,10 @@ function normalizeSchema(schema, name) {
44
29
  }
45
30
  return schema;
46
31
  }
32
+ var convertStandardSchemaToSchemaProperties = (standardSchema) => {
33
+ const jsonSchema = z.toJSONSchema(standardSchema);
34
+ return convertMCPSchemaToToolSchema(jsonSchema);
35
+ };
47
36
 
48
37
  // src/mcp.ts
49
38
  var createMCPTools = async (client) => {
@@ -82,9 +71,10 @@ var Inherit = /* @__PURE__ */ ((Inherit2) => {
82
71
 
83
72
  // src/utils.ts
84
73
  var toolConfigToToolDefinition = (tool) => {
74
+ const schema = isStandardSchema(tool.schema) ? convertStandardSchemaToSchemaProperties(tool.schema) : tool.schema;
85
75
  const properties = {};
86
76
  const required = [];
87
- for (const [key, prop] of Object.entries(tool.schema)) {
77
+ for (const [key, prop] of Object.entries(schema)) {
88
78
  properties[key] = convertSchemaProperty(prop);
89
79
  if (!prop.optional) {
90
80
  required.push(key);
@@ -150,6 +140,49 @@ var maxCalls = (toolConfig, maxCalls2) => ({
150
140
  _maxCalls: maxCalls2
151
141
  });
152
142
 
143
+ // src/embed.ts
144
+ import { pipeline } from "@huggingface/transformers";
145
+ var modelCache = /* @__PURE__ */ new Map();
146
+ var embed = async (model2, text, config) => {
147
+ if (model2.startsWith("openai/")) {
148
+ const modelName = model2.replace("openai/", "");
149
+ const apiKey = getKey("openai") || process.env.OPENAI_API_KEY;
150
+ if (!apiKey) {
151
+ throw new Error("OpenAI API key not found");
152
+ }
153
+ const body = {
154
+ model: modelName,
155
+ input: text
156
+ };
157
+ if (config?.dimensions) {
158
+ body.dimensions = config.dimensions;
159
+ }
160
+ const response = await fetch("https://api.openai.com/v1/embeddings", {
161
+ method: "POST",
162
+ headers: {
163
+ "Content-Type": "application/json",
164
+ Authorization: `Bearer ${apiKey}`
165
+ },
166
+ body: JSON.stringify(body)
167
+ });
168
+ if (!response.ok) {
169
+ const error = await response.text();
170
+ throw new Error(`OpenAI API error: ${error}`);
171
+ }
172
+ const data = await response.json();
173
+ return data.data[0].embedding;
174
+ }
175
+ if (!modelCache.has(model2)) {
176
+ const extractor2 = await pipeline("feature-extraction", model2, {
177
+ dtype: "fp32"
178
+ });
179
+ modelCache.set(model2, extractor2);
180
+ }
181
+ const extractor = modelCache.get(model2);
182
+ const result = await extractor(text, { pooling: "mean", normalize: true });
183
+ return Array.from(result.data);
184
+ };
185
+
153
186
  // src/providers/openai.ts
154
187
  var appendToolCalls = (toolCalls, tcchunklist) => {
155
188
  for (const tcchunk of tcchunklist) {
@@ -281,18 +314,66 @@ var handleOpenAIStream = async (response, ctx) => {
281
314
  };
282
315
 
283
316
  // src/providers/anthropic.ts
317
+ var convertToAnthropicFormat = (messages) => {
318
+ const result = [];
319
+ let i = 0;
320
+ while (i < messages.length) {
321
+ const msg = messages[i];
322
+ if (msg.role === "system") {
323
+ i++;
324
+ continue;
325
+ }
326
+ if (msg.role === "assistant") {
327
+ if (msg.tool_calls) {
328
+ result.push({
329
+ role: "assistant",
330
+ content: msg.tool_calls.map((tc) => ({
331
+ type: "tool_use",
332
+ id: tc.id,
333
+ name: tc.function.name,
334
+ input: JSON.parse(tc.function.arguments)
335
+ }))
336
+ });
337
+ } else {
338
+ result.push({
339
+ role: "assistant",
340
+ content: msg.content
341
+ });
342
+ }
343
+ i++;
344
+ } else if (msg.role === "tool") {
345
+ const toolResults = [];
346
+ while (i < messages.length && messages[i].role === "tool") {
347
+ const toolMsg = messages[i];
348
+ toolResults.push({
349
+ type: "tool_result",
350
+ tool_use_id: toolMsg.tool_call_id,
351
+ content: toolMsg.content
352
+ });
353
+ i++;
354
+ }
355
+ result.push({
356
+ role: "user",
357
+ content: toolResults
358
+ });
359
+ } else {
360
+ result.push(msg);
361
+ i++;
362
+ }
363
+ }
364
+ return result;
365
+ };
284
366
  var callAnthropic = async (config, ctx) => {
285
367
  const { model: model2, instructions, schema } = config;
286
368
  const apiKey = getKey("anthropic") || process.env.ANTHROPIC_API_KEY;
287
369
  if (!apiKey) {
288
370
  throw new Error("Anthropic API key not found");
289
371
  }
290
- const messages = [...ctx.history];
291
372
  let system = instructions;
292
- if (messages[0]?.role === "system") {
293
- system = messages[0].content;
294
- messages.shift();
373
+ if (ctx.history[0]?.role === "system") {
374
+ system = ctx.history[0].content;
295
375
  }
376
+ const messages = convertToAnthropicFormat(ctx.history);
296
377
  if (schema) {
297
378
  const schemaPrompt = `
298
379
 
@@ -394,10 +475,17 @@ var handleAnthropicStream = async (response, ctx) => {
394
475
  type: "function",
395
476
  function: {
396
477
  name: toolUse.name,
397
- arguments: JSON.stringify(toolUse.input)
398
- }
478
+ arguments: ""
479
+ },
480
+ index: parsed.index
399
481
  });
400
482
  }
483
+ if (parsed.type === "content_block_delta" && parsed.delta?.type === "input_json_delta") {
484
+ const toolCall = toolCalls.find((tc) => tc.index === parsed.index);
485
+ if (toolCall) {
486
+ toolCall.function.arguments += parsed.delta.partial_json;
487
+ }
488
+ }
401
489
  } catch (e) {
402
490
  }
403
491
  }
@@ -411,7 +499,7 @@ var handleAnthropicStream = async (response, ctx) => {
411
499
  content: fullContent
412
500
  };
413
501
  if (toolCalls.length > 0) {
414
- msg.tool_calls = toolCalls;
502
+ msg.tool_calls = toolCalls.map(({ index, ...tc }) => tc);
415
503
  }
416
504
  return {
417
505
  ...ctx,
@@ -633,7 +721,7 @@ var model = ({
633
721
  tools: []
634
722
  }
635
723
  ) : (
636
- // model()(/* few shot / history */);
724
+ // model()(/* few shot or history */);
637
725
  ctxOrMessage
638
726
  );
639
727
  const normalizedSchema = schema ? normalizeSchema(schema) : void 0;
@@ -664,27 +752,12 @@ var executeTools = async (ctx) => {
664
752
  approvalCallback,
665
753
  parallel = false,
666
754
  retryCount = 0,
667
- approvalId
755
+ approvalId,
756
+ executeOnApproval = false
668
757
  } = toolConfig;
669
- const approvalPromises = calls.map(async (call) => {
670
- if (requireApproval) {
671
- let approved;
672
- if (approvalCallback) {
673
- approved = await approvalCallback(call);
674
- } else {
675
- const response = await requestApproval(call, approvalId);
676
- approved = response.approved;
677
- }
678
- return { call, approved };
679
- } else {
680
- return { call, approved: true };
681
- }
682
- });
683
- const approvals = await Promise.all(approvalPromises);
684
758
  const updatedCounts = { ...ctx.toolCallCounts || {} };
685
- const runCall = async (call) => {
686
- const approval = approvals.find((a) => a.call.id === call.id);
687
- if (!approval?.approved) {
759
+ const runCall = async (call, approved) => {
760
+ if (!approved) {
688
761
  if (ctx.stream) {
689
762
  ctx.stream({
690
763
  type: "tool_error",
@@ -745,7 +818,51 @@ var executeTools = async (ctx) => {
745
818
  }
746
819
  return { call, result: { error } };
747
820
  };
748
- const results = parallel ? await Promise.all(calls.map(runCall)) : await runCallsSequentially(calls, runCall);
821
+ if (executeOnApproval && requireApproval) {
822
+ const resultPromises = calls.map(async (call) => {
823
+ let approved;
824
+ if (approvalCallback) {
825
+ approved = await approvalCallback(call);
826
+ } else {
827
+ const response = await requestApproval(call, approvalId);
828
+ approved = response.approved;
829
+ }
830
+ return runCall(call, approved);
831
+ });
832
+ const results2 = await Promise.all(resultPromises);
833
+ return {
834
+ ...ctx,
835
+ history: [
836
+ ...ctx.history,
837
+ ...results2.map(({ call, result }) => ({
838
+ role: "tool",
839
+ tool_call_id: call.id,
840
+ content: JSON.stringify(result)
841
+ }))
842
+ ],
843
+ toolCallCounts: updatedCounts
844
+ };
845
+ }
846
+ const approvalPromises = calls.map(async (call) => {
847
+ if (requireApproval) {
848
+ let approved;
849
+ if (approvalCallback) {
850
+ approved = await approvalCallback(call);
851
+ } else {
852
+ const response = await requestApproval(call, approvalId);
853
+ approved = response.approved;
854
+ }
855
+ return { call, approved };
856
+ } else {
857
+ return { call, approved: true };
858
+ }
859
+ });
860
+ const approvals = await Promise.all(approvalPromises);
861
+ const runCallWithApproval = async (call) => {
862
+ const approval = approvals.find((a) => a.call.id === call.id);
863
+ return runCall(call, approval?.approved ?? true);
864
+ };
865
+ const results = parallel ? await Promise.all(calls.map(runCallWithApproval)) : await runCallsSequentially(calls, runCallWithApproval);
749
866
  return {
750
867
  ...ctx,
751
868
  history: [
@@ -1074,13 +1191,68 @@ var scope = (config, ...steps) => {
1074
1191
  };
1075
1192
  };
1076
1193
  };
1194
+
1195
+ // src/utils/rateLimited.ts
1196
+ var rateLimited = (config) => (fn) => {
1197
+ const { rps, burst, concurrency } = config;
1198
+ let tokens = burst;
1199
+ let inFlight = 0;
1200
+ const queue = [];
1201
+ let intervalId = null;
1202
+ const refillTokens = () => {
1203
+ tokens = Math.min(tokens + 1, burst);
1204
+ processQueue();
1205
+ };
1206
+ const startInterval = () => {
1207
+ if (!intervalId) {
1208
+ intervalId = setInterval(refillTokens, 1e3 / rps);
1209
+ }
1210
+ };
1211
+ const stopInterval = () => {
1212
+ if (intervalId && queue.length === 0 && inFlight === 0) {
1213
+ clearInterval(intervalId);
1214
+ intervalId = null;
1215
+ }
1216
+ };
1217
+ const processQueue = () => {
1218
+ while (queue.length > 0 && tokens > 0 && inFlight < concurrency) {
1219
+ tokens--;
1220
+ inFlight++;
1221
+ const item = queue.shift();
1222
+ item.fn().then((result) => {
1223
+ inFlight--;
1224
+ item.resolve(result);
1225
+ processQueue();
1226
+ stopInterval();
1227
+ }).catch((error) => {
1228
+ inFlight--;
1229
+ item.reject(error);
1230
+ processQueue();
1231
+ stopInterval();
1232
+ });
1233
+ }
1234
+ };
1235
+ return (async (...args) => {
1236
+ return new Promise((resolve, reject) => {
1237
+ queue.push({
1238
+ fn: () => fn(...args),
1239
+ resolve,
1240
+ reject
1241
+ });
1242
+ startInterval();
1243
+ processQueue();
1244
+ });
1245
+ });
1246
+ };
1077
1247
  export {
1078
1248
  Inherit,
1079
1249
  appendToLastRequest,
1080
1250
  compose,
1081
1251
  convertMCPSchemaToToolSchema,
1082
1252
  convertStandardSchemaToJsonSchema,
1253
+ convertStandardSchemaToSchemaProperties,
1083
1254
  createMCPTools,
1255
+ embed,
1084
1256
  everyNMessages,
1085
1257
  everyNTokens,
1086
1258
  generateApprovalToken,
@@ -1094,6 +1266,7 @@ export {
1094
1266
  onApprovalRequested,
1095
1267
  onApprovalResolved,
1096
1268
  parseModelName,
1269
+ rateLimited,
1097
1270
  removeApprovalListener,
1098
1271
  requestApproval,
1099
1272
  resolveApproval,