@workglow/ai 0.0.121 → 0.0.123

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 (131) hide show
  1. package/README.md +20 -27
  2. package/dist/browser.js +245 -135
  3. package/dist/browser.js.map +60 -57
  4. package/dist/bun.js +245 -135
  5. package/dist/bun.js.map +60 -57
  6. package/dist/common.d.ts +2 -0
  7. package/dist/common.d.ts.map +1 -1
  8. package/dist/job/AiJob.d.ts +1 -1
  9. package/dist/job/AiJob.d.ts.map +1 -1
  10. package/dist/model/InMemoryModelRepository.d.ts.map +1 -1
  11. package/dist/model/ModelRepository.d.ts +10 -10
  12. package/dist/model/ModelRepository.d.ts.map +1 -1
  13. package/dist/model/ModelSchema.d.ts +1 -1
  14. package/dist/model/ModelSchema.d.ts.map +1 -1
  15. package/dist/node.js +245 -135
  16. package/dist/node.js.map +60 -57
  17. package/dist/provider/AiProvider.d.ts +33 -30
  18. package/dist/provider/AiProvider.d.ts.map +1 -1
  19. package/dist/provider/AiProviderRegistry.d.ts +4 -4
  20. package/dist/provider/AiProviderRegistry.d.ts.map +1 -1
  21. package/dist/provider/QueuedAiProvider.d.ts +18 -0
  22. package/dist/provider/QueuedAiProvider.d.ts.map +1 -0
  23. package/dist/task/AgentTask.d.ts +2 -2
  24. package/dist/task/AgentTask.d.ts.map +1 -1
  25. package/dist/task/AgentTypes.d.ts +1 -1
  26. package/dist/task/AgentTypes.d.ts.map +1 -1
  27. package/dist/task/AgentUtils.d.ts +1 -1
  28. package/dist/task/AgentUtils.d.ts.map +1 -1
  29. package/dist/task/BackgroundRemovalTask.d.ts +32 -2
  30. package/dist/task/BackgroundRemovalTask.d.ts.map +1 -1
  31. package/dist/task/ChunkRetrievalTask.d.ts +7 -7
  32. package/dist/task/ChunkRetrievalTask.d.ts.map +1 -1
  33. package/dist/task/ChunkToVectorTask.d.ts +26 -4
  34. package/dist/task/ChunkToVectorTask.d.ts.map +1 -1
  35. package/dist/task/ChunkVectorHybridSearchTask.d.ts +23 -2
  36. package/dist/task/ChunkVectorHybridSearchTask.d.ts.map +1 -1
  37. package/dist/task/ChunkVectorSearchTask.d.ts +13 -5
  38. package/dist/task/ChunkVectorSearchTask.d.ts.map +1 -1
  39. package/dist/task/ChunkVectorUpsertTask.d.ts +12 -3
  40. package/dist/task/ChunkVectorUpsertTask.d.ts.map +1 -1
  41. package/dist/task/ContextBuilderTask.d.ts +30 -4
  42. package/dist/task/ContextBuilderTask.d.ts.map +1 -1
  43. package/dist/task/CountTokensTask.d.ts +19 -2
  44. package/dist/task/CountTokensTask.d.ts.map +1 -1
  45. package/dist/task/DocumentEnricherTask.d.ts +39 -18
  46. package/dist/task/DocumentEnricherTask.d.ts.map +1 -1
  47. package/dist/task/DownloadModelTask.d.ts +25 -4
  48. package/dist/task/DownloadModelTask.d.ts.map +1 -1
  49. package/dist/task/FaceDetectorTask.d.ts +39 -7
  50. package/dist/task/FaceDetectorTask.d.ts.map +1 -1
  51. package/dist/task/FaceLandmarkerTask.d.ts +44 -8
  52. package/dist/task/FaceLandmarkerTask.d.ts.map +1 -1
  53. package/dist/task/GestureRecognizerTask.d.ts +49 -15
  54. package/dist/task/GestureRecognizerTask.d.ts.map +1 -1
  55. package/dist/task/HandLandmarkerTask.d.ts +46 -12
  56. package/dist/task/HandLandmarkerTask.d.ts.map +1 -1
  57. package/dist/task/HierarchicalChunkerTask.d.ts +33 -22
  58. package/dist/task/HierarchicalChunkerTask.d.ts.map +1 -1
  59. package/dist/task/HierarchyJoinTask.d.ts +36 -11
  60. package/dist/task/HierarchyJoinTask.d.ts.map +1 -1
  61. package/dist/task/ImageClassificationTask.d.ts +37 -5
  62. package/dist/task/ImageClassificationTask.d.ts.map +1 -1
  63. package/dist/task/ImageEmbeddingTask.d.ts +33 -3
  64. package/dist/task/ImageEmbeddingTask.d.ts.map +1 -1
  65. package/dist/task/ImageSegmentationTask.d.ts +37 -5
  66. package/dist/task/ImageSegmentationTask.d.ts.map +1 -1
  67. package/dist/task/ImageToTextTask.d.ts +33 -2
  68. package/dist/task/ImageToTextTask.d.ts.map +1 -1
  69. package/dist/task/ModelInfoTask.d.ts +36 -10
  70. package/dist/task/ModelInfoTask.d.ts.map +1 -1
  71. package/dist/task/ModelSearchTask.d.ts +66 -0
  72. package/dist/task/ModelSearchTask.d.ts.map +1 -0
  73. package/dist/task/ObjectDetectionTask.d.ts +39 -7
  74. package/dist/task/ObjectDetectionTask.d.ts.map +1 -1
  75. package/dist/task/PoseLandmarkerTask.d.ts +53 -18
  76. package/dist/task/PoseLandmarkerTask.d.ts.map +1 -1
  77. package/dist/task/QueryExpanderTask.d.ts +9 -4
  78. package/dist/task/QueryExpanderTask.d.ts.map +1 -1
  79. package/dist/task/RerankerTask.d.ts +27 -3
  80. package/dist/task/RerankerTask.d.ts.map +1 -1
  81. package/dist/task/StructuralParserTask.d.ts +8 -2
  82. package/dist/task/StructuralParserTask.d.ts.map +1 -1
  83. package/dist/task/StructuredGenerationTask.d.ts +24 -2
  84. package/dist/task/StructuredGenerationTask.d.ts.map +1 -1
  85. package/dist/task/TextChunkerTask.d.ts +11 -6
  86. package/dist/task/TextChunkerTask.d.ts.map +1 -1
  87. package/dist/task/TextClassificationTask.d.ts +24 -5
  88. package/dist/task/TextClassificationTask.d.ts.map +1 -1
  89. package/dist/task/TextEmbeddingTask.d.ts +20 -3
  90. package/dist/task/TextEmbeddingTask.d.ts.map +1 -1
  91. package/dist/task/TextFillMaskTask.d.ts +23 -6
  92. package/dist/task/TextFillMaskTask.d.ts.map +1 -1
  93. package/dist/task/TextGenerationTask.d.ts +24 -2
  94. package/dist/task/TextGenerationTask.d.ts.map +1 -1
  95. package/dist/task/TextLanguageDetectionTask.d.ts +23 -5
  96. package/dist/task/TextLanguageDetectionTask.d.ts.map +1 -1
  97. package/dist/task/TextNamedEntityRecognitionTask.d.ts +24 -6
  98. package/dist/task/TextNamedEntityRecognitionTask.d.ts.map +1 -1
  99. package/dist/task/TextQuestionAnswerTask.d.ts +20 -2
  100. package/dist/task/TextQuestionAnswerTask.d.ts.map +1 -1
  101. package/dist/task/TextRewriterTask.d.ts +20 -2
  102. package/dist/task/TextRewriterTask.d.ts.map +1 -1
  103. package/dist/task/TextSummaryTask.d.ts +19 -2
  104. package/dist/task/TextSummaryTask.d.ts.map +1 -1
  105. package/dist/task/TextTranslationTask.d.ts +21 -2
  106. package/dist/task/TextTranslationTask.d.ts.map +1 -1
  107. package/dist/task/ToolCallingTask.d.ts +10 -66
  108. package/dist/task/ToolCallingTask.d.ts.map +1 -1
  109. package/dist/task/ToolCallingUtils.d.ts +65 -0
  110. package/dist/task/ToolCallingUtils.d.ts.map +1 -0
  111. package/dist/task/TopicSegmenterTask.d.ts +11 -5
  112. package/dist/task/TopicSegmenterTask.d.ts.map +1 -1
  113. package/dist/task/UnloadModelTask.d.ts +19 -3
  114. package/dist/task/UnloadModelTask.d.ts.map +1 -1
  115. package/dist/task/VectorQuantizeTask.d.ts +12 -8
  116. package/dist/task/VectorQuantizeTask.d.ts.map +1 -1
  117. package/dist/task/VectorSimilarityTask.d.ts +10 -5
  118. package/dist/task/VectorSimilarityTask.d.ts.map +1 -1
  119. package/dist/task/base/AiTask.d.ts +1 -1
  120. package/dist/task/base/AiTask.d.ts.map +1 -1
  121. package/dist/task/base/AiTaskSchemas.d.ts +1 -1
  122. package/dist/task/base/AiTaskSchemas.d.ts.map +1 -1
  123. package/dist/task/base/AiVisionTask.d.ts.map +1 -1
  124. package/dist/task/base/StreamingAiTask.d.ts.map +1 -1
  125. package/dist/task/index.d.ts +4 -1
  126. package/dist/task/index.d.ts.map +1 -1
  127. package/dist/worker.d.ts +21 -0
  128. package/dist/worker.d.ts.map +1 -0
  129. package/dist/worker.js +460 -0
  130. package/dist/worker.js.map +14 -0
  131. package/package.json +28 -21
package/dist/worker.js ADDED
@@ -0,0 +1,460 @@
1
+ // src/provider/AiProvider.ts
2
+ import {
3
+ globalServiceRegistry as globalServiceRegistry2,
4
+ WORKER_MANAGER as WORKER_MANAGER2
5
+ } from "@workglow/util/worker";
6
+
7
+ // src/provider/AiProviderRegistry.ts
8
+ import { globalServiceRegistry, WORKER_MANAGER } from "@workglow/util/worker";
9
+
10
+ class AiProviderRegistry {
11
+ runFnRegistry = new Map;
12
+ streamFnRegistry = new Map;
13
+ reactiveRunFnRegistry = new Map;
14
+ providers = new Map;
15
+ registerProvider(provider) {
16
+ this.providers.set(provider.name, provider);
17
+ }
18
+ getProvider(name) {
19
+ return this.providers.get(name);
20
+ }
21
+ getProviders() {
22
+ return new Map(this.providers);
23
+ }
24
+ registerRunFn(modelProvider, taskType, runFn) {
25
+ if (!this.runFnRegistry.has(taskType)) {
26
+ this.runFnRegistry.set(taskType, new Map);
27
+ }
28
+ this.runFnRegistry.get(taskType).set(modelProvider, runFn);
29
+ }
30
+ registerAsWorkerRunFn(modelProvider, taskType) {
31
+ const workerFn = async (input, model, update_progress, signal, outputSchema) => {
32
+ const workerManager = globalServiceRegistry.get(WORKER_MANAGER);
33
+ const result = await workerManager.callWorkerFunction(modelProvider, taskType, [input, model, outputSchema], {
34
+ signal,
35
+ onProgress: update_progress
36
+ });
37
+ return result;
38
+ };
39
+ this.registerRunFn(modelProvider, taskType, workerFn);
40
+ }
41
+ registerStreamFn(modelProvider, taskType, streamFn) {
42
+ if (!this.streamFnRegistry.has(taskType)) {
43
+ this.streamFnRegistry.set(taskType, new Map);
44
+ }
45
+ this.streamFnRegistry.get(taskType).set(modelProvider, streamFn);
46
+ }
47
+ registerAsWorkerStreamFn(modelProvider, taskType) {
48
+ const streamFn = async function* (input, model, signal, outputSchema) {
49
+ const workerManager = globalServiceRegistry.get(WORKER_MANAGER);
50
+ yield* workerManager.callWorkerStreamFunction(modelProvider, taskType, [input, model, outputSchema], { signal });
51
+ };
52
+ this.registerStreamFn(modelProvider, taskType, streamFn);
53
+ }
54
+ getStreamFn(modelProvider, taskType) {
55
+ const taskTypeMap = this.streamFnRegistry.get(taskType);
56
+ return taskTypeMap?.get(modelProvider);
57
+ }
58
+ registerAsWorkerReactiveRunFn(modelProvider, taskType) {
59
+ const reactiveFn = async (input, output, model) => {
60
+ const workerManager = globalServiceRegistry.get(WORKER_MANAGER);
61
+ return workerManager.callWorkerReactiveFunction(modelProvider, taskType, [
62
+ input,
63
+ output,
64
+ model
65
+ ]);
66
+ };
67
+ this.registerReactiveRunFn(modelProvider, taskType, reactiveFn);
68
+ }
69
+ registerReactiveRunFn(modelProvider, taskType, reactiveRunFn) {
70
+ if (!this.reactiveRunFnRegistry.has(taskType)) {
71
+ this.reactiveRunFnRegistry.set(taskType, new Map);
72
+ }
73
+ this.reactiveRunFnRegistry.get(taskType).set(modelProvider, reactiveRunFn);
74
+ }
75
+ getReactiveRunFn(modelProvider, taskType) {
76
+ const taskTypeMap = this.reactiveRunFnRegistry.get(taskType);
77
+ return taskTypeMap?.get(modelProvider);
78
+ }
79
+ getDirectRunFn(modelProvider, taskType) {
80
+ const taskTypeMap = this.runFnRegistry.get(taskType);
81
+ const runFn = taskTypeMap?.get(modelProvider);
82
+ if (!runFn) {
83
+ throw new Error(`No run function found for task type ${taskType} and model provider ${modelProvider}`);
84
+ }
85
+ return runFn;
86
+ }
87
+ }
88
+ var providerRegistry;
89
+ function getAiProviderRegistry() {
90
+ if (!providerRegistry)
91
+ providerRegistry = new AiProviderRegistry;
92
+ return providerRegistry;
93
+ }
94
+ function setAiProviderRegistry(pr) {
95
+ providerRegistry = pr;
96
+ }
97
+
98
+ // src/provider/AiProvider.ts
99
+ class AiProvider {
100
+ tasks;
101
+ streamTasks;
102
+ reactiveTasks;
103
+ constructor(tasks, streamTasks, reactiveTasks) {
104
+ this.tasks = tasks;
105
+ this.streamTasks = streamTasks;
106
+ this.reactiveTasks = reactiveTasks;
107
+ }
108
+ get supportedTaskTypes() {
109
+ return this.taskTypes;
110
+ }
111
+ getRunFn(taskType) {
112
+ return this.tasks?.[taskType];
113
+ }
114
+ getStreamFn(taskType) {
115
+ return this.streamTasks?.[taskType];
116
+ }
117
+ getReactiveRunFn(taskType) {
118
+ return this.reactiveTasks?.[taskType];
119
+ }
120
+ async register(options = {}) {
121
+ const isInline = !!this.tasks;
122
+ const context = { ...options, isInline };
123
+ await this.onInitialize(context);
124
+ if (isInline) {
125
+ if (!this.tasks) {
126
+ throw new Error(`AiProvider "${this.name}": tasks must be provided via the constructor for inline registration. ` + `Pass the tasks record when constructing the provider, e.g. new MyProvider(MY_TASKS).`);
127
+ }
128
+ } else {
129
+ if (!options.worker) {
130
+ throw new Error(`AiProvider "${this.name}": worker is required when no tasks are provided (worker-backed registration). ` + `Pass worker: new Worker(...) or worker: () => new Worker(...).`);
131
+ }
132
+ }
133
+ const registry = getAiProviderRegistry();
134
+ if (!isInline && options.worker) {
135
+ const workerManager = globalServiceRegistry2.get(WORKER_MANAGER2);
136
+ workerManager.registerWorker(this.name, options.worker);
137
+ for (const taskType of this.taskTypes) {
138
+ registry.registerAsWorkerRunFn(this.name, taskType);
139
+ registry.registerAsWorkerStreamFn(this.name, taskType);
140
+ registry.registerAsWorkerReactiveRunFn(this.name, taskType);
141
+ }
142
+ } else {
143
+ for (const [taskType, fn] of Object.entries(this.tasks)) {
144
+ registry.registerRunFn(this.name, taskType, fn);
145
+ }
146
+ if (this.streamTasks) {
147
+ for (const [taskType, fn] of Object.entries(this.streamTasks)) {
148
+ registry.registerStreamFn(this.name, taskType, fn);
149
+ }
150
+ }
151
+ }
152
+ if (this.reactiveTasks) {
153
+ for (const [taskType, fn] of Object.entries(this.reactiveTasks)) {
154
+ registry.registerReactiveRunFn(this.name, taskType, fn);
155
+ }
156
+ }
157
+ registry.registerProvider(this);
158
+ await this.afterRegister(options);
159
+ }
160
+ registerOnWorkerServer(workerServer) {
161
+ if (!this.tasks) {
162
+ throw new Error(`AiProvider "${this.name}": tasks must be provided via the constructor for worker server registration. ` + `Pass the tasks record when constructing the provider, e.g. new MyProvider(MY_TASKS).`);
163
+ }
164
+ for (const [taskType, fn] of Object.entries(this.tasks)) {
165
+ workerServer.registerFunction(taskType, fn);
166
+ }
167
+ if (this.streamTasks) {
168
+ for (const [taskType, fn] of Object.entries(this.streamTasks)) {
169
+ workerServer.registerStreamFunction(taskType, fn);
170
+ }
171
+ }
172
+ if (this.reactiveTasks) {
173
+ for (const [taskType, fn] of Object.entries(this.reactiveTasks)) {
174
+ workerServer.registerReactiveFunction(taskType, fn);
175
+ }
176
+ }
177
+ }
178
+ async onInitialize(_options) {}
179
+ async dispose() {}
180
+ async afterRegister(_options) {}
181
+ }
182
+ // src/task/ToolCallingUtils.ts
183
+ import { getLogger } from "@workglow/util/worker";
184
+ function buildToolDescription(tool) {
185
+ let desc = tool.description;
186
+ if (tool.outputSchema && typeof tool.outputSchema === "object") {
187
+ desc += `
188
+
189
+ Returns: ${JSON.stringify(tool.outputSchema)}`;
190
+ }
191
+ return desc;
192
+ }
193
+ function isAllowedToolName(name, allowedTools) {
194
+ return allowedTools.some((t) => t.name === name);
195
+ }
196
+ function filterValidToolCalls(toolCalls, allowedTools) {
197
+ return toolCalls.filter((tc) => {
198
+ if (tc.name && isAllowedToolName(tc.name, allowedTools)) {
199
+ return true;
200
+ }
201
+ getLogger().warn(`Filtered out tool call with unknown name "${tc.name ?? "(missing)"}"`, {
202
+ callId: tc.id,
203
+ toolName: tc.name
204
+ });
205
+ return false;
206
+ });
207
+ }
208
+ // src/task/MessageConversion.ts
209
+ function getInputMessages(input) {
210
+ const messages = input.messages;
211
+ if (!messages || messages.length === 0)
212
+ return;
213
+ return messages;
214
+ }
215
+ function toOpenAIMessages(input) {
216
+ const messages = [];
217
+ if (input.systemPrompt) {
218
+ messages.push({ role: "system", content: input.systemPrompt });
219
+ }
220
+ const inputMessages = getInputMessages(input);
221
+ if (!inputMessages) {
222
+ if (!Array.isArray(input.prompt)) {
223
+ messages.push({ role: "user", content: input.prompt });
224
+ } else if (input.prompt.every((item) => typeof item === "string")) {
225
+ messages.push({ role: "user", content: input.prompt.join(`
226
+ `) });
227
+ } else {
228
+ const parts = [];
229
+ for (const item of input.prompt) {
230
+ if (typeof item === "string") {
231
+ parts.push({ type: "text", text: item });
232
+ } else {
233
+ const b = item;
234
+ if (b.type === "text") {
235
+ parts.push({ type: "text", text: b.text });
236
+ } else if (b.type === "image") {
237
+ parts.push({
238
+ type: "image_url",
239
+ image_url: { url: `data:${b.mimeType};base64,${b.data}` }
240
+ });
241
+ } else if (b.type === "audio") {
242
+ const format = b.mimeType.replace(/^audio\//, "");
243
+ parts.push({
244
+ type: "input_audio",
245
+ input_audio: { data: b.data, format }
246
+ });
247
+ }
248
+ }
249
+ }
250
+ messages.push({ role: "user", content: parts });
251
+ }
252
+ return messages;
253
+ }
254
+ for (const msg of inputMessages) {
255
+ if (msg.role === "user") {
256
+ if (typeof msg.content === "string") {
257
+ messages.push({ role: "user", content: msg.content });
258
+ } else if (Array.isArray(msg.content) && msg.content.length > 0 && typeof msg.content[0]?.type === "string") {
259
+ const parts = [];
260
+ for (const block of msg.content) {
261
+ const b = block;
262
+ if (b.type === "text") {
263
+ parts.push({ type: "text", text: b.text });
264
+ } else if (b.type === "image") {
265
+ parts.push({
266
+ type: "image_url",
267
+ image_url: { url: `data:${b.mimeType};base64,${b.data}` }
268
+ });
269
+ } else if (b.type === "audio") {
270
+ const format = b.mimeType.replace(/^audio\//, "");
271
+ parts.push({
272
+ type: "input_audio",
273
+ input_audio: { data: b.data, format }
274
+ });
275
+ }
276
+ }
277
+ messages.push({ role: "user", content: parts });
278
+ } else {
279
+ try {
280
+ messages.push({ role: "user", content: JSON.stringify(msg.content) });
281
+ } catch {
282
+ messages.push({ role: "user", content: String(msg.content) });
283
+ }
284
+ }
285
+ } else if (msg.role === "assistant") {
286
+ if (typeof msg.content === "string") {
287
+ messages.push({ role: "assistant", content: msg.content.length > 0 ? msg.content : null });
288
+ } else if (Array.isArray(msg.content)) {
289
+ const textParts = msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
290
+ const toolCalls = msg.content.filter((b) => b.type === "tool_use").map((b) => ({
291
+ id: b.id,
292
+ type: "function",
293
+ function: {
294
+ name: b.name,
295
+ arguments: JSON.stringify(b.input)
296
+ }
297
+ }));
298
+ const entry = {
299
+ role: "assistant",
300
+ content: textParts.length > 0 ? textParts : null
301
+ };
302
+ if (toolCalls.length > 0) {
303
+ entry.tool_calls = toolCalls;
304
+ }
305
+ messages.push(entry);
306
+ }
307
+ } else if (msg.role === "tool" && Array.isArray(msg.content)) {
308
+ for (const block of msg.content) {
309
+ const b = block;
310
+ let content;
311
+ if (typeof b.content === "string") {
312
+ content = b.content;
313
+ } else if (Array.isArray(b.content)) {
314
+ const parts = [];
315
+ for (const inner of b.content) {
316
+ if (inner.type === "text") {
317
+ parts.push({ type: "text", text: inner.text });
318
+ } else if (inner.type === "image") {
319
+ parts.push({
320
+ type: "image_url",
321
+ image_url: { url: `data:${inner.mimeType};base64,${inner.data}` }
322
+ });
323
+ }
324
+ }
325
+ content = parts;
326
+ } else {
327
+ content = "";
328
+ }
329
+ messages.push({
330
+ role: "tool",
331
+ content,
332
+ tool_call_id: b.tool_use_id
333
+ });
334
+ }
335
+ }
336
+ }
337
+ return messages;
338
+ }
339
+ function toTextFlatMessages(input) {
340
+ const messages = [];
341
+ if (input.systemPrompt) {
342
+ messages.push({ role: "system", content: input.systemPrompt });
343
+ }
344
+ const inputMessages = getInputMessages(input);
345
+ if (!inputMessages) {
346
+ let promptContent;
347
+ if (!Array.isArray(input.prompt)) {
348
+ promptContent = input.prompt;
349
+ } else {
350
+ promptContent = input.prompt.map((item) => {
351
+ if (typeof item === "string")
352
+ return item;
353
+ const b = item;
354
+ return b.type === "text" ? b.text : "";
355
+ }).filter((s) => s !== "").join(`
356
+ `);
357
+ }
358
+ messages.push({ role: "user", content: promptContent });
359
+ return messages;
360
+ }
361
+ for (const msg of inputMessages) {
362
+ if (msg.role === "user") {
363
+ let content = "";
364
+ if (typeof msg.content === "string") {
365
+ content = msg.content;
366
+ } else if (Array.isArray(msg.content) && msg.content.length > 0 && typeof msg.content[0]?.type === "string") {
367
+ content = msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
368
+ } else if (msg.content != null) {
369
+ try {
370
+ content = JSON.stringify(msg.content);
371
+ } catch {
372
+ content = String(msg.content);
373
+ }
374
+ }
375
+ messages.push({ role: "user", content });
376
+ } else if (msg.role === "assistant") {
377
+ if (typeof msg.content === "string") {
378
+ if (msg.content) {
379
+ messages.push({ role: "assistant", content: msg.content });
380
+ }
381
+ } else if (Array.isArray(msg.content)) {
382
+ const text = msg.content.filter((b) => b.type === "text").map((b) => b.text).join("");
383
+ if (text) {
384
+ messages.push({ role: "assistant", content: text });
385
+ }
386
+ }
387
+ } else if (msg.role === "tool" && Array.isArray(msg.content)) {
388
+ for (const block of msg.content) {
389
+ const b = block;
390
+ let content;
391
+ if (typeof b.content === "string") {
392
+ content = b.content;
393
+ } else if (Array.isArray(b.content)) {
394
+ content = b.content.filter((inner) => inner.type === "text").map((inner) => inner.text).join("");
395
+ } else {
396
+ content = "";
397
+ }
398
+ messages.push({ role: "tool", content });
399
+ }
400
+ }
401
+ }
402
+ return messages;
403
+ }
404
+ // src/model/ModelSchema.ts
405
+ var ModelConfigSchema = {
406
+ type: "object",
407
+ properties: {
408
+ model_id: { type: "string" },
409
+ tasks: { type: "array", items: { type: "string" }, "x-ui-editor": "multiselect" },
410
+ title: { type: "string" },
411
+ description: { type: "string", "x-ui-editor": "textarea" },
412
+ provider: { type: "string" },
413
+ provider_config: {
414
+ type: "object",
415
+ properties: {
416
+ credential_key: { type: "string", format: "credential", "x-ui-hidden": true }
417
+ },
418
+ additionalProperties: true,
419
+ default: {}
420
+ },
421
+ metadata: { type: "object", default: {}, "x-ui-hidden": true }
422
+ },
423
+ required: ["provider", "provider_config"],
424
+ format: "model",
425
+ additionalProperties: true
426
+ };
427
+ var ModelRecordSchema = {
428
+ type: "object",
429
+ properties: {
430
+ ...ModelConfigSchema.properties
431
+ },
432
+ required: [
433
+ "model_id",
434
+ "tasks",
435
+ "provider",
436
+ "title",
437
+ "description",
438
+ "provider_config",
439
+ "metadata"
440
+ ],
441
+ format: "model",
442
+ additionalProperties: false
443
+ };
444
+ var ModelPrimaryKeyNames = ["model_id"];
445
+ export {
446
+ toTextFlatMessages,
447
+ toOpenAIMessages,
448
+ setAiProviderRegistry,
449
+ isAllowedToolName,
450
+ getAiProviderRegistry,
451
+ filterValidToolCalls,
452
+ buildToolDescription,
453
+ ModelRecordSchema,
454
+ ModelPrimaryKeyNames,
455
+ ModelConfigSchema,
456
+ AiProviderRegistry,
457
+ AiProvider
458
+ };
459
+
460
+ //# debugId=4D2BD86FECB58DEF64756E2164756E21
@@ -0,0 +1,14 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/provider/AiProvider.ts", "../src/provider/AiProviderRegistry.ts", "../src/task/ToolCallingUtils.ts", "../src/task/MessageConversion.ts", "../src/model/ModelSchema.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { TaskInput, TaskOutput } from \"@workglow/task-graph\";\nimport {\n globalServiceRegistry,\n WORKER_MANAGER,\n type WorkerServerBase as WorkerServer,\n} from \"@workglow/util/worker\";\nimport type { ModelConfig } from \"../model/ModelSchema\";\nimport {\n type AiProviderReactiveRunFn,\n type AiProviderRunFn,\n type AiProviderStreamFn,\n getAiProviderRegistry,\n} from \"./AiProviderRegistry\";\n\n/**\n * Options for registering an AI provider on the main thread.\n *\n * - If the provider was constructed **with** task run functions → **inline** registration\n * (direct run fns). No `worker` option.\n * - If the provider was constructed **without** tasks → **worker** registration (proxies).\n * A `worker` (instance or lazy factory) is **required**.\n */\nexport interface AiProviderRegisterOptions {\n /**\n * Web Worker for worker-backed registration. Pass a `Worker` or a factory\n * `() => Worker` to defer instantiation until the first job (lazy worker).\n */\n worker?: Worker | (() => Worker);\n /** Job queue configuration */\n queue?: {\n /** Maximum number of concurrent jobs. Defaults to 1. */\n concurrency?: number;\n /** Set to false to skip automatic queue creation. Defaults to true. */\n autoCreate?: boolean;\n };\n}\n\n/**\n * Registration context passed to {@link AiProvider.onInitialize}, including whether\n * the provider is registering inline (tasks present) or worker-backed (no tasks).\n */\nexport interface AiProviderRegisterContext extends AiProviderRegisterOptions {\n readonly isInline: boolean;\n}\n\n/**\n * Abstract base class for AI providers.\n *\n * Each provider subclass declares a `taskTypes` array listing the task type\n * names it supports. The actual run function implementations (`tasks` record)\n * are **injected via the constructor** so that heavy ML library imports remain\n * at the call site. This allows the provider class to be imported on the main\n * thread without pulling in heavy dependencies when running in worker mode.\n *\n * The base class handles:\n * - Registering run functions with the AiProviderRegistry (inline or worker proxies)\n * - Registering functions on a WorkerServer (for worker-side code)\n * - Lifecycle management (initialize / dispose)\n *\n * @example\n * ```typescript\n * // Worker host (main thread) -- lightweight, no heavy task imports:\n * await new MyProvider().register({\n * worker: () => new Worker(new URL(\"./worker.ts\", import.meta.url), { type: \"module\" }),\n * });\n *\n * // Inline -- caller provides the tasks (imports heavy library):\n * import { MY_TASKS } from \"./MyJobRunFns\";\n * await new MyProvider(MY_TASKS).register();\n *\n * // Worker side -- caller provides the tasks:\n * import { MY_TASKS } from \"./MyJobRunFns\";\n * new MyProvider(MY_TASKS).registerOnWorkerServer(workerServer);\n * ```\n */\nexport abstract class AiProvider<TModelConfig extends ModelConfig = ModelConfig> {\n /** Unique provider identifier (e.g., \"HF_TRANSFORMERS_ONNX\") */\n abstract readonly name: string;\n\n /** Whether this provider runs models locally (on the same machine). */\n abstract readonly isLocal: boolean;\n\n /** Whether this provider can run in a browser environment. */\n abstract readonly supportsBrowser: boolean;\n\n /**\n * List of task type names this provider supports.\n * This is lightweight metadata -- no heavy library imports needed.\n */\n abstract readonly taskTypes: readonly string[];\n\n /**\n * Map of task type names to their run functions.\n * Injected via constructor. Required for inline mode and worker-server\n * registration; not needed for worker-mode registration on the main thread.\n */\n protected readonly tasks?: Record<string, AiProviderRunFn<any, any, TModelConfig>>;\n\n /**\n * Map of task type names to their streaming run functions.\n * Injected via constructor alongside `tasks`. Only needed for tasks that\n * support streaming output (e.g., text generation, summarization).\n */\n protected readonly streamTasks?: Record<string, AiProviderStreamFn<any, any, TModelConfig>>;\n\n /**\n * Map of task type names to their reactive run functions.\n * Injected via constructor alongside `tasks`. Only needed for tasks that\n * provide lightweight reactive previews via executeReactive().\n */\n protected readonly reactiveTasks?: Record<\n string,\n AiProviderReactiveRunFn<any, any, TModelConfig>\n >;\n\n constructor(\n tasks?: Record<string, AiProviderRunFn<any, any, TModelConfig>>,\n streamTasks?: Record<string, AiProviderStreamFn<any, any, TModelConfig>>,\n reactiveTasks?: Record<string, AiProviderReactiveRunFn<any, any, TModelConfig>>\n ) {\n this.tasks = tasks;\n this.streamTasks = streamTasks;\n this.reactiveTasks = reactiveTasks;\n }\n\n /** Get all task type names this provider supports */\n get supportedTaskTypes(): readonly string[] {\n return this.taskTypes;\n }\n\n /**\n * Get the run function for a specific task type.\n * @param taskType - The task type name (e.g., \"TextEmbeddingTask\")\n * @returns The run function, or undefined if the task type is not supported or tasks not provided\n */\n getRunFn<I extends TaskInput = TaskInput, O extends TaskOutput = TaskOutput>(\n taskType: string\n ): AiProviderRunFn<I, O, TModelConfig> | undefined {\n return this.tasks?.[taskType] as AiProviderRunFn<I, O, TModelConfig> | undefined;\n }\n\n /**\n * Get the streaming function for a specific task type.\n * @param taskType - The task type name (e.g., \"TextGenerationTask\")\n * @returns The stream function, or undefined if streaming is not supported for this task type\n */\n getStreamFn<I extends TaskInput = TaskInput, O extends TaskOutput = TaskOutput>(\n taskType: string\n ): AiProviderStreamFn<I, O, TModelConfig> | undefined {\n return this.streamTasks?.[taskType] as AiProviderStreamFn<I, O, TModelConfig> | undefined;\n }\n\n /**\n * Get the reactive run function for a specific task type.\n * @param taskType - The task type name (e.g., \"CountTokensTask\")\n * @returns The reactive function, or undefined if not supported for this task type\n */\n getReactiveRunFn<I extends TaskInput = TaskInput, O extends TaskOutput = TaskOutput>(\n taskType: string\n ): AiProviderReactiveRunFn<I, O, TModelConfig> | undefined {\n return this.reactiveTasks?.[taskType] as\n | AiProviderReactiveRunFn<I, O, TModelConfig>\n | undefined;\n }\n\n /**\n * Register this provider on the main thread.\n *\n * Inferred from constructor: **with** tasks → direct run functions; **without** tasks →\n * worker proxies (requires `worker` in options).\n *\n * Creates a job queue unless `queue.autoCreate` is set to false.\n *\n * @param options - Registration options (worker for worker-backed, queue config)\n */\n async register(options: AiProviderRegisterOptions = {}): Promise<void> {\n const isInline = !!this.tasks;\n const context: AiProviderRegisterContext = { ...options, isInline };\n await this.onInitialize(context);\n\n if (isInline) {\n if (!this.tasks) {\n throw new Error(\n `AiProvider \"${this.name}\": tasks must be provided via the constructor for inline registration. ` +\n `Pass the tasks record when constructing the provider, e.g. new MyProvider(MY_TASKS).`\n );\n }\n } else {\n if (!options.worker) {\n throw new Error(\n `AiProvider \"${this.name}\": worker is required when no tasks are provided (worker-backed registration). ` +\n `Pass worker: new Worker(...) or worker: () => new Worker(...).`\n );\n }\n }\n\n const registry = getAiProviderRegistry();\n\n if (!isInline && options.worker) {\n const workerManager = globalServiceRegistry.get(WORKER_MANAGER);\n workerManager.registerWorker(this.name, options.worker);\n for (const taskType of this.taskTypes) {\n registry.registerAsWorkerRunFn(this.name, taskType);\n registry.registerAsWorkerStreamFn(this.name, taskType);\n registry.registerAsWorkerReactiveRunFn(this.name, taskType);\n }\n } else {\n for (const [taskType, fn] of Object.entries(this.tasks!)) {\n registry.registerRunFn(this.name, taskType, fn as AiProviderRunFn);\n }\n if (this.streamTasks) {\n for (const [taskType, fn] of Object.entries(this.streamTasks)) {\n registry.registerStreamFn(this.name, taskType, fn as AiProviderStreamFn);\n }\n }\n }\n\n if (this.reactiveTasks) {\n for (const [taskType, fn] of Object.entries(this.reactiveTasks)) {\n registry.registerReactiveRunFn(this.name, taskType, fn as AiProviderReactiveRunFn);\n }\n }\n\n registry.registerProvider(this);\n\n await this.afterRegister(options);\n }\n\n /**\n * Register this provider's run functions on a WorkerServer.\n * Call this inside a Web Worker to make the provider's functions\n * available for remote invocation from the main thread.\n *\n * Requires `tasks` to have been provided via the constructor.\n *\n * @param workerServer - The WorkerServer instance to register on\n */\n registerOnWorkerServer(workerServer: WorkerServer): void {\n if (!this.tasks) {\n throw new Error(\n `AiProvider \"${this.name}\": tasks must be provided via the constructor for worker server registration. ` +\n `Pass the tasks record when constructing the provider, e.g. new MyProvider(MY_TASKS).`\n );\n }\n for (const [taskType, fn] of Object.entries(this.tasks)) {\n workerServer.registerFunction(taskType, fn);\n }\n if (this.streamTasks) {\n for (const [taskType, fn] of Object.entries(this.streamTasks)) {\n workerServer.registerStreamFunction(taskType, fn);\n }\n }\n if (this.reactiveTasks) {\n for (const [taskType, fn] of Object.entries(this.reactiveTasks)) {\n workerServer.registerReactiveFunction(taskType, fn);\n }\n }\n }\n\n /**\n * Hook for provider-specific initialization.\n * Called at the start of `register()`, before any functions are registered.\n * Override in subclasses to perform setup (e.g., configuring WASM backends).\n */\n protected async onInitialize(_options: AiProviderRegisterContext): Promise<void> {}\n\n /**\n * Dispose of provider resources.\n * Override in subclasses to clean up (e.g., clearing pipeline caches).\n */\n async dispose(): Promise<void> {}\n\n /**\n * Called at the end of {@link register} after registry wiring.\n * {@link QueuedAiProvider} overrides this to create the default job queue; the base\n * implementation is a no-op so worker-only provider classes stay free of queue/storage.\n */\n protected async afterRegister(_options: AiProviderRegisterOptions): Promise<void> {}\n}\n",
6
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { TaskInput, TaskOutput, type StreamEvent } from \"@workglow/task-graph\";\nimport { globalServiceRegistry, WORKER_MANAGER, type JsonSchema } from \"@workglow/util/worker\";\nimport type { ModelConfig } from \"../model/ModelSchema\";\nimport type { AiProvider } from \"./AiProvider\";\n\n/**\n * Type for the run function for the AiJob.\n * The optional `outputSchema` is provided when the task declares structured output\n * (via `x-structured-output: true`). Providers use it to request schema-conformant\n * JSON output from the model API.\n */\nexport type AiProviderRunFn<\n Input extends TaskInput = TaskInput,\n Output extends TaskOutput = TaskOutput,\n Model extends ModelConfig = ModelConfig,\n> = (\n input: Input,\n model: Model | undefined,\n update_progress: (progress: number, message?: string, details?: any) => void,\n signal: AbortSignal,\n outputSchema?: JsonSchema\n) => Promise<Output>;\n\n/**\n * Type for the reactive run function for AiTask.executeReactive().\n * Receives the current output alongside the input so it can return a fast preview.\n * No `signal` or `update_progress` -- reactive execution is lightweight and synchronous-ish.\n */\nexport type AiProviderReactiveRunFn<\n Input extends TaskInput = TaskInput,\n Output extends TaskOutput = TaskOutput,\n Model extends ModelConfig = ModelConfig,\n> = (input: Input, output: Output, model: Model | undefined) => Promise<Output | undefined>;\n\n/**\n * Type for the streaming run function for the AiJob.\n * Returns an AsyncIterable of StreamEvents instead of a Promise.\n * No `update_progress` callback -- for streaming providers, the stream itself IS the progress signal.\n * The optional `outputSchema` is provided for structured output tasks.\n */\nexport type AiProviderStreamFn<\n Input extends TaskInput = TaskInput,\n Output extends TaskOutput = TaskOutput,\n Model extends ModelConfig = ModelConfig,\n> = (\n input: Input,\n model: Model | undefined,\n signal: AbortSignal,\n outputSchema?: JsonSchema\n) => AsyncIterable<StreamEvent<Output>>;\n\n/**\n * Registry that manages provider-specific task execution functions and job queues.\n * Handles the registration, retrieval, and execution of task processing functions\n * for different model providers and task types.\n */\nexport class AiProviderRegistry {\n runFnRegistry: Map<string, Map<string, AiProviderRunFn<any, any>>> = new Map();\n streamFnRegistry: Map<string, Map<string, AiProviderStreamFn<any, any>>> = new Map();\n reactiveRunFnRegistry: Map<string, Map<string, AiProviderReactiveRunFn<any, any>>> = new Map();\n private providers: Map<string, AiProvider<any>> = new Map();\n\n /**\n * Registers an AiProvider instance for lifecycle management and introspection.\n * @param provider - The provider instance to register\n */\n registerProvider(provider: AiProvider<any>): void {\n this.providers.set(provider.name, provider);\n }\n\n /**\n * Retrieves a registered AiProvider instance by name.\n * @param name - The provider name (e.g., \"HF_TRANSFORMERS_ONNX\")\n * @returns The provider instance, or undefined if not found\n */\n getProvider(name: string): AiProvider<any> | undefined {\n return this.providers.get(name);\n }\n\n /**\n * Returns all registered AiProvider instances.\n */\n getProviders(): Map<string, AiProvider<any>> {\n return new Map(this.providers);\n }\n\n /**\n * Registers a task execution function for a specific task type and model provider\n * @param taskType - The type of task (e.g., 'text-generation', 'embedding')\n * @param modelProvider - The provider of the model (e.g., 'hf-transformers', 'tf-mediapipe', 'openai', etc)\n * @param runFn - The function that executes the task\n */\n registerRunFn<Input extends TaskInput = TaskInput, Output extends TaskOutput = TaskOutput>(\n modelProvider: string,\n taskType: string,\n runFn: AiProviderRunFn<Input, Output>\n ) {\n if (!this.runFnRegistry.has(taskType)) {\n this.runFnRegistry.set(taskType, new Map());\n }\n this.runFnRegistry.get(taskType)!.set(modelProvider, runFn);\n }\n\n registerAsWorkerRunFn<\n Input extends TaskInput = TaskInput,\n Output extends TaskOutput = TaskOutput,\n >(modelProvider: string, taskType: string) {\n const workerFn: AiProviderRunFn<Input, Output> = async (\n input: Input,\n model: ModelConfig | undefined,\n update_progress: (progress: number, message?: string, details?: any) => void,\n signal?: AbortSignal,\n outputSchema?: JsonSchema\n ) => {\n const workerManager = globalServiceRegistry.get(WORKER_MANAGER);\n const result = await workerManager.callWorkerFunction<Output>(\n modelProvider,\n taskType,\n [input, model, outputSchema],\n {\n signal: signal,\n onProgress: update_progress,\n }\n );\n return result;\n };\n this.registerRunFn<Input, Output>(modelProvider, taskType, workerFn);\n }\n\n /**\n * Registers a streaming execution function for a specific task type and model provider.\n * @param modelProvider - The provider of the model (e.g., 'openai', 'anthropic', etc.)\n * @param taskType - The type of task (e.g., 'TextGenerationTask')\n * @param streamFn - The async generator function that yields StreamEvents\n */\n registerStreamFn<Input extends TaskInput = TaskInput, Output extends TaskOutput = TaskOutput>(\n modelProvider: string,\n taskType: string,\n streamFn: AiProviderStreamFn<Input, Output>\n ) {\n if (!this.streamFnRegistry.has(taskType)) {\n this.streamFnRegistry.set(taskType, new Map());\n }\n this.streamFnRegistry.get(taskType)!.set(modelProvider, streamFn);\n }\n\n /**\n * Registers a worker-proxied streaming function for a specific task type and model provider.\n * Creates a proxy that delegates streaming to a Web Worker via WorkerManager.\n * The proxy calls `callWorkerStreamFunction()` which sends a `stream: true` call message\n * and yields `stream_chunk` messages from the worker as an AsyncIterable.\n */\n registerAsWorkerStreamFn<\n Input extends TaskInput = TaskInput,\n Output extends TaskOutput = TaskOutput,\n >(modelProvider: string, taskType: string) {\n const streamFn: AiProviderStreamFn<Input, Output> = async function* (\n input: Input,\n model: ModelConfig | undefined,\n signal: AbortSignal,\n outputSchema?: JsonSchema\n ) {\n const workerManager = globalServiceRegistry.get(WORKER_MANAGER);\n yield* workerManager.callWorkerStreamFunction<StreamEvent<Output>>(\n modelProvider,\n taskType,\n [input, model, outputSchema],\n { signal }\n );\n };\n this.registerStreamFn<Input, Output>(modelProvider, taskType, streamFn);\n }\n\n /**\n * Retrieves the streaming execution function for a task type and model provider.\n * Returns undefined if no streaming function is registered (fallback to non-streaming).\n */\n getStreamFn<Input extends TaskInput = TaskInput, Output extends TaskOutput = TaskOutput>(\n modelProvider: string,\n taskType: string\n ): AiProviderStreamFn<Input, Output> | undefined {\n const taskTypeMap = this.streamFnRegistry.get(taskType);\n return taskTypeMap?.get(modelProvider) as AiProviderStreamFn<Input, Output> | undefined;\n }\n\n /**\n * Registers a worker-proxied reactive function for a specific task type and model provider.\n * Creates a proxy that delegates reactive execution to a Web Worker via WorkerManager.\n * Returns undefined (non-throwing) if the worker has no reactive function for the task type.\n */\n registerAsWorkerReactiveRunFn<\n Input extends TaskInput = TaskInput,\n Output extends TaskOutput = TaskOutput,\n >(modelProvider: string, taskType: string) {\n const reactiveFn: AiProviderReactiveRunFn<Input, Output> = async (\n input: Input,\n output: Output,\n model: ModelConfig | undefined\n ) => {\n const workerManager = globalServiceRegistry.get(WORKER_MANAGER);\n return workerManager.callWorkerReactiveFunction<Output>(modelProvider, taskType, [\n input,\n output,\n model,\n ]);\n };\n this.registerReactiveRunFn<Input, Output>(modelProvider, taskType, reactiveFn);\n }\n\n /**\n * Registers a reactive execution function for a specific task type and model provider.\n * Called by AiTask.executeReactive() to provide a fast, lightweight preview without a network call.\n */\n registerReactiveRunFn<\n Input extends TaskInput = TaskInput,\n Output extends TaskOutput = TaskOutput,\n >(\n modelProvider: string,\n taskType: string,\n reactiveRunFn: AiProviderReactiveRunFn<Input, Output>\n ) {\n if (!this.reactiveRunFnRegistry.has(taskType)) {\n this.reactiveRunFnRegistry.set(taskType, new Map());\n }\n this.reactiveRunFnRegistry.get(taskType)!.set(modelProvider, reactiveRunFn);\n }\n\n /**\n * Retrieves the reactive execution function for a task type and model provider.\n * Returns undefined if no reactive function is registered (fallback to default behavior).\n */\n getReactiveRunFn<Input extends TaskInput = TaskInput, Output extends TaskOutput = TaskOutput>(\n modelProvider: string,\n taskType: string\n ): AiProviderReactiveRunFn<Input, Output> | undefined {\n const taskTypeMap = this.reactiveRunFnRegistry.get(taskType);\n return taskTypeMap?.get(modelProvider) as AiProviderReactiveRunFn<Input, Output> | undefined;\n }\n\n /**\n * Retrieves the direct execution function for a task type and model\n * Bypasses the job queue system for immediate execution\n */\n getDirectRunFn<Input extends TaskInput = TaskInput, Output extends TaskOutput = TaskOutput>(\n modelProvider: string,\n taskType: string\n ) {\n const taskTypeMap = this.runFnRegistry.get(taskType);\n const runFn = taskTypeMap?.get(modelProvider) as AiProviderRunFn<Input, Output> | undefined;\n if (!runFn) {\n throw new Error(\n `No run function found for task type ${taskType} and model provider ${modelProvider}`\n );\n }\n return runFn;\n }\n}\n\n// Singleton instance management for the ProviderRegistry\nlet providerRegistry: AiProviderRegistry;\nexport function getAiProviderRegistry() {\n if (!providerRegistry) providerRegistry = new AiProviderRegistry();\n return providerRegistry;\n}\nexport function setAiProviderRegistry(pr: AiProviderRegistry) {\n providerRegistry = pr;\n}\n",
7
+ "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { getLogger, type JsonSchema } from \"@workglow/util/worker\";\n\n/**\n * A tool definition that can be passed to an LLM for tool calling.\n * Can be created manually or generated from TaskRegistry entries via `taskTypesToTools` in ToolCallingTask.\n *\n * The `name` is used both as the tool name presented to the LLM and as a\n * lookup key for the backing Task in the TaskRegistry. When a tool is\n * backed by a configurable task (e.g. `McpToolCallTask`, `JavaScriptTask`),\n * `configSchema` describes what configuration the task accepts and `config`\n * provides the concrete values. The LLM never sees `configSchema` or\n * `config` — they are setup-time concerns used when instantiating the task.\n */\nexport interface ToolDefinition {\n name: string;\n description: string;\n inputSchema: JsonSchema;\n outputSchema?: JsonSchema;\n /** JSON Schema describing the task's configuration options. */\n configSchema?: JsonSchema;\n /** Concrete configuration values matching {@link configSchema}. */\n config?: Record<string, unknown>;\n /**\n * Optional custom executor function. When provided, the tool is executed\n * by calling this function directly instead of instantiating a Task.\n */\n execute?: (input: Record<string, unknown>) => Promise<Record<string, unknown>>;\n}\n\n/**\n * A tool call returned by the LLM, requesting invocation of a specific tool.\n */\nexport interface ToolCall {\n id: string;\n name: string;\n input: Record<string, unknown>;\n}\n\nexport type ToolCalls = Array<ToolCall>;\n\n/**\n * Controls which tools the model may call.\n * - `\"auto\"` — model decides whether to call tools\n * - `\"none\"` — model must not call any tools\n * - `\"required\"` — model must call at least one tool\n * - any other string — model must call the tool with that name\n */\nexport type ToolChoiceOption = \"auto\" | \"none\" | \"required\" | (string & {});\n\n/**\n * Builds a tool description string for provider APIs, appending the output\n * schema when present. Shared across all provider implementations.\n */\nexport function buildToolDescription(tool: ToolDefinition): string {\n let desc = tool.description;\n if (tool.outputSchema && typeof tool.outputSchema === \"object\") {\n desc += `\\n\\nReturns: ${JSON.stringify(tool.outputSchema)}`;\n }\n return desc;\n}\n\n/**\n * Validates that a tool call name returned by the LLM matches one of the\n * allowed tool definitions. Returns true if valid, false otherwise.\n */\nexport function isAllowedToolName(\n name: string,\n allowedTools: ReadonlyArray<ToolDefinition>\n): boolean {\n return allowedTools.some((t) => t.name === name);\n}\n\n/**\n * Filters an array of tool calls, removing any whose name does not appear\n * in the provided tools list. Returns the filtered array.\n */\nexport function filterValidToolCalls(\n toolCalls: ToolCalls,\n allowedTools: ReadonlyArray<ToolDefinition>\n): ToolCalls {\n return toolCalls.filter((tc) => {\n if (tc.name && isAllowedToolName(tc.name, allowedTools)) {\n return true;\n }\n getLogger().warn(`Filtered out tool call with unknown name \"${tc.name ?? \"(missing)\"}\"`, {\n callId: tc.id,\n toolName: tc.name,\n });\n return false;\n });\n}\n",
8
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Shared message conversion utilities for converting provider-agnostic\n * ChatMessage arrays to provider-specific formats.\n *\n * These are pure functions safe for both main-thread and worker contexts.\n * Providers with unique requirements (Anthropic, Gemini, LlamaCpp)\n * maintain their own conversion logic.\n */\n\nimport type { ToolCallingTaskInput } from \"./ToolCallingTask\";\n\n// ========================================================================\n// Internal helpers\n// ========================================================================\n\ntype InputMessages = ReadonlyArray<{ readonly role: string; readonly content: unknown }>;\n\n/**\n * Extract the messages array from a ToolCallingTaskInput.\n * Returns undefined if no messages are present.\n */\nfunction getInputMessages(input: ToolCallingTaskInput): InputMessages | undefined {\n const messages = input.messages;\n if (!messages || messages.length === 0) return undefined;\n return messages;\n}\n\n// ========================================================================\n// OpenAI-compatible format (OpenAI, HF Inference)\n// ========================================================================\n\nexport interface OpenAICompatMessage {\n role: string;\n content: string | null | Array<{ type: string; [key: string]: unknown }>;\n tool_calls?: Array<{\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n }>;\n tool_call_id?: string;\n}\n\n/**\n * Converts ToolCallingTaskInput to OpenAI-compatible message format.\n * Used by OpenAI and HuggingFace Inference providers.\n *\n * Multi-turn capable: preserves full tool call metadata across turns.\n */\nexport function toOpenAIMessages(input: ToolCallingTaskInput): OpenAICompatMessage[] {\n const messages: OpenAICompatMessage[] = [];\n\n if (input.systemPrompt) {\n messages.push({ role: \"system\", content: input.systemPrompt });\n }\n\n const inputMessages = getInputMessages(input);\n if (!inputMessages) {\n if (!Array.isArray(input.prompt)) {\n messages.push({ role: \"user\", content: input.prompt });\n } else if (input.prompt.every((item) => typeof item === \"string\")) {\n messages.push({ role: \"user\", content: (input.prompt as string[]).join(\"\\n\") });\n } else {\n const parts: Array<{ type: string; [key: string]: unknown }> = [];\n for (const item of input.prompt) {\n if (typeof item === \"string\") {\n parts.push({ type: \"text\", text: item });\n } else {\n const b = item as Record<string, unknown>;\n if (b.type === \"text\") {\n parts.push({ type: \"text\", text: b.text as string });\n } else if (b.type === \"image\") {\n parts.push({\n type: \"image_url\",\n image_url: { url: `data:${b.mimeType};base64,${b.data}` },\n });\n } else if (b.type === \"audio\") {\n const format = (b.mimeType as string).replace(/^audio\\//, \"\");\n parts.push({\n type: \"input_audio\",\n input_audio: { data: b.data as string, format },\n });\n }\n }\n }\n messages.push({ role: \"user\", content: parts });\n }\n return messages;\n }\n\n for (const msg of inputMessages) {\n if (msg.role === \"user\") {\n if (typeof msg.content === \"string\") {\n messages.push({ role: \"user\", content: msg.content });\n } else if (\n Array.isArray(msg.content) &&\n msg.content.length > 0 &&\n typeof (msg.content[0] as Record<string, unknown>)?.type === \"string\"\n ) {\n const parts: Array<{ type: string; [key: string]: unknown }> = [];\n for (const block of msg.content) {\n const b = block as Record<string, unknown>;\n if (b.type === \"text\") {\n parts.push({ type: \"text\", text: b.text as string });\n } else if (b.type === \"image\") {\n parts.push({\n type: \"image_url\",\n image_url: { url: `data:${b.mimeType};base64,${b.data}` },\n });\n } else if (b.type === \"audio\") {\n const format = (b.mimeType as string).replace(/^audio\\//, \"\");\n parts.push({\n type: \"input_audio\",\n input_audio: { data: b.data as string, format },\n });\n }\n }\n messages.push({ role: \"user\", content: parts });\n } else {\n try {\n messages.push({ role: \"user\", content: JSON.stringify(msg.content) });\n } catch {\n messages.push({ role: \"user\", content: String(msg.content) });\n }\n }\n } else if (msg.role === \"assistant\") {\n if (typeof msg.content === \"string\") {\n messages.push({ role: \"assistant\", content: msg.content.length > 0 ? msg.content : null });\n } else if (Array.isArray(msg.content)) {\n const textParts = msg.content\n .filter((b: Record<string, unknown>) => b.type === \"text\")\n .map((b: Record<string, unknown>) => b.text as string)\n .join(\"\");\n const toolCalls = msg.content\n .filter((b: Record<string, unknown>) => b.type === \"tool_use\")\n .map((b: Record<string, unknown>) => ({\n id: b.id as string,\n type: \"function\" as const,\n function: {\n name: b.name as string,\n arguments: JSON.stringify(b.input),\n },\n }));\n const entry: OpenAICompatMessage = {\n role: \"assistant\",\n content: textParts.length > 0 ? textParts : null,\n };\n if (toolCalls.length > 0) {\n entry.tool_calls = toolCalls;\n }\n messages.push(entry);\n }\n } else if (msg.role === \"tool\" && Array.isArray(msg.content)) {\n for (const block of msg.content) {\n const b = block as Record<string, unknown>;\n let content: string | Array<{ type: string; [key: string]: unknown }>;\n if (typeof b.content === \"string\") {\n content = b.content;\n } else if (Array.isArray(b.content)) {\n const parts: Array<{ type: string; [key: string]: unknown }> = [];\n for (const inner of b.content as Array<Record<string, unknown>>) {\n if (inner.type === \"text\") {\n parts.push({ type: \"text\", text: inner.text as string });\n } else if (inner.type === \"image\") {\n parts.push({\n type: \"image_url\",\n image_url: { url: `data:${inner.mimeType};base64,${inner.data}` },\n });\n }\n }\n content = parts;\n } else {\n content = \"\";\n }\n messages.push({\n role: \"tool\",\n content,\n tool_call_id: b.tool_use_id as string,\n });\n }\n }\n }\n\n return messages;\n}\n\n// ========================================================================\n// Text-flat format (Ollama, HF Transformers)\n// ========================================================================\n\nexport interface TextFlatMessage {\n role: string;\n content: string;\n}\n\n/**\n * Converts ToolCallingTaskInput to a simplified text-only message format.\n * Used by providers that don't natively support structured multi-turn\n * tool calling (Ollama, HuggingFace Transformers).\n *\n * NOTE: This format discards tool_use blocks from assistant messages.\n * The LLM will not see what tools it previously called. Multi-turn tool\n * calling will have degraded quality on these providers.\n */\nexport function toTextFlatMessages(input: ToolCallingTaskInput): TextFlatMessage[] {\n const messages: TextFlatMessage[] = [];\n\n if (input.systemPrompt) {\n messages.push({ role: \"system\", content: input.systemPrompt });\n }\n\n const inputMessages = getInputMessages(input);\n if (!inputMessages) {\n let promptContent: string;\n if (!Array.isArray(input.prompt)) {\n promptContent = input.prompt;\n } else {\n // Extract text content only; media blocks are dropped in text-flat format\n promptContent = input.prompt\n .map((item) => {\n if (typeof item === \"string\") return item;\n const b = item as Record<string, unknown>;\n return b.type === \"text\" ? (b.text as string) : \"\";\n })\n .filter((s) => s !== \"\")\n .join(\"\\n\");\n }\n messages.push({ role: \"user\", content: promptContent });\n return messages;\n }\n\n for (const msg of inputMessages) {\n if (msg.role === \"user\") {\n let content = \"\";\n if (typeof msg.content === \"string\") {\n content = msg.content;\n } else if (\n Array.isArray(msg.content) &&\n msg.content.length > 0 &&\n typeof (msg.content[0] as Record<string, unknown>)?.type === \"string\"\n ) {\n // Extract only text blocks; media blocks are dropped in text-flat format\n content = (msg.content as Array<Record<string, unknown>>)\n .filter((b) => b.type === \"text\")\n .map((b) => b.text as string)\n .join(\"\");\n } else if (msg.content != null) {\n try {\n content = JSON.stringify(msg.content);\n } catch {\n content = String(msg.content);\n }\n }\n messages.push({ role: \"user\", content });\n } else if (msg.role === \"assistant\") {\n if (typeof msg.content === \"string\") {\n if (msg.content) {\n messages.push({ role: \"assistant\", content: msg.content });\n }\n } else if (Array.isArray(msg.content)) {\n const text = msg.content\n .filter((b: Record<string, unknown>) => b.type === \"text\")\n .map((b: Record<string, unknown>) => b.text as string)\n .join(\"\");\n if (text) {\n messages.push({ role: \"assistant\", content: text });\n }\n }\n } else if (msg.role === \"tool\" && Array.isArray(msg.content)) {\n for (const block of msg.content) {\n const b = block as Record<string, unknown>;\n let content: string;\n if (typeof b.content === \"string\") {\n content = b.content;\n } else if (Array.isArray(b.content)) {\n // Extract only text blocks from multi-part tool results\n content = (b.content as Array<Record<string, unknown>>)\n .filter((inner) => inner.type === \"text\")\n .map((inner) => inner.text as string)\n .join(\"\");\n } else {\n content = \"\";\n }\n messages.push({ role: \"tool\", content });\n }\n }\n }\n\n return messages;\n}\n",
9
+ "/**\n * @license\n * Copyright 2025 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { DataPortSchemaObject, FromSchema } from \"@workglow/util/worker\";\n\n/**\n * A model configuration suitable for task/job inputs.\n *\n * @remarks\n * This is intentionally less strict than {@link ModelRecord} so jobs can carry only the\n * provider configuration required to execute, without requiring access to a model repository.\n */\nexport const ModelConfigSchema = {\n type: \"object\",\n properties: {\n model_id: { type: \"string\" },\n tasks: { type: \"array\", items: { type: \"string\" }, \"x-ui-editor\": \"multiselect\" },\n title: { type: \"string\" },\n description: { type: \"string\", \"x-ui-editor\": \"textarea\" },\n provider: { type: \"string\" },\n provider_config: {\n type: \"object\",\n properties: {\n credential_key: { type: \"string\", format: \"credential\", \"x-ui-hidden\": true },\n },\n additionalProperties: true,\n default: {},\n },\n metadata: { type: \"object\", default: {}, \"x-ui-hidden\": true },\n },\n required: [\"provider\", \"provider_config\"],\n format: \"model\",\n additionalProperties: true,\n} as const satisfies DataPortSchemaObject;\n\n/**\n * A fully-specified model record suitable for persistence in a repository.\n */\nexport const ModelRecordSchema = {\n type: \"object\",\n properties: {\n ...ModelConfigSchema.properties,\n },\n required: [\n \"model_id\",\n \"tasks\",\n \"provider\",\n \"title\",\n \"description\",\n \"provider_config\",\n \"metadata\",\n ],\n format: \"model\",\n additionalProperties: false,\n} as const satisfies DataPortSchemaObject;\n\nexport type ModelConfig = FromSchema<typeof ModelConfigSchema>;\nexport type ModelRecord = FromSchema<typeof ModelRecordSchema>;\nexport const ModelPrimaryKeyNames = [\"model_id\"] as const;\n"
10
+ ],
11
+ "mappings": "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",
12
+ "debugId": "4D2BD86FECB58DEF64756E2164756E21",
13
+ "names": []
14
+ }