@threaded/ai 1.0.2 → 1.0.4

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