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