@eko-ai/eko 1.0.8 → 1.0.10
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/LICENSE +21 -21
- package/README.md +139 -131
- package/dist/core/eko.d.ts +3 -2
- package/dist/extension/script/bing.js +0 -0
- package/dist/extension/script/build_dom_tree.js +661 -661
- package/dist/extension/script/common.js +0 -0
- package/dist/extension/script/duckduckgo.js +0 -0
- package/dist/extension/script/google.js +0 -0
- package/dist/extension/tools/cancel_workflow.d.ts +9 -0
- package/dist/extension/tools/get_all_tabs.d.ts +9 -0
- package/dist/extension/tools/index.d.ts +3 -1
- package/dist/extension/tools/tab_management.d.ts +1 -1
- package/dist/extension/utils.d.ts +1 -1
- package/dist/extension.cjs.js +749 -278
- package/dist/extension.esm.js +749 -278
- package/dist/extension_content_script.js +55 -55
- package/dist/fellou.cjs.js +18 -18
- package/dist/fellou.esm.js +18 -18
- package/dist/index.cjs.js +2034 -1609
- package/dist/index.d.ts +3 -1
- package/dist/index.esm.js +2033 -1610
- package/dist/jest.config.js +10 -0
- package/dist/jest.config.js.map +1 -0
- package/dist/models/action.d.ts +8 -4
- package/dist/models/workflow.d.ts +8 -3
- package/dist/nodejs/tools/index.d.ts +1 -0
- package/dist/nodejs.cjs.js +1832 -1623
- package/dist/nodejs.esm.js +1832 -1623
- package/dist/rollup.config.js +171 -0
- package/dist/rollup.config.js.map +1 -0
- package/dist/schemas/workflow.schema.d.ts +2 -13
- package/dist/script.js +10 -0
- package/dist/script.js.map +1 -0
- package/dist/services/llm/claude-provider.d.ts +2 -1
- package/dist/services/llm/deepseek-provider.d.ts +13 -0
- package/dist/services/llm/openai-provider.d.ts +2 -1
- package/dist/services/llm/provider-factory.d.ts +4 -0
- package/dist/services/llm/siliconflow-provider.d.ts +13 -0
- package/dist/services/parser/workflow-parser.d.ts +0 -7
- package/dist/services/workflow/generator.d.ts +1 -0
- package/dist/src/core/eko.js +99 -0
- package/dist/src/core/eko.js.map +1 -0
- package/dist/src/core/tool-registry.js +51 -0
- package/dist/src/core/tool-registry.js.map +1 -0
- package/dist/src/extension/content/index.js +409 -0
- package/dist/src/extension/content/index.js.map +1 -0
- package/dist/src/extension/core.js +29 -0
- package/dist/src/extension/core.js.map +1 -0
- package/dist/src/extension/index.js +12 -0
- package/dist/src/extension/index.js.map +1 -0
- package/dist/src/extension/script/bing.js +25 -0
- package/dist/src/extension/script/bing.js.map +1 -0
- package/dist/src/extension/script/build_dom_tree.js +585 -0
- package/dist/src/extension/script/build_dom_tree.js.map +1 -0
- package/dist/src/extension/script/common.js +203 -0
- package/dist/src/extension/script/common.js.map +1 -0
- package/dist/src/extension/script/duckduckgo.js +25 -0
- package/dist/src/extension/script/duckduckgo.js.map +1 -0
- package/dist/src/extension/script/google.js +26 -0
- package/dist/src/extension/script/google.js.map +1 -0
- package/dist/src/extension/tools/browser.js +174 -0
- package/dist/src/extension/tools/browser.js.map +1 -0
- package/dist/src/extension/tools/browser_use.js +186 -0
- package/dist/src/extension/tools/browser_use.js.map +1 -0
- package/dist/src/extension/tools/element_click.js +123 -0
- package/dist/src/extension/tools/element_click.js.map +1 -0
- package/dist/src/extension/tools/export_file.js +93 -0
- package/dist/src/extension/tools/export_file.js.map +1 -0
- package/dist/src/extension/tools/extract_content.js +38 -0
- package/dist/src/extension/tools/extract_content.js.map +1 -0
- package/dist/src/extension/tools/find_element_position.js +125 -0
- package/dist/src/extension/tools/find_element_position.js.map +1 -0
- package/dist/src/extension/tools/html_script.js +219 -0
- package/dist/src/extension/tools/html_script.js.map +1 -0
- package/dist/src/extension/tools/index.js +12 -0
- package/dist/src/extension/tools/index.js.map +1 -0
- package/dist/src/extension/tools/open_url.js +68 -0
- package/dist/src/extension/tools/open_url.js.map +1 -0
- package/dist/src/extension/tools/request_login.js +87 -0
- package/dist/src/extension/tools/request_login.js.map +1 -0
- package/dist/src/extension/tools/screenshot.js +26 -0
- package/dist/src/extension/tools/screenshot.js.map +1 -0
- package/dist/src/extension/tools/tab_management.js +160 -0
- package/dist/src/extension/tools/tab_management.js.map +1 -0
- package/dist/src/extension/tools/web_search.js +281 -0
- package/dist/src/extension/tools/web_search.js.map +1 -0
- package/dist/src/extension/utils.js +244 -0
- package/dist/src/extension/utils.js.map +1 -0
- package/dist/src/fellou/computer.js +104 -0
- package/dist/src/fellou/computer.js.map +1 -0
- package/dist/src/fellou/index.js +7 -0
- package/dist/src/fellou/index.js.map +1 -0
- package/dist/src/fellou/tools/computer_use.js +111 -0
- package/dist/src/fellou/tools/computer_use.js.map +1 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/models/action.js +364 -0
- package/dist/src/models/action.js.map +1 -0
- package/dist/src/models/workflow.js +120 -0
- package/dist/src/models/workflow.js.map +1 -0
- package/dist/src/nodejs/core.js +18 -0
- package/dist/src/nodejs/core.js.map +1 -0
- package/dist/src/nodejs/index.js +6 -0
- package/dist/src/nodejs/index.js.map +1 -0
- package/dist/src/nodejs/script/build_dom_tree.js +586 -0
- package/dist/src/nodejs/script/build_dom_tree.js.map +1 -0
- package/dist/src/nodejs/tools/browser_use.js +458 -0
- package/dist/src/nodejs/tools/browser_use.js.map +1 -0
- package/dist/src/nodejs/tools/command_execute.js +65 -0
- package/dist/src/nodejs/tools/command_execute.js.map +1 -0
- package/dist/src/nodejs/tools/file_read.js +45 -0
- package/dist/src/nodejs/tools/file_read.js.map +1 -0
- package/dist/src/nodejs/tools/file_write.js +95 -0
- package/dist/src/nodejs/tools/file_write.js.map +1 -0
- package/dist/src/nodejs/tools/index.js +5 -0
- package/dist/src/nodejs/tools/index.js.map +1 -0
- package/dist/src/schemas/workflow.schema.js +64 -0
- package/dist/src/schemas/workflow.schema.js.map +1 -0
- package/dist/src/services/llm/claude-provider.js +140 -0
- package/dist/src/services/llm/claude-provider.js.map +1 -0
- package/dist/src/services/llm/deepseek-provider.js +432 -0
- package/dist/src/services/llm/deepseek-provider.js.map +1 -0
- package/dist/src/services/llm/glm-provider.js +317 -0
- package/dist/src/services/llm/glm-provider.js.map +1 -0
- package/dist/src/services/llm/openai-provider copy.js +317 -0
- package/dist/src/services/llm/openai-provider copy.js.map +1 -0
- package/dist/src/services/llm/openai-provider.js +317 -0
- package/dist/src/services/llm/openai-provider.js.map +1 -0
- package/dist/src/services/parser/workflow-parser.js +208 -0
- package/dist/src/services/parser/workflow-parser.js.map +1 -0
- package/dist/src/services/workflow/generator.js +105 -0
- package/dist/src/services/workflow/generator.js.map +1 -0
- package/dist/src/services/workflow/templates.js +42 -0
- package/dist/src/services/workflow/templates.js.map +1 -0
- package/dist/src/types/action.types.js +2 -0
- package/dist/src/types/action.types.js.map +1 -0
- package/dist/src/types/eko.types.js +2 -0
- package/dist/src/types/eko.types.js.map +1 -0
- package/dist/src/types/index.js +6 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/types/llm.types.js +2 -0
- package/dist/src/types/llm.types.js.map +1 -0
- package/dist/src/types/parser.types.js +2 -0
- package/dist/src/types/parser.types.js.map +1 -0
- package/dist/src/types/tools.types.js +2 -0
- package/dist/src/types/tools.types.js.map +1 -0
- package/dist/src/types/workflow.types.js +3 -0
- package/dist/src/types/workflow.types.js.map +1 -0
- package/dist/src/web/core.js +18 -0
- package/dist/src/web/core.js.map +1 -0
- package/dist/src/web/index.js +9 -0
- package/dist/src/web/index.js.map +1 -0
- package/dist/src/web/script/build_dom_tree.js +584 -0
- package/dist/src/web/script/build_dom_tree.js.map +1 -0
- package/dist/src/web/tools/browser.js +249 -0
- package/dist/src/web/tools/browser.js.map +1 -0
- package/dist/src/web/tools/browser_use.js +176 -0
- package/dist/src/web/tools/browser_use.js.map +1 -0
- package/dist/src/web/tools/element_click.js +121 -0
- package/dist/src/web/tools/element_click.js.map +1 -0
- package/dist/src/web/tools/export_file.js +74 -0
- package/dist/src/web/tools/export_file.js.map +1 -0
- package/dist/src/web/tools/extract_content.js +24 -0
- package/dist/src/web/tools/extract_content.js.map +1 -0
- package/dist/src/web/tools/find_element_position.js +121 -0
- package/dist/src/web/tools/find_element_position.js.map +1 -0
- package/dist/src/web/tools/html_script.js +219 -0
- package/dist/src/web/tools/html_script.js.map +1 -0
- package/dist/src/web/tools/index.js +8 -0
- package/dist/src/web/tools/index.js.map +1 -0
- package/dist/src/web/tools/screenshot.js +24 -0
- package/dist/src/web/tools/screenshot.js.map +1 -0
- package/dist/test/integration/claude-provider.test.js +170 -0
- package/dist/test/integration/claude-provider.test.js.map +1 -0
- package/dist/test/integration/deepseek-provider.test.js +171 -0
- package/dist/test/integration/deepseek-provider.test.js.map +1 -0
- package/dist/test/integration/glm-provider.test.js +173 -0
- package/dist/test/integration/glm-provider.test.js.map +1 -0
- package/dist/test/integration/openai-provider.test copy.js +170 -0
- package/dist/test/integration/openai-provider.test copy.js.map +1 -0
- package/dist/test/integration/openai-provider.test.js +170 -0
- package/dist/test/integration/openai-provider.test.js.map +1 -0
- package/dist/test/integration/qwen-provider.js +170 -0
- package/dist/test/integration/qwen-provider.js.map +1 -0
- package/dist/test/integration/qwen-provider.test copy.js +170 -0
- package/dist/test/integration/qwen-provider.test copy.js.map +1 -0
- package/dist/test/integration/qwen-provider.test.js +170 -0
- package/dist/test/integration/qwen-provider.test.js.map +1 -0
- package/dist/test/integration/workflow.execution.test.js +152 -0
- package/dist/test/integration/workflow.execution.test.js.map +1 -0
- package/dist/test/integration/workflow.generation-and-execution.test.js +131 -0
- package/dist/test/integration/workflow.generation-and-execution.test.js.map +1 -0
- package/dist/test/integration/workflow.generator.test.js +207 -0
- package/dist/test/integration/workflow.generator.test.js.map +1 -0
- package/dist/test/unit/action.test.js +186 -0
- package/dist/test/unit/action.test.js.map +1 -0
- package/dist/test/unit/tool-registry.test.js +99 -0
- package/dist/test/unit/tool-registry.test.js.map +1 -0
- package/dist/test/unit/workflow-parser.test.js +189 -0
- package/dist/test/unit/workflow-parser.test.js.map +1 -0
- package/dist/test/unit/workflow.test.js +102 -0
- package/dist/test/unit/workflow.test.js.map +1 -0
- package/dist/types/action.types.d.ts +8 -3
- package/dist/types/jest.config.d.ts +10 -0
- package/dist/types/rollup.config.d.ts +16 -0
- package/dist/types/script.d.ts +1 -0
- package/dist/types/src/core/eko.d.ts +20 -0
- package/dist/types/src/core/tool-registry.d.ts +13 -0
- package/dist/types/src/extension/content/index.d.ts +16 -0
- package/dist/types/src/extension/core.d.ts +11 -0
- package/dist/types/src/extension/index.d.ts +7 -0
- package/dist/types/src/extension/script/bing.d.ts +0 -0
- package/dist/types/src/extension/script/build_dom_tree.d.ts +38 -0
- package/dist/types/src/extension/script/common.d.ts +0 -0
- package/dist/types/src/extension/script/duckduckgo.d.ts +0 -0
- package/dist/types/src/extension/script/google.d.ts +0 -0
- package/dist/types/src/extension/tools/browser.d.ts +22 -0
- package/dist/types/src/extension/tools/browser_use.d.ts +19 -0
- package/dist/types/src/extension/tools/element_click.d.ts +12 -0
- package/dist/types/src/extension/tools/export_file.d.ts +18 -0
- package/dist/types/src/extension/tools/extract_content.d.ts +18 -0
- package/dist/types/src/extension/tools/find_element_position.d.ts +12 -0
- package/dist/types/src/extension/tools/html_script.d.ts +10 -0
- package/dist/types/src/extension/tools/index.d.ts +11 -0
- package/dist/types/src/extension/tools/open_url.d.ts +18 -0
- package/dist/{extension/tools/form_autofill.d.ts → types/src/extension/tools/request_login.d.ts} +3 -4
- package/dist/types/src/extension/tools/screenshot.d.ts +18 -0
- package/dist/types/src/extension/tools/tab_management.d.ts +19 -0
- package/dist/types/src/extension/tools/web_search.d.ts +18 -0
- package/dist/types/src/extension/utils.d.ts +31 -0
- package/dist/types/src/fellou/computer.d.ts +20 -0
- package/dist/types/src/fellou/index.d.ts +6 -0
- package/dist/types/src/fellou/tools/computer_use.d.ts +18 -0
- package/dist/types/src/index.d.ts +8 -0
- package/dist/types/src/models/action.d.ts +22 -0
- package/dist/types/src/models/workflow.d.ts +16 -0
- package/dist/types/src/nodejs/core.d.ts +2 -0
- package/dist/types/src/nodejs/index.d.ts +3 -0
- package/dist/types/src/nodejs/script/build_dom_tree.d.ts +1 -0
- package/dist/types/src/nodejs/tools/browser_use.d.ts +28 -0
- package/dist/types/src/nodejs/tools/command_execute.d.ts +12 -0
- package/dist/types/src/nodejs/tools/file_read.d.ts +11 -0
- package/dist/types/src/nodejs/tools/file_write.d.ts +15 -0
- package/dist/types/src/nodejs/tools/index.d.ts +4 -0
- package/dist/types/src/schemas/workflow.schema.d.ts +88 -0
- package/dist/types/src/services/llm/claude-provider.d.ts +11 -0
- package/dist/types/src/services/llm/deepseek-provider.d.ts +15 -0
- package/dist/types/src/services/llm/glm-provider.d.ts +11 -0
- package/dist/types/src/services/llm/openai-provider copy.d.ts +11 -0
- package/dist/types/src/services/llm/openai-provider.d.ts +11 -0
- package/dist/types/src/services/parser/workflow-parser.d.ts +29 -0
- package/dist/types/src/services/workflow/generator.d.ts +13 -0
- package/dist/types/src/services/workflow/templates.d.ts +8 -0
- package/dist/types/src/types/action.types.d.ts +38 -0
- package/dist/types/src/types/eko.types.d.ts +21 -0
- package/dist/types/src/types/index.d.ts +5 -0
- package/dist/types/src/types/llm.types.d.ts +54 -0
- package/dist/types/src/types/parser.types.d.ts +9 -0
- package/dist/types/src/types/tools.types.d.ts +88 -0
- package/dist/types/src/types/workflow.types.d.ts +39 -0
- package/dist/types/src/web/core.d.ts +2 -0
- package/dist/types/src/web/index.d.ts +5 -0
- package/dist/types/src/web/script/build_dom_tree.d.ts +10 -0
- package/dist/types/src/web/tools/browser.d.ts +21 -0
- package/dist/types/src/web/tools/browser_use.d.ts +19 -0
- package/dist/types/src/web/tools/element_click.d.ts +12 -0
- package/dist/types/src/web/tools/export_file.d.ts +18 -0
- package/dist/types/src/web/tools/extract_content.d.ts +17 -0
- package/dist/types/src/web/tools/find_element_position.d.ts +12 -0
- package/dist/types/src/web/tools/html_script.d.ts +10 -0
- package/dist/types/src/web/tools/index.d.ts +7 -0
- package/dist/types/src/web/tools/screenshot.d.ts +18 -0
- package/dist/types/test/integration/claude-provider.test.d.ts +1 -0
- package/dist/types/test/integration/deepseek-provider.test.d.ts +1 -0
- package/dist/types/test/integration/glm-provider.test.d.ts +1 -0
- package/dist/types/test/integration/openai-provider.test copy.d.ts +1 -0
- package/dist/types/test/integration/openai-provider.test.d.ts +1 -0
- package/dist/types/test/integration/qwen-provider.d.ts +1 -0
- package/dist/types/test/integration/qwen-provider.test copy.d.ts +1 -0
- package/dist/types/test/integration/qwen-provider.test.d.ts +1 -0
- package/dist/types/test/integration/workflow.execution.test.d.ts +1 -0
- package/dist/types/test/integration/workflow.generation-and-execution.test.d.ts +1 -0
- package/dist/types/test/integration/workflow.generator.test.d.ts +1 -0
- package/dist/types/test/unit/action.test.d.ts +1 -0
- package/dist/types/test/unit/tool-registry.test.d.ts +1 -0
- package/dist/types/test/unit/workflow-parser.test.d.ts +1 -0
- package/dist/types/test/unit/workflow.test.d.ts +1 -0
- package/dist/types/tools.types.d.ts +44 -1
- package/dist/types/workflow.types.d.ts +22 -9
- package/dist/universal_tools/cancel_workflow.d.ts +9 -0
- package/dist/universal_tools/human/text.d.ts +9 -0
- package/dist/universal_tools/human.d.ts +30 -0
- package/dist/universal_tools/index.d.ts +4 -0
- package/dist/universal_tools/summary_workflow.d.ts +9 -0
- package/dist/utils/execution-logger.d.ts +69 -0
- package/dist/web.cjs.js +117 -117
- package/dist/web.esm.js +117 -117
- package/package.json +106 -107
- package/dist/fellou/tools/index.d.ts +0 -2
- package/dist/types/framework.types.d.ts +0 -11
package/dist/index.esm.js
CHANGED
|
@@ -1,933 +1,255 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
const VERSION$1 = '0.33.1'; // x-release-please-version
|
|
2
|
+
|
|
3
|
+
let auto$1 = false;
|
|
4
|
+
let kind$1 = undefined;
|
|
5
|
+
let fetch$2 = undefined;
|
|
6
|
+
let File$2 = undefined;
|
|
7
|
+
let ReadableStream$2 = undefined;
|
|
8
|
+
let getDefaultAgent$1 = undefined;
|
|
9
|
+
let fileFromPath$1 = undefined;
|
|
10
|
+
function setShims$1(shims, options = { auto: false }) {
|
|
11
|
+
if (auto$1) {
|
|
12
|
+
throw new Error(`you must \`import '@anthropic-ai/sdk/shims/${shims.kind}'\` before importing anything else from @anthropic-ai/sdk`);
|
|
9
13
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (!this.validateDAG()) {
|
|
13
|
-
throw new Error("Invalid workflow: Contains circular dependencies");
|
|
14
|
-
}
|
|
15
|
-
this.abort = false;
|
|
16
|
-
callback && await ((_b = (_a = callback.hooks).beforeWorkflow) === null || _b === void 0 ? void 0 : _b.call(_a, this));
|
|
17
|
-
const executed = new Set();
|
|
18
|
-
const executing = new Set();
|
|
19
|
-
const executeNode = async (nodeId) => {
|
|
20
|
-
var _a, _b, _c, _d, _e;
|
|
21
|
-
if (this.abort) {
|
|
22
|
-
throw new Error("Abort");
|
|
23
|
-
}
|
|
24
|
-
if (executed.has(nodeId)) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (executing.has(nodeId)) {
|
|
28
|
-
throw new Error(`Circular dependency detected at node: ${nodeId}`);
|
|
29
|
-
}
|
|
30
|
-
const node = this.getNode(nodeId);
|
|
31
|
-
// Execute the node's action
|
|
32
|
-
const context = {
|
|
33
|
-
__skip: false,
|
|
34
|
-
__abort: false,
|
|
35
|
-
variables: this.variables,
|
|
36
|
-
llmProvider: this.llmProvider,
|
|
37
|
-
tools: new Map(node.action.tools.map(tool => [tool.name, tool])),
|
|
38
|
-
callback,
|
|
39
|
-
next: () => context.__skip = true,
|
|
40
|
-
abortAll: () => this.abort = context.__abort = true,
|
|
41
|
-
};
|
|
42
|
-
callback && await ((_b = (_a = callback.hooks).beforeSubtask) === null || _b === void 0 ? void 0 : _b.call(_a, node, context));
|
|
43
|
-
if (context.__abort) {
|
|
44
|
-
throw new Error("Abort");
|
|
45
|
-
}
|
|
46
|
-
else if (context.__skip) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
executing.add(nodeId);
|
|
50
|
-
// Execute dependencies first
|
|
51
|
-
for (const depId of node.dependencies) {
|
|
52
|
-
await executeNode(depId);
|
|
53
|
-
}
|
|
54
|
-
// Prepare input by gathering outputs from dependencies
|
|
55
|
-
const input = {};
|
|
56
|
-
for (const depId of node.dependencies) {
|
|
57
|
-
const depNode = this.getNode(depId);
|
|
58
|
-
input[depId] = depNode.output.value;
|
|
59
|
-
}
|
|
60
|
-
node.input.value = input;
|
|
61
|
-
node.output.value = await node.action.execute(node.input.value, context);
|
|
62
|
-
executing.delete(nodeId);
|
|
63
|
-
executed.add(nodeId);
|
|
64
|
-
callback && await ((_d = (_c = callback.hooks).afterSubtask) === null || _d === void 0 ? void 0 : _d.call(_c, node, context, (_e = node.output) === null || _e === void 0 ? void 0 : _e.value));
|
|
65
|
-
};
|
|
66
|
-
// Execute all terminal nodes (nodes with no dependents)
|
|
67
|
-
const terminalNodes = this.nodes.filter(node => !this.nodes.some(n => n.dependencies.includes(node.id)));
|
|
68
|
-
await Promise.all(terminalNodes.map(node => executeNode(node.id)));
|
|
69
|
-
callback && await ((_d = (_c = callback.hooks).afterWorkflow) === null || _d === void 0 ? void 0 : _d.call(_c, this, this.variables));
|
|
14
|
+
if (kind$1) {
|
|
15
|
+
throw new Error(`can't \`import '@anthropic-ai/sdk/shims/${shims.kind}'\` after \`import '@anthropic-ai/sdk/shims/${kind$1}'\``);
|
|
70
16
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
17
|
+
auto$1 = options.auto;
|
|
18
|
+
kind$1 = shims.kind;
|
|
19
|
+
fetch$2 = shims.fetch;
|
|
20
|
+
File$2 = shims.File;
|
|
21
|
+
ReadableStream$2 = shims.ReadableStream;
|
|
22
|
+
getDefaultAgent$1 = shims.getDefaultAgent;
|
|
23
|
+
fileFromPath$1 = shims.fileFromPath;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Disclaimer: modules in _shims aren't intended to be imported by SDK users.
|
|
28
|
+
*/
|
|
29
|
+
let MultipartBody$1 = class MultipartBody {
|
|
30
|
+
constructor(body) {
|
|
31
|
+
this.body = body;
|
|
76
32
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (index === -1) {
|
|
80
|
-
throw new Error(`Node with id ${nodeId} not found`);
|
|
81
|
-
}
|
|
82
|
-
// Check if any nodes depend on this one
|
|
83
|
-
const dependentNodes = this.nodes.filter(n => n.dependencies.includes(nodeId));
|
|
84
|
-
if (dependentNodes.length > 0) {
|
|
85
|
-
throw new Error(`Cannot remove node ${nodeId}: Nodes ${dependentNodes.map(n => n.id).join(", ")} depend on it`);
|
|
86
|
-
}
|
|
87
|
-
this.nodes.splice(index, 1);
|
|
33
|
+
get [Symbol.toStringTag]() {
|
|
34
|
+
return 'MultipartBody';
|
|
88
35
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
function getRuntime$1({ manuallyImported } = {}) {
|
|
39
|
+
const recommendation = manuallyImported ?
|
|
40
|
+
`You may need to use polyfills`
|
|
41
|
+
: `Add one of these imports before your first \`import … from '@anthropic-ai/sdk'\`:
|
|
42
|
+
- \`import '@anthropic-ai/sdk/shims/node'\` (if you're running on Node)
|
|
43
|
+
- \`import '@anthropic-ai/sdk/shims/web'\` (otherwise)
|
|
44
|
+
`;
|
|
45
|
+
let _fetch, _Request, _Response, _Headers;
|
|
46
|
+
try {
|
|
47
|
+
// @ts-ignore
|
|
48
|
+
_fetch = fetch;
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
_Request = Request;
|
|
51
|
+
// @ts-ignore
|
|
52
|
+
_Response = Response;
|
|
53
|
+
// @ts-ignore
|
|
54
|
+
_Headers = Headers;
|
|
95
55
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
56
|
+
catch (error) {
|
|
57
|
+
throw new Error(`this environment is missing the following Web Fetch API type: ${error.message}. ${recommendation}`);
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
kind: 'web',
|
|
61
|
+
fetch: _fetch,
|
|
62
|
+
Request: _Request,
|
|
63
|
+
Response: _Response,
|
|
64
|
+
Headers: _Headers,
|
|
65
|
+
FormData:
|
|
66
|
+
// @ts-ignore
|
|
67
|
+
typeof FormData !== 'undefined' ? FormData : (class FormData {
|
|
68
|
+
// @ts-ignore
|
|
69
|
+
constructor() {
|
|
70
|
+
throw new Error(`file uploads aren't supported in this environment yet as 'FormData' is undefined. ${recommendation}`);
|
|
102
71
|
}
|
|
103
|
-
|
|
104
|
-
|
|
72
|
+
}),
|
|
73
|
+
Blob: typeof Blob !== 'undefined' ? Blob : (class Blob {
|
|
74
|
+
constructor() {
|
|
75
|
+
throw new Error(`file uploads aren't supported in this environment yet as 'Blob' is undefined. ${recommendation}`);
|
|
105
76
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
77
|
+
}),
|
|
78
|
+
File:
|
|
79
|
+
// @ts-ignore
|
|
80
|
+
typeof File !== 'undefined' ? File : (class File {
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
constructor() {
|
|
83
|
+
throw new Error(`file uploads aren't supported in this environment yet as 'File' is undefined. ${recommendation}`);
|
|
113
84
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
85
|
+
}),
|
|
86
|
+
ReadableStream:
|
|
87
|
+
// @ts-ignore
|
|
88
|
+
typeof ReadableStream !== 'undefined' ? ReadableStream : (class ReadableStream {
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
constructor() {
|
|
91
|
+
throw new Error(`streaming isn't supported in this environment yet as 'ReadableStream' is undefined. ${recommendation}`);
|
|
92
|
+
}
|
|
93
|
+
}),
|
|
94
|
+
getMultipartRequestOptions: async (
|
|
95
|
+
// @ts-ignore
|
|
96
|
+
form, opts) => ({
|
|
97
|
+
...opts,
|
|
98
|
+
body: new MultipartBody$1(form),
|
|
99
|
+
}),
|
|
100
|
+
getDefaultAgent: (url) => undefined,
|
|
101
|
+
fileFromPath: () => {
|
|
102
|
+
throw new Error('The `fileFromPath` function is only supported in Node. See the README for more details: https://www.github.com/anthropics/anthropic-sdk-typescript#file-uploads');
|
|
103
|
+
},
|
|
104
|
+
isFsReadStream: (value) => false,
|
|
105
|
+
};
|
|
119
106
|
}
|
|
120
107
|
|
|
121
|
-
// src/models/action.ts
|
|
122
108
|
/**
|
|
123
|
-
*
|
|
109
|
+
* Disclaimer: modules in _shims aren't intended to be imported by SDK users.
|
|
124
110
|
*/
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
type: 'string',
|
|
138
|
-
description: 'The value to store (must be JSON stringified if object/array)',
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
required: ['key', 'value'],
|
|
142
|
-
};
|
|
111
|
+
if (!kind$1) setShims$1(getRuntime$1(), { auto: true });
|
|
112
|
+
|
|
113
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
114
|
+
class AnthropicError extends Error {
|
|
115
|
+
}
|
|
116
|
+
let APIError$1 = class APIError extends AnthropicError {
|
|
117
|
+
constructor(status, error, message, headers) {
|
|
118
|
+
super(`${APIError.makeMessage(status, error, message)}`);
|
|
119
|
+
this.status = status;
|
|
120
|
+
this.headers = headers;
|
|
121
|
+
this.request_id = headers?.['request-id'];
|
|
122
|
+
this.error = error;
|
|
143
123
|
}
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
124
|
+
static makeMessage(status, error, message) {
|
|
125
|
+
const msg = error?.message ?
|
|
126
|
+
typeof error.message === 'string' ?
|
|
127
|
+
error.message
|
|
128
|
+
: JSON.stringify(error.message)
|
|
129
|
+
: error ? JSON.stringify(error)
|
|
130
|
+
: message;
|
|
131
|
+
if (status && msg) {
|
|
132
|
+
return `${status} ${msg}`;
|
|
150
133
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
context.variables.set(key, value);
|
|
134
|
+
if (status) {
|
|
135
|
+
return `${status} status code (no body)`;
|
|
154
136
|
}
|
|
155
|
-
|
|
137
|
+
if (msg) {
|
|
138
|
+
return msg;
|
|
139
|
+
}
|
|
140
|
+
return '(no status code or body)';
|
|
156
141
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
name: 'return_output',
|
|
161
|
-
description: 'Return the final output of this action. Use this to return a value matching the required output schema.',
|
|
162
|
-
input_schema: {
|
|
163
|
-
type: 'object',
|
|
164
|
-
properties: {
|
|
165
|
-
value: outputSchema || {
|
|
166
|
-
// Default to accepting any JSON value
|
|
167
|
-
type: ['string', 'number', 'boolean', 'object', 'null'],
|
|
168
|
-
description: 'The output value',
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
required: ['value'],
|
|
172
|
-
},
|
|
173
|
-
async execute(context, params) {
|
|
174
|
-
const { value } = params;
|
|
175
|
-
context.variables.set('__action_output', value);
|
|
176
|
-
return { returned: value };
|
|
177
|
-
},
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
class ActionImpl {
|
|
181
|
-
constructor(type, // Only support prompt type
|
|
182
|
-
name, description, tools, llmProvider, llmConfig, config) {
|
|
183
|
-
this.type = type;
|
|
184
|
-
this.name = name;
|
|
185
|
-
this.description = description;
|
|
186
|
-
this.tools = tools;
|
|
187
|
-
this.llmProvider = llmProvider;
|
|
188
|
-
this.llmConfig = llmConfig;
|
|
189
|
-
this.maxRounds = 10; // Default max rounds
|
|
190
|
-
this.writeContextTool = new WriteContextTool();
|
|
191
|
-
this.tools = [...tools, this.writeContextTool];
|
|
192
|
-
if (config === null || config === void 0 ? void 0 : config.maxRounds) {
|
|
193
|
-
this.maxRounds = config.maxRounds;
|
|
142
|
+
static generate(status, errorResponse, message, headers) {
|
|
143
|
+
if (!status || !headers) {
|
|
144
|
+
return new APIConnectionError$1({ message, cause: castToError$1(errorResponse) });
|
|
194
145
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
let hasToolUse = false;
|
|
199
|
-
let response = null;
|
|
200
|
-
// Buffer to collect into roundMessages
|
|
201
|
-
let assistantTextMessage = '';
|
|
202
|
-
let toolUseMessage = null;
|
|
203
|
-
let toolResultMessage = null;
|
|
204
|
-
// Track tool execution promise
|
|
205
|
-
let toolExecutionPromise = null;
|
|
206
|
-
const handler = {
|
|
207
|
-
onContent: (content) => {
|
|
208
|
-
if (content.trim()) {
|
|
209
|
-
assistantTextMessage += content;
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
onToolUse: async (toolCall) => {
|
|
213
|
-
console.log('Tool Call:', toolCall.name, toolCall.input);
|
|
214
|
-
hasToolUse = true;
|
|
215
|
-
const tool = toolMap.get(toolCall.name);
|
|
216
|
-
if (!tool) {
|
|
217
|
-
throw new Error(`Tool not found: ${toolCall.name}`);
|
|
218
|
-
}
|
|
219
|
-
toolUseMessage = {
|
|
220
|
-
role: 'assistant',
|
|
221
|
-
content: [
|
|
222
|
-
{
|
|
223
|
-
type: 'tool_use',
|
|
224
|
-
id: toolCall.id,
|
|
225
|
-
name: tool.name,
|
|
226
|
-
input: toolCall.input,
|
|
227
|
-
},
|
|
228
|
-
],
|
|
229
|
-
};
|
|
230
|
-
// Store the promise of tool execution
|
|
231
|
-
toolExecutionPromise = (async () => {
|
|
232
|
-
try {
|
|
233
|
-
// beforeToolUse
|
|
234
|
-
context.__skip = false;
|
|
235
|
-
if (context.callback && context.callback.hooks.beforeToolUse) {
|
|
236
|
-
let modified_input = await context.callback.hooks.beforeToolUse(tool, context, toolCall.input);
|
|
237
|
-
if (modified_input) {
|
|
238
|
-
toolCall.input = modified_input;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
if (context.__skip || context.__abort) {
|
|
242
|
-
toolResultMessage = {
|
|
243
|
-
role: 'user',
|
|
244
|
-
content: [
|
|
245
|
-
{
|
|
246
|
-
type: 'tool_result',
|
|
247
|
-
tool_use_id: toolCall.id,
|
|
248
|
-
content: 'skip',
|
|
249
|
-
},
|
|
250
|
-
],
|
|
251
|
-
};
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
// Execute the tool
|
|
255
|
-
let result = await tool.execute(context, toolCall.input);
|
|
256
|
-
// afterToolUse
|
|
257
|
-
if (context.callback && context.callback.hooks.afterToolUse) {
|
|
258
|
-
let modified_result = await context.callback.hooks.afterToolUse(tool, context, result);
|
|
259
|
-
if (modified_result) {
|
|
260
|
-
result = modified_result;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
const resultMessage = {
|
|
264
|
-
role: 'user',
|
|
265
|
-
content: [
|
|
266
|
-
result.image && result.image.type
|
|
267
|
-
? {
|
|
268
|
-
type: 'tool_result',
|
|
269
|
-
tool_use_id: toolCall.id,
|
|
270
|
-
content: result.text
|
|
271
|
-
? [
|
|
272
|
-
{ type: 'image', source: result.image },
|
|
273
|
-
{ type: 'text', text: result.text },
|
|
274
|
-
]
|
|
275
|
-
: [{ type: 'image', source: result.image }],
|
|
276
|
-
}
|
|
277
|
-
: {
|
|
278
|
-
type: 'tool_result',
|
|
279
|
-
tool_use_id: toolCall.id,
|
|
280
|
-
content: [{ type: 'text', text: JSON.stringify(result) }],
|
|
281
|
-
},
|
|
282
|
-
],
|
|
283
|
-
};
|
|
284
|
-
toolResultMessage = resultMessage;
|
|
285
|
-
console.log('Tool Result:', result);
|
|
286
|
-
}
|
|
287
|
-
catch (err) {
|
|
288
|
-
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
|
|
289
|
-
const errorResult = {
|
|
290
|
-
role: 'user',
|
|
291
|
-
content: [
|
|
292
|
-
{
|
|
293
|
-
type: 'tool_result',
|
|
294
|
-
tool_use_id: toolCall.id,
|
|
295
|
-
content: [{ type: 'text', text: `Error: ${errorMessage}` }],
|
|
296
|
-
is_error: true,
|
|
297
|
-
},
|
|
298
|
-
],
|
|
299
|
-
};
|
|
300
|
-
toolResultMessage = errorResult;
|
|
301
|
-
console.error('Tool Error:', err);
|
|
302
|
-
}
|
|
303
|
-
})();
|
|
304
|
-
},
|
|
305
|
-
onComplete: (llmResponse) => {
|
|
306
|
-
response = llmResponse;
|
|
307
|
-
},
|
|
308
|
-
onError: (error) => {
|
|
309
|
-
console.error('Stream Error:', error);
|
|
310
|
-
},
|
|
311
|
-
};
|
|
312
|
-
this.handleHistoryImageMessages(messages);
|
|
313
|
-
// Wait for stream to complete
|
|
314
|
-
await this.llmProvider.generateStream(messages, params, handler);
|
|
315
|
-
// Wait for tool execution to complete if it was started
|
|
316
|
-
if (toolExecutionPromise) {
|
|
317
|
-
await toolExecutionPromise;
|
|
146
|
+
const error = errorResponse;
|
|
147
|
+
if (status === 400) {
|
|
148
|
+
return new BadRequestError$1(status, error, message, headers);
|
|
318
149
|
}
|
|
319
|
-
if (
|
|
320
|
-
|
|
150
|
+
if (status === 401) {
|
|
151
|
+
return new AuthenticationError$1(status, error, message, headers);
|
|
321
152
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
roundMessages.push({ role: 'assistant', content: assistantTextMessage });
|
|
153
|
+
if (status === 403) {
|
|
154
|
+
return new PermissionDeniedError$1(status, error, message, headers);
|
|
325
155
|
}
|
|
326
|
-
if (
|
|
327
|
-
|
|
156
|
+
if (status === 404) {
|
|
157
|
+
return new NotFoundError$1(status, error, message, headers);
|
|
328
158
|
}
|
|
329
|
-
if (
|
|
330
|
-
|
|
159
|
+
if (status === 409) {
|
|
160
|
+
return new ConflictError$1(status, error, message, headers);
|
|
331
161
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
handleHistoryImageMessages(messages) {
|
|
335
|
-
// Remove all images of the historical tool call results, except for the last one.
|
|
336
|
-
let last_user = true;
|
|
337
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
338
|
-
const message = messages[i];
|
|
339
|
-
if (message.role === 'user') {
|
|
340
|
-
if (last_user) {
|
|
341
|
-
last_user = false;
|
|
342
|
-
continue;
|
|
343
|
-
}
|
|
344
|
-
if (message.content instanceof Array) {
|
|
345
|
-
let content = message.content;
|
|
346
|
-
for (let j = 0; j < content.length; j++) {
|
|
347
|
-
if (content[j].type === 'tool_result' && content[j].content instanceof Array) {
|
|
348
|
-
let tool_content = content[j].content;
|
|
349
|
-
if (tool_content.length > 0) {
|
|
350
|
-
for (let k = tool_content.length - 1; k >= 0; k--) {
|
|
351
|
-
if (tool_content[k].type === 'image') {
|
|
352
|
-
tool_content.splice(k, 1);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
else if (tool_content[0].type === 'image') {
|
|
357
|
-
tool_content = [{ type: 'text', text: 'ok' }];
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
162
|
+
if (status === 422) {
|
|
163
|
+
return new UnprocessableEntityError$1(status, error, message, headers);
|
|
363
164
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
var _a;
|
|
367
|
-
// Create return tool with output schema
|
|
368
|
-
const returnTool = createReturnTool(outputSchema);
|
|
369
|
-
// Create tool map combining context tools, action tools, and return tool
|
|
370
|
-
const toolMap = new Map();
|
|
371
|
-
this.tools.forEach((tool) => toolMap.set(tool.name, tool));
|
|
372
|
-
(_a = context.tools) === null || _a === void 0 ? void 0 : _a.forEach((tool) => toolMap.set(tool.name, tool));
|
|
373
|
-
toolMap.set(returnTool.name, returnTool);
|
|
374
|
-
// Prepare initial messages
|
|
375
|
-
const messages = [
|
|
376
|
-
{ role: 'system', content: this.formatSystemPrompt() },
|
|
377
|
-
{ role: 'user', content: this.formatUserPrompt(context, input) },
|
|
378
|
-
];
|
|
379
|
-
console.log('Starting LLM conversation...');
|
|
380
|
-
console.log('Initial messages:', messages);
|
|
381
|
-
console.log('Output schema:', outputSchema);
|
|
382
|
-
// Configure tool parameters
|
|
383
|
-
const params = {
|
|
384
|
-
...this.llmConfig,
|
|
385
|
-
tools: Array.from(toolMap.values()).map((tool) => ({
|
|
386
|
-
name: tool.name,
|
|
387
|
-
description: tool.description,
|
|
388
|
-
input_schema: tool.input_schema,
|
|
389
|
-
})),
|
|
390
|
-
};
|
|
391
|
-
let roundCount = 0;
|
|
392
|
-
while (roundCount < this.maxRounds) {
|
|
393
|
-
roundCount++;
|
|
394
|
-
console.log(`Starting round ${roundCount} of ${this.maxRounds}`);
|
|
395
|
-
console.log('Current conversation status:', JSON.stringify(messages, null, 2));
|
|
396
|
-
const { response, hasToolUse, roundMessages } = await this.executeSingleRound(messages, params, toolMap, context);
|
|
397
|
-
// Add round messages to conversation history
|
|
398
|
-
messages.push(...roundMessages);
|
|
399
|
-
// Check termination conditions
|
|
400
|
-
if (!hasToolUse && response) {
|
|
401
|
-
// LLM sent a message without using tools - request explicit return
|
|
402
|
-
console.log('No tool use detected, requesting explicit return');
|
|
403
|
-
console.log('Response:', response);
|
|
404
|
-
const returnOnlyParams = {
|
|
405
|
-
...params,
|
|
406
|
-
tools: [
|
|
407
|
-
{
|
|
408
|
-
name: returnTool.name,
|
|
409
|
-
description: returnTool.description,
|
|
410
|
-
input_schema: returnTool.input_schema,
|
|
411
|
-
},
|
|
412
|
-
],
|
|
413
|
-
};
|
|
414
|
-
messages.push({
|
|
415
|
-
role: 'user',
|
|
416
|
-
content: 'Please process the above information and return a final result using the return_output tool.',
|
|
417
|
-
});
|
|
418
|
-
const { roundMessages: finalRoundMessages } = await this.executeSingleRound(messages, returnOnlyParams, new Map([[returnTool.name, returnTool]]), context);
|
|
419
|
-
messages.push(...finalRoundMessages);
|
|
420
|
-
break;
|
|
421
|
-
}
|
|
422
|
-
if (response === null || response === void 0 ? void 0 : response.toolCalls.some((call) => call.name === 'return_output')) {
|
|
423
|
-
console.log('Task completed with return_output tool');
|
|
424
|
-
break;
|
|
425
|
-
}
|
|
426
|
-
// If this is the last round, force an explicit return
|
|
427
|
-
if (roundCount === this.maxRounds) {
|
|
428
|
-
console.log('Max rounds reached, requesting explicit return');
|
|
429
|
-
const returnOnlyParams = {
|
|
430
|
-
...params,
|
|
431
|
-
tools: [
|
|
432
|
-
{
|
|
433
|
-
name: returnTool.name,
|
|
434
|
-
description: returnTool.description,
|
|
435
|
-
input_schema: returnTool.input_schema,
|
|
436
|
-
},
|
|
437
|
-
],
|
|
438
|
-
};
|
|
439
|
-
messages.push({
|
|
440
|
-
role: 'user',
|
|
441
|
-
content: 'Maximum number of steps reached. Please return the best result possible with the return_output tool.',
|
|
442
|
-
});
|
|
443
|
-
const { roundMessages: finalRoundMessages } = await this.executeSingleRound(messages, returnOnlyParams, new Map([[returnTool.name, returnTool]]), context);
|
|
444
|
-
messages.push(...finalRoundMessages);
|
|
445
|
-
}
|
|
165
|
+
if (status === 429) {
|
|
166
|
+
return new RateLimitError$1(status, error, message, headers);
|
|
446
167
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
context.variables.delete('__action_output');
|
|
450
|
-
if (output === undefined) {
|
|
451
|
-
console.warn('Action completed without returning a value');
|
|
452
|
-
return {};
|
|
168
|
+
if (status >= 500) {
|
|
169
|
+
return new InternalServerError$1(status, error, message, headers);
|
|
453
170
|
}
|
|
454
|
-
return
|
|
455
|
-
}
|
|
456
|
-
formatSystemPrompt() {
|
|
457
|
-
return `You are a task executor. You need to complete the task specified by the user, using the tools provided. When you need to store results or outputs, use the write_context tool. When you are ready to return the final output, use the return_output tool.
|
|
458
|
-
|
|
459
|
-
Remember to:
|
|
460
|
-
1. Use tools when needed to accomplish the task
|
|
461
|
-
2. Store important results using write_context, including intermediate and final results
|
|
462
|
-
3. Think step by step about what needs to be done`;
|
|
171
|
+
return new APIError(status, error, message, headers);
|
|
463
172
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
.join('\n');
|
|
469
|
-
return `You are executing the action "${this.name}". The specific instructions are: "${this.description}". You have access to the following context:
|
|
470
|
-
|
|
471
|
-
${contextDescription || 'No context variables set'}
|
|
472
|
-
|
|
473
|
-
You have been provided with the following input:
|
|
474
|
-
${(typeof input === 'string' ? input : JSON.stringify(input, null, 2)) || 'No additional input provided'}
|
|
475
|
-
`;
|
|
476
|
-
}
|
|
477
|
-
// Static factory method
|
|
478
|
-
static createPromptAction(name, description, tools, llmProvider, llmConfig) {
|
|
479
|
-
return new ActionImpl('prompt', name, description, tools, llmProvider, llmConfig);
|
|
173
|
+
};
|
|
174
|
+
let APIUserAbortError$1 = class APIUserAbortError extends APIError$1 {
|
|
175
|
+
constructor({ message } = {}) {
|
|
176
|
+
super(undefined, undefined, message || 'Request was aborted.', undefined);
|
|
480
177
|
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
Tool: ${tool.name}
|
|
490
|
-
Description: ${tool.description}
|
|
491
|
-
Input Schema: ${JSON.stringify(tool.input_schema, null, 2)}
|
|
492
|
-
`)
|
|
493
|
-
.join('\n');
|
|
494
|
-
return `You are a workflow generation assistant that creates Eko framework workflows.
|
|
495
|
-
The following tools are available:
|
|
496
|
-
|
|
497
|
-
${toolDescriptions}
|
|
498
|
-
|
|
499
|
-
Generate a complete workflow that:
|
|
500
|
-
1. Only uses the tools listed above
|
|
501
|
-
2. Properly sequences tool usage based on dependencies
|
|
502
|
-
3. Ensures each action has appropriate input/output schemas, and that the "tools" field in each action is populated with the sufficient subset of all available tools needed to complete the action
|
|
503
|
-
4. Creates a clear, logical flow to accomplish the user's goal
|
|
504
|
-
5. Includes detailed descriptions for each action, ensuring that the actions, when combined, is a complete solution to the user's problem`;
|
|
505
|
-
},
|
|
506
|
-
formatUserPrompt: (requirement) => `Create a workflow for the following requirement: ${requirement}`,
|
|
507
|
-
modifyUserPrompt: (prompt) => `Modify workflow: ${prompt}`,
|
|
508
|
-
};
|
|
509
|
-
}
|
|
510
|
-
function createWorkflowGenerationTool(registry) {
|
|
511
|
-
return {
|
|
512
|
-
name: 'generate_workflow',
|
|
513
|
-
description: `Generate a workflow following the Eko framework DSL schema.
|
|
514
|
-
The workflow must only use the available tools and ensure proper dependencies between nodes.`,
|
|
515
|
-
input_schema: {
|
|
516
|
-
type: 'object',
|
|
517
|
-
properties: {
|
|
518
|
-
workflow: registry.getWorkflowSchema(),
|
|
519
|
-
},
|
|
520
|
-
required: ['workflow'],
|
|
521
|
-
},
|
|
522
|
-
};
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
const byteToHex = [];
|
|
526
|
-
for (let i = 0; i < 256; ++i) {
|
|
527
|
-
byteToHex.push((i + 0x100).toString(16).slice(1));
|
|
528
|
-
}
|
|
529
|
-
function unsafeStringify(arr, offset = 0) {
|
|
530
|
-
return (byteToHex[arr[offset + 0]] +
|
|
531
|
-
byteToHex[arr[offset + 1]] +
|
|
532
|
-
byteToHex[arr[offset + 2]] +
|
|
533
|
-
byteToHex[arr[offset + 3]] +
|
|
534
|
-
'-' +
|
|
535
|
-
byteToHex[arr[offset + 4]] +
|
|
536
|
-
byteToHex[arr[offset + 5]] +
|
|
537
|
-
'-' +
|
|
538
|
-
byteToHex[arr[offset + 6]] +
|
|
539
|
-
byteToHex[arr[offset + 7]] +
|
|
540
|
-
'-' +
|
|
541
|
-
byteToHex[arr[offset + 8]] +
|
|
542
|
-
byteToHex[arr[offset + 9]] +
|
|
543
|
-
'-' +
|
|
544
|
-
byteToHex[arr[offset + 10]] +
|
|
545
|
-
byteToHex[arr[offset + 11]] +
|
|
546
|
-
byteToHex[arr[offset + 12]] +
|
|
547
|
-
byteToHex[arr[offset + 13]] +
|
|
548
|
-
byteToHex[arr[offset + 14]] +
|
|
549
|
-
byteToHex[arr[offset + 15]]).toLowerCase();
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
let getRandomValues;
|
|
553
|
-
const rnds8 = new Uint8Array(16);
|
|
554
|
-
function rng() {
|
|
555
|
-
if (!getRandomValues) {
|
|
556
|
-
if (typeof crypto === 'undefined' || !crypto.getRandomValues) {
|
|
557
|
-
throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
|
|
558
|
-
}
|
|
559
|
-
getRandomValues = crypto.getRandomValues.bind(crypto);
|
|
178
|
+
};
|
|
179
|
+
let APIConnectionError$1 = class APIConnectionError extends APIError$1 {
|
|
180
|
+
constructor({ message, cause }) {
|
|
181
|
+
super(undefined, undefined, message || 'Connection error.', undefined);
|
|
182
|
+
// in some environments the 'cause' property is already declared
|
|
183
|
+
// @ts-ignore
|
|
184
|
+
if (cause)
|
|
185
|
+
this.cause = cause;
|
|
560
186
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
var native = { randomUUID };
|
|
566
|
-
|
|
567
|
-
function v4(options, buf, offset) {
|
|
568
|
-
if (native.randomUUID && !buf && !options) {
|
|
569
|
-
return native.randomUUID();
|
|
187
|
+
};
|
|
188
|
+
let APIConnectionTimeoutError$1 = class APIConnectionTimeoutError extends APIConnectionError$1 {
|
|
189
|
+
constructor({ message } = {}) {
|
|
190
|
+
super({ message: message ?? 'Request timed out.' });
|
|
570
191
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
192
|
+
};
|
|
193
|
+
let BadRequestError$1 = class BadRequestError extends APIError$1 {
|
|
194
|
+
};
|
|
195
|
+
let AuthenticationError$1 = class AuthenticationError extends APIError$1 {
|
|
196
|
+
};
|
|
197
|
+
let PermissionDeniedError$1 = class PermissionDeniedError extends APIError$1 {
|
|
198
|
+
};
|
|
199
|
+
let NotFoundError$1 = class NotFoundError extends APIError$1 {
|
|
200
|
+
};
|
|
201
|
+
let ConflictError$1 = class ConflictError extends APIError$1 {
|
|
202
|
+
};
|
|
203
|
+
let UnprocessableEntityError$1 = class UnprocessableEntityError extends APIError$1 {
|
|
204
|
+
};
|
|
205
|
+
let RateLimitError$1 = class RateLimitError extends APIError$1 {
|
|
206
|
+
};
|
|
207
|
+
let InternalServerError$1 = class InternalServerError extends APIError$1 {
|
|
208
|
+
};
|
|
577
209
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
return this.doGenerateWorkflow(prompt, true);
|
|
210
|
+
/**
|
|
211
|
+
* A re-implementation of httpx's `LineDecoder` in Python that handles incrementally
|
|
212
|
+
* reading lines from text.
|
|
213
|
+
*
|
|
214
|
+
* https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258
|
|
215
|
+
*/
|
|
216
|
+
let LineDecoder$1 = class LineDecoder {
|
|
217
|
+
constructor() {
|
|
218
|
+
this.buffer = [];
|
|
219
|
+
this.trailingCR = false;
|
|
589
220
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
messages = this.message_history;
|
|
596
|
-
messages.push({
|
|
597
|
-
role: 'user',
|
|
598
|
-
content: prompts.modifyUserPrompt(prompt),
|
|
599
|
-
});
|
|
221
|
+
decode(chunk) {
|
|
222
|
+
let text = this.decodeText(chunk);
|
|
223
|
+
if (this.trailingCR) {
|
|
224
|
+
text = '\r' + text;
|
|
225
|
+
this.trailingCR = false;
|
|
600
226
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
role: 'system',
|
|
605
|
-
content: prompts.formatSystemPrompt(),
|
|
606
|
-
},
|
|
607
|
-
{
|
|
608
|
-
role: 'user',
|
|
609
|
-
content: prompts.formatUserPrompt(prompt),
|
|
610
|
-
},
|
|
611
|
-
];
|
|
227
|
+
if (text.endsWith('\r')) {
|
|
228
|
+
this.trailingCR = true;
|
|
229
|
+
text = text.slice(0, -1);
|
|
612
230
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
maxTokens: 8192,
|
|
616
|
-
tools: [createWorkflowGenerationTool(this.toolRegistry)],
|
|
617
|
-
toolChoice: { type: 'tool', name: 'generate_workflow' },
|
|
618
|
-
};
|
|
619
|
-
const response = await this.llmProvider.generateText(messages, params);
|
|
620
|
-
if (!response.toolCalls.length || !response.toolCalls[0].input.workflow) {
|
|
621
|
-
messages.pop();
|
|
622
|
-
throw new Error('Failed to generate workflow: Invalid response from LLM');
|
|
231
|
+
if (!text) {
|
|
232
|
+
return [];
|
|
623
233
|
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
name: response.toolCalls[0].name,
|
|
631
|
-
input: response.toolCalls[0].input,
|
|
632
|
-
},
|
|
633
|
-
],
|
|
634
|
-
}, {
|
|
635
|
-
role: 'user',
|
|
636
|
-
content: [
|
|
637
|
-
{
|
|
638
|
-
type: 'tool_result',
|
|
639
|
-
tool_use_id: response.toolCalls[0].id,
|
|
640
|
-
content: 'ok',
|
|
641
|
-
},
|
|
642
|
-
],
|
|
643
|
-
});
|
|
644
|
-
const workflowData = response.toolCalls[0].input.workflow;
|
|
645
|
-
// Validate all tools exist
|
|
646
|
-
for (const node of workflowData.nodes) {
|
|
647
|
-
if (!this.toolRegistry.hasTools(node.action.tools)) {
|
|
648
|
-
throw new Error(`Workflow contains undefined tools: ${node.action.tools}`);
|
|
649
|
-
}
|
|
234
|
+
const trailingNewline = LineDecoder.NEWLINE_CHARS.has(text[text.length - 1] || '');
|
|
235
|
+
let lines = text.split(LineDecoder.NEWLINE_REGEXP);
|
|
236
|
+
// if there is a trailing new line then the last entry will be an empty
|
|
237
|
+
// string which we don't care about
|
|
238
|
+
if (trailingNewline) {
|
|
239
|
+
lines.pop();
|
|
650
240
|
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
241
|
+
if (lines.length === 1 && !trailingNewline) {
|
|
242
|
+
this.buffer.push(lines[0]);
|
|
243
|
+
return [];
|
|
654
244
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
const workflow = new WorkflowImpl(data.id, data.name, data.description || '', [], new Map(Object.entries(data.variables || {})), this.llmProvider);
|
|
659
|
-
// Add nodes to workflow
|
|
660
|
-
if (Array.isArray(data.nodes)) {
|
|
661
|
-
data.nodes.forEach((nodeData) => {
|
|
662
|
-
const tools = nodeData.action.tools.map((toolName) => this.toolRegistry.getTool(toolName));
|
|
663
|
-
const action = ActionImpl.createPromptAction(nodeData.action.name, nodeData.action.description, tools, this.llmProvider, { maxTokens: 1000 });
|
|
664
|
-
const node = {
|
|
665
|
-
id: nodeData.id,
|
|
666
|
-
name: nodeData.name || nodeData.id,
|
|
667
|
-
input: nodeData.input || { type: 'any', schema: {}, value: undefined },
|
|
668
|
-
output: nodeData.output || { type: 'any', schema: {}, value: undefined },
|
|
669
|
-
action: action,
|
|
670
|
-
dependencies: nodeData.dependencies || [],
|
|
671
|
-
};
|
|
672
|
-
workflow.addNode(node);
|
|
673
|
-
});
|
|
245
|
+
if (this.buffer.length > 0) {
|
|
246
|
+
lines = [this.buffer.join('') + lines[0], ...lines.slice(1)];
|
|
247
|
+
this.buffer = [];
|
|
674
248
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
const VERSION$1 = '0.33.1'; // x-release-please-version
|
|
680
|
-
|
|
681
|
-
let auto$1 = false;
|
|
682
|
-
let kind$1 = undefined;
|
|
683
|
-
let fetch$2 = undefined;
|
|
684
|
-
let File$2 = undefined;
|
|
685
|
-
let ReadableStream$2 = undefined;
|
|
686
|
-
let getDefaultAgent$1 = undefined;
|
|
687
|
-
let fileFromPath$1 = undefined;
|
|
688
|
-
function setShims$1(shims, options = { auto: false }) {
|
|
689
|
-
if (auto$1) {
|
|
690
|
-
throw new Error(`you must \`import '@anthropic-ai/sdk/shims/${shims.kind}'\` before importing anything else from @anthropic-ai/sdk`);
|
|
691
|
-
}
|
|
692
|
-
if (kind$1) {
|
|
693
|
-
throw new Error(`can't \`import '@anthropic-ai/sdk/shims/${shims.kind}'\` after \`import '@anthropic-ai/sdk/shims/${kind$1}'\``);
|
|
694
|
-
}
|
|
695
|
-
auto$1 = options.auto;
|
|
696
|
-
kind$1 = shims.kind;
|
|
697
|
-
fetch$2 = shims.fetch;
|
|
698
|
-
File$2 = shims.File;
|
|
699
|
-
ReadableStream$2 = shims.ReadableStream;
|
|
700
|
-
getDefaultAgent$1 = shims.getDefaultAgent;
|
|
701
|
-
fileFromPath$1 = shims.fileFromPath;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
/**
|
|
705
|
-
* Disclaimer: modules in _shims aren't intended to be imported by SDK users.
|
|
706
|
-
*/
|
|
707
|
-
let MultipartBody$1 = class MultipartBody {
|
|
708
|
-
constructor(body) {
|
|
709
|
-
this.body = body;
|
|
710
|
-
}
|
|
711
|
-
get [Symbol.toStringTag]() {
|
|
712
|
-
return 'MultipartBody';
|
|
713
|
-
}
|
|
714
|
-
};
|
|
715
|
-
|
|
716
|
-
function getRuntime$1({ manuallyImported } = {}) {
|
|
717
|
-
const recommendation = manuallyImported ?
|
|
718
|
-
`You may need to use polyfills`
|
|
719
|
-
: `Add one of these imports before your first \`import … from '@anthropic-ai/sdk'\`:
|
|
720
|
-
- \`import '@anthropic-ai/sdk/shims/node'\` (if you're running on Node)
|
|
721
|
-
- \`import '@anthropic-ai/sdk/shims/web'\` (otherwise)
|
|
722
|
-
`;
|
|
723
|
-
let _fetch, _Request, _Response, _Headers;
|
|
724
|
-
try {
|
|
725
|
-
// @ts-ignore
|
|
726
|
-
_fetch = fetch;
|
|
727
|
-
// @ts-ignore
|
|
728
|
-
_Request = Request;
|
|
729
|
-
// @ts-ignore
|
|
730
|
-
_Response = Response;
|
|
731
|
-
// @ts-ignore
|
|
732
|
-
_Headers = Headers;
|
|
733
|
-
}
|
|
734
|
-
catch (error) {
|
|
735
|
-
throw new Error(`this environment is missing the following Web Fetch API type: ${error.message}. ${recommendation}`);
|
|
736
|
-
}
|
|
737
|
-
return {
|
|
738
|
-
kind: 'web',
|
|
739
|
-
fetch: _fetch,
|
|
740
|
-
Request: _Request,
|
|
741
|
-
Response: _Response,
|
|
742
|
-
Headers: _Headers,
|
|
743
|
-
FormData:
|
|
744
|
-
// @ts-ignore
|
|
745
|
-
typeof FormData !== 'undefined' ? FormData : (class FormData {
|
|
746
|
-
// @ts-ignore
|
|
747
|
-
constructor() {
|
|
748
|
-
throw new Error(`file uploads aren't supported in this environment yet as 'FormData' is undefined. ${recommendation}`);
|
|
749
|
-
}
|
|
750
|
-
}),
|
|
751
|
-
Blob: typeof Blob !== 'undefined' ? Blob : (class Blob {
|
|
752
|
-
constructor() {
|
|
753
|
-
throw new Error(`file uploads aren't supported in this environment yet as 'Blob' is undefined. ${recommendation}`);
|
|
754
|
-
}
|
|
755
|
-
}),
|
|
756
|
-
File:
|
|
757
|
-
// @ts-ignore
|
|
758
|
-
typeof File !== 'undefined' ? File : (class File {
|
|
759
|
-
// @ts-ignore
|
|
760
|
-
constructor() {
|
|
761
|
-
throw new Error(`file uploads aren't supported in this environment yet as 'File' is undefined. ${recommendation}`);
|
|
762
|
-
}
|
|
763
|
-
}),
|
|
764
|
-
ReadableStream:
|
|
765
|
-
// @ts-ignore
|
|
766
|
-
typeof ReadableStream !== 'undefined' ? ReadableStream : (class ReadableStream {
|
|
767
|
-
// @ts-ignore
|
|
768
|
-
constructor() {
|
|
769
|
-
throw new Error(`streaming isn't supported in this environment yet as 'ReadableStream' is undefined. ${recommendation}`);
|
|
770
|
-
}
|
|
771
|
-
}),
|
|
772
|
-
getMultipartRequestOptions: async (
|
|
773
|
-
// @ts-ignore
|
|
774
|
-
form, opts) => ({
|
|
775
|
-
...opts,
|
|
776
|
-
body: new MultipartBody$1(form),
|
|
777
|
-
}),
|
|
778
|
-
getDefaultAgent: (url) => undefined,
|
|
779
|
-
fileFromPath: () => {
|
|
780
|
-
throw new Error('The `fileFromPath` function is only supported in Node. See the README for more details: https://www.github.com/anthropics/anthropic-sdk-typescript#file-uploads');
|
|
781
|
-
},
|
|
782
|
-
isFsReadStream: (value) => false,
|
|
783
|
-
};
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
/**
|
|
787
|
-
* Disclaimer: modules in _shims aren't intended to be imported by SDK users.
|
|
788
|
-
*/
|
|
789
|
-
if (!kind$1) setShims$1(getRuntime$1(), { auto: true });
|
|
790
|
-
|
|
791
|
-
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
792
|
-
class AnthropicError extends Error {
|
|
793
|
-
}
|
|
794
|
-
let APIError$1 = class APIError extends AnthropicError {
|
|
795
|
-
constructor(status, error, message, headers) {
|
|
796
|
-
super(`${APIError.makeMessage(status, error, message)}`);
|
|
797
|
-
this.status = status;
|
|
798
|
-
this.headers = headers;
|
|
799
|
-
this.request_id = headers?.['request-id'];
|
|
800
|
-
this.error = error;
|
|
801
|
-
}
|
|
802
|
-
static makeMessage(status, error, message) {
|
|
803
|
-
const msg = error?.message ?
|
|
804
|
-
typeof error.message === 'string' ?
|
|
805
|
-
error.message
|
|
806
|
-
: JSON.stringify(error.message)
|
|
807
|
-
: error ? JSON.stringify(error)
|
|
808
|
-
: message;
|
|
809
|
-
if (status && msg) {
|
|
810
|
-
return `${status} ${msg}`;
|
|
811
|
-
}
|
|
812
|
-
if (status) {
|
|
813
|
-
return `${status} status code (no body)`;
|
|
814
|
-
}
|
|
815
|
-
if (msg) {
|
|
816
|
-
return msg;
|
|
817
|
-
}
|
|
818
|
-
return '(no status code or body)';
|
|
819
|
-
}
|
|
820
|
-
static generate(status, errorResponse, message, headers) {
|
|
821
|
-
if (!status || !headers) {
|
|
822
|
-
return new APIConnectionError$1({ message, cause: castToError$1(errorResponse) });
|
|
823
|
-
}
|
|
824
|
-
const error = errorResponse;
|
|
825
|
-
if (status === 400) {
|
|
826
|
-
return new BadRequestError$1(status, error, message, headers);
|
|
827
|
-
}
|
|
828
|
-
if (status === 401) {
|
|
829
|
-
return new AuthenticationError$1(status, error, message, headers);
|
|
830
|
-
}
|
|
831
|
-
if (status === 403) {
|
|
832
|
-
return new PermissionDeniedError$1(status, error, message, headers);
|
|
833
|
-
}
|
|
834
|
-
if (status === 404) {
|
|
835
|
-
return new NotFoundError$1(status, error, message, headers);
|
|
836
|
-
}
|
|
837
|
-
if (status === 409) {
|
|
838
|
-
return new ConflictError$1(status, error, message, headers);
|
|
839
|
-
}
|
|
840
|
-
if (status === 422) {
|
|
841
|
-
return new UnprocessableEntityError$1(status, error, message, headers);
|
|
842
|
-
}
|
|
843
|
-
if (status === 429) {
|
|
844
|
-
return new RateLimitError$1(status, error, message, headers);
|
|
845
|
-
}
|
|
846
|
-
if (status >= 500) {
|
|
847
|
-
return new InternalServerError$1(status, error, message, headers);
|
|
848
|
-
}
|
|
849
|
-
return new APIError(status, error, message, headers);
|
|
850
|
-
}
|
|
851
|
-
};
|
|
852
|
-
let APIUserAbortError$1 = class APIUserAbortError extends APIError$1 {
|
|
853
|
-
constructor({ message } = {}) {
|
|
854
|
-
super(undefined, undefined, message || 'Request was aborted.', undefined);
|
|
855
|
-
}
|
|
856
|
-
};
|
|
857
|
-
let APIConnectionError$1 = class APIConnectionError extends APIError$1 {
|
|
858
|
-
constructor({ message, cause }) {
|
|
859
|
-
super(undefined, undefined, message || 'Connection error.', undefined);
|
|
860
|
-
// in some environments the 'cause' property is already declared
|
|
861
|
-
// @ts-ignore
|
|
862
|
-
if (cause)
|
|
863
|
-
this.cause = cause;
|
|
864
|
-
}
|
|
865
|
-
};
|
|
866
|
-
let APIConnectionTimeoutError$1 = class APIConnectionTimeoutError extends APIConnectionError$1 {
|
|
867
|
-
constructor({ message } = {}) {
|
|
868
|
-
super({ message: message ?? 'Request timed out.' });
|
|
869
|
-
}
|
|
870
|
-
};
|
|
871
|
-
let BadRequestError$1 = class BadRequestError extends APIError$1 {
|
|
872
|
-
};
|
|
873
|
-
let AuthenticationError$1 = class AuthenticationError extends APIError$1 {
|
|
874
|
-
};
|
|
875
|
-
let PermissionDeniedError$1 = class PermissionDeniedError extends APIError$1 {
|
|
876
|
-
};
|
|
877
|
-
let NotFoundError$1 = class NotFoundError extends APIError$1 {
|
|
878
|
-
};
|
|
879
|
-
let ConflictError$1 = class ConflictError extends APIError$1 {
|
|
880
|
-
};
|
|
881
|
-
let UnprocessableEntityError$1 = class UnprocessableEntityError extends APIError$1 {
|
|
882
|
-
};
|
|
883
|
-
let RateLimitError$1 = class RateLimitError extends APIError$1 {
|
|
884
|
-
};
|
|
885
|
-
let InternalServerError$1 = class InternalServerError extends APIError$1 {
|
|
886
|
-
};
|
|
887
|
-
|
|
888
|
-
/**
|
|
889
|
-
* A re-implementation of httpx's `LineDecoder` in Python that handles incrementally
|
|
890
|
-
* reading lines from text.
|
|
891
|
-
*
|
|
892
|
-
* https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258
|
|
893
|
-
*/
|
|
894
|
-
let LineDecoder$1 = class LineDecoder {
|
|
895
|
-
constructor() {
|
|
896
|
-
this.buffer = [];
|
|
897
|
-
this.trailingCR = false;
|
|
898
|
-
}
|
|
899
|
-
decode(chunk) {
|
|
900
|
-
let text = this.decodeText(chunk);
|
|
901
|
-
if (this.trailingCR) {
|
|
902
|
-
text = '\r' + text;
|
|
903
|
-
this.trailingCR = false;
|
|
904
|
-
}
|
|
905
|
-
if (text.endsWith('\r')) {
|
|
906
|
-
this.trailingCR = true;
|
|
907
|
-
text = text.slice(0, -1);
|
|
908
|
-
}
|
|
909
|
-
if (!text) {
|
|
910
|
-
return [];
|
|
911
|
-
}
|
|
912
|
-
const trailingNewline = LineDecoder.NEWLINE_CHARS.has(text[text.length - 1] || '');
|
|
913
|
-
let lines = text.split(LineDecoder.NEWLINE_REGEXP);
|
|
914
|
-
// if there is a trailing new line then the last entry will be an empty
|
|
915
|
-
// string which we don't care about
|
|
916
|
-
if (trailingNewline) {
|
|
917
|
-
lines.pop();
|
|
918
|
-
}
|
|
919
|
-
if (lines.length === 1 && !trailingNewline) {
|
|
920
|
-
this.buffer.push(lines[0]);
|
|
921
|
-
return [];
|
|
922
|
-
}
|
|
923
|
-
if (this.buffer.length > 0) {
|
|
924
|
-
lines = [this.buffer.join('') + lines[0], ...lines.slice(1)];
|
|
925
|
-
this.buffer = [];
|
|
926
|
-
}
|
|
927
|
-
if (!trailingNewline) {
|
|
928
|
-
this.buffer = [lines.pop() || ''];
|
|
929
|
-
}
|
|
930
|
-
return lines;
|
|
249
|
+
if (!trailingNewline) {
|
|
250
|
+
this.buffer = [lines.pop() || ''];
|
|
251
|
+
}
|
|
252
|
+
return lines;
|
|
931
253
|
}
|
|
932
254
|
decodeText(bytes) {
|
|
933
255
|
if (bytes == null)
|
|
@@ -1039,7 +361,7 @@ let Stream$1 = class Stream {
|
|
|
1039
361
|
let consumed = false;
|
|
1040
362
|
async function* iterLines() {
|
|
1041
363
|
const lineDecoder = new LineDecoder$1();
|
|
1042
|
-
const iter = readableStreamAsyncIterable
|
|
364
|
+
const iter = readableStreamAsyncIterable(readableStream);
|
|
1043
365
|
for await (const chunk of iter) {
|
|
1044
366
|
for (const line of lineDecoder.decode(chunk)) {
|
|
1045
367
|
yield line;
|
|
@@ -1144,7 +466,7 @@ async function* _iterSSEMessages$1(response, controller) {
|
|
|
1144
466
|
}
|
|
1145
467
|
const sseDecoder = new SSEDecoder$1();
|
|
1146
468
|
const lineDecoder = new LineDecoder$1();
|
|
1147
|
-
const iter = readableStreamAsyncIterable
|
|
469
|
+
const iter = readableStreamAsyncIterable(response.body);
|
|
1148
470
|
for await (const sseChunk of iterSSEChunks$1(iter)) {
|
|
1149
471
|
for (const line of lineDecoder.decode(sseChunk)) {
|
|
1150
472
|
const sse = sseDecoder.decode(line);
|
|
@@ -1265,7 +587,7 @@ function partition$1(str, delimiter) {
|
|
|
1265
587
|
*
|
|
1266
588
|
* This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490
|
|
1267
589
|
*/
|
|
1268
|
-
function readableStreamAsyncIterable
|
|
590
|
+
function readableStreamAsyncIterable(stream) {
|
|
1269
591
|
if (stream[Symbol.asyncIterator])
|
|
1270
592
|
return stream;
|
|
1271
593
|
const reader = stream.getReader();
|
|
@@ -1828,7 +1150,7 @@ let APIClient$1 = class APIClient {
|
|
|
1828
1150
|
};
|
|
1829
1151
|
let AbstractPage$1 = class AbstractPage {
|
|
1830
1152
|
constructor(client, response, body, options) {
|
|
1831
|
-
_AbstractPage_client$1.set(this,
|
|
1153
|
+
_AbstractPage_client$1.set(this, undefined);
|
|
1832
1154
|
__classPrivateFieldSet$5(this, _AbstractPage_client$1, client, "f");
|
|
1833
1155
|
this.options = options;
|
|
1834
1156
|
this.response = response;
|
|
@@ -2307,7 +1629,7 @@ class JSONLDecoder {
|
|
|
2307
1629
|
controller.abort();
|
|
2308
1630
|
throw new AnthropicError(`Attempted to iterate over a response with no body`);
|
|
2309
1631
|
}
|
|
2310
|
-
return new JSONLDecoder(readableStreamAsyncIterable
|
|
1632
|
+
return new JSONLDecoder(readableStreamAsyncIterable(response.body), controller);
|
|
2311
1633
|
}
|
|
2312
1634
|
}
|
|
2313
1635
|
|
|
@@ -2759,12 +2081,12 @@ class MessageStream {
|
|
|
2759
2081
|
_MessageStream_instances.add(this);
|
|
2760
2082
|
this.messages = [];
|
|
2761
2083
|
this.receivedMessages = [];
|
|
2762
|
-
_MessageStream_currentMessageSnapshot.set(this,
|
|
2084
|
+
_MessageStream_currentMessageSnapshot.set(this, undefined);
|
|
2763
2085
|
this.controller = new AbortController();
|
|
2764
|
-
_MessageStream_connectedPromise.set(this,
|
|
2086
|
+
_MessageStream_connectedPromise.set(this, undefined);
|
|
2765
2087
|
_MessageStream_resolveConnectedPromise.set(this, () => { });
|
|
2766
2088
|
_MessageStream_rejectConnectedPromise.set(this, () => { });
|
|
2767
|
-
_MessageStream_endPromise.set(this,
|
|
2089
|
+
_MessageStream_endPromise.set(this, undefined);
|
|
2768
2090
|
_MessageStream_resolveEndPromise.set(this, () => { });
|
|
2769
2091
|
_MessageStream_rejectEndPromise.set(this, () => { });
|
|
2770
2092
|
_MessageStream_listeners.set(this, {});
|
|
@@ -3387,14 +2709,14 @@ class ClaudeProvider {
|
|
|
3387
2709
|
if (typeof window !== 'undefined' &&
|
|
3388
2710
|
typeof document !== 'undefined' &&
|
|
3389
2711
|
(typeof param == 'string' || param.apiKey)) {
|
|
3390
|
-
console.warn(`
|
|
3391
|
-
⚠️ Security Warning:
|
|
3392
|
-
DO NOT use API Keys in browser/frontend code!
|
|
3393
|
-
This will expose your credentials and may lead to unauthorized usage.
|
|
3394
|
-
|
|
3395
|
-
Best Practices: Configure backend API proxy request through baseURL and request headers.
|
|
3396
|
-
|
|
3397
|
-
Please refer to the link: https://eko.fellou.ai/docs/getting-started/configuration#web-environment
|
|
2712
|
+
console.warn(`
|
|
2713
|
+
⚠️ Security Warning:
|
|
2714
|
+
DO NOT use API Keys in browser/frontend code!
|
|
2715
|
+
This will expose your credentials and may lead to unauthorized usage.
|
|
2716
|
+
|
|
2717
|
+
Best Practices: Configure backend API proxy request through baseURL and request headers.
|
|
2718
|
+
|
|
2719
|
+
Please refer to the link: https://eko.fellou.ai/docs/getting-started/configuration#web-environment
|
|
3398
2720
|
`);
|
|
3399
2721
|
}
|
|
3400
2722
|
if (typeof param == 'string') {
|
|
@@ -3404,8 +2726,13 @@ class ClaudeProvider {
|
|
|
3404
2726
|
...options,
|
|
3405
2727
|
});
|
|
3406
2728
|
}
|
|
2729
|
+
else if (param.messages && param.completions) {
|
|
2730
|
+
this.client = param;
|
|
2731
|
+
}
|
|
3407
2732
|
else {
|
|
3408
|
-
|
|
2733
|
+
let options = param;
|
|
2734
|
+
options.dangerouslyAllowBrowser = true;
|
|
2735
|
+
this.client = new Anthropic(options);
|
|
3409
2736
|
}
|
|
3410
2737
|
}
|
|
3411
2738
|
processResponse(response) {
|
|
@@ -3441,7 +2768,7 @@ class ClaudeProvider {
|
|
|
3441
2768
|
const response = await this.client.messages.create({
|
|
3442
2769
|
system,
|
|
3443
2770
|
model: params.model || this.defaultModel,
|
|
3444
|
-
max_tokens: params.maxTokens ||
|
|
2771
|
+
max_tokens: params.maxTokens || 8192,
|
|
3445
2772
|
temperature: params.temperature,
|
|
3446
2773
|
messages: messages.filter((s) => s.role != 'system'),
|
|
3447
2774
|
tools: params.tools,
|
|
@@ -3464,13 +2791,13 @@ class ClaudeProvider {
|
|
|
3464
2791
|
const stream = await this.client.messages.stream({
|
|
3465
2792
|
system,
|
|
3466
2793
|
model: params.model || this.defaultModel,
|
|
3467
|
-
max_tokens: params.maxTokens ||
|
|
2794
|
+
max_tokens: params.maxTokens || 8192,
|
|
3468
2795
|
temperature: params.temperature,
|
|
3469
2796
|
messages: messages.filter((s) => s.role != 'system'),
|
|
3470
2797
|
tools: params.tools,
|
|
3471
2798
|
tool_choice: params.toolChoice,
|
|
3472
2799
|
});
|
|
3473
|
-
(_a = handler.onStart) === null || _a ===
|
|
2800
|
+
(_a = handler.onStart) === null || _a === undefined ? undefined : _a.call(handler);
|
|
3474
2801
|
let currentToolUse = null;
|
|
3475
2802
|
try {
|
|
3476
2803
|
for await (const event of stream) {
|
|
@@ -3512,7 +2839,7 @@ class ClaudeProvider {
|
|
|
3512
2839
|
(_e = handler.onComplete) === null || _e === void 0 ? void 0 : _e.call(handler, this.processResponse(message));
|
|
3513
2840
|
}
|
|
3514
2841
|
catch (error) {
|
|
3515
|
-
(_f = handler.onError) === null || _f ===
|
|
2842
|
+
(_f = handler.onError) === null || _f === undefined ? undefined : _f.call(handler, error);
|
|
3516
2843
|
}
|
|
3517
2844
|
}
|
|
3518
2845
|
}
|
|
@@ -3665,7 +2992,7 @@ function inner_stringify(object, prefix, generateArrayPrefix, commaRoundTrip, al
|
|
|
3665
2992
|
let tmp_sc = sideChannel;
|
|
3666
2993
|
let step = 0;
|
|
3667
2994
|
let find_flag = false;
|
|
3668
|
-
while ((tmp_sc = tmp_sc.get(sentinel)) !==
|
|
2995
|
+
while ((tmp_sc = tmp_sc.get(sentinel)) !== undefined && !find_flag) {
|
|
3669
2996
|
// Where object last appeared in the ref tree
|
|
3670
2997
|
const pos = tmp_sc.get(object);
|
|
3671
2998
|
step += 1;
|
|
@@ -3729,7 +3056,7 @@ function inner_stringify(object, prefix, generateArrayPrefix, commaRoundTrip, al
|
|
|
3729
3056
|
// @ts-expect-error values only
|
|
3730
3057
|
obj = maybe_map(obj, encoder);
|
|
3731
3058
|
}
|
|
3732
|
-
obj_keys = [{ value: obj.length > 0 ? obj.join(',') || null :
|
|
3059
|
+
obj_keys = [{ value: obj.length > 0 ? obj.join(',') || null : undefined }];
|
|
3733
3060
|
}
|
|
3734
3061
|
else if (is_array(filter)) {
|
|
3735
3062
|
obj_keys = filter;
|
|
@@ -3885,7 +3212,7 @@ function stringify(object, opts = {}) {
|
|
|
3885
3212
|
return joined.length > 0 ? prefix + joined : '';
|
|
3886
3213
|
}
|
|
3887
3214
|
|
|
3888
|
-
const VERSION = '4.
|
|
3215
|
+
const VERSION = '4.79.4'; // x-release-please-version
|
|
3889
3216
|
|
|
3890
3217
|
let auto = false;
|
|
3891
3218
|
let kind = undefined;
|
|
@@ -4197,13 +3524,48 @@ class LineDecoder {
|
|
|
4197
3524
|
LineDecoder.NEWLINE_CHARS = new Set(['\n', '\r']);
|
|
4198
3525
|
LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r]/g;
|
|
4199
3526
|
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
3527
|
+
/**
|
|
3528
|
+
* Most browsers don't yet have async iterable support for ReadableStream,
|
|
3529
|
+
* and Node has a very different way of reading bytes from its "ReadableStream".
|
|
3530
|
+
*
|
|
3531
|
+
* This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490
|
|
3532
|
+
*/
|
|
3533
|
+
function ReadableStreamToAsyncIterable(stream) {
|
|
3534
|
+
if (stream[Symbol.asyncIterator])
|
|
3535
|
+
return stream;
|
|
3536
|
+
const reader = stream.getReader();
|
|
3537
|
+
return {
|
|
3538
|
+
async next() {
|
|
3539
|
+
try {
|
|
3540
|
+
const result = await reader.read();
|
|
3541
|
+
if (result?.done)
|
|
3542
|
+
reader.releaseLock(); // release lock when stream becomes closed
|
|
3543
|
+
return result;
|
|
3544
|
+
}
|
|
3545
|
+
catch (e) {
|
|
3546
|
+
reader.releaseLock(); // release lock when stream becomes errored
|
|
3547
|
+
throw e;
|
|
3548
|
+
}
|
|
3549
|
+
},
|
|
3550
|
+
async return() {
|
|
3551
|
+
const cancelPromise = reader.cancel();
|
|
3552
|
+
reader.releaseLock();
|
|
3553
|
+
await cancelPromise;
|
|
3554
|
+
return { done: true, value: undefined };
|
|
3555
|
+
},
|
|
3556
|
+
[Symbol.asyncIterator]() {
|
|
3557
|
+
return this;
|
|
3558
|
+
},
|
|
3559
|
+
};
|
|
3560
|
+
}
|
|
3561
|
+
|
|
3562
|
+
class Stream {
|
|
3563
|
+
constructor(iterator, controller) {
|
|
3564
|
+
this.iterator = iterator;
|
|
3565
|
+
this.controller = controller;
|
|
3566
|
+
}
|
|
3567
|
+
static fromSSEResponse(response, controller) {
|
|
3568
|
+
let consumed = false;
|
|
4207
3569
|
async function* iterator() {
|
|
4208
3570
|
if (consumed) {
|
|
4209
3571
|
throw new Error('Cannot iterate over a consumed stream, use `.tee()` to split the stream.');
|
|
@@ -4274,7 +3636,7 @@ class Stream {
|
|
|
4274
3636
|
let consumed = false;
|
|
4275
3637
|
async function* iterLines() {
|
|
4276
3638
|
const lineDecoder = new LineDecoder();
|
|
4277
|
-
const iter =
|
|
3639
|
+
const iter = ReadableStreamToAsyncIterable(readableStream);
|
|
4278
3640
|
for await (const chunk of iter) {
|
|
4279
3641
|
for (const line of lineDecoder.decode(chunk)) {
|
|
4280
3642
|
yield line;
|
|
@@ -4379,7 +3741,7 @@ async function* _iterSSEMessages(response, controller) {
|
|
|
4379
3741
|
}
|
|
4380
3742
|
const sseDecoder = new SSEDecoder();
|
|
4381
3743
|
const lineDecoder = new LineDecoder();
|
|
4382
|
-
const iter =
|
|
3744
|
+
const iter = ReadableStreamToAsyncIterable(response.body);
|
|
4383
3745
|
for await (const sseChunk of iterSSEChunks(iter)) {
|
|
4384
3746
|
for (const line of lineDecoder.decode(sseChunk)) {
|
|
4385
3747
|
const sse = sseDecoder.decode(line);
|
|
@@ -4494,40 +3856,6 @@ function partition(str, delimiter) {
|
|
|
4494
3856
|
}
|
|
4495
3857
|
return [str, '', ''];
|
|
4496
3858
|
}
|
|
4497
|
-
/**
|
|
4498
|
-
* Most browsers don't yet have async iterable support for ReadableStream,
|
|
4499
|
-
* and Node has a very different way of reading bytes from its "ReadableStream".
|
|
4500
|
-
*
|
|
4501
|
-
* This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490
|
|
4502
|
-
*/
|
|
4503
|
-
function readableStreamAsyncIterable(stream) {
|
|
4504
|
-
if (stream[Symbol.asyncIterator])
|
|
4505
|
-
return stream;
|
|
4506
|
-
const reader = stream.getReader();
|
|
4507
|
-
return {
|
|
4508
|
-
async next() {
|
|
4509
|
-
try {
|
|
4510
|
-
const result = await reader.read();
|
|
4511
|
-
if (result?.done)
|
|
4512
|
-
reader.releaseLock(); // release lock when stream becomes closed
|
|
4513
|
-
return result;
|
|
4514
|
-
}
|
|
4515
|
-
catch (e) {
|
|
4516
|
-
reader.releaseLock(); // release lock when stream becomes errored
|
|
4517
|
-
throw e;
|
|
4518
|
-
}
|
|
4519
|
-
},
|
|
4520
|
-
async return() {
|
|
4521
|
-
const cancelPromise = reader.cancel();
|
|
4522
|
-
reader.releaseLock();
|
|
4523
|
-
await cancelPromise;
|
|
4524
|
-
return { done: true, value: undefined };
|
|
4525
|
-
},
|
|
4526
|
-
[Symbol.asyncIterator]() {
|
|
4527
|
-
return this;
|
|
4528
|
-
},
|
|
4529
|
-
};
|
|
4530
|
-
}
|
|
4531
3859
|
|
|
4532
3860
|
const isResponseLike = (value) => value != null &&
|
|
4533
3861
|
typeof value === 'object' &&
|
|
@@ -5026,9 +4354,18 @@ class APIClient {
|
|
|
5026
4354
|
if (signal)
|
|
5027
4355
|
signal.addEventListener('abort', () => controller.abort());
|
|
5028
4356
|
const timeout = setTimeout(() => controller.abort(), ms);
|
|
4357
|
+
const fetchOptions = {
|
|
4358
|
+
signal: controller.signal,
|
|
4359
|
+
...options,
|
|
4360
|
+
};
|
|
4361
|
+
if (fetchOptions.method) {
|
|
4362
|
+
// Custom methods like 'patch' need to be uppercased
|
|
4363
|
+
// See https://github.com/nodejs/undici/issues/2294
|
|
4364
|
+
fetchOptions.method = fetchOptions.method.toUpperCase();
|
|
4365
|
+
}
|
|
5029
4366
|
return (
|
|
5030
4367
|
// use undefined this binding; fetch errors if bound to something else in browser/cloudflare
|
|
5031
|
-
this.fetch.call(undefined, url,
|
|
4368
|
+
this.fetch.call(undefined, url, fetchOptions).finally(() => {
|
|
5032
4369
|
clearTimeout(timeout);
|
|
5033
4370
|
}));
|
|
5034
4371
|
}
|
|
@@ -5100,7 +4437,7 @@ class APIClient {
|
|
|
5100
4437
|
}
|
|
5101
4438
|
class AbstractPage {
|
|
5102
4439
|
constructor(client, response, body, options) {
|
|
5103
|
-
_AbstractPage_client.set(this,
|
|
4440
|
+
_AbstractPage_client.set(this, undefined);
|
|
5104
4441
|
__classPrivateFieldSet$3(this, _AbstractPage_client, client, "f");
|
|
5105
4442
|
this.options = options;
|
|
5106
4443
|
this.response = response;
|
|
@@ -5423,9 +4760,36 @@ function applyHeadersMut(targetHeaders, newHeaders) {
|
|
|
5423
4760
|
}
|
|
5424
4761
|
}
|
|
5425
4762
|
}
|
|
4763
|
+
const SENSITIVE_HEADERS = new Set(['authorization', 'api-key']);
|
|
5426
4764
|
function debug(action, ...args) {
|
|
5427
4765
|
if (typeof process !== 'undefined' && process?.env?.['DEBUG'] === 'true') {
|
|
5428
|
-
|
|
4766
|
+
const modifiedArgs = args.map((arg) => {
|
|
4767
|
+
if (!arg) {
|
|
4768
|
+
return arg;
|
|
4769
|
+
}
|
|
4770
|
+
// Check for sensitive headers in request body 'headers' object
|
|
4771
|
+
if (arg['headers']) {
|
|
4772
|
+
// clone so we don't mutate
|
|
4773
|
+
const modifiedArg = { ...arg, headers: { ...arg['headers'] } };
|
|
4774
|
+
for (const header in arg['headers']) {
|
|
4775
|
+
if (SENSITIVE_HEADERS.has(header.toLowerCase())) {
|
|
4776
|
+
modifiedArg['headers'][header] = 'REDACTED';
|
|
4777
|
+
}
|
|
4778
|
+
}
|
|
4779
|
+
return modifiedArg;
|
|
4780
|
+
}
|
|
4781
|
+
let modifiedArg = null;
|
|
4782
|
+
// Check for sensitive headers in headers object
|
|
4783
|
+
for (const header in arg) {
|
|
4784
|
+
if (SENSITIVE_HEADERS.has(header.toLowerCase())) {
|
|
4785
|
+
// avoid making a copy until we need to
|
|
4786
|
+
modifiedArg ?? (modifiedArg = { ...arg });
|
|
4787
|
+
modifiedArg[header] = 'REDACTED';
|
|
4788
|
+
}
|
|
4789
|
+
}
|
|
4790
|
+
return modifiedArg ?? arg;
|
|
4791
|
+
});
|
|
4792
|
+
console.log(`OpenAI:DEBUG:${action}`, ...modifiedArgs);
|
|
5429
4793
|
}
|
|
5430
4794
|
}
|
|
5431
4795
|
/**
|
|
@@ -5567,7 +4931,12 @@ class Speech extends APIResource {
|
|
|
5567
4931
|
* Generates audio from the input text.
|
|
5568
4932
|
*/
|
|
5569
4933
|
create(body, options) {
|
|
5570
|
-
return this._client.post('/audio/speech', {
|
|
4934
|
+
return this._client.post('/audio/speech', {
|
|
4935
|
+
body,
|
|
4936
|
+
...options,
|
|
4937
|
+
headers: { Accept: 'application/octet-stream', ...options?.headers },
|
|
4938
|
+
__binaryResponse: true,
|
|
4939
|
+
});
|
|
5571
4940
|
}
|
|
5572
4941
|
}
|
|
5573
4942
|
|
|
@@ -5716,10 +5085,10 @@ class EventStream {
|
|
|
5716
5085
|
constructor() {
|
|
5717
5086
|
_EventStream_instances.add(this);
|
|
5718
5087
|
this.controller = new AbortController();
|
|
5719
|
-
_EventStream_connectedPromise.set(this,
|
|
5088
|
+
_EventStream_connectedPromise.set(this, undefined);
|
|
5720
5089
|
_EventStream_resolveConnectedPromise.set(this, () => { });
|
|
5721
5090
|
_EventStream_rejectConnectedPromise.set(this, () => { });
|
|
5722
|
-
_EventStream_endPromise.set(this,
|
|
5091
|
+
_EventStream_endPromise.set(this, undefined);
|
|
5723
5092
|
_EventStream_resolveEndPromise.set(this, () => { });
|
|
5724
5093
|
_EventStream_rejectEndPromise.set(this, () => { });
|
|
5725
5094
|
_EventStream_listeners.set(this, {});
|
|
@@ -6630,9 +5999,9 @@ class ChatCompletionStream extends AbstractChatCompletionRunner {
|
|
|
6630
5999
|
constructor(params) {
|
|
6631
6000
|
super();
|
|
6632
6001
|
_ChatCompletionStream_instances.add(this);
|
|
6633
|
-
_ChatCompletionStream_params.set(this,
|
|
6634
|
-
_ChatCompletionStream_choiceEventStates.set(this,
|
|
6635
|
-
_ChatCompletionStream_currentChatCompletionSnapshot.set(this,
|
|
6002
|
+
_ChatCompletionStream_params.set(this, undefined);
|
|
6003
|
+
_ChatCompletionStream_choiceEventStates.set(this, undefined);
|
|
6004
|
+
_ChatCompletionStream_currentChatCompletionSnapshot.set(this, undefined);
|
|
6636
6005
|
__classPrivateFieldSet$1(this, _ChatCompletionStream_params, params, "f");
|
|
6637
6006
|
__classPrivateFieldSet$1(this, _ChatCompletionStream_choiceEventStates, [], "f");
|
|
6638
6007
|
}
|
|
@@ -7170,7 +6539,36 @@ class Chat extends APIResource {
|
|
|
7170
6539
|
}
|
|
7171
6540
|
(function (Chat) {
|
|
7172
6541
|
Chat.Completions = Completions$1;
|
|
7173
|
-
})(Chat
|
|
6542
|
+
})(Chat);
|
|
6543
|
+
|
|
6544
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
6545
|
+
class Sessions extends APIResource {
|
|
6546
|
+
/**
|
|
6547
|
+
* Create an ephemeral API token for use in client-side applications with the
|
|
6548
|
+
* Realtime API. Can be configured with the same session parameters as the
|
|
6549
|
+
* `session.update` client event.
|
|
6550
|
+
*
|
|
6551
|
+
* It responds with a session object, plus a `client_secret` key which contains a
|
|
6552
|
+
* usable ephemeral API token that can be used to authenticate browser clients for
|
|
6553
|
+
* the Realtime API.
|
|
6554
|
+
*/
|
|
6555
|
+
create(body, options) {
|
|
6556
|
+
return this._client.post('/realtime/sessions', {
|
|
6557
|
+
body,
|
|
6558
|
+
...options,
|
|
6559
|
+
headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers },
|
|
6560
|
+
});
|
|
6561
|
+
}
|
|
6562
|
+
}
|
|
6563
|
+
|
|
6564
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
6565
|
+
class Realtime extends APIResource {
|
|
6566
|
+
constructor() {
|
|
6567
|
+
super(...arguments);
|
|
6568
|
+
this.sessions = new Sessions(this._client);
|
|
6569
|
+
}
|
|
6570
|
+
}
|
|
6571
|
+
Realtime.Sessions = Sessions;
|
|
7174
6572
|
|
|
7175
6573
|
var __classPrivateFieldGet = (undefined && undefined.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
7176
6574
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
@@ -7194,16 +6592,16 @@ class AssistantStream extends EventStream {
|
|
|
7194
6592
|
//We are accumulating many types so the value here is not strict
|
|
7195
6593
|
_AssistantStream_runStepSnapshots.set(this, {});
|
|
7196
6594
|
_AssistantStream_messageSnapshots.set(this, {});
|
|
7197
|
-
_AssistantStream_messageSnapshot.set(this,
|
|
7198
|
-
_AssistantStream_finalRun.set(this,
|
|
7199
|
-
_AssistantStream_currentContentIndex.set(this,
|
|
7200
|
-
_AssistantStream_currentContent.set(this,
|
|
7201
|
-
_AssistantStream_currentToolCallIndex.set(this,
|
|
7202
|
-
_AssistantStream_currentToolCall.set(this,
|
|
6595
|
+
_AssistantStream_messageSnapshot.set(this, undefined);
|
|
6596
|
+
_AssistantStream_finalRun.set(this, undefined);
|
|
6597
|
+
_AssistantStream_currentContentIndex.set(this, undefined);
|
|
6598
|
+
_AssistantStream_currentContent.set(this, undefined);
|
|
6599
|
+
_AssistantStream_currentToolCallIndex.set(this, undefined);
|
|
6600
|
+
_AssistantStream_currentToolCall.set(this, undefined);
|
|
7203
6601
|
//For current snapshot methods
|
|
7204
|
-
_AssistantStream_currentEvent.set(this,
|
|
7205
|
-
_AssistantStream_currentRunSnapshot.set(this,
|
|
7206
|
-
_AssistantStream_currentRunStepSnapshot.set(this,
|
|
6602
|
+
_AssistantStream_currentEvent.set(this, undefined);
|
|
6603
|
+
_AssistantStream_currentRunSnapshot.set(this, undefined);
|
|
6604
|
+
_AssistantStream_currentRunStepSnapshot.set(this, undefined);
|
|
7207
6605
|
}
|
|
7208
6606
|
[(_AssistantStream_events = new WeakMap(), _AssistantStream_runStepSnapshots = new WeakMap(), _AssistantStream_messageSnapshots = new WeakMap(), _AssistantStream_messageSnapshot = new WeakMap(), _AssistantStream_finalRun = new WeakMap(), _AssistantStream_currentContentIndex = new WeakMap(), _AssistantStream_currentContent = new WeakMap(), _AssistantStream_currentToolCallIndex = new WeakMap(), _AssistantStream_currentToolCall = new WeakMap(), _AssistantStream_currentEvent = new WeakMap(), _AssistantStream_currentRunSnapshot = new WeakMap(), _AssistantStream_currentRunStepSnapshot = new WeakMap(), _AssistantStream_instances = new WeakSet(), Symbol.asyncIterator)]() {
|
|
7209
6607
|
const pushQueue = [];
|
|
@@ -8349,12 +7747,14 @@ VectorStores.FileBatches = FileBatches;
|
|
|
8349
7747
|
class Beta extends APIResource {
|
|
8350
7748
|
constructor() {
|
|
8351
7749
|
super(...arguments);
|
|
7750
|
+
this.realtime = new Realtime(this._client);
|
|
8352
7751
|
this.vectorStores = new VectorStores(this._client);
|
|
8353
7752
|
this.chat = new Chat(this._client);
|
|
8354
7753
|
this.assistants = new Assistants(this._client);
|
|
8355
7754
|
this.threads = new Threads(this._client);
|
|
8356
7755
|
}
|
|
8357
7756
|
}
|
|
7757
|
+
Beta.Realtime = Realtime;
|
|
8358
7758
|
Beta.VectorStores = VectorStores;
|
|
8359
7759
|
Beta.VectorStoresPage = VectorStoresPage;
|
|
8360
7760
|
Beta.Assistants = Assistants;
|
|
@@ -8428,7 +7828,11 @@ class Files extends APIResource {
|
|
|
8428
7828
|
* Returns the contents of the specified file.
|
|
8429
7829
|
*/
|
|
8430
7830
|
content(fileId, options) {
|
|
8431
|
-
return this._client.get(`/files/${fileId}/content`, {
|
|
7831
|
+
return this._client.get(`/files/${fileId}/content`, {
|
|
7832
|
+
...options,
|
|
7833
|
+
headers: { Accept: 'application/binary', ...options?.headers },
|
|
7834
|
+
__binaryResponse: true,
|
|
7835
|
+
});
|
|
8432
7836
|
}
|
|
8433
7837
|
/**
|
|
8434
7838
|
* Returns the contents of the specified file.
|
|
@@ -8436,10 +7840,7 @@ class Files extends APIResource {
|
|
|
8436
7840
|
* @deprecated The `.content()` method should be used instead
|
|
8437
7841
|
*/
|
|
8438
7842
|
retrieveContent(fileId, options) {
|
|
8439
|
-
return this._client.get(`/files/${fileId}/content`,
|
|
8440
|
-
...options,
|
|
8441
|
-
headers: { Accept: 'application/json', ...options?.headers },
|
|
8442
|
-
});
|
|
7843
|
+
return this._client.get(`/files/${fileId}/content`, options);
|
|
8443
7844
|
}
|
|
8444
7845
|
/**
|
|
8445
7846
|
* Waits for the given file to be processed, default timeout is 30 mins.
|
|
@@ -8457,660 +7858,1698 @@ class Files extends APIResource {
|
|
|
8457
7858
|
});
|
|
8458
7859
|
}
|
|
8459
7860
|
}
|
|
8460
|
-
return file;
|
|
7861
|
+
return file;
|
|
7862
|
+
}
|
|
7863
|
+
}
|
|
7864
|
+
class FileObjectsPage extends CursorPage {
|
|
7865
|
+
}
|
|
7866
|
+
Files.FileObjectsPage = FileObjectsPage;
|
|
7867
|
+
|
|
7868
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
7869
|
+
class Checkpoints extends APIResource {
|
|
7870
|
+
list(fineTuningJobId, query = {}, options) {
|
|
7871
|
+
if (isRequestOptions(query)) {
|
|
7872
|
+
return this.list(fineTuningJobId, {}, query);
|
|
7873
|
+
}
|
|
7874
|
+
return this._client.getAPIList(`/fine_tuning/jobs/${fineTuningJobId}/checkpoints`, FineTuningJobCheckpointsPage, { query, ...options });
|
|
7875
|
+
}
|
|
7876
|
+
}
|
|
7877
|
+
class FineTuningJobCheckpointsPage extends CursorPage {
|
|
7878
|
+
}
|
|
7879
|
+
Checkpoints.FineTuningJobCheckpointsPage = FineTuningJobCheckpointsPage;
|
|
7880
|
+
|
|
7881
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
7882
|
+
class Jobs extends APIResource {
|
|
7883
|
+
constructor() {
|
|
7884
|
+
super(...arguments);
|
|
7885
|
+
this.checkpoints = new Checkpoints(this._client);
|
|
7886
|
+
}
|
|
7887
|
+
/**
|
|
7888
|
+
* Creates a fine-tuning job which begins the process of creating a new model from
|
|
7889
|
+
* a given dataset.
|
|
7890
|
+
*
|
|
7891
|
+
* Response includes details of the enqueued job including job status and the name
|
|
7892
|
+
* of the fine-tuned models once complete.
|
|
7893
|
+
*
|
|
7894
|
+
* [Learn more about fine-tuning](https://platform.openai.com/docs/guides/fine-tuning)
|
|
7895
|
+
*/
|
|
7896
|
+
create(body, options) {
|
|
7897
|
+
return this._client.post('/fine_tuning/jobs', { body, ...options });
|
|
7898
|
+
}
|
|
7899
|
+
/**
|
|
7900
|
+
* Get info about a fine-tuning job.
|
|
7901
|
+
*
|
|
7902
|
+
* [Learn more about fine-tuning](https://platform.openai.com/docs/guides/fine-tuning)
|
|
7903
|
+
*/
|
|
7904
|
+
retrieve(fineTuningJobId, options) {
|
|
7905
|
+
return this._client.get(`/fine_tuning/jobs/${fineTuningJobId}`, options);
|
|
7906
|
+
}
|
|
7907
|
+
list(query = {}, options) {
|
|
7908
|
+
if (isRequestOptions(query)) {
|
|
7909
|
+
return this.list({}, query);
|
|
7910
|
+
}
|
|
7911
|
+
return this._client.getAPIList('/fine_tuning/jobs', FineTuningJobsPage, { query, ...options });
|
|
7912
|
+
}
|
|
7913
|
+
/**
|
|
7914
|
+
* Immediately cancel a fine-tune job.
|
|
7915
|
+
*/
|
|
7916
|
+
cancel(fineTuningJobId, options) {
|
|
7917
|
+
return this._client.post(`/fine_tuning/jobs/${fineTuningJobId}/cancel`, options);
|
|
7918
|
+
}
|
|
7919
|
+
listEvents(fineTuningJobId, query = {}, options) {
|
|
7920
|
+
if (isRequestOptions(query)) {
|
|
7921
|
+
return this.listEvents(fineTuningJobId, {}, query);
|
|
7922
|
+
}
|
|
7923
|
+
return this._client.getAPIList(`/fine_tuning/jobs/${fineTuningJobId}/events`, FineTuningJobEventsPage, {
|
|
7924
|
+
query,
|
|
7925
|
+
...options,
|
|
7926
|
+
});
|
|
7927
|
+
}
|
|
7928
|
+
}
|
|
7929
|
+
class FineTuningJobsPage extends CursorPage {
|
|
7930
|
+
}
|
|
7931
|
+
class FineTuningJobEventsPage extends CursorPage {
|
|
7932
|
+
}
|
|
7933
|
+
Jobs.FineTuningJobsPage = FineTuningJobsPage;
|
|
7934
|
+
Jobs.FineTuningJobEventsPage = FineTuningJobEventsPage;
|
|
7935
|
+
Jobs.Checkpoints = Checkpoints;
|
|
7936
|
+
Jobs.FineTuningJobCheckpointsPage = FineTuningJobCheckpointsPage;
|
|
7937
|
+
|
|
7938
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
7939
|
+
class FineTuning extends APIResource {
|
|
7940
|
+
constructor() {
|
|
7941
|
+
super(...arguments);
|
|
7942
|
+
this.jobs = new Jobs(this._client);
|
|
7943
|
+
}
|
|
7944
|
+
}
|
|
7945
|
+
FineTuning.Jobs = Jobs;
|
|
7946
|
+
FineTuning.FineTuningJobsPage = FineTuningJobsPage;
|
|
7947
|
+
FineTuning.FineTuningJobEventsPage = FineTuningJobEventsPage;
|
|
7948
|
+
|
|
7949
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
7950
|
+
class Images extends APIResource {
|
|
7951
|
+
/**
|
|
7952
|
+
* Creates a variation of a given image.
|
|
7953
|
+
*/
|
|
7954
|
+
createVariation(body, options) {
|
|
7955
|
+
return this._client.post('/images/variations', multipartFormRequestOptions({ body, ...options }));
|
|
7956
|
+
}
|
|
7957
|
+
/**
|
|
7958
|
+
* Creates an edited or extended image given an original image and a prompt.
|
|
7959
|
+
*/
|
|
7960
|
+
edit(body, options) {
|
|
7961
|
+
return this._client.post('/images/edits', multipartFormRequestOptions({ body, ...options }));
|
|
7962
|
+
}
|
|
7963
|
+
/**
|
|
7964
|
+
* Creates an image given a prompt.
|
|
7965
|
+
*/
|
|
7966
|
+
generate(body, options) {
|
|
7967
|
+
return this._client.post('/images/generations', { body, ...options });
|
|
7968
|
+
}
|
|
7969
|
+
}
|
|
7970
|
+
|
|
7971
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
7972
|
+
class Models extends APIResource {
|
|
7973
|
+
/**
|
|
7974
|
+
* Retrieves a model instance, providing basic information about the model such as
|
|
7975
|
+
* the owner and permissioning.
|
|
7976
|
+
*/
|
|
7977
|
+
retrieve(model, options) {
|
|
7978
|
+
return this._client.get(`/models/${model}`, options);
|
|
7979
|
+
}
|
|
7980
|
+
/**
|
|
7981
|
+
* Lists the currently available models, and provides basic information about each
|
|
7982
|
+
* one such as the owner and availability.
|
|
7983
|
+
*/
|
|
7984
|
+
list(options) {
|
|
7985
|
+
return this._client.getAPIList('/models', ModelsPage, options);
|
|
7986
|
+
}
|
|
7987
|
+
/**
|
|
7988
|
+
* Delete a fine-tuned model. You must have the Owner role in your organization to
|
|
7989
|
+
* delete a model.
|
|
7990
|
+
*/
|
|
7991
|
+
del(model, options) {
|
|
7992
|
+
return this._client.delete(`/models/${model}`, options);
|
|
7993
|
+
}
|
|
7994
|
+
}
|
|
7995
|
+
/**
|
|
7996
|
+
* Note: no pagination actually occurs yet, this is for forwards-compatibility.
|
|
7997
|
+
*/
|
|
7998
|
+
class ModelsPage extends Page {
|
|
7999
|
+
}
|
|
8000
|
+
Models.ModelsPage = ModelsPage;
|
|
8001
|
+
|
|
8002
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
8003
|
+
class Moderations extends APIResource {
|
|
8004
|
+
/**
|
|
8005
|
+
* Classifies if text and/or image inputs are potentially harmful. Learn more in
|
|
8006
|
+
* the [moderation guide](https://platform.openai.com/docs/guides/moderation).
|
|
8007
|
+
*/
|
|
8008
|
+
create(body, options) {
|
|
8009
|
+
return this._client.post('/moderations', { body, ...options });
|
|
8010
|
+
}
|
|
8011
|
+
}
|
|
8012
|
+
|
|
8013
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
8014
|
+
class Parts extends APIResource {
|
|
8015
|
+
/**
|
|
8016
|
+
* Adds a
|
|
8017
|
+
* [Part](https://platform.openai.com/docs/api-reference/uploads/part-object) to an
|
|
8018
|
+
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object.
|
|
8019
|
+
* A Part represents a chunk of bytes from the file you are trying to upload.
|
|
8020
|
+
*
|
|
8021
|
+
* Each Part can be at most 64 MB, and you can add Parts until you hit the Upload
|
|
8022
|
+
* maximum of 8 GB.
|
|
8023
|
+
*
|
|
8024
|
+
* It is possible to add multiple Parts in parallel. You can decide the intended
|
|
8025
|
+
* order of the Parts when you
|
|
8026
|
+
* [complete the Upload](https://platform.openai.com/docs/api-reference/uploads/complete).
|
|
8027
|
+
*/
|
|
8028
|
+
create(uploadId, body, options) {
|
|
8029
|
+
return this._client.post(`/uploads/${uploadId}/parts`, multipartFormRequestOptions({ body, ...options }));
|
|
8030
|
+
}
|
|
8031
|
+
}
|
|
8032
|
+
|
|
8033
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
8034
|
+
class Uploads extends APIResource {
|
|
8035
|
+
constructor() {
|
|
8036
|
+
super(...arguments);
|
|
8037
|
+
this.parts = new Parts(this._client);
|
|
8038
|
+
}
|
|
8039
|
+
/**
|
|
8040
|
+
* Creates an intermediate
|
|
8041
|
+
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object
|
|
8042
|
+
* that you can add
|
|
8043
|
+
* [Parts](https://platform.openai.com/docs/api-reference/uploads/part-object) to.
|
|
8044
|
+
* Currently, an Upload can accept at most 8 GB in total and expires after an hour
|
|
8045
|
+
* after you create it.
|
|
8046
|
+
*
|
|
8047
|
+
* Once you complete the Upload, we will create a
|
|
8048
|
+
* [File](https://platform.openai.com/docs/api-reference/files/object) object that
|
|
8049
|
+
* contains all the parts you uploaded. This File is usable in the rest of our
|
|
8050
|
+
* platform as a regular File object.
|
|
8051
|
+
*
|
|
8052
|
+
* For certain `purpose`s, the correct `mime_type` must be specified. Please refer
|
|
8053
|
+
* to documentation for the supported MIME types for your use case:
|
|
8054
|
+
*
|
|
8055
|
+
* - [Assistants](https://platform.openai.com/docs/assistants/tools/file-search#supported-files)
|
|
8056
|
+
*
|
|
8057
|
+
* For guidance on the proper filename extensions for each purpose, please follow
|
|
8058
|
+
* the documentation on
|
|
8059
|
+
* [creating a File](https://platform.openai.com/docs/api-reference/files/create).
|
|
8060
|
+
*/
|
|
8061
|
+
create(body, options) {
|
|
8062
|
+
return this._client.post('/uploads', { body, ...options });
|
|
8063
|
+
}
|
|
8064
|
+
/**
|
|
8065
|
+
* Cancels the Upload. No Parts may be added after an Upload is cancelled.
|
|
8066
|
+
*/
|
|
8067
|
+
cancel(uploadId, options) {
|
|
8068
|
+
return this._client.post(`/uploads/${uploadId}/cancel`, options);
|
|
8069
|
+
}
|
|
8070
|
+
/**
|
|
8071
|
+
* Completes the
|
|
8072
|
+
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object).
|
|
8073
|
+
*
|
|
8074
|
+
* Within the returned Upload object, there is a nested
|
|
8075
|
+
* [File](https://platform.openai.com/docs/api-reference/files/object) object that
|
|
8076
|
+
* is ready to use in the rest of the platform.
|
|
8077
|
+
*
|
|
8078
|
+
* You can specify the order of the Parts by passing in an ordered list of the Part
|
|
8079
|
+
* IDs.
|
|
8080
|
+
*
|
|
8081
|
+
* The number of bytes uploaded upon completion must match the number of bytes
|
|
8082
|
+
* initially specified when creating the Upload object. No Parts may be added after
|
|
8083
|
+
* an Upload is completed.
|
|
8084
|
+
*/
|
|
8085
|
+
complete(uploadId, body, options) {
|
|
8086
|
+
return this._client.post(`/uploads/${uploadId}/complete`, { body, ...options });
|
|
8087
|
+
}
|
|
8088
|
+
}
|
|
8089
|
+
Uploads.Parts = Parts;
|
|
8090
|
+
|
|
8091
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
8092
|
+
var _a;
|
|
8093
|
+
/**
|
|
8094
|
+
* API Client for interfacing with the OpenAI API.
|
|
8095
|
+
*/
|
|
8096
|
+
class OpenAI extends APIClient {
|
|
8097
|
+
/**
|
|
8098
|
+
* API Client for interfacing with the OpenAI API.
|
|
8099
|
+
*
|
|
8100
|
+
* @param {string | undefined} [opts.apiKey=process.env['OPENAI_API_KEY'] ?? undefined]
|
|
8101
|
+
* @param {string | null | undefined} [opts.organization=process.env['OPENAI_ORG_ID'] ?? null]
|
|
8102
|
+
* @param {string | null | undefined} [opts.project=process.env['OPENAI_PROJECT_ID'] ?? null]
|
|
8103
|
+
* @param {string} [opts.baseURL=process.env['OPENAI_BASE_URL'] ?? https://api.openai.com/v1] - Override the default base URL for the API.
|
|
8104
|
+
* @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
|
|
8105
|
+
* @param {number} [opts.httpAgent] - An HTTP agent used to manage HTTP(s) connections.
|
|
8106
|
+
* @param {Core.Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
|
|
8107
|
+
* @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.
|
|
8108
|
+
* @param {Core.Headers} opts.defaultHeaders - Default headers to include with every request to the API.
|
|
8109
|
+
* @param {Core.DefaultQuery} opts.defaultQuery - Default query parameters to include with every request to the API.
|
|
8110
|
+
* @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
|
|
8111
|
+
*/
|
|
8112
|
+
constructor({ baseURL = readEnv('OPENAI_BASE_URL'), apiKey = readEnv('OPENAI_API_KEY'), organization = readEnv('OPENAI_ORG_ID') ?? null, project = readEnv('OPENAI_PROJECT_ID') ?? null, ...opts } = {}) {
|
|
8113
|
+
if (apiKey === undefined) {
|
|
8114
|
+
throw new OpenAIError("The OPENAI_API_KEY environment variable is missing or empty; either provide it, or instantiate the OpenAI client with an apiKey option, like new OpenAI({ apiKey: 'My API Key' }).");
|
|
8115
|
+
}
|
|
8116
|
+
const options = {
|
|
8117
|
+
apiKey,
|
|
8118
|
+
organization,
|
|
8119
|
+
project,
|
|
8120
|
+
...opts,
|
|
8121
|
+
baseURL: baseURL || `https://api.openai.com/v1`,
|
|
8122
|
+
};
|
|
8123
|
+
if (!options.dangerouslyAllowBrowser && isRunningInBrowser()) {
|
|
8124
|
+
throw new OpenAIError("It looks like you're running in a browser-like environment.\n\nThis is disabled by default, as it risks exposing your secret API credentials to attackers.\nIf you understand the risks and have appropriate mitigations in place,\nyou can set the `dangerouslyAllowBrowser` option to `true`, e.g.,\n\nnew OpenAI({ apiKey, dangerouslyAllowBrowser: true });\n\nhttps://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety\n");
|
|
8125
|
+
}
|
|
8126
|
+
super({
|
|
8127
|
+
baseURL: options.baseURL,
|
|
8128
|
+
timeout: options.timeout ?? 600000 /* 10 minutes */,
|
|
8129
|
+
httpAgent: options.httpAgent,
|
|
8130
|
+
maxRetries: options.maxRetries,
|
|
8131
|
+
fetch: options.fetch,
|
|
8132
|
+
});
|
|
8133
|
+
this.completions = new Completions(this);
|
|
8134
|
+
this.chat = new Chat$1(this);
|
|
8135
|
+
this.embeddings = new Embeddings(this);
|
|
8136
|
+
this.files = new Files(this);
|
|
8137
|
+
this.images = new Images(this);
|
|
8138
|
+
this.audio = new Audio(this);
|
|
8139
|
+
this.moderations = new Moderations(this);
|
|
8140
|
+
this.models = new Models(this);
|
|
8141
|
+
this.fineTuning = new FineTuning(this);
|
|
8142
|
+
this.beta = new Beta(this);
|
|
8143
|
+
this.batches = new Batches(this);
|
|
8144
|
+
this.uploads = new Uploads(this);
|
|
8145
|
+
this._options = options;
|
|
8146
|
+
this.apiKey = apiKey;
|
|
8147
|
+
this.organization = organization;
|
|
8148
|
+
this.project = project;
|
|
8149
|
+
}
|
|
8150
|
+
defaultQuery() {
|
|
8151
|
+
return this._options.defaultQuery;
|
|
8152
|
+
}
|
|
8153
|
+
defaultHeaders(opts) {
|
|
8154
|
+
return {
|
|
8155
|
+
...super.defaultHeaders(opts),
|
|
8156
|
+
'OpenAI-Organization': this.organization,
|
|
8157
|
+
'OpenAI-Project': this.project,
|
|
8158
|
+
...this._options.defaultHeaders,
|
|
8159
|
+
};
|
|
8160
|
+
}
|
|
8161
|
+
authHeaders(opts) {
|
|
8162
|
+
return { Authorization: `Bearer ${this.apiKey}` };
|
|
8163
|
+
}
|
|
8164
|
+
stringifyQuery(query) {
|
|
8165
|
+
return stringify(query, { arrayFormat: 'brackets' });
|
|
8166
|
+
}
|
|
8167
|
+
}
|
|
8168
|
+
_a = OpenAI;
|
|
8169
|
+
OpenAI.OpenAI = _a;
|
|
8170
|
+
OpenAI.DEFAULT_TIMEOUT = 600000; // 10 minutes
|
|
8171
|
+
OpenAI.OpenAIError = OpenAIError;
|
|
8172
|
+
OpenAI.APIError = APIError;
|
|
8173
|
+
OpenAI.APIConnectionError = APIConnectionError;
|
|
8174
|
+
OpenAI.APIConnectionTimeoutError = APIConnectionTimeoutError;
|
|
8175
|
+
OpenAI.APIUserAbortError = APIUserAbortError;
|
|
8176
|
+
OpenAI.NotFoundError = NotFoundError;
|
|
8177
|
+
OpenAI.ConflictError = ConflictError;
|
|
8178
|
+
OpenAI.RateLimitError = RateLimitError;
|
|
8179
|
+
OpenAI.BadRequestError = BadRequestError;
|
|
8180
|
+
OpenAI.AuthenticationError = AuthenticationError;
|
|
8181
|
+
OpenAI.InternalServerError = InternalServerError;
|
|
8182
|
+
OpenAI.PermissionDeniedError = PermissionDeniedError;
|
|
8183
|
+
OpenAI.UnprocessableEntityError = UnprocessableEntityError;
|
|
8184
|
+
OpenAI.toFile = toFile;
|
|
8185
|
+
OpenAI.fileFromPath = fileFromPath;
|
|
8186
|
+
OpenAI.Completions = Completions;
|
|
8187
|
+
OpenAI.Chat = Chat$1;
|
|
8188
|
+
OpenAI.Embeddings = Embeddings;
|
|
8189
|
+
OpenAI.Files = Files;
|
|
8190
|
+
OpenAI.FileObjectsPage = FileObjectsPage;
|
|
8191
|
+
OpenAI.Images = Images;
|
|
8192
|
+
OpenAI.Audio = Audio;
|
|
8193
|
+
OpenAI.Moderations = Moderations;
|
|
8194
|
+
OpenAI.Models = Models;
|
|
8195
|
+
OpenAI.ModelsPage = ModelsPage;
|
|
8196
|
+
OpenAI.FineTuning = FineTuning;
|
|
8197
|
+
OpenAI.Beta = Beta;
|
|
8198
|
+
OpenAI.Batches = Batches;
|
|
8199
|
+
OpenAI.BatchesPage = BatchesPage;
|
|
8200
|
+
OpenAI.Uploads = Uploads;
|
|
8201
|
+
|
|
8202
|
+
class OpenaiProvider {
|
|
8203
|
+
constructor(param, defaultModel, options) {
|
|
8204
|
+
this.defaultModel = 'gpt-4o';
|
|
8205
|
+
if (defaultModel) {
|
|
8206
|
+
this.defaultModel = defaultModel;
|
|
8207
|
+
}
|
|
8208
|
+
if (typeof window !== 'undefined' &&
|
|
8209
|
+
typeof document !== 'undefined' &&
|
|
8210
|
+
(typeof param == 'string' || param.apiKey)) {
|
|
8211
|
+
console.warn(`
|
|
8212
|
+
⚠️ Security Warning:
|
|
8213
|
+
DO NOT use API Keys in browser/frontend code!
|
|
8214
|
+
This will expose your credentials and may lead to unauthorized usage.
|
|
8215
|
+
|
|
8216
|
+
Best Practices: Configure backend API proxy request through baseURL and request headers.
|
|
8217
|
+
|
|
8218
|
+
Please refer to the link: https://eko.fellou.ai/docs/getting-started/configuration#web-environment
|
|
8219
|
+
`);
|
|
8220
|
+
}
|
|
8221
|
+
if (typeof param == 'string') {
|
|
8222
|
+
this.client = new OpenAI({
|
|
8223
|
+
apiKey: param,
|
|
8224
|
+
dangerouslyAllowBrowser: true,
|
|
8225
|
+
...options,
|
|
8226
|
+
});
|
|
8227
|
+
}
|
|
8228
|
+
else if (param.chat && param.chat.completions) {
|
|
8229
|
+
this.client = param;
|
|
8230
|
+
}
|
|
8231
|
+
else {
|
|
8232
|
+
let options = param;
|
|
8233
|
+
options.dangerouslyAllowBrowser = true;
|
|
8234
|
+
this.client = new OpenAI(options);
|
|
8235
|
+
}
|
|
8236
|
+
}
|
|
8237
|
+
buildParams(messages, params, stream) {
|
|
8238
|
+
let tools = undefined;
|
|
8239
|
+
if (params.tools && params.tools.length > 0) {
|
|
8240
|
+
tools = [];
|
|
8241
|
+
for (let i = 0; i < params.tools.length; i++) {
|
|
8242
|
+
let tool = params.tools[i];
|
|
8243
|
+
tools.push({
|
|
8244
|
+
type: 'function',
|
|
8245
|
+
function: {
|
|
8246
|
+
name: tool.name,
|
|
8247
|
+
description: tool.description,
|
|
8248
|
+
parameters: tool.input_schema,
|
|
8249
|
+
},
|
|
8250
|
+
});
|
|
8251
|
+
}
|
|
8252
|
+
}
|
|
8253
|
+
let tool_choice = undefined;
|
|
8254
|
+
if (params.toolChoice) {
|
|
8255
|
+
if (params.toolChoice.type == 'auto') {
|
|
8256
|
+
tool_choice = 'auto';
|
|
8257
|
+
}
|
|
8258
|
+
else if (params.toolChoice.type == 'tool') {
|
|
8259
|
+
if (params.toolChoice.name) {
|
|
8260
|
+
tool_choice = {
|
|
8261
|
+
type: 'function',
|
|
8262
|
+
function: { name: params.toolChoice.name },
|
|
8263
|
+
};
|
|
8264
|
+
}
|
|
8265
|
+
else {
|
|
8266
|
+
tool_choice = 'required';
|
|
8267
|
+
}
|
|
8268
|
+
}
|
|
8269
|
+
}
|
|
8270
|
+
let _messages = [];
|
|
8271
|
+
for (let i = 0; i < messages.length; i++) {
|
|
8272
|
+
let message = messages[i];
|
|
8273
|
+
if (message.role == 'assistant' && typeof message.content !== 'string') {
|
|
8274
|
+
let _content = undefined;
|
|
8275
|
+
let _tool_calls = undefined;
|
|
8276
|
+
for (let j = 0; j < message.content.length; j++) {
|
|
8277
|
+
let content = message.content[j];
|
|
8278
|
+
if (content.type == 'text') {
|
|
8279
|
+
if (!_content) {
|
|
8280
|
+
_content = [];
|
|
8281
|
+
}
|
|
8282
|
+
_content.push(content);
|
|
8283
|
+
}
|
|
8284
|
+
else if (content.type == 'tool_use') {
|
|
8285
|
+
if (!_tool_calls) {
|
|
8286
|
+
_tool_calls = [];
|
|
8287
|
+
}
|
|
8288
|
+
_tool_calls.push({
|
|
8289
|
+
id: content.id,
|
|
8290
|
+
type: 'function',
|
|
8291
|
+
function: {
|
|
8292
|
+
name: content.name,
|
|
8293
|
+
arguments: typeof content.input == 'string' ? content.input : JSON.stringify(content.input),
|
|
8294
|
+
},
|
|
8295
|
+
});
|
|
8296
|
+
}
|
|
8297
|
+
}
|
|
8298
|
+
_messages.push({
|
|
8299
|
+
role: 'assistant',
|
|
8300
|
+
content: _content,
|
|
8301
|
+
tool_calls: _tool_calls,
|
|
8302
|
+
});
|
|
8303
|
+
}
|
|
8304
|
+
else if (message.role == 'user' && typeof message.content !== 'string') {
|
|
8305
|
+
for (let j = 0; j < message.content.length; j++) {
|
|
8306
|
+
let content = message.content[j];
|
|
8307
|
+
if (content.type == 'text') {
|
|
8308
|
+
_messages.push({
|
|
8309
|
+
role: 'user',
|
|
8310
|
+
content: content.text,
|
|
8311
|
+
});
|
|
8312
|
+
}
|
|
8313
|
+
else if (content.type == 'image') {
|
|
8314
|
+
_messages.push({
|
|
8315
|
+
role: 'user',
|
|
8316
|
+
content: [
|
|
8317
|
+
{
|
|
8318
|
+
type: 'image_url',
|
|
8319
|
+
image_url: {
|
|
8320
|
+
url: `data:${content.source.media_type};base64,${content.source.data}`,
|
|
8321
|
+
},
|
|
8322
|
+
},
|
|
8323
|
+
],
|
|
8324
|
+
});
|
|
8325
|
+
}
|
|
8326
|
+
else if (content.type == 'tool_result') {
|
|
8327
|
+
let _content = [];
|
|
8328
|
+
if (content.content == 'string') {
|
|
8329
|
+
_content.push({ type: 'text', text: content.content });
|
|
8330
|
+
}
|
|
8331
|
+
else {
|
|
8332
|
+
for (let k = 0; k < content.content.length; k++) {
|
|
8333
|
+
let item = content.content[k];
|
|
8334
|
+
if (item.type == 'text') {
|
|
8335
|
+
_content.push({ ...item });
|
|
8336
|
+
}
|
|
8337
|
+
else if (item.type == 'image') {
|
|
8338
|
+
_content.push({
|
|
8339
|
+
type: 'image_url',
|
|
8340
|
+
image_url: {
|
|
8341
|
+
url: `data:${item.source.media_type};base64,${item.source.data}`,
|
|
8342
|
+
},
|
|
8343
|
+
});
|
|
8344
|
+
}
|
|
8345
|
+
}
|
|
8346
|
+
}
|
|
8347
|
+
let hasImage = _content.filter((s) => s.type == 'image_url').length > 0;
|
|
8348
|
+
if (hasImage) {
|
|
8349
|
+
// OpenAI does not support images returned by the tool.
|
|
8350
|
+
_messages.push({
|
|
8351
|
+
role: 'tool',
|
|
8352
|
+
content: 'ok',
|
|
8353
|
+
tool_call_id: content.tool_call_id || content.tool_use_id,
|
|
8354
|
+
});
|
|
8355
|
+
_messages.push({
|
|
8356
|
+
role: 'user',
|
|
8357
|
+
content: _content,
|
|
8358
|
+
});
|
|
8359
|
+
}
|
|
8360
|
+
else {
|
|
8361
|
+
_messages.push({
|
|
8362
|
+
role: 'tool',
|
|
8363
|
+
content: _content,
|
|
8364
|
+
tool_call_id: content.tool_call_id || content.tool_use_id,
|
|
8365
|
+
});
|
|
8366
|
+
}
|
|
8367
|
+
}
|
|
8368
|
+
}
|
|
8369
|
+
}
|
|
8370
|
+
else {
|
|
8371
|
+
_messages.push(message);
|
|
8372
|
+
}
|
|
8373
|
+
}
|
|
8374
|
+
return {
|
|
8375
|
+
stream: stream,
|
|
8376
|
+
model: params.model || this.defaultModel,
|
|
8377
|
+
max_tokens: params.maxTokens || 8192,
|
|
8378
|
+
temperature: params.temperature,
|
|
8379
|
+
messages: _messages,
|
|
8380
|
+
tools: tools,
|
|
8381
|
+
tool_choice: tool_choice,
|
|
8382
|
+
};
|
|
8383
|
+
}
|
|
8384
|
+
async generateText(messages, params) {
|
|
8385
|
+
const response = await this.client.chat.completions.create(this.buildParams(messages, params, false));
|
|
8386
|
+
let textContent = null;
|
|
8387
|
+
let toolCalls = [];
|
|
8388
|
+
let stop_reason = null;
|
|
8389
|
+
for (let i = 0; i < response.choices.length; i++) {
|
|
8390
|
+
let choice = response.choices[i];
|
|
8391
|
+
let message = choice.message;
|
|
8392
|
+
if (message.content) {
|
|
8393
|
+
if (textContent == null) {
|
|
8394
|
+
textContent = '';
|
|
8395
|
+
}
|
|
8396
|
+
textContent += message.content;
|
|
8397
|
+
}
|
|
8398
|
+
if (message.tool_calls) {
|
|
8399
|
+
for (let j = 0; j < message.tool_calls.length; j++) {
|
|
8400
|
+
let tool_call = message.tool_calls[j];
|
|
8401
|
+
toolCalls.push({
|
|
8402
|
+
id: tool_call.id,
|
|
8403
|
+
name: tool_call.function.name,
|
|
8404
|
+
input: JSON.parse(tool_call.function.arguments),
|
|
8405
|
+
});
|
|
8406
|
+
}
|
|
8407
|
+
}
|
|
8408
|
+
if (choice.finish_reason) {
|
|
8409
|
+
stop_reason = choice.finish_reason;
|
|
8410
|
+
}
|
|
8411
|
+
}
|
|
8412
|
+
let content = [];
|
|
8413
|
+
if (textContent) {
|
|
8414
|
+
content.push({
|
|
8415
|
+
type: 'text',
|
|
8416
|
+
text: textContent,
|
|
8417
|
+
});
|
|
8418
|
+
}
|
|
8419
|
+
if (toolCalls.length > 0) {
|
|
8420
|
+
for (let i = 0; i < toolCalls.length; i++) {
|
|
8421
|
+
let toolCall = toolCalls[i];
|
|
8422
|
+
content.push({
|
|
8423
|
+
type: 'tool_use',
|
|
8424
|
+
id: toolCall.id,
|
|
8425
|
+
name: toolCall.name,
|
|
8426
|
+
input: toolCall.input,
|
|
8427
|
+
});
|
|
8428
|
+
}
|
|
8429
|
+
}
|
|
8430
|
+
return {
|
|
8431
|
+
textContent,
|
|
8432
|
+
content,
|
|
8433
|
+
toolCalls,
|
|
8434
|
+
stop_reason,
|
|
8435
|
+
};
|
|
8461
8436
|
}
|
|
8462
|
-
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
|
|
8466
|
-
|
|
8467
|
-
|
|
8468
|
-
|
|
8469
|
-
|
|
8470
|
-
|
|
8471
|
-
|
|
8437
|
+
async generateStream(messages, params, handler) {
|
|
8438
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
8439
|
+
const stream = await this.client.chat.completions.create(this.buildParams(messages, params, true));
|
|
8440
|
+
(_a = handler.onStart) === null || _a === undefined ? undefined : _a.call(handler);
|
|
8441
|
+
let textContent = null;
|
|
8442
|
+
let toolCalls = [];
|
|
8443
|
+
let stop_reason = null;
|
|
8444
|
+
let currentToolUse = null;
|
|
8445
|
+
try {
|
|
8446
|
+
for await (const chunk of stream) {
|
|
8447
|
+
for (let i = 0; i < chunk.choices.length; i++) {
|
|
8448
|
+
let choice = chunk.choices[i];
|
|
8449
|
+
if (choice.delta) {
|
|
8450
|
+
if (choice.delta.content) {
|
|
8451
|
+
if (textContent == null) {
|
|
8452
|
+
textContent = '';
|
|
8453
|
+
}
|
|
8454
|
+
textContent += choice.delta.content;
|
|
8455
|
+
(_b = handler.onContent) === null || _b === void 0 ? void 0 : _b.call(handler, choice.delta.content);
|
|
8456
|
+
}
|
|
8457
|
+
else if (choice.delta.tool_calls && choice.delta.tool_calls.length > 0) {
|
|
8458
|
+
let tool_calls = choice.delta.tool_calls[0];
|
|
8459
|
+
if (!currentToolUse) {
|
|
8460
|
+
currentToolUse = {
|
|
8461
|
+
id: tool_calls.id || '',
|
|
8462
|
+
name: ((_c = tool_calls.function) === null || _c === void 0 ? void 0 : _c.name) || '',
|
|
8463
|
+
accumulatedJson: ((_d = tool_calls.function) === null || _d === void 0 ? void 0 : _d.arguments) || '',
|
|
8464
|
+
};
|
|
8465
|
+
}
|
|
8466
|
+
else {
|
|
8467
|
+
if (tool_calls.id) {
|
|
8468
|
+
currentToolUse.id = tool_calls.id;
|
|
8469
|
+
}
|
|
8470
|
+
if ((_e = tool_calls.function) === null || _e === void 0 ? void 0 : _e.name) {
|
|
8471
|
+
currentToolUse.name = (_f = tool_calls.function) === null || _f === void 0 ? void 0 : _f.name;
|
|
8472
|
+
}
|
|
8473
|
+
currentToolUse.accumulatedJson += ((_g = tool_calls.function) === null || _g === void 0 ? void 0 : _g.arguments) || '';
|
|
8474
|
+
}
|
|
8475
|
+
}
|
|
8476
|
+
}
|
|
8477
|
+
if (choice.finish_reason) {
|
|
8478
|
+
stop_reason = choice.finish_reason;
|
|
8479
|
+
if (currentToolUse) {
|
|
8480
|
+
const toolCall = {
|
|
8481
|
+
id: currentToolUse.id,
|
|
8482
|
+
name: currentToolUse.name,
|
|
8483
|
+
input: JSON.parse(currentToolUse.accumulatedJson),
|
|
8484
|
+
};
|
|
8485
|
+
toolCalls.push(toolCall);
|
|
8486
|
+
(_h = handler.onToolUse) === null || _h === void 0 ? void 0 : _h.call(handler, toolCall);
|
|
8487
|
+
currentToolUse = null;
|
|
8488
|
+
}
|
|
8489
|
+
}
|
|
8490
|
+
}
|
|
8491
|
+
}
|
|
8492
|
+
let content = [];
|
|
8493
|
+
if (textContent) {
|
|
8494
|
+
content.push({
|
|
8495
|
+
type: 'text',
|
|
8496
|
+
text: textContent,
|
|
8497
|
+
});
|
|
8498
|
+
}
|
|
8499
|
+
if (toolCalls && toolCalls.length > 0) {
|
|
8500
|
+
for (let i = 0; i < toolCalls.length; i++) {
|
|
8501
|
+
let toolCall = toolCalls[i];
|
|
8502
|
+
content.push({
|
|
8503
|
+
type: 'tool_use',
|
|
8504
|
+
id: toolCall.id,
|
|
8505
|
+
name: toolCall.name,
|
|
8506
|
+
input: toolCall.input,
|
|
8507
|
+
});
|
|
8508
|
+
}
|
|
8509
|
+
}
|
|
8510
|
+
(_j = handler.onComplete) === null || _j === void 0 ? void 0 : _j.call(handler, {
|
|
8511
|
+
textContent: textContent,
|
|
8512
|
+
content: content,
|
|
8513
|
+
toolCalls: toolCalls,
|
|
8514
|
+
stop_reason: stop_reason,
|
|
8515
|
+
});
|
|
8516
|
+
}
|
|
8517
|
+
catch (error) {
|
|
8518
|
+
(_k = handler.onError) === null || _k === undefined ? undefined : _k.call(handler, error);
|
|
8472
8519
|
}
|
|
8473
|
-
return this._client.getAPIList(`/fine_tuning/jobs/${fineTuningJobId}/checkpoints`, FineTuningJobCheckpointsPage, { query, ...options });
|
|
8474
8520
|
}
|
|
8475
8521
|
}
|
|
8476
|
-
class FineTuningJobCheckpointsPage extends CursorPage {
|
|
8477
|
-
}
|
|
8478
|
-
Checkpoints.FineTuningJobCheckpointsPage = FineTuningJobCheckpointsPage;
|
|
8479
8522
|
|
|
8480
|
-
|
|
8481
|
-
|
|
8482
|
-
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
}
|
|
8486
|
-
/**
|
|
8487
|
-
* Creates a fine-tuning job which begins the process of creating a new model from
|
|
8488
|
-
* a given dataset.
|
|
8489
|
-
*
|
|
8490
|
-
* Response includes details of the enqueued job including job status and the name
|
|
8491
|
-
* of the fine-tuned models once complete.
|
|
8492
|
-
*
|
|
8493
|
-
* [Learn more about fine-tuning](https://platform.openai.com/docs/guides/fine-tuning)
|
|
8494
|
-
*/
|
|
8495
|
-
create(body, options) {
|
|
8496
|
-
return this._client.post('/fine_tuning/jobs', { body, ...options });
|
|
8497
|
-
}
|
|
8498
|
-
/**
|
|
8499
|
-
* Get info about a fine-tuning job.
|
|
8500
|
-
*
|
|
8501
|
-
* [Learn more about fine-tuning](https://platform.openai.com/docs/guides/fine-tuning)
|
|
8502
|
-
*/
|
|
8503
|
-
retrieve(fineTuningJobId, options) {
|
|
8504
|
-
return this._client.get(`/fine_tuning/jobs/${fineTuningJobId}`, options);
|
|
8505
|
-
}
|
|
8506
|
-
list(query = {}, options) {
|
|
8507
|
-
if (isRequestOptions(query)) {
|
|
8508
|
-
return this.list({}, query);
|
|
8523
|
+
class LLMProviderFactory {
|
|
8524
|
+
static buildLLMProvider(config) {
|
|
8525
|
+
let llmProvider;
|
|
8526
|
+
if (typeof config == 'string') {
|
|
8527
|
+
llmProvider = new ClaudeProvider(config);
|
|
8509
8528
|
}
|
|
8510
|
-
|
|
8511
|
-
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8529
|
+
else if ('llm' in config) {
|
|
8530
|
+
if (config.llm == 'claude') {
|
|
8531
|
+
let claudeConfig = config;
|
|
8532
|
+
llmProvider = new ClaudeProvider(claudeConfig.apiKey, claudeConfig.modelName, claudeConfig.options);
|
|
8533
|
+
}
|
|
8534
|
+
else if (config.llm == 'openai') {
|
|
8535
|
+
let openaiConfig = config;
|
|
8536
|
+
llmProvider = new OpenaiProvider(openaiConfig.apiKey, openaiConfig.modelName, openaiConfig.options);
|
|
8537
|
+
}
|
|
8538
|
+
else {
|
|
8539
|
+
throw new Error('Unknown parameter: llm > ' + config['llm']);
|
|
8540
|
+
}
|
|
8521
8541
|
}
|
|
8522
|
-
|
|
8523
|
-
|
|
8524
|
-
|
|
8525
|
-
|
|
8526
|
-
}
|
|
8527
|
-
}
|
|
8528
|
-
class FineTuningJobsPage extends CursorPage {
|
|
8529
|
-
}
|
|
8530
|
-
class FineTuningJobEventsPage extends CursorPage {
|
|
8531
|
-
}
|
|
8532
|
-
Jobs.FineTuningJobsPage = FineTuningJobsPage;
|
|
8533
|
-
Jobs.FineTuningJobEventsPage = FineTuningJobEventsPage;
|
|
8534
|
-
Jobs.Checkpoints = Checkpoints;
|
|
8535
|
-
Jobs.FineTuningJobCheckpointsPage = FineTuningJobCheckpointsPage;
|
|
8536
|
-
|
|
8537
|
-
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
8538
|
-
class FineTuning extends APIResource {
|
|
8539
|
-
constructor() {
|
|
8540
|
-
super(...arguments);
|
|
8541
|
-
this.jobs = new Jobs(this._client);
|
|
8542
|
-
}
|
|
8543
|
-
}
|
|
8544
|
-
FineTuning.Jobs = Jobs;
|
|
8545
|
-
FineTuning.FineTuningJobsPage = FineTuningJobsPage;
|
|
8546
|
-
FineTuning.FineTuningJobEventsPage = FineTuningJobEventsPage;
|
|
8547
|
-
|
|
8548
|
-
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
8549
|
-
class Images extends APIResource {
|
|
8550
|
-
/**
|
|
8551
|
-
* Creates a variation of a given image.
|
|
8552
|
-
*/
|
|
8553
|
-
createVariation(body, options) {
|
|
8554
|
-
return this._client.post('/images/variations', multipartFormRequestOptions({ body, ...options }));
|
|
8555
|
-
}
|
|
8556
|
-
/**
|
|
8557
|
-
* Creates an edited or extended image given an original image and a prompt.
|
|
8558
|
-
*/
|
|
8559
|
-
edit(body, options) {
|
|
8560
|
-
return this._client.post('/images/edits', multipartFormRequestOptions({ body, ...options }));
|
|
8561
|
-
}
|
|
8562
|
-
/**
|
|
8563
|
-
* Creates an image given a prompt.
|
|
8564
|
-
*/
|
|
8565
|
-
generate(body, options) {
|
|
8566
|
-
return this._client.post('/images/generations', { body, ...options });
|
|
8542
|
+
else {
|
|
8543
|
+
llmProvider = config;
|
|
8544
|
+
}
|
|
8545
|
+
return llmProvider;
|
|
8567
8546
|
}
|
|
8568
8547
|
}
|
|
8569
8548
|
|
|
8570
|
-
|
|
8571
|
-
|
|
8572
|
-
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
|
|
8549
|
+
/**
|
|
8550
|
+
* Manages logging for action execution, providing a cleaner view of the execution
|
|
8551
|
+
* flow while maintaining important context and history.
|
|
8552
|
+
*/
|
|
8553
|
+
class ExecutionLogger {
|
|
8554
|
+
constructor(options = {}) {
|
|
8555
|
+
var _a;
|
|
8556
|
+
this.history = [];
|
|
8557
|
+
this.maxHistoryLength = options.maxHistoryLength || 10;
|
|
8558
|
+
this.logLevel = options.logLevel || 'info';
|
|
8559
|
+
this.includeTimestamp = (_a = options.includeTimestamp) !== null && _a !== undefined ? _a : true;
|
|
8560
|
+
this.debugImagePath = options.debugImagePath;
|
|
8561
|
+
this.imageSaver = options.imageSaver;
|
|
8562
|
+
// Check if running in Node.js environment
|
|
8563
|
+
this.isNode =
|
|
8564
|
+
typeof process !== 'undefined' && process.versions != null && process.versions.node != null;
|
|
8578
8565
|
}
|
|
8579
8566
|
/**
|
|
8580
|
-
*
|
|
8581
|
-
* one such as the owner and availability.
|
|
8567
|
+
* Logs a message with execution context
|
|
8582
8568
|
*/
|
|
8583
|
-
|
|
8584
|
-
|
|
8569
|
+
log(level, message, context) {
|
|
8570
|
+
if (this.shouldLog(level)) {
|
|
8571
|
+
const timestamp = this.includeTimestamp ? new Date().toISOString() : '';
|
|
8572
|
+
const contextSummary = this.summarizeContext(context);
|
|
8573
|
+
console.log(`${timestamp} [${level.toUpperCase()}] ${message}${contextSummary}`);
|
|
8574
|
+
}
|
|
8585
8575
|
}
|
|
8586
8576
|
/**
|
|
8587
|
-
*
|
|
8588
|
-
* delete a model.
|
|
8577
|
+
* Updates conversation history while maintaining size limit
|
|
8589
8578
|
*/
|
|
8590
|
-
|
|
8591
|
-
|
|
8579
|
+
updateHistory(messages) {
|
|
8580
|
+
// Keep system messages and last N messages
|
|
8581
|
+
const systemMessages = messages.filter((m) => m.role === 'system');
|
|
8582
|
+
const nonSystemMessages = messages.filter((m) => m.role !== 'system');
|
|
8583
|
+
const recentMessages = nonSystemMessages.slice(-this.maxHistoryLength);
|
|
8584
|
+
this.history = [...systemMessages, ...recentMessages];
|
|
8592
8585
|
}
|
|
8593
|
-
}
|
|
8594
|
-
/**
|
|
8595
|
-
* Note: no pagination actually occurs yet, this is for forwards-compatibility.
|
|
8596
|
-
*/
|
|
8597
|
-
class ModelsPage extends Page {
|
|
8598
|
-
}
|
|
8599
|
-
Models.ModelsPage = ModelsPage;
|
|
8600
|
-
|
|
8601
|
-
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
8602
|
-
class Moderations extends APIResource {
|
|
8603
8586
|
/**
|
|
8604
|
-
*
|
|
8605
|
-
* the [moderation guide](https://platform.openai.com/docs/guides/moderation).
|
|
8587
|
+
* Gets current conversation history
|
|
8606
8588
|
*/
|
|
8607
|
-
|
|
8608
|
-
return this.
|
|
8589
|
+
getHistory() {
|
|
8590
|
+
return this.history;
|
|
8609
8591
|
}
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
8613
|
-
class Parts extends APIResource {
|
|
8614
|
-
/**
|
|
8615
|
-
* Adds a
|
|
8616
|
-
* [Part](https://platform.openai.com/docs/api-reference/uploads/part-object) to an
|
|
8617
|
-
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object.
|
|
8618
|
-
* A Part represents a chunk of bytes from the file you are trying to upload.
|
|
8619
|
-
*
|
|
8620
|
-
* Each Part can be at most 64 MB, and you can add Parts until you hit the Upload
|
|
8621
|
-
* maximum of 8 GB.
|
|
8622
|
-
*
|
|
8623
|
-
* It is possible to add multiple Parts in parallel. You can decide the intended
|
|
8624
|
-
* order of the Parts when you
|
|
8625
|
-
* [complete the Upload](https://platform.openai.com/docs/api-reference/uploads/complete).
|
|
8592
|
+
/**
|
|
8593
|
+
* Summarizes the execution context for logging
|
|
8626
8594
|
*/
|
|
8627
|
-
|
|
8628
|
-
|
|
8595
|
+
summarizeContext(context) {
|
|
8596
|
+
if (!context)
|
|
8597
|
+
return '';
|
|
8598
|
+
const summary = {
|
|
8599
|
+
variables: Object.fromEntries(context.variables),
|
|
8600
|
+
tools: context.tools ? Array.from(context.tools.keys()) : [],
|
|
8601
|
+
};
|
|
8602
|
+
return `\nContext: ${JSON.stringify(summary, null, 2)}`;
|
|
8629
8603
|
}
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
8604
|
+
/**
|
|
8605
|
+
* Checks if message should be logged based on log level
|
|
8606
|
+
*/
|
|
8607
|
+
shouldLog(level) {
|
|
8608
|
+
const levels = {
|
|
8609
|
+
error: 0,
|
|
8610
|
+
warn: 1,
|
|
8611
|
+
info: 2,
|
|
8612
|
+
debug: 3,
|
|
8613
|
+
};
|
|
8614
|
+
return levels[level] <= levels[this.logLevel];
|
|
8637
8615
|
}
|
|
8638
8616
|
/**
|
|
8639
|
-
*
|
|
8640
|
-
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object) object
|
|
8641
|
-
* that you can add
|
|
8642
|
-
* [Parts](https://platform.openai.com/docs/api-reference/uploads/part-object) to.
|
|
8643
|
-
* Currently, an Upload can accept at most 8 GB in total and expires after an hour
|
|
8644
|
-
* after you create it.
|
|
8645
|
-
*
|
|
8646
|
-
* Once you complete the Upload, we will create a
|
|
8647
|
-
* [File](https://platform.openai.com/docs/api-reference/files/object) object that
|
|
8648
|
-
* contains all the parts you uploaded. This File is usable in the rest of our
|
|
8649
|
-
* platform as a regular File object.
|
|
8650
|
-
*
|
|
8651
|
-
* For certain `purpose`s, the correct `mime_type` must be specified. Please refer
|
|
8652
|
-
* to documentation for the supported MIME types for your use case:
|
|
8653
|
-
*
|
|
8654
|
-
* - [Assistants](https://platform.openai.com/docs/assistants/tools/file-search#supported-files)
|
|
8655
|
-
*
|
|
8656
|
-
* For guidance on the proper filename extensions for each purpose, please follow
|
|
8657
|
-
* the documentation on
|
|
8658
|
-
* [creating a File](https://platform.openai.com/docs/api-reference/files/create).
|
|
8617
|
+
* Logs the start of an action execution
|
|
8659
8618
|
*/
|
|
8660
|
-
|
|
8661
|
-
|
|
8619
|
+
logActionStart(actionName, input, context) {
|
|
8620
|
+
this.log('info', `Starting action: ${actionName}`, context);
|
|
8621
|
+
this.log('info', `Input: ${JSON.stringify(input, null, 2)}`);
|
|
8662
8622
|
}
|
|
8663
8623
|
/**
|
|
8664
|
-
*
|
|
8624
|
+
* Logs the completion of an action execution
|
|
8665
8625
|
*/
|
|
8666
|
-
|
|
8667
|
-
|
|
8626
|
+
logActionComplete(actionName, result, context) {
|
|
8627
|
+
this.log('info', `Completed action: ${actionName}`, context);
|
|
8628
|
+
this.log('info', `Result: ${JSON.stringify(result, null, 2)}`);
|
|
8668
8629
|
}
|
|
8669
8630
|
/**
|
|
8670
|
-
*
|
|
8671
|
-
* [Upload](https://platform.openai.com/docs/api-reference/uploads/object).
|
|
8672
|
-
*
|
|
8673
|
-
* Within the returned Upload object, there is a nested
|
|
8674
|
-
* [File](https://platform.openai.com/docs/api-reference/files/object) object that
|
|
8675
|
-
* is ready to use in the rest of the platform.
|
|
8676
|
-
*
|
|
8677
|
-
* You can specify the order of the Parts by passing in an ordered list of the Part
|
|
8678
|
-
* IDs.
|
|
8679
|
-
*
|
|
8680
|
-
* The number of bytes uploaded upon completion must match the number of bytes
|
|
8681
|
-
* initially specified when creating the Upload object. No Parts may be added after
|
|
8682
|
-
* an Upload is completed.
|
|
8631
|
+
* Logs a tool execution
|
|
8683
8632
|
*/
|
|
8684
|
-
|
|
8685
|
-
|
|
8633
|
+
logToolExecution(toolName, input, context) {
|
|
8634
|
+
this.log('info', `Executing tool: ${toolName}`);
|
|
8635
|
+
this.log('info', `Tool input: ${JSON.stringify(input, null, 2)}`);
|
|
8686
8636
|
}
|
|
8687
|
-
}
|
|
8688
|
-
Uploads.Parts = Parts;
|
|
8689
|
-
|
|
8690
|
-
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
8691
|
-
var _a;
|
|
8692
|
-
/**
|
|
8693
|
-
* API Client for interfacing with the OpenAI API.
|
|
8694
|
-
*/
|
|
8695
|
-
class OpenAI extends APIClient {
|
|
8696
8637
|
/**
|
|
8697
|
-
*
|
|
8698
|
-
*
|
|
8699
|
-
* @param {string | undefined} [opts.apiKey=process.env['OPENAI_API_KEY'] ?? undefined]
|
|
8700
|
-
* @param {string | null | undefined} [opts.organization=process.env['OPENAI_ORG_ID'] ?? null]
|
|
8701
|
-
* @param {string | null | undefined} [opts.project=process.env['OPENAI_PROJECT_ID'] ?? null]
|
|
8702
|
-
* @param {string} [opts.baseURL=process.env['OPENAI_BASE_URL'] ?? https://api.openai.com/v1] - Override the default base URL for the API.
|
|
8703
|
-
* @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
|
|
8704
|
-
* @param {number} [opts.httpAgent] - An HTTP agent used to manage HTTP(s) connections.
|
|
8705
|
-
* @param {Core.Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
|
|
8706
|
-
* @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.
|
|
8707
|
-
* @param {Core.Headers} opts.defaultHeaders - Default headers to include with every request to the API.
|
|
8708
|
-
* @param {Core.DefaultQuery} opts.defaultQuery - Default query parameters to include with every request to the API.
|
|
8709
|
-
* @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
|
|
8638
|
+
* Logs an error that occurred during execution
|
|
8710
8639
|
*/
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8640
|
+
logError(error, context) {
|
|
8641
|
+
console.error(error);
|
|
8642
|
+
try {
|
|
8643
|
+
this.log('error', `Error occurred: ${error.message}`, context);
|
|
8644
|
+
if (error.stack) {
|
|
8645
|
+
this.log('debug', `Stack trace: ${error.stack}`);
|
|
8646
|
+
}
|
|
8714
8647
|
}
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
project,
|
|
8719
|
-
...opts,
|
|
8720
|
-
baseURL: baseURL || `https://api.openai.com/v1`,
|
|
8721
|
-
};
|
|
8722
|
-
if (!options.dangerouslyAllowBrowser && isRunningInBrowser()) {
|
|
8723
|
-
throw new OpenAIError("It looks like you're running in a browser-like environment.\n\nThis is disabled by default, as it risks exposing your secret API credentials to attackers.\nIf you understand the risks and have appropriate mitigations in place,\nyou can set the `dangerouslyAllowBrowser` option to `true`, e.g.,\n\nnew OpenAI({ apiKey, dangerouslyAllowBrowser: true });\n\nhttps://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety\n");
|
|
8648
|
+
catch (error) {
|
|
8649
|
+
console.error("An error occurs when trying to log another error:");
|
|
8650
|
+
console.error(error);
|
|
8724
8651
|
}
|
|
8725
|
-
super({
|
|
8726
|
-
baseURL: options.baseURL,
|
|
8727
|
-
timeout: options.timeout ?? 600000 /* 10 minutes */,
|
|
8728
|
-
httpAgent: options.httpAgent,
|
|
8729
|
-
maxRetries: options.maxRetries,
|
|
8730
|
-
fetch: options.fetch,
|
|
8731
|
-
});
|
|
8732
|
-
this.completions = new Completions(this);
|
|
8733
|
-
this.chat = new Chat$1(this);
|
|
8734
|
-
this.embeddings = new Embeddings(this);
|
|
8735
|
-
this.files = new Files(this);
|
|
8736
|
-
this.images = new Images(this);
|
|
8737
|
-
this.audio = new Audio(this);
|
|
8738
|
-
this.moderations = new Moderations(this);
|
|
8739
|
-
this.models = new Models(this);
|
|
8740
|
-
this.fineTuning = new FineTuning(this);
|
|
8741
|
-
this.beta = new Beta(this);
|
|
8742
|
-
this.batches = new Batches(this);
|
|
8743
|
-
this.uploads = new Uploads(this);
|
|
8744
|
-
this._options = options;
|
|
8745
|
-
this.apiKey = apiKey;
|
|
8746
|
-
this.organization = organization;
|
|
8747
|
-
this.project = project;
|
|
8748
|
-
}
|
|
8749
|
-
defaultQuery() {
|
|
8750
|
-
return this._options.defaultQuery;
|
|
8751
8652
|
}
|
|
8752
|
-
|
|
8653
|
+
extractFromDataUrl(dataUrl) {
|
|
8654
|
+
const matches = dataUrl.match(/^data:image\/([a-zA-Z0-9]+);base64,(.+)$/);
|
|
8655
|
+
if (!matches) {
|
|
8656
|
+
throw new Error('Invalid data URL format');
|
|
8657
|
+
}
|
|
8753
8658
|
return {
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
'OpenAI-Project': this.project,
|
|
8757
|
-
...this._options.defaultHeaders,
|
|
8659
|
+
extension: matches[1],
|
|
8660
|
+
base64Data: matches[2],
|
|
8758
8661
|
};
|
|
8759
8662
|
}
|
|
8760
|
-
|
|
8761
|
-
|
|
8663
|
+
async saveDebugImage(imageData, toolName) {
|
|
8664
|
+
try {
|
|
8665
|
+
let extension;
|
|
8666
|
+
let base64Data;
|
|
8667
|
+
// Handle both data URL strings and ImageData objects
|
|
8668
|
+
if (typeof imageData === 'string' && imageData.startsWith('data:')) {
|
|
8669
|
+
const extracted = this.extractFromDataUrl(imageData);
|
|
8670
|
+
extension = extracted.extension;
|
|
8671
|
+
base64Data = extracted.base64Data;
|
|
8672
|
+
}
|
|
8673
|
+
else if (typeof imageData === 'object' && 'type' in imageData) {
|
|
8674
|
+
extension = imageData.media_type.split('/')[1] || 'png';
|
|
8675
|
+
base64Data = imageData.data;
|
|
8676
|
+
}
|
|
8677
|
+
else {
|
|
8678
|
+
return '[image]';
|
|
8679
|
+
}
|
|
8680
|
+
// If custom image saver is provided, use it
|
|
8681
|
+
if (this.imageSaver) {
|
|
8682
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
8683
|
+
const filename = `${toolName}_${timestamp}.${extension}`;
|
|
8684
|
+
return await this.imageSaver({ type: 'base64', media_type: `image/${extension}`, data: base64Data }, filename);
|
|
8685
|
+
}
|
|
8686
|
+
// If in Node.js environment and debugImagePath is set
|
|
8687
|
+
if (this.isNode && this.debugImagePath) {
|
|
8688
|
+
// Dynamically import Node.js modules only when needed
|
|
8689
|
+
const { promises: fs } = await import('fs');
|
|
8690
|
+
const { join } = await import('path');
|
|
8691
|
+
await fs.mkdir(this.debugImagePath, { recursive: true });
|
|
8692
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
8693
|
+
const filename = `${toolName}_${timestamp}.${extension}`;
|
|
8694
|
+
const filepath = join(this.debugImagePath, filename);
|
|
8695
|
+
const buffer = Buffer.from(base64Data, 'base64');
|
|
8696
|
+
await fs.writeFile(filepath, buffer);
|
|
8697
|
+
return `[image saved to: ${filepath}]`;
|
|
8698
|
+
}
|
|
8699
|
+
// Default case - just return placeholder
|
|
8700
|
+
return '[image]';
|
|
8701
|
+
}
|
|
8702
|
+
catch (error) {
|
|
8703
|
+
console.warn('Failed to save debug image:', error);
|
|
8704
|
+
return '[image]';
|
|
8705
|
+
}
|
|
8706
|
+
}
|
|
8707
|
+
async formatToolResult(result) {
|
|
8708
|
+
// Handle null/undefined
|
|
8709
|
+
if (result == null) {
|
|
8710
|
+
return 'null';
|
|
8711
|
+
}
|
|
8712
|
+
// Handle direct image result
|
|
8713
|
+
if (result.image) {
|
|
8714
|
+
const imagePlaceholder = await this.saveDebugImage(result.image, 'tool');
|
|
8715
|
+
const modifiedResult = { ...result, image: imagePlaceholder };
|
|
8716
|
+
return JSON.stringify(modifiedResult);
|
|
8717
|
+
}
|
|
8718
|
+
// Handle nested images in result object
|
|
8719
|
+
if (typeof result === 'object') {
|
|
8720
|
+
const formatted = { ...result };
|
|
8721
|
+
for (const [key, value] of Object.entries(formatted)) {
|
|
8722
|
+
if (value && typeof value === 'string' && value.startsWith('data:image/')) {
|
|
8723
|
+
formatted[key] = await this.saveDebugImage(value, key);
|
|
8724
|
+
}
|
|
8725
|
+
else if (value &&
|
|
8726
|
+
typeof value === 'object' &&
|
|
8727
|
+
'type' in value &&
|
|
8728
|
+
value.type === 'base64') {
|
|
8729
|
+
formatted[key] = await this.saveDebugImage(value, key);
|
|
8730
|
+
}
|
|
8731
|
+
}
|
|
8732
|
+
return JSON.stringify(formatted);
|
|
8733
|
+
}
|
|
8734
|
+
// Handle primitive values
|
|
8735
|
+
return String(result);
|
|
8762
8736
|
}
|
|
8763
|
-
|
|
8764
|
-
|
|
8737
|
+
async logToolResult(toolName, result, context) {
|
|
8738
|
+
if (this.shouldLog('info')) {
|
|
8739
|
+
const timestamp = this.includeTimestamp ? new Date().toISOString() : '';
|
|
8740
|
+
const contextSummary = this.summarizeContext(context);
|
|
8741
|
+
const formattedResult = await this.formatToolResult(result);
|
|
8742
|
+
console.log(`${timestamp} [INFO] Tool executed: ${toolName}\n` +
|
|
8743
|
+
`${timestamp} [INFO] Tool result: ${formattedResult}${contextSummary}`);
|
|
8744
|
+
}
|
|
8765
8745
|
}
|
|
8766
8746
|
}
|
|
8767
|
-
_a = OpenAI;
|
|
8768
|
-
OpenAI.OpenAI = _a;
|
|
8769
|
-
OpenAI.DEFAULT_TIMEOUT = 600000; // 10 minutes
|
|
8770
|
-
OpenAI.OpenAIError = OpenAIError;
|
|
8771
|
-
OpenAI.APIError = APIError;
|
|
8772
|
-
OpenAI.APIConnectionError = APIConnectionError;
|
|
8773
|
-
OpenAI.APIConnectionTimeoutError = APIConnectionTimeoutError;
|
|
8774
|
-
OpenAI.APIUserAbortError = APIUserAbortError;
|
|
8775
|
-
OpenAI.NotFoundError = NotFoundError;
|
|
8776
|
-
OpenAI.ConflictError = ConflictError;
|
|
8777
|
-
OpenAI.RateLimitError = RateLimitError;
|
|
8778
|
-
OpenAI.BadRequestError = BadRequestError;
|
|
8779
|
-
OpenAI.AuthenticationError = AuthenticationError;
|
|
8780
|
-
OpenAI.InternalServerError = InternalServerError;
|
|
8781
|
-
OpenAI.PermissionDeniedError = PermissionDeniedError;
|
|
8782
|
-
OpenAI.UnprocessableEntityError = UnprocessableEntityError;
|
|
8783
|
-
OpenAI.toFile = toFile;
|
|
8784
|
-
OpenAI.fileFromPath = fileFromPath;
|
|
8785
|
-
OpenAI.Completions = Completions;
|
|
8786
|
-
OpenAI.Chat = Chat$1;
|
|
8787
|
-
OpenAI.Embeddings = Embeddings;
|
|
8788
|
-
OpenAI.Files = Files;
|
|
8789
|
-
OpenAI.FileObjectsPage = FileObjectsPage;
|
|
8790
|
-
OpenAI.Images = Images;
|
|
8791
|
-
OpenAI.Audio = Audio;
|
|
8792
|
-
OpenAI.Moderations = Moderations;
|
|
8793
|
-
OpenAI.Models = Models;
|
|
8794
|
-
OpenAI.ModelsPage = ModelsPage;
|
|
8795
|
-
OpenAI.FineTuning = FineTuning;
|
|
8796
|
-
OpenAI.Beta = Beta;
|
|
8797
|
-
OpenAI.Batches = Batches;
|
|
8798
|
-
OpenAI.BatchesPage = BatchesPage;
|
|
8799
|
-
OpenAI.Uploads = Uploads;
|
|
8800
8747
|
|
|
8801
|
-
class
|
|
8802
|
-
constructor(
|
|
8803
|
-
this.
|
|
8804
|
-
|
|
8805
|
-
|
|
8748
|
+
class WorkflowImpl {
|
|
8749
|
+
constructor(id, name, description, nodes = [], variables = new Map(), llmProvider, loggerOptions) {
|
|
8750
|
+
this.id = id;
|
|
8751
|
+
this.name = name;
|
|
8752
|
+
this.description = description;
|
|
8753
|
+
this.nodes = nodes;
|
|
8754
|
+
this.variables = variables;
|
|
8755
|
+
this.llmProvider = llmProvider;
|
|
8756
|
+
this.abortControllers = new Map();
|
|
8757
|
+
if (loggerOptions) {
|
|
8758
|
+
this.logger = new ExecutionLogger(loggerOptions);
|
|
8806
8759
|
}
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
8810
|
-
|
|
8811
|
-
|
|
8812
|
-
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
8760
|
+
}
|
|
8761
|
+
setLogger(logger) {
|
|
8762
|
+
this.logger = logger;
|
|
8763
|
+
}
|
|
8764
|
+
async cancel() {
|
|
8765
|
+
this.abort = true;
|
|
8766
|
+
for (const controller of this.abortControllers.values()) {
|
|
8767
|
+
controller.abort("Workflow cancelled");
|
|
8768
|
+
}
|
|
8769
|
+
}
|
|
8770
|
+
async execute(callback) {
|
|
8771
|
+
var _a, _b, _c, _d;
|
|
8772
|
+
if (!this.validateDAG()) {
|
|
8773
|
+
throw new Error("Invalid workflow: Contains circular dependencies");
|
|
8774
|
+
}
|
|
8775
|
+
this.abort = false;
|
|
8776
|
+
callback && await ((_b = (_a = callback.hooks).beforeWorkflow) === null || _b === undefined ? undefined : _b.call(_a, this));
|
|
8777
|
+
const executed = new Set();
|
|
8778
|
+
const executing = new Set();
|
|
8779
|
+
const executeNode = async (nodeId) => {
|
|
8780
|
+
var _a, _b, _c, _d, _e;
|
|
8781
|
+
if (this.abort) {
|
|
8782
|
+
throw new Error("Abort");
|
|
8783
|
+
}
|
|
8784
|
+
if (executed.has(nodeId)) {
|
|
8785
|
+
return;
|
|
8786
|
+
}
|
|
8787
|
+
if (executing.has(nodeId)) {
|
|
8788
|
+
throw new Error(`Circular dependency detected at node: ${nodeId}`);
|
|
8789
|
+
}
|
|
8790
|
+
const node = this.getNode(nodeId);
|
|
8791
|
+
const abortController = new AbortController();
|
|
8792
|
+
this.abortControllers.set(nodeId, abortController);
|
|
8793
|
+
// Execute the node's action
|
|
8794
|
+
const context = {
|
|
8795
|
+
__skip: false,
|
|
8796
|
+
__abort: false,
|
|
8797
|
+
workflow: this,
|
|
8798
|
+
variables: this.variables,
|
|
8799
|
+
llmProvider: this.llmProvider,
|
|
8800
|
+
tools: new Map(node.action.tools.map(tool => [tool.name, tool])),
|
|
8801
|
+
callback,
|
|
8802
|
+
logger: this.logger,
|
|
8803
|
+
next: () => context.__skip = true,
|
|
8804
|
+
abortAll: () => {
|
|
8805
|
+
this.abort = context.__abort = true;
|
|
8806
|
+
// Abort all running tasks
|
|
8807
|
+
for (const controller of this.abortControllers.values()) {
|
|
8808
|
+
controller.abort("Workflow cancelled");
|
|
8809
|
+
}
|
|
8810
|
+
},
|
|
8811
|
+
signal: abortController.signal
|
|
8812
|
+
};
|
|
8813
|
+
executing.add(nodeId);
|
|
8814
|
+
// Execute dependencies first
|
|
8815
|
+
for (const depId of node.dependencies) {
|
|
8816
|
+
await executeNode(depId);
|
|
8817
|
+
}
|
|
8818
|
+
// Prepare input by gathering outputs from dependencies
|
|
8819
|
+
const input = { items: [] };
|
|
8820
|
+
for (const depId of node.dependencies) {
|
|
8821
|
+
const depNode = this.getNode(depId);
|
|
8822
|
+
input.items.push(depNode.output);
|
|
8823
|
+
}
|
|
8824
|
+
node.input = input;
|
|
8825
|
+
// Run pre-execution hooks and execute action
|
|
8826
|
+
callback && await ((_b = (_a = callback.hooks).beforeSubtask) === null || _b === undefined ? undefined : _b.call(_a, node, context));
|
|
8827
|
+
if (context.__abort) {
|
|
8828
|
+
throw new Error("Abort");
|
|
8829
|
+
}
|
|
8830
|
+
else if (context.__skip) {
|
|
8831
|
+
return;
|
|
8832
|
+
}
|
|
8833
|
+
node.output.value = await node.action.execute(node.input, node.output, context);
|
|
8834
|
+
executing.delete(nodeId);
|
|
8835
|
+
executed.add(nodeId);
|
|
8836
|
+
callback && await ((_d = (_c = callback.hooks).afterSubtask) === null || _d === undefined ? undefined : _d.call(_c, node, context, (_e = node.output) === null || _e === undefined ? undefined : _e.value));
|
|
8837
|
+
};
|
|
8838
|
+
// Execute all terminal nodes (nodes with no dependents)
|
|
8839
|
+
const terminalNodes = this.nodes.filter(node => !this.nodes.some(n => n.dependencies.includes(node.id)));
|
|
8840
|
+
await Promise.all(terminalNodes.map(node => executeNode(node.id)));
|
|
8841
|
+
callback && await ((_d = (_c = callback.hooks).afterWorkflow) === null || _d === undefined ? undefined : _d.call(_c, this, this.variables));
|
|
8842
|
+
return terminalNodes.map(node => node.output);
|
|
8843
|
+
}
|
|
8844
|
+
addNode(node) {
|
|
8845
|
+
if (this.nodes.some(n => n.id === node.id)) {
|
|
8846
|
+
throw new Error(`Node with id ${node.id} already exists`);
|
|
8847
|
+
}
|
|
8848
|
+
this.nodes.push(node);
|
|
8849
|
+
}
|
|
8850
|
+
removeNode(nodeId) {
|
|
8851
|
+
const index = this.nodes.findIndex(n => n.id === nodeId);
|
|
8852
|
+
if (index === -1) {
|
|
8853
|
+
throw new Error(`Node with id ${nodeId} not found`);
|
|
8819
8854
|
}
|
|
8820
|
-
if
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
...options,
|
|
8825
|
-
});
|
|
8855
|
+
// Check if any nodes depend on this one
|
|
8856
|
+
const dependentNodes = this.nodes.filter(n => n.dependencies.includes(nodeId));
|
|
8857
|
+
if (dependentNodes.length > 0) {
|
|
8858
|
+
throw new Error(`Cannot remove node ${nodeId}: Nodes ${dependentNodes.map(n => n.id).join(", ")} depend on it`);
|
|
8826
8859
|
}
|
|
8827
|
-
|
|
8828
|
-
|
|
8860
|
+
this.nodes.splice(index, 1);
|
|
8861
|
+
}
|
|
8862
|
+
getNode(nodeId) {
|
|
8863
|
+
const node = this.nodes.find(n => n.id === nodeId);
|
|
8864
|
+
if (!node) {
|
|
8865
|
+
throw new Error(`Node with id ${nodeId} not found`);
|
|
8829
8866
|
}
|
|
8867
|
+
return node;
|
|
8830
8868
|
}
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
|
|
8836
|
-
|
|
8837
|
-
tools.push({
|
|
8838
|
-
type: 'function',
|
|
8839
|
-
function: {
|
|
8840
|
-
name: tool.name,
|
|
8841
|
-
description: tool.description,
|
|
8842
|
-
parameters: tool.input_schema,
|
|
8843
|
-
},
|
|
8844
|
-
});
|
|
8869
|
+
validateDAG() {
|
|
8870
|
+
const visited = new Set();
|
|
8871
|
+
const recursionStack = new Set();
|
|
8872
|
+
const hasCycle = (nodeId) => {
|
|
8873
|
+
if (recursionStack.has(nodeId)) {
|
|
8874
|
+
return true;
|
|
8845
8875
|
}
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
if (params.toolChoice) {
|
|
8849
|
-
if (params.toolChoice.type == 'auto') {
|
|
8850
|
-
tool_choice = 'auto';
|
|
8876
|
+
if (visited.has(nodeId)) {
|
|
8877
|
+
return false;
|
|
8851
8878
|
}
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
}
|
|
8859
|
-
else {
|
|
8860
|
-
tool_choice = 'required';
|
|
8879
|
+
visited.add(nodeId);
|
|
8880
|
+
recursionStack.add(nodeId);
|
|
8881
|
+
const node = this.getNode(nodeId);
|
|
8882
|
+
for (const depId of node.dependencies) {
|
|
8883
|
+
if (hasCycle(depId)) {
|
|
8884
|
+
return true;
|
|
8861
8885
|
}
|
|
8862
8886
|
}
|
|
8887
|
+
recursionStack.delete(nodeId);
|
|
8888
|
+
return false;
|
|
8889
|
+
};
|
|
8890
|
+
return !this.nodes.some(node => hasCycle(node.id));
|
|
8891
|
+
}
|
|
8892
|
+
}
|
|
8893
|
+
|
|
8894
|
+
// src/models/action.ts
|
|
8895
|
+
/**
|
|
8896
|
+
* Special tool that allows LLM to write values to context
|
|
8897
|
+
*/
|
|
8898
|
+
class WriteContextTool {
|
|
8899
|
+
constructor() {
|
|
8900
|
+
this.name = 'write_context';
|
|
8901
|
+
this.description = 'Write a value to the global workflow context. Use this to store important intermediate results, but only when a piece of information is essential for future reference but missing from the final output specification of the current action.';
|
|
8902
|
+
this.input_schema = {
|
|
8903
|
+
type: 'object',
|
|
8904
|
+
properties: {
|
|
8905
|
+
key: {
|
|
8906
|
+
type: 'string',
|
|
8907
|
+
description: 'The key to store the value under',
|
|
8908
|
+
},
|
|
8909
|
+
value: {
|
|
8910
|
+
type: 'string',
|
|
8911
|
+
description: 'The value to store (must be JSON stringified if object/array)',
|
|
8912
|
+
},
|
|
8913
|
+
},
|
|
8914
|
+
required: ['key', 'value'],
|
|
8915
|
+
};
|
|
8916
|
+
}
|
|
8917
|
+
async execute(context, params) {
|
|
8918
|
+
const { key, value } = params;
|
|
8919
|
+
try {
|
|
8920
|
+
// Try to parse the value as JSON
|
|
8921
|
+
const parsedValue = JSON.parse(value);
|
|
8922
|
+
context.variables.set(key, parsedValue);
|
|
8863
8923
|
}
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
|
|
8868
|
-
|
|
8869
|
-
|
|
8870
|
-
|
|
8871
|
-
|
|
8872
|
-
|
|
8873
|
-
|
|
8874
|
-
|
|
8875
|
-
|
|
8876
|
-
|
|
8877
|
-
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
|
|
8881
|
-
|
|
8882
|
-
|
|
8883
|
-
|
|
8884
|
-
|
|
8885
|
-
|
|
8886
|
-
|
|
8887
|
-
|
|
8888
|
-
|
|
8889
|
-
|
|
8890
|
-
|
|
8924
|
+
catch (_a) {
|
|
8925
|
+
// If parsing fails, store as string
|
|
8926
|
+
context.variables.set(key, value);
|
|
8927
|
+
}
|
|
8928
|
+
return { success: true, key, value };
|
|
8929
|
+
}
|
|
8930
|
+
}
|
|
8931
|
+
function createReturnTool(actionName, outputDescription, outputSchema) {
|
|
8932
|
+
return {
|
|
8933
|
+
name: 'return_output',
|
|
8934
|
+
description: `Return the final output of this action. Use this to return a value matching the required output schema (if specified) and the following description:
|
|
8935
|
+
${outputDescription}
|
|
8936
|
+
|
|
8937
|
+
You can either set 'use_tool_result=true' to return the result of a previous tool call, or explicitly specify 'value' with 'use_tool_result=false' to return a value according to your own understanding. Whenever possible, reuse tool results to avoid redundancy.
|
|
8938
|
+
`,
|
|
8939
|
+
input_schema: {
|
|
8940
|
+
type: 'object',
|
|
8941
|
+
properties: {
|
|
8942
|
+
use_tool_result: {
|
|
8943
|
+
type: ['boolean'],
|
|
8944
|
+
description: `Whether to use the latest tool result as output. When set to true, the 'value' parameter is ignored.`,
|
|
8945
|
+
},
|
|
8946
|
+
value: outputSchema || {
|
|
8947
|
+
// Default to accepting any JSON value
|
|
8948
|
+
type: ['string', 'number', 'boolean', 'object', 'null'],
|
|
8949
|
+
description: 'The output value. Only provide a value if the previous tool result is not suitable for the output description. Otherwise, leave this as null.',
|
|
8950
|
+
},
|
|
8951
|
+
},
|
|
8952
|
+
required: ['use_tool_result', 'value'],
|
|
8953
|
+
},
|
|
8954
|
+
async execute(context, params) {
|
|
8955
|
+
context.variables.set(`__action_${actionName}_output`, params);
|
|
8956
|
+
return { success: true };
|
|
8957
|
+
},
|
|
8958
|
+
};
|
|
8959
|
+
}
|
|
8960
|
+
class ActionImpl {
|
|
8961
|
+
constructor(type, // Only support prompt type
|
|
8962
|
+
name, description, tools, llmProvider, llmConfig, config) {
|
|
8963
|
+
this.type = type;
|
|
8964
|
+
this.name = name;
|
|
8965
|
+
this.description = description;
|
|
8966
|
+
this.tools = tools;
|
|
8967
|
+
this.llmProvider = llmProvider;
|
|
8968
|
+
this.llmConfig = llmConfig;
|
|
8969
|
+
this.maxRounds = 10; // Default max rounds
|
|
8970
|
+
this.toolResults = new Map();
|
|
8971
|
+
this.logger = new ExecutionLogger();
|
|
8972
|
+
this.writeContextTool = new WriteContextTool();
|
|
8973
|
+
this.tools = [...tools, this.writeContextTool];
|
|
8974
|
+
if (config === null || config === undefined ? undefined : config.maxRounds) {
|
|
8975
|
+
this.maxRounds = config.maxRounds;
|
|
8976
|
+
}
|
|
8977
|
+
}
|
|
8978
|
+
async executeSingleRound(messages, params, toolMap, context) {
|
|
8979
|
+
this.logger = context.logger;
|
|
8980
|
+
const roundMessages = [];
|
|
8981
|
+
let hasToolUse = false;
|
|
8982
|
+
let response = null;
|
|
8983
|
+
// Buffer to collect into roundMessages
|
|
8984
|
+
let assistantTextMessage = '';
|
|
8985
|
+
let toolUseMessage = null;
|
|
8986
|
+
let toolResultMessage = null;
|
|
8987
|
+
// Track tool execution promise
|
|
8988
|
+
let toolExecutionPromise = null;
|
|
8989
|
+
// Listen for abort signal
|
|
8990
|
+
if (context.signal) {
|
|
8991
|
+
context.signal.addEventListener('abort', () => {
|
|
8992
|
+
context.__abort = true;
|
|
8993
|
+
});
|
|
8994
|
+
}
|
|
8995
|
+
const handler = {
|
|
8996
|
+
onContent: (content) => {
|
|
8997
|
+
if (content.trim()) {
|
|
8998
|
+
assistantTextMessage += content;
|
|
8891
8999
|
}
|
|
8892
|
-
|
|
9000
|
+
},
|
|
9001
|
+
onToolUse: async (toolCall) => {
|
|
9002
|
+
this.logger.log('info', `Assistant: ${assistantTextMessage}`);
|
|
9003
|
+
this.logger.logToolExecution(toolCall.name, toolCall.input, context);
|
|
9004
|
+
hasToolUse = true;
|
|
9005
|
+
const tool = toolMap.get(toolCall.name);
|
|
9006
|
+
if (!tool) {
|
|
9007
|
+
throw new Error(`Tool not found: ${toolCall.name}`);
|
|
9008
|
+
}
|
|
9009
|
+
toolUseMessage = {
|
|
8893
9010
|
role: 'assistant',
|
|
8894
|
-
content:
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8899
|
-
|
|
8900
|
-
|
|
8901
|
-
|
|
8902
|
-
|
|
9011
|
+
content: [
|
|
9012
|
+
{
|
|
9013
|
+
type: 'tool_use',
|
|
9014
|
+
id: toolCall.id,
|
|
9015
|
+
name: tool.name,
|
|
9016
|
+
input: toolCall.input,
|
|
9017
|
+
},
|
|
9018
|
+
],
|
|
9019
|
+
};
|
|
9020
|
+
// Store the promise of tool execution
|
|
9021
|
+
toolExecutionPromise = (async () => {
|
|
9022
|
+
var _a;
|
|
9023
|
+
try {
|
|
9024
|
+
// beforeToolUse
|
|
9025
|
+
context.__skip = false;
|
|
9026
|
+
if (context.callback && context.callback.hooks.beforeToolUse) {
|
|
9027
|
+
let modified_input = await context.callback.hooks.beforeToolUse(tool, context, toolCall.input);
|
|
9028
|
+
if (modified_input) {
|
|
9029
|
+
toolCall.input = modified_input;
|
|
9030
|
+
}
|
|
9031
|
+
}
|
|
9032
|
+
if (context.__skip || context.__abort || ((_a = context.signal) === null || _a === void 0 ? void 0 : _a.aborted)) {
|
|
9033
|
+
toolResultMessage = {
|
|
9034
|
+
role: 'user',
|
|
9035
|
+
content: [
|
|
9036
|
+
{
|
|
9037
|
+
type: 'tool_result',
|
|
9038
|
+
tool_use_id: toolCall.id,
|
|
9039
|
+
content: 'skip',
|
|
9040
|
+
},
|
|
9041
|
+
],
|
|
9042
|
+
};
|
|
9043
|
+
return;
|
|
9044
|
+
}
|
|
9045
|
+
// Execute the tool
|
|
9046
|
+
let result = await tool.execute(context, toolCall.input);
|
|
9047
|
+
// afterToolUse
|
|
9048
|
+
if (context.callback && context.callback.hooks.afterToolUse) {
|
|
9049
|
+
let modified_result = await context.callback.hooks.afterToolUse(tool, context, result);
|
|
9050
|
+
if (modified_result) {
|
|
9051
|
+
result = modified_result;
|
|
9052
|
+
}
|
|
9053
|
+
}
|
|
9054
|
+
const result_has_image = result && "image" in result;
|
|
9055
|
+
const resultContent = result_has_image
|
|
9056
|
+
? {
|
|
9057
|
+
type: 'tool_result',
|
|
9058
|
+
tool_use_id: toolCall.id,
|
|
9059
|
+
content: result.text
|
|
9060
|
+
? [
|
|
9061
|
+
{ type: 'image', source: result.image },
|
|
9062
|
+
{ type: 'text', text: result.text },
|
|
9063
|
+
]
|
|
9064
|
+
: [{ type: 'image', source: result.image }],
|
|
9065
|
+
}
|
|
9066
|
+
: {
|
|
9067
|
+
type: 'tool_result',
|
|
9068
|
+
tool_use_id: toolCall.id,
|
|
9069
|
+
content: [{ type: 'text', text: JSON.stringify(result) }],
|
|
9070
|
+
};
|
|
9071
|
+
const resultContentText = result_has_image
|
|
9072
|
+
? result.text
|
|
9073
|
+
? result.text + ' [Image]'
|
|
9074
|
+
: '[Image]'
|
|
9075
|
+
: JSON.stringify(result);
|
|
9076
|
+
const resultMessage = {
|
|
8903
9077
|
role: 'user',
|
|
8904
|
-
content:
|
|
8905
|
-
}
|
|
9078
|
+
content: [resultContent],
|
|
9079
|
+
};
|
|
9080
|
+
toolResultMessage = resultMessage;
|
|
9081
|
+
this.logger.logToolResult(tool.name, result, context);
|
|
9082
|
+
// Store tool results except for the return_output tool
|
|
9083
|
+
if (tool.name !== 'return_output') {
|
|
9084
|
+
this.toolResults.set(toolCall.id, resultContentText);
|
|
9085
|
+
}
|
|
8906
9086
|
}
|
|
8907
|
-
|
|
8908
|
-
|
|
9087
|
+
catch (err) {
|
|
9088
|
+
console.log("An error occurred when calling tool:");
|
|
9089
|
+
console.log(err);
|
|
9090
|
+
const errorMessage = err instanceof Error ? err.message : 'Unknown error occurred';
|
|
9091
|
+
const errorResult = {
|
|
8909
9092
|
role: 'user',
|
|
8910
9093
|
content: [
|
|
8911
9094
|
{
|
|
8912
|
-
type: '
|
|
8913
|
-
|
|
8914
|
-
|
|
8915
|
-
|
|
9095
|
+
type: 'tool_result',
|
|
9096
|
+
tool_use_id: toolCall.id,
|
|
9097
|
+
content: [{ type: 'text', text: `Error: ${errorMessage}` }],
|
|
9098
|
+
is_error: true,
|
|
8916
9099
|
},
|
|
8917
9100
|
],
|
|
8918
|
-
}
|
|
9101
|
+
};
|
|
9102
|
+
toolResultMessage = errorResult;
|
|
9103
|
+
this.logger.logError(err, context);
|
|
8919
9104
|
}
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
|
|
8936
|
-
|
|
8937
|
-
|
|
9105
|
+
})();
|
|
9106
|
+
},
|
|
9107
|
+
onComplete: (llmResponse) => {
|
|
9108
|
+
response = llmResponse;
|
|
9109
|
+
},
|
|
9110
|
+
onError: (error) => {
|
|
9111
|
+
console.error('Stream Error:', error);
|
|
9112
|
+
console.log('Last message array sent to LLM:', JSON.stringify(messages, null, 2));
|
|
9113
|
+
},
|
|
9114
|
+
};
|
|
9115
|
+
this.handleHistoryImageMessages(messages);
|
|
9116
|
+
// Wait for stream to complete
|
|
9117
|
+
if (!this.llmProvider) {
|
|
9118
|
+
throw new Error('LLM provider not set');
|
|
9119
|
+
}
|
|
9120
|
+
await this.llmProvider.generateStream(messages, params, handler);
|
|
9121
|
+
// Wait for tool execution to complete if it was started
|
|
9122
|
+
if (toolExecutionPromise) {
|
|
9123
|
+
await toolExecutionPromise;
|
|
9124
|
+
}
|
|
9125
|
+
if (context.__abort) {
|
|
9126
|
+
throw new Error('Abort');
|
|
9127
|
+
}
|
|
9128
|
+
// Add messages in the correct order after everything is complete
|
|
9129
|
+
if (assistantTextMessage) {
|
|
9130
|
+
roundMessages.push({ role: 'assistant', content: assistantTextMessage });
|
|
9131
|
+
}
|
|
9132
|
+
if (toolUseMessage) {
|
|
9133
|
+
roundMessages.push(toolUseMessage);
|
|
9134
|
+
}
|
|
9135
|
+
if (toolResultMessage) {
|
|
9136
|
+
roundMessages.push(toolResultMessage);
|
|
9137
|
+
}
|
|
9138
|
+
return { response, hasToolUse, roundMessages };
|
|
9139
|
+
}
|
|
9140
|
+
handleHistoryImageMessages(messages) {
|
|
9141
|
+
// Remove all images from historical tool results except the most recent user message
|
|
9142
|
+
const initialImageCount = this.countImages(messages);
|
|
9143
|
+
let foundFirstUser = false;
|
|
9144
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
9145
|
+
const message = messages[i];
|
|
9146
|
+
if (message.role === 'user') {
|
|
9147
|
+
if (!foundFirstUser) {
|
|
9148
|
+
foundFirstUser = true;
|
|
9149
|
+
continue;
|
|
9150
|
+
}
|
|
9151
|
+
if (Array.isArray(message.content)) {
|
|
9152
|
+
// Directly modify the message content array
|
|
9153
|
+
message.content = message.content.map((item) => {
|
|
9154
|
+
if (item.type === 'tool_result' && Array.isArray(item.content)) {
|
|
9155
|
+
// Create a new content array without images
|
|
9156
|
+
if (item.content.length > 0) {
|
|
9157
|
+
item.content = item.content.filter((c) => c.type !== 'image');
|
|
9158
|
+
// If all content was images and got filtered out, replace with ok message
|
|
9159
|
+
if (item.content.length === 0) {
|
|
9160
|
+
item.content = [{ type: 'text', text: 'ok' }];
|
|
8938
9161
|
}
|
|
8939
9162
|
}
|
|
8940
9163
|
}
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
// OpenAI does not support images returned by the tool.
|
|
8944
|
-
_messages.push({
|
|
8945
|
-
role: 'tool',
|
|
8946
|
-
content: 'ok',
|
|
8947
|
-
tool_call_id: content.tool_call_id || content.tool_use_id,
|
|
8948
|
-
});
|
|
8949
|
-
_messages.push({
|
|
8950
|
-
role: 'user',
|
|
8951
|
-
content: _content,
|
|
8952
|
-
});
|
|
8953
|
-
}
|
|
8954
|
-
else {
|
|
8955
|
-
_messages.push({
|
|
8956
|
-
role: 'tool',
|
|
8957
|
-
content: _content,
|
|
8958
|
-
tool_call_id: content.tool_call_id || content.tool_use_id,
|
|
8959
|
-
});
|
|
8960
|
-
}
|
|
8961
|
-
}
|
|
9164
|
+
return item;
|
|
9165
|
+
});
|
|
8962
9166
|
}
|
|
8963
9167
|
}
|
|
8964
|
-
else {
|
|
8965
|
-
_messages.push(message);
|
|
8966
|
-
}
|
|
8967
9168
|
}
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
temperature: params.temperature,
|
|
8973
|
-
messages: _messages,
|
|
8974
|
-
tools: tools,
|
|
8975
|
-
tool_choice: tool_choice,
|
|
8976
|
-
};
|
|
9169
|
+
const finalImageCount = this.countImages(messages);
|
|
9170
|
+
if (initialImageCount !== finalImageCount) {
|
|
9171
|
+
this.logger.log("info", `Removed ${initialImageCount - finalImageCount} images from history`);
|
|
9172
|
+
}
|
|
8977
9173
|
}
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
if (textContent == null) {
|
|
8988
|
-
textContent = '';
|
|
8989
|
-
}
|
|
8990
|
-
textContent += message.content;
|
|
9174
|
+
countImages(messages) {
|
|
9175
|
+
let count = 0;
|
|
9176
|
+
messages.forEach(msg => {
|
|
9177
|
+
if (Array.isArray(msg.content)) {
|
|
9178
|
+
msg.content.forEach((item) => {
|
|
9179
|
+
if (item.type === 'tool_result' && Array.isArray(item.content)) {
|
|
9180
|
+
count += item.content.filter((c) => c.type === 'image').length;
|
|
9181
|
+
}
|
|
9182
|
+
});
|
|
8991
9183
|
}
|
|
8992
|
-
|
|
8993
|
-
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9184
|
+
});
|
|
9185
|
+
return count;
|
|
9186
|
+
}
|
|
9187
|
+
async execute(input, output, context, outputSchema) {
|
|
9188
|
+
var _a, _b, _c, _d, _e;
|
|
9189
|
+
this.logger = context.logger;
|
|
9190
|
+
console.log(`Executing action started: ${this.name}`);
|
|
9191
|
+
// Create return tool with output schema
|
|
9192
|
+
const returnTool = createReturnTool(this.name, output.description, outputSchema);
|
|
9193
|
+
// Create tool map combining context tools, action tools, and return tool
|
|
9194
|
+
const toolMap = new Map();
|
|
9195
|
+
this.tools.forEach((tool) => toolMap.set(tool.name, tool));
|
|
9196
|
+
(_a = context.tools) === null || _a === undefined ? undefined : _a.forEach((tool) => toolMap.set(tool.name, tool));
|
|
9197
|
+
toolMap.set(returnTool.name, returnTool);
|
|
9198
|
+
// Prepare initial messages
|
|
9199
|
+
const messages = [
|
|
9200
|
+
{ role: 'system', content: this.formatSystemPrompt() },
|
|
9201
|
+
{ role: 'user', content: this.formatUserPrompt(context, input) },
|
|
9202
|
+
];
|
|
9203
|
+
this.logger.logActionStart(this.name, input, context);
|
|
9204
|
+
// Configure tool parameters
|
|
9205
|
+
const params = {
|
|
9206
|
+
...this.llmConfig,
|
|
9207
|
+
tools: Array.from(toolMap.values()).map((tool) => ({
|
|
9208
|
+
name: tool.name,
|
|
9209
|
+
description: tool.description,
|
|
9210
|
+
input_schema: tool.input_schema,
|
|
9211
|
+
})),
|
|
9212
|
+
};
|
|
9213
|
+
let roundCount = 0;
|
|
9214
|
+
while (roundCount < this.maxRounds) {
|
|
9215
|
+
// Check for abort signal
|
|
9216
|
+
if ((_b = context.signal) === null || _b === undefined ? undefined : _b.aborted) {
|
|
9217
|
+
throw new Error('Workflow cancelled');
|
|
9001
9218
|
}
|
|
9002
|
-
|
|
9003
|
-
|
|
9219
|
+
roundCount++;
|
|
9220
|
+
this.logger.log('info', `Starting round ${roundCount} of ${this.maxRounds}`, context);
|
|
9221
|
+
console.log(messages);
|
|
9222
|
+
const { response, hasToolUse, roundMessages } = await this.executeSingleRound(messages, params, toolMap, context);
|
|
9223
|
+
console.log(response);
|
|
9224
|
+
console.log(hasToolUse);
|
|
9225
|
+
console.log(roundMessages);
|
|
9226
|
+
if (response === null || response === undefined ? undefined : response.textContent) {
|
|
9227
|
+
(_e = (_d = (_c = context.callback) === null || _c === undefined ? undefined : _c.hooks) === null || _d === undefined ? undefined : _d.onLlmMessage) === null || _e === undefined ? undefined : _e.call(_d, response.textContent);
|
|
9228
|
+
}
|
|
9229
|
+
// Add round messages to conversation history
|
|
9230
|
+
messages.push(...roundMessages);
|
|
9231
|
+
this.logger.log('debug', `Round ${roundCount} messages: ${JSON.stringify(roundMessages)}`, context);
|
|
9232
|
+
// Check termination conditions
|
|
9233
|
+
if (!hasToolUse && response) {
|
|
9234
|
+
// LLM sent a message without using tools - request explicit return
|
|
9235
|
+
this.logger.log('info', `Assistant: ${response.textContent}`);
|
|
9236
|
+
this.logger.log('warn', 'LLM sent a message without using tools; requesting explicit return');
|
|
9237
|
+
const returnOnlyParams = {
|
|
9238
|
+
...params,
|
|
9239
|
+
tools: [
|
|
9240
|
+
{
|
|
9241
|
+
name: returnTool.name,
|
|
9242
|
+
description: returnTool.description,
|
|
9243
|
+
input_schema: returnTool.input_schema,
|
|
9244
|
+
},
|
|
9245
|
+
],
|
|
9246
|
+
};
|
|
9247
|
+
messages.push({
|
|
9248
|
+
role: 'user',
|
|
9249
|
+
content: 'Please process the above information and return a final result using the return_output tool.',
|
|
9250
|
+
});
|
|
9251
|
+
const { roundMessages: finalRoundMessages } = await this.executeSingleRound(messages, returnOnlyParams, new Map([[returnTool.name, returnTool]]), context);
|
|
9252
|
+
messages.push(...finalRoundMessages);
|
|
9253
|
+
break;
|
|
9254
|
+
}
|
|
9255
|
+
if (response === null || response === undefined ? undefined : response.toolCalls.some((call) => call.name === 'return_output')) {
|
|
9256
|
+
break;
|
|
9257
|
+
}
|
|
9258
|
+
// If this is the last round, force an explicit return
|
|
9259
|
+
if (roundCount === this.maxRounds) {
|
|
9260
|
+
this.logger.log('warn', 'Max rounds reached, requesting explicit return');
|
|
9261
|
+
const returnOnlyParams = {
|
|
9262
|
+
...params,
|
|
9263
|
+
tools: [
|
|
9264
|
+
{
|
|
9265
|
+
name: returnTool.name,
|
|
9266
|
+
description: returnTool.description,
|
|
9267
|
+
input_schema: returnTool.input_schema,
|
|
9268
|
+
},
|
|
9269
|
+
],
|
|
9270
|
+
};
|
|
9271
|
+
messages.push({
|
|
9272
|
+
role: 'user',
|
|
9273
|
+
content: 'Maximum number of steps reached. Please return the best result possible with the return_output tool.',
|
|
9274
|
+
});
|
|
9275
|
+
const { roundMessages: finalRoundMessages } = await this.executeSingleRound(messages, returnOnlyParams, new Map([[returnTool.name, returnTool]]), context);
|
|
9276
|
+
messages.push(...finalRoundMessages);
|
|
9004
9277
|
}
|
|
9005
9278
|
}
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9279
|
+
// Get and clean up output value
|
|
9280
|
+
const outputKey = `__action_${this.name}_output`;
|
|
9281
|
+
const outputParams = context.variables.get(outputKey);
|
|
9282
|
+
context.variables.delete(outputKey);
|
|
9283
|
+
// Get output value, first checking for use_tool_result
|
|
9284
|
+
const outputParams_has_use_tool_result = outputParams && "use_tool_result" in outputParams;
|
|
9285
|
+
const outputValue = outputParams_has_use_tool_result
|
|
9286
|
+
? Array.from(this.toolResults.values()).pop()
|
|
9287
|
+
: outputParams === null || outputParams === undefined ? undefined : outputParams.value;
|
|
9288
|
+
if (outputValue === undefined) {
|
|
9289
|
+
console.warn('Action completed without returning a value');
|
|
9290
|
+
return {};
|
|
9291
|
+
}
|
|
9292
|
+
return outputValue;
|
|
9293
|
+
}
|
|
9294
|
+
formatSystemPrompt() {
|
|
9295
|
+
return `You are a subtask executor. You need to complete the subtask specified by the user, which is a consisting part of the overall task. Help the user by calling the tools provided.
|
|
9296
|
+
|
|
9297
|
+
Remember to:
|
|
9298
|
+
1. Use tools when needed to accomplish the task
|
|
9299
|
+
2. Think step by step about what needs to be done
|
|
9300
|
+
3. Return the output of the subtask using the 'return_output' tool when you are done; prefer using the 'tool_use_id' parameter to refer to the output of a tool call over providing a long text as the value
|
|
9301
|
+
4. Use the context to store important information for later reference, but use it sparingly: most of the time, the output of the subtask should be sufficient for the next steps
|
|
9302
|
+
5. If there are any unclear points during the task execution, please use the human-related tool to inquire with the user
|
|
9303
|
+
6. If user intervention is required during the task execution, please use the human-related tool to transfer the operation rights to the user
|
|
9304
|
+
`;
|
|
9305
|
+
}
|
|
9306
|
+
formatUserPrompt(context, input) {
|
|
9307
|
+
var _a;
|
|
9308
|
+
const workflowDescription = ((_a = context.workflow) === null || _a === undefined ? undefined : _a.description) || null;
|
|
9309
|
+
const actionDescription = `${this.name} -- ${this.description}`;
|
|
9310
|
+
const inputDescription = JSON.stringify(input, null, 2) || null;
|
|
9311
|
+
const contextVariables = Array.from(context.variables.entries())
|
|
9312
|
+
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
|
|
9313
|
+
.join('\n');
|
|
9314
|
+
return `You are executing a subtask in the workflow. The workflow description is as follows:
|
|
9315
|
+
${workflowDescription}
|
|
9316
|
+
|
|
9317
|
+
The subtask description is as follows:
|
|
9318
|
+
${actionDescription}
|
|
9319
|
+
|
|
9320
|
+
The input to the subtask is as follows:
|
|
9321
|
+
${inputDescription}
|
|
9322
|
+
|
|
9323
|
+
There are some variables stored in the context that you can use for reference:
|
|
9324
|
+
${contextVariables}
|
|
9325
|
+
`;
|
|
9326
|
+
}
|
|
9327
|
+
// Static factory method
|
|
9328
|
+
static createPromptAction(name, description, tools, llmProvider, llmConfig) {
|
|
9329
|
+
return new ActionImpl('prompt', name, description, tools, llmProvider, llmConfig);
|
|
9330
|
+
}
|
|
9331
|
+
}
|
|
9332
|
+
|
|
9333
|
+
// src/services/workflow/templates.ts
|
|
9334
|
+
function createWorkflowPrompts(tools) {
|
|
9335
|
+
return {
|
|
9336
|
+
formatSystemPrompt: () => {
|
|
9337
|
+
const toolDescriptions = tools
|
|
9338
|
+
.map((tool) => `
|
|
9339
|
+
Tool: ${tool.name}
|
|
9340
|
+
Description: ${tool.description}
|
|
9341
|
+
Input Schema: ${JSON.stringify(tool.input_schema, null, 2)}
|
|
9342
|
+
`)
|
|
9343
|
+
.join('\n');
|
|
9344
|
+
return `You are a workflow generation assistant that creates Eko framework workflows.
|
|
9345
|
+
The following tools are available:
|
|
9346
|
+
|
|
9347
|
+
${toolDescriptions}
|
|
9348
|
+
|
|
9349
|
+
Generate a complete workflow that:
|
|
9350
|
+
1. Only uses the tools listed above
|
|
9351
|
+
2. Properly sequences tool usage based on dependencies
|
|
9352
|
+
3. Ensures each action has appropriate input/output schemas, and that the "tools" field in each action is populated with the sufficient subset of all available tools needed to complete the action
|
|
9353
|
+
4. Creates a clear, logical flow to accomplish the user's goal
|
|
9354
|
+
5. Includes detailed descriptions for each action, ensuring that the actions, when combined, is a complete solution to the user's problem
|
|
9355
|
+
6. You should always add a SubTask at the end of the workflow to summarize it, and this SubTask should always call the "summary_workflow" tool. It's dependencies should be all of the SubTasks`;
|
|
9356
|
+
},
|
|
9357
|
+
formatUserPrompt: (requirement) => `Create a workflow for the following requirement: ${requirement}`,
|
|
9358
|
+
modifyUserPrompt: (prompt) => `Modify workflow: ${prompt}`,
|
|
9359
|
+
};
|
|
9360
|
+
}
|
|
9361
|
+
function createWorkflowGenerationTool(registry) {
|
|
9362
|
+
return {
|
|
9363
|
+
name: 'generate_workflow',
|
|
9364
|
+
description: `Generate a workflow following the Eko framework DSL schema.
|
|
9365
|
+
The workflow must only use the available tools and ensure proper dependencies between nodes.`,
|
|
9366
|
+
input_schema: {
|
|
9367
|
+
type: 'object',
|
|
9368
|
+
properties: {
|
|
9369
|
+
workflow: registry.getWorkflowSchema(),
|
|
9370
|
+
},
|
|
9371
|
+
required: ['workflow'],
|
|
9372
|
+
},
|
|
9373
|
+
};
|
|
9374
|
+
}
|
|
9375
|
+
|
|
9376
|
+
const byteToHex = [];
|
|
9377
|
+
for (let i = 0; i < 256; ++i) {
|
|
9378
|
+
byteToHex.push((i + 0x100).toString(16).slice(1));
|
|
9379
|
+
}
|
|
9380
|
+
function unsafeStringify(arr, offset = 0) {
|
|
9381
|
+
return (byteToHex[arr[offset + 0]] +
|
|
9382
|
+
byteToHex[arr[offset + 1]] +
|
|
9383
|
+
byteToHex[arr[offset + 2]] +
|
|
9384
|
+
byteToHex[arr[offset + 3]] +
|
|
9385
|
+
'-' +
|
|
9386
|
+
byteToHex[arr[offset + 4]] +
|
|
9387
|
+
byteToHex[arr[offset + 5]] +
|
|
9388
|
+
'-' +
|
|
9389
|
+
byteToHex[arr[offset + 6]] +
|
|
9390
|
+
byteToHex[arr[offset + 7]] +
|
|
9391
|
+
'-' +
|
|
9392
|
+
byteToHex[arr[offset + 8]] +
|
|
9393
|
+
byteToHex[arr[offset + 9]] +
|
|
9394
|
+
'-' +
|
|
9395
|
+
byteToHex[arr[offset + 10]] +
|
|
9396
|
+
byteToHex[arr[offset + 11]] +
|
|
9397
|
+
byteToHex[arr[offset + 12]] +
|
|
9398
|
+
byteToHex[arr[offset + 13]] +
|
|
9399
|
+
byteToHex[arr[offset + 14]] +
|
|
9400
|
+
byteToHex[arr[offset + 15]]).toLowerCase();
|
|
9401
|
+
}
|
|
9402
|
+
|
|
9403
|
+
let getRandomValues;
|
|
9404
|
+
const rnds8 = new Uint8Array(16);
|
|
9405
|
+
function rng() {
|
|
9406
|
+
if (!getRandomValues) {
|
|
9407
|
+
if (typeof crypto === 'undefined' || !crypto.getRandomValues) {
|
|
9408
|
+
throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
|
|
9409
|
+
}
|
|
9410
|
+
getRandomValues = crypto.getRandomValues.bind(crypto);
|
|
9411
|
+
}
|
|
9412
|
+
return getRandomValues(rnds8);
|
|
9413
|
+
}
|
|
9414
|
+
|
|
9415
|
+
const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
9416
|
+
var native = { randomUUID };
|
|
9417
|
+
|
|
9418
|
+
function v4(options, buf, offset) {
|
|
9419
|
+
if (native.randomUUID && true && !options) {
|
|
9420
|
+
return native.randomUUID();
|
|
9421
|
+
}
|
|
9422
|
+
options = options || {};
|
|
9423
|
+
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
9424
|
+
if (rnds.length < 16) {
|
|
9425
|
+
throw new Error('Random bytes length must be >= 16');
|
|
9426
|
+
}
|
|
9427
|
+
rnds[6] = (rnds[6] & 0x0f) | 0x40;
|
|
9428
|
+
rnds[8] = (rnds[8] & 0x3f) | 0x80;
|
|
9429
|
+
return unsafeStringify(rnds);
|
|
9430
|
+
}
|
|
9431
|
+
|
|
9432
|
+
class WorkflowGenerator {
|
|
9433
|
+
constructor(llmProvider, toolRegistry) {
|
|
9434
|
+
this.llmProvider = llmProvider;
|
|
9435
|
+
this.toolRegistry = toolRegistry;
|
|
9436
|
+
this.message_history = [];
|
|
9437
|
+
}
|
|
9438
|
+
async generateWorkflow(prompt) {
|
|
9439
|
+
return this.doGenerateWorkflow(prompt, false);
|
|
9440
|
+
}
|
|
9441
|
+
async generateWorkflowFromJson(json) {
|
|
9442
|
+
return this.createWorkflowFromData(json);
|
|
9443
|
+
}
|
|
9444
|
+
async modifyWorkflow(prompt) {
|
|
9445
|
+
return this.doGenerateWorkflow(prompt, true);
|
|
9446
|
+
}
|
|
9447
|
+
async doGenerateWorkflow(prompt, modify) {
|
|
9448
|
+
// Create prompts with current set of tools
|
|
9449
|
+
const prompts = createWorkflowPrompts(this.toolRegistry.getToolDefinitions());
|
|
9450
|
+
let messages = [];
|
|
9451
|
+
if (modify) {
|
|
9452
|
+
messages = this.message_history;
|
|
9453
|
+
messages.push({
|
|
9454
|
+
role: 'user',
|
|
9455
|
+
content: prompts.modifyUserPrompt(prompt),
|
|
9011
9456
|
});
|
|
9012
9457
|
}
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
|
|
9021
|
-
|
|
9022
|
-
|
|
9458
|
+
else {
|
|
9459
|
+
messages = this.message_history = [
|
|
9460
|
+
{
|
|
9461
|
+
role: 'system',
|
|
9462
|
+
content: prompts.formatSystemPrompt(),
|
|
9463
|
+
},
|
|
9464
|
+
{
|
|
9465
|
+
role: 'user',
|
|
9466
|
+
content: prompts.formatUserPrompt(prompt),
|
|
9467
|
+
},
|
|
9468
|
+
];
|
|
9023
9469
|
}
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
|
|
9027
|
-
|
|
9028
|
-
|
|
9470
|
+
const params = {
|
|
9471
|
+
temperature: 0.7,
|
|
9472
|
+
maxTokens: 8192,
|
|
9473
|
+
tools: [createWorkflowGenerationTool(this.toolRegistry)],
|
|
9474
|
+
toolChoice: { type: 'tool', name: 'generate_workflow' },
|
|
9029
9475
|
};
|
|
9030
|
-
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
}
|
|
9067
|
-
currentToolUse.accumulatedJson += ((_g = tool_calls.function) === null || _g === void 0 ? void 0 : _g.arguments) || '';
|
|
9068
|
-
}
|
|
9069
|
-
}
|
|
9070
|
-
}
|
|
9071
|
-
if (choice.finish_reason) {
|
|
9072
|
-
stop_reason = choice.finish_reason;
|
|
9073
|
-
if (currentToolUse) {
|
|
9074
|
-
const toolCall = {
|
|
9075
|
-
id: currentToolUse.id,
|
|
9076
|
-
name: currentToolUse.name,
|
|
9077
|
-
input: JSON.parse(currentToolUse.accumulatedJson),
|
|
9078
|
-
};
|
|
9079
|
-
toolCalls.push(toolCall);
|
|
9080
|
-
(_h = handler.onToolUse) === null || _h === void 0 ? void 0 : _h.call(handler, toolCall);
|
|
9081
|
-
currentToolUse = null;
|
|
9082
|
-
}
|
|
9083
|
-
}
|
|
9476
|
+
const response = await this.llmProvider.generateText(messages, params);
|
|
9477
|
+
if (!response.toolCalls.length || !response.toolCalls[0].input.workflow) {
|
|
9478
|
+
messages.pop();
|
|
9479
|
+
throw new Error('Failed to generate workflow: Invalid response from LLM');
|
|
9480
|
+
}
|
|
9481
|
+
messages.push({
|
|
9482
|
+
role: 'assistant',
|
|
9483
|
+
content: [
|
|
9484
|
+
{
|
|
9485
|
+
type: 'tool_use',
|
|
9486
|
+
id: response.toolCalls[0].id,
|
|
9487
|
+
name: response.toolCalls[0].name,
|
|
9488
|
+
input: response.toolCalls[0].input,
|
|
9489
|
+
},
|
|
9490
|
+
],
|
|
9491
|
+
}, {
|
|
9492
|
+
role: 'user',
|
|
9493
|
+
content: [
|
|
9494
|
+
{
|
|
9495
|
+
type: 'tool_result',
|
|
9496
|
+
tool_use_id: response.toolCalls[0].id,
|
|
9497
|
+
content: 'ok',
|
|
9498
|
+
},
|
|
9499
|
+
],
|
|
9500
|
+
});
|
|
9501
|
+
const workflowData = response.toolCalls[0].input.workflow;
|
|
9502
|
+
// Forcibly add special tools
|
|
9503
|
+
const specialTools = [
|
|
9504
|
+
"cancel_workflow",
|
|
9505
|
+
"human_input_text",
|
|
9506
|
+
"human_operate",
|
|
9507
|
+
];
|
|
9508
|
+
for (const node of workflowData.nodes) {
|
|
9509
|
+
for (const tool of specialTools) {
|
|
9510
|
+
if (!node.action.tools.includes(tool)) {
|
|
9511
|
+
node.action.tools.push(tool);
|
|
9084
9512
|
}
|
|
9085
9513
|
}
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
});
|
|
9092
|
-
}
|
|
9093
|
-
if (toolCalls && toolCalls.length > 0) {
|
|
9094
|
-
for (let i = 0; i < toolCalls.length; i++) {
|
|
9095
|
-
let toolCall = toolCalls[i];
|
|
9096
|
-
content.push({
|
|
9097
|
-
type: 'tool_use',
|
|
9098
|
-
id: toolCall.id,
|
|
9099
|
-
name: toolCall.name,
|
|
9100
|
-
input: toolCall.input,
|
|
9101
|
-
});
|
|
9102
|
-
}
|
|
9514
|
+
}
|
|
9515
|
+
// Validate all tools exist
|
|
9516
|
+
for (const node of workflowData.nodes) {
|
|
9517
|
+
if (!this.toolRegistry.hasTools(node.action.tools)) {
|
|
9518
|
+
throw new Error(`Workflow contains undefined tools: ${node.action.tools}`);
|
|
9103
9519
|
}
|
|
9104
|
-
(_j = handler.onComplete) === null || _j === void 0 ? void 0 : _j.call(handler, {
|
|
9105
|
-
textContent: textContent,
|
|
9106
|
-
content: content,
|
|
9107
|
-
toolCalls: toolCalls,
|
|
9108
|
-
stop_reason: stop_reason,
|
|
9109
|
-
});
|
|
9110
9520
|
}
|
|
9111
|
-
|
|
9112
|
-
|
|
9521
|
+
// Generate a new UUID if not provided
|
|
9522
|
+
if (!workflowData.id) {
|
|
9523
|
+
workflowData.id = v4();
|
|
9524
|
+
}
|
|
9525
|
+
// debug
|
|
9526
|
+
console.log("Debug the workflow...");
|
|
9527
|
+
console.log(workflowData);
|
|
9528
|
+
console.log("Debug the workflow...Done");
|
|
9529
|
+
return this.createWorkflowFromData(workflowData);
|
|
9530
|
+
}
|
|
9531
|
+
createWorkflowFromData(data) {
|
|
9532
|
+
const workflow = new WorkflowImpl(data.id, data.name, data.description || '', [], new Map(Object.entries(data.variables || {})), this.llmProvider, {
|
|
9533
|
+
logLevel: 'info',
|
|
9534
|
+
includeTimestamp: true,
|
|
9535
|
+
});
|
|
9536
|
+
// Add nodes to workflow
|
|
9537
|
+
if (Array.isArray(data.nodes)) {
|
|
9538
|
+
data.nodes.forEach((nodeData) => {
|
|
9539
|
+
const tools = nodeData.action.tools.map((toolName) => this.toolRegistry.getTool(toolName));
|
|
9540
|
+
const action = ActionImpl.createPromptAction(nodeData.action.name, nodeData.action.description, tools, this.llmProvider, { maxTokens: 8192 });
|
|
9541
|
+
const node = {
|
|
9542
|
+
id: nodeData.id,
|
|
9543
|
+
name: nodeData.name || nodeData.id,
|
|
9544
|
+
input: nodeData.input || { type: 'any', schema: {}, value: undefined },
|
|
9545
|
+
output: nodeData.output || { type: 'any', schema: {}, value: undefined },
|
|
9546
|
+
action: action,
|
|
9547
|
+
dependencies: nodeData.dependencies || [],
|
|
9548
|
+
};
|
|
9549
|
+
workflow.addNode(node);
|
|
9550
|
+
});
|
|
9113
9551
|
}
|
|
9552
|
+
return workflow;
|
|
9114
9553
|
}
|
|
9115
9554
|
}
|
|
9116
9555
|
|
|
@@ -9136,18 +9575,11 @@ const workflowSchema = {
|
|
|
9136
9575
|
type: "array",
|
|
9137
9576
|
items: { type: "string" },
|
|
9138
9577
|
},
|
|
9139
|
-
input: {
|
|
9140
|
-
type: "object",
|
|
9141
|
-
properties: {
|
|
9142
|
-
type: { type: "string" },
|
|
9143
|
-
schema: { type: "object" },
|
|
9144
|
-
},
|
|
9145
|
-
},
|
|
9146
9578
|
output: {
|
|
9147
9579
|
type: "object",
|
|
9148
9580
|
properties: {
|
|
9149
|
-
|
|
9150
|
-
|
|
9581
|
+
name: { type: "string" },
|
|
9582
|
+
description: { type: "string" },
|
|
9151
9583
|
},
|
|
9152
9584
|
},
|
|
9153
9585
|
action: {
|
|
@@ -9235,25 +9667,7 @@ class Eko {
|
|
|
9235
9667
|
constructor(config) {
|
|
9236
9668
|
this.toolRegistry = new ToolRegistry();
|
|
9237
9669
|
this.workflowGeneratorMap = new Map();
|
|
9238
|
-
|
|
9239
|
-
this.llmProvider = new ClaudeProvider(config);
|
|
9240
|
-
}
|
|
9241
|
-
else if ('llm' in config) {
|
|
9242
|
-
if (config.llm == 'claude') {
|
|
9243
|
-
let claudeConfig = config;
|
|
9244
|
-
this.llmProvider = new ClaudeProvider(claudeConfig.apiKey, claudeConfig.modelName, claudeConfig.options);
|
|
9245
|
-
}
|
|
9246
|
-
else if (config.llm == 'openai') {
|
|
9247
|
-
let openaiConfig = config;
|
|
9248
|
-
this.llmProvider = new OpenaiProvider(openaiConfig.apiKey, openaiConfig.modelName, openaiConfig.options);
|
|
9249
|
-
}
|
|
9250
|
-
else {
|
|
9251
|
-
throw new Error('Unknown parameter: llm > ' + config['llm']);
|
|
9252
|
-
}
|
|
9253
|
-
}
|
|
9254
|
-
else {
|
|
9255
|
-
this.llmProvider = config;
|
|
9256
|
-
}
|
|
9670
|
+
this.llmProvider = LLMProviderFactory.buildLLMProvider(config);
|
|
9257
9671
|
Eko.tools.forEach((tool) => this.toolRegistry.registerTool(tool));
|
|
9258
9672
|
}
|
|
9259
9673
|
async generate(prompt, param) {
|
|
@@ -9276,8 +9690,27 @@ class Eko {
|
|
|
9276
9690
|
return workflow;
|
|
9277
9691
|
}
|
|
9278
9692
|
async execute(workflow, callback) {
|
|
9693
|
+
// Inject LLM provider at workflow level
|
|
9694
|
+
workflow.llmProvider = this.llmProvider;
|
|
9695
|
+
// Process each node's action
|
|
9696
|
+
for (const node of workflow.nodes) {
|
|
9697
|
+
if (node.action.type === 'prompt') {
|
|
9698
|
+
// Inject LLM provider
|
|
9699
|
+
node.action.llmProvider = this.llmProvider;
|
|
9700
|
+
// Resolve tools
|
|
9701
|
+
node.action.tools = node.action.tools.map(tool => {
|
|
9702
|
+
if (typeof tool === 'string') {
|
|
9703
|
+
return this.toolRegistry.getTool(tool);
|
|
9704
|
+
}
|
|
9705
|
+
return tool;
|
|
9706
|
+
});
|
|
9707
|
+
}
|
|
9708
|
+
}
|
|
9279
9709
|
return await workflow.execute(callback);
|
|
9280
9710
|
}
|
|
9711
|
+
async cancel(workflow) {
|
|
9712
|
+
return await workflow.cancel();
|
|
9713
|
+
}
|
|
9281
9714
|
async modify(workflow, prompt) {
|
|
9282
9715
|
const generator = this.workflowGeneratorMap.get(workflow);
|
|
9283
9716
|
workflow = await generator.modifyWorkflow(prompt);
|
|
@@ -9461,31 +9894,30 @@ class WorkflowParser {
|
|
|
9461
9894
|
errors,
|
|
9462
9895
|
};
|
|
9463
9896
|
}
|
|
9464
|
-
/**
|
|
9465
|
-
* Convert parsed JSON to runtime Workflow object
|
|
9466
|
-
*/
|
|
9467
9897
|
static toRuntime(json) {
|
|
9468
9898
|
const variables = new Map(Object.entries(json.variables || {}));
|
|
9469
|
-
const workflow = new WorkflowImpl(json.id, json.name, json.description, [], variables
|
|
9899
|
+
const workflow = new WorkflowImpl(json.id, json.name, json.description, [], variables, undefined, {
|
|
9900
|
+
logLevel: 'info',
|
|
9901
|
+
includeTimestamp: true,
|
|
9902
|
+
});
|
|
9470
9903
|
// Convert nodes
|
|
9471
9904
|
json.nodes.forEach((nodeJson) => {
|
|
9905
|
+
const action = ActionImpl.createPromptAction(nodeJson.action.name, nodeJson.action.description,
|
|
9906
|
+
// Pass tool names as strings, they'll be resolved at execution time
|
|
9907
|
+
nodeJson.action.tools || [], undefined, // LLM provider will be injected at execution time
|
|
9908
|
+
{ maxTokens: 8192 });
|
|
9472
9909
|
const node = {
|
|
9473
9910
|
id: nodeJson.id,
|
|
9474
9911
|
name: nodeJson.name || nodeJson.id,
|
|
9475
9912
|
description: nodeJson.description,
|
|
9476
9913
|
dependencies: nodeJson.dependencies || [],
|
|
9477
|
-
input:
|
|
9478
|
-
output:
|
|
9479
|
-
|
|
9480
|
-
|
|
9481
|
-
|
|
9482
|
-
description: nodeJson.action.description,
|
|
9483
|
-
tools: nodeJson.action.tools || [],
|
|
9484
|
-
execute: async (input, context) => {
|
|
9485
|
-
// Default implementation - should be overridden by specific action types
|
|
9486
|
-
return input;
|
|
9487
|
-
},
|
|
9914
|
+
input: { items: [] },
|
|
9915
|
+
output: nodeJson.output || {
|
|
9916
|
+
name: `${nodeJson.name || nodeJson.id}_output`,
|
|
9917
|
+
description: `Output of node ${nodeJson.name || nodeJson.id}`,
|
|
9918
|
+
value: null,
|
|
9488
9919
|
},
|
|
9920
|
+
action: action,
|
|
9489
9921
|
};
|
|
9490
9922
|
workflow.addNode(node);
|
|
9491
9923
|
});
|
|
@@ -9505,28 +9937,19 @@ class WorkflowParser {
|
|
|
9505
9937
|
name: node.name,
|
|
9506
9938
|
description: node.description,
|
|
9507
9939
|
dependencies: node.dependencies,
|
|
9508
|
-
input: node.input,
|
|
9509
9940
|
output: node.output,
|
|
9510
9941
|
action: {
|
|
9511
9942
|
type: node.action.type,
|
|
9512
9943
|
name: node.action.name,
|
|
9513
9944
|
description: node.action.description,
|
|
9514
|
-
tools: node.action.tools
|
|
9945
|
+
tools: node.action.tools
|
|
9946
|
+
.map((tool) => (typeof tool === 'string' ? tool : tool.name))
|
|
9947
|
+
.filter((tool) => tool !== 'write_context'),
|
|
9515
9948
|
},
|
|
9516
9949
|
})),
|
|
9517
9950
|
variables: Object.fromEntries(workflow.variables),
|
|
9518
9951
|
};
|
|
9519
9952
|
}
|
|
9520
|
-
/**
|
|
9521
|
-
* Helper to convert IO definitions
|
|
9522
|
-
*/
|
|
9523
|
-
static convertIO(io) {
|
|
9524
|
-
return {
|
|
9525
|
-
type: (io === null || io === void 0 ? void 0 : io.type) || 'object',
|
|
9526
|
-
schema: (io === null || io === void 0 ? void 0 : io.schema) || {},
|
|
9527
|
-
value: null,
|
|
9528
|
-
};
|
|
9529
|
-
}
|
|
9530
9953
|
}
|
|
9531
9954
|
|
|
9532
|
-
export { ClaudeProvider, Eko, OpenaiProvider, ToolRegistry, WorkflowGenerator, WorkflowParser, Eko as default };
|
|
9955
|
+
export { ClaudeProvider, Eko, ExecutionLogger, LLMProviderFactory, OpenaiProvider, ToolRegistry, WorkflowGenerator, WorkflowParser, Eko as default };
|