@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.cjs +226 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -8
- package/dist/index.d.ts +66 -8
- package/dist/index.js +223 -50
- package/dist/index.js.map +1 -1
- package/package.json +6 -11
package/dist/index.cjs
CHANGED
|
@@ -25,7 +25,9 @@ __export(index_exports, {
|
|
|
25
25
|
compose: () => compose,
|
|
26
26
|
convertMCPSchemaToToolSchema: () => convertMCPSchemaToToolSchema,
|
|
27
27
|
convertStandardSchemaToJsonSchema: () => convertStandardSchemaToJsonSchema,
|
|
28
|
+
convertStandardSchemaToSchemaProperties: () => convertStandardSchemaToSchemaProperties,
|
|
28
29
|
createMCPTools: () => createMCPTools,
|
|
30
|
+
embed: () => embed,
|
|
29
31
|
everyNMessages: () => everyNMessages,
|
|
30
32
|
everyNTokens: () => everyNTokens,
|
|
31
33
|
generateApprovalToken: () => generateApprovalToken,
|
|
@@ -39,6 +41,7 @@ __export(index_exports, {
|
|
|
39
41
|
onApprovalRequested: () => onApprovalRequested,
|
|
40
42
|
onApprovalResolved: () => onApprovalResolved,
|
|
41
43
|
parseModelName: () => parseModelName,
|
|
44
|
+
rateLimited: () => rateLimited,
|
|
42
45
|
removeApprovalListener: () => removeApprovalListener,
|
|
43
46
|
requestApproval: () => requestApproval,
|
|
44
47
|
resolveApproval: () => resolveApproval,
|
|
@@ -54,24 +57,16 @@ __export(index_exports, {
|
|
|
54
57
|
module.exports = __toCommonJS(index_exports);
|
|
55
58
|
|
|
56
59
|
// src/schema.ts
|
|
60
|
+
var import_zod = require("zod");
|
|
57
61
|
var isStandardSchema = (schema) => {
|
|
58
62
|
return schema && typeof schema === "object" && "~standard" in schema;
|
|
59
63
|
};
|
|
60
64
|
var convertStandardSchemaToJsonSchema = (standardSchema, name = "Schema") => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
name,
|
|
67
|
-
schema: jsonSchema
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
} catch (error) {
|
|
71
|
-
}
|
|
72
|
-
throw new Error(
|
|
73
|
-
"Standard Schema conversion requires zod v4+ with toJSONSchema support. Please install zod@^4.0.0 or provide a JsonSchema object instead."
|
|
74
|
-
);
|
|
65
|
+
const jsonSchema = import_zod.z.toJSONSchema(standardSchema);
|
|
66
|
+
return {
|
|
67
|
+
name,
|
|
68
|
+
schema: jsonSchema
|
|
69
|
+
};
|
|
75
70
|
};
|
|
76
71
|
var convertMCPSchemaToToolSchema = (mcpSchema) => {
|
|
77
72
|
if (!mcpSchema?.properties) return {};
|
|
@@ -92,6 +87,10 @@ function normalizeSchema(schema, name) {
|
|
|
92
87
|
}
|
|
93
88
|
return schema;
|
|
94
89
|
}
|
|
90
|
+
var convertStandardSchemaToSchemaProperties = (standardSchema) => {
|
|
91
|
+
const jsonSchema = import_zod.z.toJSONSchema(standardSchema);
|
|
92
|
+
return convertMCPSchemaToToolSchema(jsonSchema);
|
|
93
|
+
};
|
|
95
94
|
|
|
96
95
|
// src/mcp.ts
|
|
97
96
|
var createMCPTools = async (client) => {
|
|
@@ -130,9 +129,10 @@ var Inherit = /* @__PURE__ */ ((Inherit2) => {
|
|
|
130
129
|
|
|
131
130
|
// src/utils.ts
|
|
132
131
|
var toolConfigToToolDefinition = (tool) => {
|
|
132
|
+
const schema = isStandardSchema(tool.schema) ? convertStandardSchemaToSchemaProperties(tool.schema) : tool.schema;
|
|
133
133
|
const properties = {};
|
|
134
134
|
const required = [];
|
|
135
|
-
for (const [key, prop] of Object.entries(
|
|
135
|
+
for (const [key, prop] of Object.entries(schema)) {
|
|
136
136
|
properties[key] = convertSchemaProperty(prop);
|
|
137
137
|
if (!prop.optional) {
|
|
138
138
|
required.push(key);
|
|
@@ -198,6 +198,49 @@ var maxCalls = (toolConfig, maxCalls2) => ({
|
|
|
198
198
|
_maxCalls: maxCalls2
|
|
199
199
|
});
|
|
200
200
|
|
|
201
|
+
// src/embed.ts
|
|
202
|
+
var import_transformers = require("@huggingface/transformers");
|
|
203
|
+
var modelCache = /* @__PURE__ */ new Map();
|
|
204
|
+
var embed = async (model2, text, config) => {
|
|
205
|
+
if (model2.startsWith("openai/")) {
|
|
206
|
+
const modelName = model2.replace("openai/", "");
|
|
207
|
+
const apiKey = getKey("openai") || process.env.OPENAI_API_KEY;
|
|
208
|
+
if (!apiKey) {
|
|
209
|
+
throw new Error("OpenAI API key not found");
|
|
210
|
+
}
|
|
211
|
+
const body = {
|
|
212
|
+
model: modelName,
|
|
213
|
+
input: text
|
|
214
|
+
};
|
|
215
|
+
if (config?.dimensions) {
|
|
216
|
+
body.dimensions = config.dimensions;
|
|
217
|
+
}
|
|
218
|
+
const response = await fetch("https://api.openai.com/v1/embeddings", {
|
|
219
|
+
method: "POST",
|
|
220
|
+
headers: {
|
|
221
|
+
"Content-Type": "application/json",
|
|
222
|
+
Authorization: `Bearer ${apiKey}`
|
|
223
|
+
},
|
|
224
|
+
body: JSON.stringify(body)
|
|
225
|
+
});
|
|
226
|
+
if (!response.ok) {
|
|
227
|
+
const error = await response.text();
|
|
228
|
+
throw new Error(`OpenAI API error: ${error}`);
|
|
229
|
+
}
|
|
230
|
+
const data = await response.json();
|
|
231
|
+
return data.data[0].embedding;
|
|
232
|
+
}
|
|
233
|
+
if (!modelCache.has(model2)) {
|
|
234
|
+
const extractor2 = await (0, import_transformers.pipeline)("feature-extraction", model2, {
|
|
235
|
+
dtype: "fp32"
|
|
236
|
+
});
|
|
237
|
+
modelCache.set(model2, extractor2);
|
|
238
|
+
}
|
|
239
|
+
const extractor = modelCache.get(model2);
|
|
240
|
+
const result = await extractor(text, { pooling: "mean", normalize: true });
|
|
241
|
+
return Array.from(result.data);
|
|
242
|
+
};
|
|
243
|
+
|
|
201
244
|
// src/providers/openai.ts
|
|
202
245
|
var appendToolCalls = (toolCalls, tcchunklist) => {
|
|
203
246
|
for (const tcchunk of tcchunklist) {
|
|
@@ -329,18 +372,66 @@ var handleOpenAIStream = async (response, ctx) => {
|
|
|
329
372
|
};
|
|
330
373
|
|
|
331
374
|
// src/providers/anthropic.ts
|
|
375
|
+
var convertToAnthropicFormat = (messages) => {
|
|
376
|
+
const result = [];
|
|
377
|
+
let i = 0;
|
|
378
|
+
while (i < messages.length) {
|
|
379
|
+
const msg = messages[i];
|
|
380
|
+
if (msg.role === "system") {
|
|
381
|
+
i++;
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
if (msg.role === "assistant") {
|
|
385
|
+
if (msg.tool_calls) {
|
|
386
|
+
result.push({
|
|
387
|
+
role: "assistant",
|
|
388
|
+
content: msg.tool_calls.map((tc) => ({
|
|
389
|
+
type: "tool_use",
|
|
390
|
+
id: tc.id,
|
|
391
|
+
name: tc.function.name,
|
|
392
|
+
input: JSON.parse(tc.function.arguments)
|
|
393
|
+
}))
|
|
394
|
+
});
|
|
395
|
+
} else {
|
|
396
|
+
result.push({
|
|
397
|
+
role: "assistant",
|
|
398
|
+
content: msg.content
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
i++;
|
|
402
|
+
} else if (msg.role === "tool") {
|
|
403
|
+
const toolResults = [];
|
|
404
|
+
while (i < messages.length && messages[i].role === "tool") {
|
|
405
|
+
const toolMsg = messages[i];
|
|
406
|
+
toolResults.push({
|
|
407
|
+
type: "tool_result",
|
|
408
|
+
tool_use_id: toolMsg.tool_call_id,
|
|
409
|
+
content: toolMsg.content
|
|
410
|
+
});
|
|
411
|
+
i++;
|
|
412
|
+
}
|
|
413
|
+
result.push({
|
|
414
|
+
role: "user",
|
|
415
|
+
content: toolResults
|
|
416
|
+
});
|
|
417
|
+
} else {
|
|
418
|
+
result.push(msg);
|
|
419
|
+
i++;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return result;
|
|
423
|
+
};
|
|
332
424
|
var callAnthropic = async (config, ctx) => {
|
|
333
425
|
const { model: model2, instructions, schema } = config;
|
|
334
426
|
const apiKey = getKey("anthropic") || process.env.ANTHROPIC_API_KEY;
|
|
335
427
|
if (!apiKey) {
|
|
336
428
|
throw new Error("Anthropic API key not found");
|
|
337
429
|
}
|
|
338
|
-
const messages = [...ctx.history];
|
|
339
430
|
let system = instructions;
|
|
340
|
-
if (
|
|
341
|
-
system =
|
|
342
|
-
messages.shift();
|
|
431
|
+
if (ctx.history[0]?.role === "system") {
|
|
432
|
+
system = ctx.history[0].content;
|
|
343
433
|
}
|
|
434
|
+
const messages = convertToAnthropicFormat(ctx.history);
|
|
344
435
|
if (schema) {
|
|
345
436
|
const schemaPrompt = `
|
|
346
437
|
|
|
@@ -442,10 +533,17 @@ var handleAnthropicStream = async (response, ctx) => {
|
|
|
442
533
|
type: "function",
|
|
443
534
|
function: {
|
|
444
535
|
name: toolUse.name,
|
|
445
|
-
arguments:
|
|
446
|
-
}
|
|
536
|
+
arguments: ""
|
|
537
|
+
},
|
|
538
|
+
index: parsed.index
|
|
447
539
|
});
|
|
448
540
|
}
|
|
541
|
+
if (parsed.type === "content_block_delta" && parsed.delta?.type === "input_json_delta") {
|
|
542
|
+
const toolCall = toolCalls.find((tc) => tc.index === parsed.index);
|
|
543
|
+
if (toolCall) {
|
|
544
|
+
toolCall.function.arguments += parsed.delta.partial_json;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
449
547
|
} catch (e) {
|
|
450
548
|
}
|
|
451
549
|
}
|
|
@@ -459,7 +557,7 @@ var handleAnthropicStream = async (response, ctx) => {
|
|
|
459
557
|
content: fullContent
|
|
460
558
|
};
|
|
461
559
|
if (toolCalls.length > 0) {
|
|
462
|
-
msg.tool_calls = toolCalls;
|
|
560
|
+
msg.tool_calls = toolCalls.map(({ index, ...tc }) => tc);
|
|
463
561
|
}
|
|
464
562
|
return {
|
|
465
563
|
...ctx,
|
|
@@ -681,7 +779,7 @@ var model = ({
|
|
|
681
779
|
tools: []
|
|
682
780
|
}
|
|
683
781
|
) : (
|
|
684
|
-
// model()(/* few shot
|
|
782
|
+
// model()(/* few shot or history */);
|
|
685
783
|
ctxOrMessage
|
|
686
784
|
);
|
|
687
785
|
const normalizedSchema = schema ? normalizeSchema(schema) : void 0;
|
|
@@ -712,27 +810,12 @@ var executeTools = async (ctx) => {
|
|
|
712
810
|
approvalCallback,
|
|
713
811
|
parallel = false,
|
|
714
812
|
retryCount = 0,
|
|
715
|
-
approvalId
|
|
813
|
+
approvalId,
|
|
814
|
+
executeOnApproval = false
|
|
716
815
|
} = toolConfig;
|
|
717
|
-
const approvalPromises = calls.map(async (call) => {
|
|
718
|
-
if (requireApproval) {
|
|
719
|
-
let approved;
|
|
720
|
-
if (approvalCallback) {
|
|
721
|
-
approved = await approvalCallback(call);
|
|
722
|
-
} else {
|
|
723
|
-
const response = await requestApproval(call, approvalId);
|
|
724
|
-
approved = response.approved;
|
|
725
|
-
}
|
|
726
|
-
return { call, approved };
|
|
727
|
-
} else {
|
|
728
|
-
return { call, approved: true };
|
|
729
|
-
}
|
|
730
|
-
});
|
|
731
|
-
const approvals = await Promise.all(approvalPromises);
|
|
732
816
|
const updatedCounts = { ...ctx.toolCallCounts || {} };
|
|
733
|
-
const runCall = async (call) => {
|
|
734
|
-
|
|
735
|
-
if (!approval?.approved) {
|
|
817
|
+
const runCall = async (call, approved) => {
|
|
818
|
+
if (!approved) {
|
|
736
819
|
if (ctx.stream) {
|
|
737
820
|
ctx.stream({
|
|
738
821
|
type: "tool_error",
|
|
@@ -793,7 +876,51 @@ var executeTools = async (ctx) => {
|
|
|
793
876
|
}
|
|
794
877
|
return { call, result: { error } };
|
|
795
878
|
};
|
|
796
|
-
|
|
879
|
+
if (executeOnApproval && requireApproval) {
|
|
880
|
+
const resultPromises = calls.map(async (call) => {
|
|
881
|
+
let approved;
|
|
882
|
+
if (approvalCallback) {
|
|
883
|
+
approved = await approvalCallback(call);
|
|
884
|
+
} else {
|
|
885
|
+
const response = await requestApproval(call, approvalId);
|
|
886
|
+
approved = response.approved;
|
|
887
|
+
}
|
|
888
|
+
return runCall(call, approved);
|
|
889
|
+
});
|
|
890
|
+
const results2 = await Promise.all(resultPromises);
|
|
891
|
+
return {
|
|
892
|
+
...ctx,
|
|
893
|
+
history: [
|
|
894
|
+
...ctx.history,
|
|
895
|
+
...results2.map(({ call, result }) => ({
|
|
896
|
+
role: "tool",
|
|
897
|
+
tool_call_id: call.id,
|
|
898
|
+
content: JSON.stringify(result)
|
|
899
|
+
}))
|
|
900
|
+
],
|
|
901
|
+
toolCallCounts: updatedCounts
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
const approvalPromises = calls.map(async (call) => {
|
|
905
|
+
if (requireApproval) {
|
|
906
|
+
let approved;
|
|
907
|
+
if (approvalCallback) {
|
|
908
|
+
approved = await approvalCallback(call);
|
|
909
|
+
} else {
|
|
910
|
+
const response = await requestApproval(call, approvalId);
|
|
911
|
+
approved = response.approved;
|
|
912
|
+
}
|
|
913
|
+
return { call, approved };
|
|
914
|
+
} else {
|
|
915
|
+
return { call, approved: true };
|
|
916
|
+
}
|
|
917
|
+
});
|
|
918
|
+
const approvals = await Promise.all(approvalPromises);
|
|
919
|
+
const runCallWithApproval = async (call) => {
|
|
920
|
+
const approval = approvals.find((a) => a.call.id === call.id);
|
|
921
|
+
return runCall(call, approval?.approved ?? true);
|
|
922
|
+
};
|
|
923
|
+
const results = parallel ? await Promise.all(calls.map(runCallWithApproval)) : await runCallsSequentially(calls, runCallWithApproval);
|
|
797
924
|
return {
|
|
798
925
|
...ctx,
|
|
799
926
|
history: [
|
|
@@ -1122,6 +1249,59 @@ var scope = (config, ...steps) => {
|
|
|
1122
1249
|
};
|
|
1123
1250
|
};
|
|
1124
1251
|
};
|
|
1252
|
+
|
|
1253
|
+
// src/utils/rateLimited.ts
|
|
1254
|
+
var rateLimited = (config) => (fn) => {
|
|
1255
|
+
const { rps, burst, concurrency } = config;
|
|
1256
|
+
let tokens = burst;
|
|
1257
|
+
let inFlight = 0;
|
|
1258
|
+
const queue = [];
|
|
1259
|
+
let intervalId = null;
|
|
1260
|
+
const refillTokens = () => {
|
|
1261
|
+
tokens = Math.min(tokens + 1, burst);
|
|
1262
|
+
processQueue();
|
|
1263
|
+
};
|
|
1264
|
+
const startInterval = () => {
|
|
1265
|
+
if (!intervalId) {
|
|
1266
|
+
intervalId = setInterval(refillTokens, 1e3 / rps);
|
|
1267
|
+
}
|
|
1268
|
+
};
|
|
1269
|
+
const stopInterval = () => {
|
|
1270
|
+
if (intervalId && queue.length === 0 && inFlight === 0) {
|
|
1271
|
+
clearInterval(intervalId);
|
|
1272
|
+
intervalId = null;
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
const processQueue = () => {
|
|
1276
|
+
while (queue.length > 0 && tokens > 0 && inFlight < concurrency) {
|
|
1277
|
+
tokens--;
|
|
1278
|
+
inFlight++;
|
|
1279
|
+
const item = queue.shift();
|
|
1280
|
+
item.fn().then((result) => {
|
|
1281
|
+
inFlight--;
|
|
1282
|
+
item.resolve(result);
|
|
1283
|
+
processQueue();
|
|
1284
|
+
stopInterval();
|
|
1285
|
+
}).catch((error) => {
|
|
1286
|
+
inFlight--;
|
|
1287
|
+
item.reject(error);
|
|
1288
|
+
processQueue();
|
|
1289
|
+
stopInterval();
|
|
1290
|
+
});
|
|
1291
|
+
}
|
|
1292
|
+
};
|
|
1293
|
+
return (async (...args) => {
|
|
1294
|
+
return new Promise((resolve, reject) => {
|
|
1295
|
+
queue.push({
|
|
1296
|
+
fn: () => fn(...args),
|
|
1297
|
+
resolve,
|
|
1298
|
+
reject
|
|
1299
|
+
});
|
|
1300
|
+
startInterval();
|
|
1301
|
+
processQueue();
|
|
1302
|
+
});
|
|
1303
|
+
});
|
|
1304
|
+
};
|
|
1125
1305
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1126
1306
|
0 && (module.exports = {
|
|
1127
1307
|
Inherit,
|
|
@@ -1129,7 +1309,9 @@ var scope = (config, ...steps) => {
|
|
|
1129
1309
|
compose,
|
|
1130
1310
|
convertMCPSchemaToToolSchema,
|
|
1131
1311
|
convertStandardSchemaToJsonSchema,
|
|
1312
|
+
convertStandardSchemaToSchemaProperties,
|
|
1132
1313
|
createMCPTools,
|
|
1314
|
+
embed,
|
|
1133
1315
|
everyNMessages,
|
|
1134
1316
|
everyNTokens,
|
|
1135
1317
|
generateApprovalToken,
|
|
@@ -1143,6 +1325,7 @@ var scope = (config, ...steps) => {
|
|
|
1143
1325
|
onApprovalRequested,
|
|
1144
1326
|
onApprovalResolved,
|
|
1145
1327
|
parseModelName,
|
|
1328
|
+
rateLimited,
|
|
1146
1329
|
removeApprovalListener,
|
|
1147
1330
|
requestApproval,
|
|
1148
1331
|
resolveApproval,
|