foliko 2.0.6 → 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/.editorconfig +56 -56
  2. package/.lintstagedrc +7 -7
  3. package/.prettierignore +29 -29
  4. package/.prettierrc +11 -11
  5. package/Dockerfile +63 -63
  6. package/install.ps1 +129 -129
  7. package/install.sh +121 -121
  8. package/package.json +1 -1
  9. package/plugins/core/scheduler/index.js +1 -0
  10. package/plugins/core/workflow/context.js +941 -0
  11. package/plugins/core/workflow/engine.js +66 -0
  12. package/plugins/core/workflow/examples/01-basic.js +42 -0
  13. package/plugins/core/workflow/examples/01-basic.json +30 -0
  14. package/plugins/core/workflow/examples/02-choice.js +75 -0
  15. package/plugins/core/workflow/examples/02-choice.json +59 -0
  16. package/plugins/core/workflow/examples/03-chain-style.js +114 -0
  17. package/plugins/core/workflow/examples/03-each.json +41 -0
  18. package/plugins/core/workflow/examples/04-parallel.js +52 -0
  19. package/plugins/core/workflow/examples/04-parallel.json +51 -0
  20. package/plugins/core/workflow/examples/05-chain-style.json +68 -0
  21. package/plugins/core/workflow/examples/05-each.js +65 -0
  22. package/plugins/core/workflow/examples/06-script.js +82 -0
  23. package/plugins/core/workflow/examples/07-module-export.js +43 -0
  24. package/plugins/core/workflow/examples/08-default-export.js +29 -0
  25. package/plugins/core/workflow/examples/09-next-with-args.js +50 -0
  26. package/plugins/core/workflow/examples/10-logger.js +34 -0
  27. package/plugins/core/workflow/examples/11-storage.js +68 -0
  28. package/plugins/core/workflow/examples/simple.js +77 -0
  29. package/plugins/core/workflow/examples/simple.json +75 -0
  30. package/plugins/core/workflow/index.js +122 -56
  31. package/plugins/core/workflow/js-runner.js +318 -0
  32. package/plugins/core/workflow/json-runner.js +323 -0
  33. package/plugins/core/workflow/stages/action.js +211 -0
  34. package/plugins/core/workflow/stages/choice.js +74 -0
  35. package/plugins/core/workflow/stages/delay.js +73 -0
  36. package/plugins/core/workflow/stages/each.js +123 -0
  37. package/plugins/core/workflow/stages/parallel.js +69 -0
  38. package/plugins/core/workflow/stages/try.js +142 -0
  39. package/plugins/executors/data-splitter/index.js +3 -2
  40. package/sandbox/check-context.js +5 -0
  41. package/sandbox/test-context.js +27 -0
  42. package/sandbox/test-fixes.js +40 -0
  43. package/sandbox/test-hello-js.js +46 -0
  44. package/skills/find-skills/SKILL.md +133 -133
  45. package/skills/workflows/SKILL.md +715 -613
  46. package/src/agent/chat.js +8 -1
  47. package/src/agent/main.js +5 -1
  48. package/src/cli/ui/chat-ui.js +4 -3
  49. package/src/common/json-safe.js +20 -0
  50. package/src/framework/framework.js +55 -1
  51. package/src/plugin/manager.js +95 -1
  52. package/src/utils/sandbox.js +1 -1
  53. package/skills/workflows/workflow-troubleshooting/DEBUGGING.md +0 -197
  54. package/skills/workflows/workflow-troubleshooting/SKILL.md +0 -331
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Script Workflow (JS Format)
3
+ * Demonstrates script execution and data transformation
4
+ */
5
+
6
+ FLOW(function($) {
7
+ // Stage 1: Initialize data
8
+ $.push('init', function($) {
9
+ const rawData = {
10
+ users: [
11
+ { id: 1, name: 'Alice', age: 30, active: true },
12
+ { id: 2, name: 'Bob', age: 25, active: false },
13
+ { id: 3, name: 'Charlie', age: 35, active: true }
14
+ ],
15
+ threshold: 28
16
+ };
17
+ $.send({ rawData });
18
+ $.next('filter');
19
+ });
20
+
21
+ // Stage 2: Filter with script
22
+ $.push('filter', function($) {
23
+ const { users, threshold } = $.data.rawData;
24
+
25
+ // Use script to filter users by age
26
+ const filtered = users.filter(u => u.age >= threshold);
27
+
28
+ $.send({ filtered, total: users.length, filteredCount: filtered.length });
29
+ $.next('transform');
30
+ });
31
+
32
+ // Stage 3: Transform with script
33
+ $.push('transform', function($) {
34
+ const { filtered } = $.data;
35
+
36
+ // Transform to summary format
37
+ const summary = filtered.map(u => ({
38
+ displayName: u.name.toUpperCase(),
39
+ age: u.age,
40
+ status: u.active ? 'Active' : 'Inactive'
41
+ }));
42
+
43
+ $.send({ summary });
44
+ $.next('log');
45
+ });
46
+
47
+ // Stage 4: Log results
48
+ $.push('log', function($) {
49
+ const { summary, filteredCount, total } = $.data;
50
+
51
+ $.tool.execute('log_event', {
52
+ event: 'filter_complete',
53
+ total: total,
54
+ filtered: filteredCount,
55
+ summary: JSON.stringify(summary)
56
+ });
57
+
58
+ $.next('notify');
59
+ });
60
+
61
+ // Stage 5: Notify
62
+ $.push('notify', function($) {
63
+ const { summary } = $.data;
64
+ const message = summary
65
+ .map(u => `${u.displayName} (${u.age}) - ${u.status}`)
66
+ .join('\n');
67
+
68
+ $.tool.execute('notification_send', {
69
+ title: 'Filtered Users',
70
+ message: message || 'No users matched criteria'
71
+ });
72
+
73
+ $.next('done');
74
+ });
75
+
76
+ // Done
77
+ $.push('done', function($) {
78
+ $.destroy();
79
+ });
80
+
81
+ $.next('init');
82
+ });
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Module Export Workflow Example
3
+ * Demonstrates module.exports = function($) {} format
4
+ */
5
+
6
+ module.exports = function ($) {
7
+ // Initialize
8
+ $.push('init', function ($) {
9
+ const data = {
10
+ userId: $.input.userId || 1,
11
+ action: 'process'
12
+ };
13
+ $.send({ data });
14
+ $.next('fetch');
15
+ });
16
+
17
+ // Fetch user data
18
+ $.push('fetch', async function ($) {
19
+ const result = await $.tool.execute('fetch', {
20
+ url: 'https://api.example.com/users/' + $.data.data.userId
21
+ });
22
+ $.send({ user: result });
23
+ $.next('process');
24
+ });
25
+
26
+ // Process based on status
27
+ $.push('process', function ($) {
28
+ const status = $.data.user?.body?.status || 'unknown';
29
+ $.tool.execute('log_event', {
30
+ event: 'user_processed',
31
+ userId: $.data.data.userId,
32
+ status: status
33
+ });
34
+ $.next('done');
35
+ });
36
+
37
+ // Done
38
+ $.push('done', function ($) {
39
+ $.destroy();
40
+ });
41
+
42
+ $.next('init');
43
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Default Export Workflow Example
3
+ * Demonstrates module.exports.default = function($) {} format
4
+ */
5
+
6
+ module.exports.default = function ($) {
7
+ $.push('start', async function ($) {
8
+ const result = await $.tool.execute('fetch', {
9
+ url: 'https://api.ipify.org?format=json'
10
+ });
11
+ $.send({ ip: result });
12
+ $.next('notify');
13
+ });
14
+
15
+ $.push('notify', function ($) {
16
+ const ip = $.data.ip?.body?.ip || 'unknown';
17
+ $.tool.execute('notification_send', {
18
+ title: 'IP Address',
19
+ message: 'Your IP is: ' + ip
20
+ });
21
+ $.next('done');
22
+ });
23
+
24
+ $.push('done', function ($) {
25
+ $.destroy();
26
+ });
27
+
28
+ $.next('start');
29
+ };
@@ -0,0 +1,50 @@
1
+ /**
2
+ * $.next() with Arguments - Function Parameters Demo
3
+ * Demonstrates $.next('stage', arg1, arg2, ...) and function($, a, b, ...) receiving args
4
+ */
5
+
6
+ FLOW(function($) {
7
+ // Stage 1: Fetch and pass data directly to next stage
8
+ $.push('fetch', async function($, ip) {
9
+ // ip is undefined in first call, use default value
10
+ const url = ip || 'https://api.ipify.org?format=json';
11
+
12
+ const result = await $.tool.execute('fetch', { url: url });
13
+ const ipAddress = result?.body?.ip || 'unknown';
14
+
15
+ // Pass result directly to next stage - no need for $.send()
16
+ $.next('process', ipAddress);
17
+ });
18
+
19
+ // Stage 2: Receive IP directly as function parameter
20
+ $.push('process', function($, ip) {
21
+ // ip is received directly from $.next('process', ip)
22
+
23
+ $.tool.execute('log_event', {
24
+ event: 'ip_processed',
25
+ ip: ip
26
+ });
27
+
28
+ // Pass multiple values to next stage
29
+ $.next('notify', ip, 'success', new Date().toISOString());
30
+ });
31
+
32
+ // Stage 3: Receive multiple parameters as function arguments
33
+ $.push('notify', function($, ip, status, timestamp) {
34
+ // ip = '1.2.3.4', status = 'success', timestamp = '2024-...'
35
+
36
+ $.tool.execute('notification_send', {
37
+ title: 'IP Address',
38
+ message: `IP: ${ip}, Status: ${status}, Time: ${timestamp}`
39
+ });
40
+
41
+ $.next('done');
42
+ });
43
+
44
+ // Done
45
+ $.push('done', function($) {
46
+ $.destroy();
47
+ });
48
+
49
+ $.next('fetch');
50
+ });
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Logger Example - Demonstrates $.logger usage
3
+ * Shows different log levels and logger.child()
4
+ */
5
+
6
+ FLOW(function($) {
7
+ // Stage 1: Logging demo
8
+ $.push('logging-demo', async function($) {
9
+ // Use different log levels
10
+ $.logger.debug('Debug: Starting workflow execution');
11
+ $.logger.info('Info: User input received', { userId: $.input.userId || 1 });
12
+ $.logger.warn('Warn: This is a warning example');
13
+ $.logger.error('Error: This is an error example');
14
+
15
+ // Use logger.child() for module-specific logging
16
+ const dbLogger = $.logger.child('database');
17
+ dbLogger.info('Connecting to database...');
18
+ dbLogger.info('Query executed successfully');
19
+
20
+ const apiLogger = $.logger.child('api');
21
+ apiLogger.debug('API request sent');
22
+ apiLogger.info('API response received', { status: 200 });
23
+
24
+ $.next('done');
25
+ });
26
+
27
+ // Done
28
+ $.push('done', function($) {
29
+ $.logger.info('Workflow completed');
30
+ $.destroy();
31
+ });
32
+
33
+ $.next('logging-demo');
34
+ });
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Storage Example - Demonstrates $.storage usage
3
+ * Shows set, get, list, delete operations
4
+ */
5
+
6
+ FLOW(function($) {
7
+ // Stage 1: Store data
8
+ $.push('store-data', async function($) {
9
+ // Store user preferences
10
+ await $.storage.set('preferences', {
11
+ theme: 'dark',
12
+ language: 'zh-CN'
13
+ });
14
+
15
+ // Store with custom namespace
16
+ await $.storage.set('session', {
17
+ userId: 12345,
18
+ loginTime: new Date().toISOString()
19
+ }, 'user');
20
+
21
+ $.next('retrieve-data');
22
+ });
23
+
24
+ // Stage 2: Retrieve data
25
+ $.push('retrieve-data', async function($) {
26
+ // Get preferences
27
+ const prefs = await $.storage.get('preferences');
28
+ $.logger.info('Preferences:', prefs?.data);
29
+
30
+ // Get user session from namespace
31
+ const session = await $.storage.get('session', 'user');
32
+ $.logger.info('User session:', session?.data);
33
+
34
+ // Store processed result
35
+ const processedData = {
36
+ preferences: prefs?.data,
37
+ session: session?.data,
38
+ processed: true
39
+ };
40
+ await $.storage.set('processed', processedData);
41
+
42
+ $.next('list-keys');
43
+ });
44
+
45
+ // Stage 3: List and cleanup
46
+ $.push('list-keys', async function($) {
47
+ // List all keys in default namespace
48
+ const allKeys = await $.storage.list();
49
+ $.logger.info('All keys:', allKeys?.data);
50
+
51
+ // List keys in user namespace
52
+ const userKeys = await $.storage.list('user');
53
+ $.logger.info('User namespace keys:', userKeys?.data);
54
+
55
+ // Delete temporary data
56
+ await $.storage.delete('processed');
57
+
58
+ $.next('done');
59
+ });
60
+
61
+ // Done
62
+ $.push('done', function($) {
63
+ $.logger.info('Storage workflow completed');
64
+ $.destroy();
65
+ });
66
+
67
+ $.next('store-data');
68
+ });
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Simple User Onboarding Workflow (JS Format - Total.js Style)
3
+ * Demonstrates $.next() with arguments and function parameter receiving
4
+ */
5
+
6
+ FLOW(function($) {
7
+ // Stage 1: Fetch user data
8
+ $.push('fetch-user', async function($, userId) {
9
+ const id = userId || $.input.userId || 1;
10
+
11
+ const result = await $.tool.execute('fetch', {
12
+ url: 'https://api.example.com/users/' + id
13
+ });
14
+
15
+ // Pass user data directly to next stage
16
+ $.next('validate', result);
17
+ });
18
+
19
+ // Stage 2: Validate user - receives result as function parameter
20
+ $.push('validate', function($, result) {
21
+ const user = result?.body || {};
22
+ const status = user.status || 'unknown';
23
+
24
+ // Route based on status - pass user to target stage
25
+ if (status === 'active') {
26
+ $.next('welcome', user);
27
+ } else if (status === 'pending') {
28
+ $.next('send-verification', user);
29
+ } else if (status === 'inactive') {
30
+ $.next('re-engage', user);
31
+ } else {
32
+ $.next('unknown-status', user);
33
+ }
34
+ });
35
+
36
+ // Stage 3: Welcome active user - receives user directly
37
+ $.push('welcome', function($, user) {
38
+ $.extension.execute('notify', 'send_email', {
39
+ template: 'welcome',
40
+ userId: user.id
41
+ });
42
+ $.next('done');
43
+ });
44
+
45
+ // Stage 4: Send verification
46
+ $.push('send-verification', function($, user) {
47
+ $.skill.execute('ambient', 'send-verification', {
48
+ userId: user.id
49
+ });
50
+ $.next('done');
51
+ });
52
+
53
+ // Stage 5: Re-engage inactive user
54
+ $.push('re-engage', function($, user) {
55
+ $.extension.execute('notify', 'send_email', {
56
+ template: 're-engage',
57
+ userId: user.id
58
+ });
59
+ $.next('done');
60
+ });
61
+
62
+ // Stage 6: Handle unknown status
63
+ $.push('unknown-status', function($, user) {
64
+ $.tool.execute('notify_admin', {
65
+ message: 'Unknown user status for user ' + user.id
66
+ });
67
+ $.next('done');
68
+ });
69
+
70
+ // Done
71
+ $.push('done', function($) {
72
+ $.destroy();
73
+ });
74
+
75
+ // Start with userId from input
76
+ $.next('fetch-user', 1);
77
+ });
@@ -0,0 +1,75 @@
1
+ {
2
+ "flow": "user-onboarding",
3
+ "version": "2.0",
4
+ "description": "User onboarding workflow demonstrating action, choice stages and chain-style accessors",
5
+ "stages": [
6
+ {
7
+ "name": "fetch-user",
8
+ "tool": "fetch",
9
+ "args": {
10
+ "url": "https://api.example.com/users/{{input.userId}}"
11
+ }
12
+ },
13
+ {
14
+ "name": "validate",
15
+ "action": "script",
16
+ "script": "return input.status === 'active' || input.status === 'pending'"
17
+ },
18
+ {
19
+ "name": "route",
20
+ "choice": [
21
+ { "when": "validate == true && fetch-user.status == 'active'", "do": "welcome" },
22
+ { "when": "fetch-user.status == 'pending'", "do": "send-verification" },
23
+ { "when": "fetch-user.status == 'inactive'", "do": "re-engage" }
24
+ ],
25
+ "default": "unknown-status"
26
+ },
27
+ {
28
+ "name": "welcome",
29
+ "description": "Using extension.execute()",
30
+ "extension": "notify",
31
+ "tool": "send_email",
32
+ "args": {
33
+ "template": "welcome",
34
+ "userId": "{{input.userId}}"
35
+ }
36
+ },
37
+ {
38
+ "name": "send-verification",
39
+ "description": "Using skill.execute()",
40
+ "skill": "ambient",
41
+ "command": "send-verification",
42
+ "args": {
43
+ "userId": "{{input.userId}}"
44
+ }
45
+ },
46
+ {
47
+ "name": "re-engage",
48
+ "description": "Using extension.execute()",
49
+ "extension": "notify",
50
+ "tool": "send_email",
51
+ "args": {
52
+ "template": "re-engage",
53
+ "userId": "{{input.userId}}"
54
+ }
55
+ },
56
+ {
57
+ "name": "unknown-status",
58
+ "description": "Using tool.execute()",
59
+ "tool": "notify_admin",
60
+ "args": {
61
+ "message": "Unknown user status for user {{input.userId}}"
62
+ }
63
+ },
64
+ {
65
+ "name": "log-completion",
66
+ "description": "Using workflow.execute()",
67
+ "workflow": "log_event",
68
+ "args": {
69
+ "event": "onboarding_complete",
70
+ "userId": "{{input.userId}}",
71
+ "finalStatus": "{{route}}"
72
+ }
73
+ }
74
+ ]
75
+ }