foliko 2.0.10 → 2.0.12

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.
@@ -1,66 +1,66 @@
1
- /**
2
- * FlowEngine v2 - Main entry point for v2 workflow system
3
- * Supports JSON and JS workflow formats
4
- */
5
-
6
- const { JsonRunner } = require('./json-runner');
7
- const { JsRunner } = require('./js-runner');
8
-
9
- class FlowEngine {
10
- constructor(framework) {
11
- this.framework = framework;
12
- this._jsonRunner = new JsonRunner(framework);
13
- this._jsRunner = new JsRunner(framework);
14
- this._log = require('../../../src/common/logger').logger.child('FlowEngine');
15
- }
16
-
17
- /**
18
- * Execute a workflow
19
- * @param {Object|string} workflow - Workflow definition
20
- * @param {Object} input - Input data
21
- * @param {string} sessionId - Session ID
22
- * @returns {Promise<Object>} execution result
23
- */
24
- async execute(workflow, input = {}, sessionId = null) {
25
- // Parse workflow if string
26
- if (typeof workflow === 'string') {
27
- try {
28
- workflow = JSON.parse(workflow);
29
- // It's JSON, use JsonRunner
30
- return await this._jsonRunner.execute(workflow, input, sessionId);
31
- } catch {
32
- // Not JSON, treat as JS workflow
33
- return await this._jsRunner.execute(workflow, input, sessionId);
34
- }
35
- }
36
-
37
- // Object format detection
38
- // v2 JSON: has flow + stages
39
- if (workflow.flow && Array.isArray(workflow.stages)) {
40
- return await this._jsonRunner.execute(workflow, input, sessionId);
41
- }
42
-
43
- // Assume JS format if it's a function (exported)
44
- if (typeof workflow === 'function') {
45
- return await this._jsRunner.execute(workflow, input, sessionId);
46
- }
47
-
48
- throw new Error(`Invalid workflow format. Expected { flow, stages } or JS function.`);
49
- }
50
-
51
- /**
52
- * Get the JSON runner for direct access
53
- */
54
- getJsonRunner() {
55
- return this._jsonRunner;
56
- }
57
-
58
- /**
59
- * Get the JS runner for direct access
60
- */
61
- getJsRunner() {
62
- return this._jsRunner;
63
- }
64
- }
65
-
66
- module.exports = { FlowEngine };
1
+ /**
2
+ * FlowEngine v2 - Main entry point for v2 workflow system
3
+ * Supports JSON and JS workflow formats
4
+ */
5
+
6
+ const { JsonRunner } = require('./json-runner');
7
+ const { JsRunner } = require('./js-runner');
8
+
9
+ class FlowEngine {
10
+ constructor(framework) {
11
+ this.framework = framework;
12
+ this._jsonRunner = new JsonRunner(framework);
13
+ this._jsRunner = new JsRunner(framework);
14
+ this._log = require('../../../src/common/logger').logger.child('FlowEngine');
15
+ }
16
+
17
+ /**
18
+ * Execute a workflow
19
+ * @param {Object|string} workflow - Workflow definition
20
+ * @param {Object} input - Input data
21
+ * @param {string} sessionId - Session ID
22
+ * @returns {Promise<Object>} execution result
23
+ */
24
+ async execute(workflow, input = {}, sessionId = null) {
25
+ // Parse workflow if string
26
+ if (typeof workflow === 'string') {
27
+ try {
28
+ workflow = JSON.parse(workflow);
29
+ // It's JSON, use JsonRunner
30
+ return await this._jsonRunner.execute(workflow, input, sessionId);
31
+ } catch {
32
+ // Not JSON, treat as JS workflow
33
+ return await this._jsRunner.execute(workflow, input, sessionId);
34
+ }
35
+ }
36
+
37
+ // Object format detection
38
+ // v2 JSON: has flow + stages
39
+ if (workflow.flow && Array.isArray(workflow.stages)) {
40
+ return await this._jsonRunner.execute(workflow, input, sessionId);
41
+ }
42
+
43
+ // Assume JS format if it's a function (exported)
44
+ if (typeof workflow === 'function') {
45
+ return await this._jsRunner.execute(workflow, input, sessionId);
46
+ }
47
+
48
+ throw new Error(`Invalid workflow format. Expected { flow, stages } or JS function.`);
49
+ }
50
+
51
+ /**
52
+ * Get the JSON runner for direct access
53
+ */
54
+ getJsonRunner() {
55
+ return this._jsonRunner;
56
+ }
57
+
58
+ /**
59
+ * Get the JS runner for direct access
60
+ */
61
+ getJsRunner() {
62
+ return this._jsRunner;
63
+ }
64
+ }
65
+
66
+ module.exports = { FlowEngine };
@@ -999,7 +999,12 @@ class WorkflowPlugin extends Plugin {
999
999
  for (const file of files) {
1000
1000
  if (!file.endsWith('.json') && !file.endsWith('.js')) continue;
1001
1001
  const filePath = path.join(dir, file);
1002
- const workflowName = path.basename(file, path.extname(file));
1002
+ let workflowName = path.basename(file, path.extname(file));
1003
+ // 兼容 .flow.js / .flow.json 命名约定:去掉 .flow 后缀
1004
+ // (如 weather_card.flow.js → workflow_weather_card 而不是 workflow_weather_card.flow)
1005
+ if (workflowName.endsWith('.flow')) {
1006
+ workflowName = workflowName.slice(0, -'.flow'.length);
1007
+ }
1003
1008
  // 跳过已存在的工作流(先加载的优先)
1004
1009
  if (this._workflows.has(workflowName)) continue;
1005
1010
  try {
@@ -1064,7 +1069,10 @@ class WorkflowPlugin extends Plugin {
1064
1069
  */
1065
1070
  _registerWorkflowTools() {
1066
1071
  for (const [name, workflow] of this._workflows) {
1067
- const toolName = `workflow_${name}`;
1072
+ // 工具名 sanitize:把文件名里的 . - 空格等替换为 _,避免 LLM 把名字当成
1073
+ // "module.method" 调用语法(如 weather_card.flow.js → workflow_weather_card_flow)
1074
+ const safeName = name.replace(/[^a-zA-Z0-9_]/g, '_');
1075
+ const toolName = `workflow_${safeName}`;
1068
1076
  const description = workflow.description || `执行工作流: ${name}`;
1069
1077
  // 注意:framework.registerTool 不做去重,导致 reload 后会有两个同名
1070
1078
  // `workflow_<name>` 工具。getTool 返回第一个(旧的)。每次注册前先清掉。