@elizaos/plugin-workflow 2.0.0-beta.1
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/README.md +71 -0
- package/auto-enable.ts +18 -0
- package/dist/actions/index.d.ts +2 -0
- package/dist/actions/index.d.ts.map +1 -0
- package/dist/actions/index.js +2 -0
- package/dist/actions/index.js.map +1 -0
- package/dist/actions/workflow.d.ts +23 -0
- package/dist/actions/workflow.d.ts.map +1 -0
- package/dist/actions/workflow.js +425 -0
- package/dist/actions/workflow.js.map +1 -0
- package/dist/data/defaultNodes.json +9887 -0
- package/dist/data/schemaIndex.json +1 -0
- package/dist/data/triggerSchemaIndex.json +1 -0
- package/dist/db/index.d.ts +2 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +2 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +588 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +59 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +126 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/automations-builder.d.ts +21 -0
- package/dist/lib/automations-builder.d.ts.map +1 -0
- package/dist/lib/automations-builder.js +557 -0
- package/dist/lib/automations-builder.js.map +1 -0
- package/dist/lib/automations-types.d.ts +153 -0
- package/dist/lib/automations-types.d.ts.map +1 -0
- package/dist/lib/automations-types.js +191 -0
- package/dist/lib/automations-types.js.map +1 -0
- package/dist/lib/index.d.ts +3 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +3 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/legacy-task-migration.d.ts +20 -0
- package/dist/lib/legacy-task-migration.d.ts.map +1 -0
- package/dist/lib/legacy-task-migration.js +110 -0
- package/dist/lib/legacy-task-migration.js.map +1 -0
- package/dist/lib/legacy-text-trigger-migration.d.ts +18 -0
- package/dist/lib/legacy-text-trigger-migration.d.ts.map +1 -0
- package/dist/lib/legacy-text-trigger-migration.js +131 -0
- package/dist/lib/legacy-text-trigger-migration.js.map +1 -0
- package/dist/lib/workflow-clarification.d.ts +113 -0
- package/dist/lib/workflow-clarification.d.ts.map +1 -0
- package/dist/lib/workflow-clarification.js +425 -0
- package/dist/lib/workflow-clarification.js.map +1 -0
- package/dist/plugin-routes.d.ts +9 -0
- package/dist/plugin-routes.d.ts.map +1 -0
- package/dist/plugin-routes.js +147 -0
- package/dist/plugin-routes.js.map +1 -0
- package/dist/providers/activeWorkflows.d.ts +11 -0
- package/dist/providers/activeWorkflows.d.ts.map +1 -0
- package/dist/providers/activeWorkflows.js +72 -0
- package/dist/providers/activeWorkflows.js.map +1 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +4 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/pendingDraft.d.ts +9 -0
- package/dist/providers/pendingDraft.d.ts.map +1 -0
- package/dist/providers/pendingDraft.js +48 -0
- package/dist/providers/pendingDraft.js.map +1 -0
- package/dist/providers/workflowStatus.d.ts +3 -0
- package/dist/providers/workflowStatus.d.ts.map +1 -0
- package/dist/providers/workflowStatus.js +69 -0
- package/dist/providers/workflowStatus.js.map +1 -0
- package/dist/register-routes.d.ts +2 -0
- package/dist/register-routes.d.ts.map +1 -0
- package/dist/register-routes.js +6 -0
- package/dist/register-routes.js.map +1 -0
- package/dist/routes/_helpers.d.ts +11 -0
- package/dist/routes/_helpers.d.ts.map +1 -0
- package/dist/routes/_helpers.js +22 -0
- package/dist/routes/_helpers.js.map +1 -0
- package/dist/routes/automations.d.ts +19 -0
- package/dist/routes/automations.d.ts.map +1 -0
- package/dist/routes/automations.js +32 -0
- package/dist/routes/automations.js.map +1 -0
- package/dist/routes/embedded-webhooks.d.ts +3 -0
- package/dist/routes/embedded-webhooks.d.ts.map +1 -0
- package/dist/routes/embedded-webhooks.js +47 -0
- package/dist/routes/embedded-webhooks.js.map +1 -0
- package/dist/routes/executions.d.ts +3 -0
- package/dist/routes/executions.d.ts.map +1 -0
- package/dist/routes/executions.js +58 -0
- package/dist/routes/executions.js.map +1 -0
- package/dist/routes/index.d.ts +4 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +14 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/nodes.d.ts +3 -0
- package/dist/routes/nodes.d.ts.map +1 -0
- package/dist/routes/nodes.js +168 -0
- package/dist/routes/nodes.js.map +1 -0
- package/dist/routes/validation.d.ts +3 -0
- package/dist/routes/validation.d.ts.map +1 -0
- package/dist/routes/validation.js +41 -0
- package/dist/routes/validation.js.map +1 -0
- package/dist/routes/workflow-routes.d.ts +27 -0
- package/dist/routes/workflow-routes.d.ts.map +1 -0
- package/dist/routes/workflow-routes.js +326 -0
- package/dist/routes/workflow-routes.js.map +1 -0
- package/dist/routes/workflows.d.ts +3 -0
- package/dist/routes/workflows.d.ts.map +1 -0
- package/dist/routes/workflows.js +252 -0
- package/dist/routes/workflows.js.map +1 -0
- package/dist/schemas/draftIntent.d.ts +22 -0
- package/dist/schemas/draftIntent.d.ts.map +1 -0
- package/dist/schemas/draftIntent.js +22 -0
- package/dist/schemas/draftIntent.js.map +1 -0
- package/dist/schemas/feasibility.d.ts +13 -0
- package/dist/schemas/feasibility.d.ts.map +1 -0
- package/dist/schemas/feasibility.js +9 -0
- package/dist/schemas/feasibility.js.map +1 -0
- package/dist/schemas/index.d.ts +5 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +5 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/keywordExtraction.d.ts +14 -0
- package/dist/schemas/keywordExtraction.d.ts.map +1 -0
- package/dist/schemas/keywordExtraction.js +12 -0
- package/dist/schemas/keywordExtraction.js.map +1 -0
- package/dist/schemas/workflowMatching.d.ts +36 -0
- package/dist/schemas/workflowMatching.d.ts.map +1 -0
- package/dist/schemas/workflowMatching.js +30 -0
- package/dist/schemas/workflowMatching.js.map +1 -0
- package/dist/services/embedded-workflow-service.d.ts +106 -0
- package/dist/services/embedded-workflow-service.d.ts.map +1 -0
- package/dist/services/embedded-workflow-service.js +1900 -0
- package/dist/services/embedded-workflow-service.js.map +1 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +5 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/workflow-credential-store.d.ts +27 -0
- package/dist/services/workflow-credential-store.d.ts.map +1 -0
- package/dist/services/workflow-credential-store.js +92 -0
- package/dist/services/workflow-credential-store.js.map +1 -0
- package/dist/services/workflow-dispatch.d.ts +41 -0
- package/dist/services/workflow-dispatch.d.ts.map +1 -0
- package/dist/services/workflow-dispatch.js +86 -0
- package/dist/services/workflow-dispatch.js.map +1 -0
- package/dist/services/workflow-service.d.ts +63 -0
- package/dist/services/workflow-service.d.ts.map +1 -0
- package/dist/services/workflow-service.js +492 -0
- package/dist/services/workflow-service.js.map +1 -0
- package/dist/trigger-routes.d.ts +153 -0
- package/dist/trigger-routes.d.ts.map +1 -0
- package/dist/trigger-routes.js +424 -0
- package/dist/trigger-routes.js.map +1 -0
- package/dist/types/index.d.ts +457 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +59 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/catalog.d.ts +16 -0
- package/dist/utils/catalog.d.ts.map +1 -0
- package/dist/utils/catalog.js +211 -0
- package/dist/utils/catalog.js.map +1 -0
- package/dist/utils/clarification.d.ts +17 -0
- package/dist/utils/clarification.d.ts.map +1 -0
- package/dist/utils/clarification.js +46 -0
- package/dist/utils/clarification.js.map +1 -0
- package/dist/utils/context.d.ts +4 -0
- package/dist/utils/context.d.ts.map +1 -0
- package/dist/utils/context.js +18 -0
- package/dist/utils/context.js.map +1 -0
- package/dist/utils/credentialResolver.d.ts +22 -0
- package/dist/utils/credentialResolver.d.ts.map +1 -0
- package/dist/utils/credentialResolver.js +146 -0
- package/dist/utils/credentialResolver.js.map +1 -0
- package/dist/utils/generation.d.ts +36 -0
- package/dist/utils/generation.d.ts.map +1 -0
- package/dist/utils/generation.js +701 -0
- package/dist/utils/generation.js.map +1 -0
- package/dist/utils/host-capabilities.d.ts +27 -0
- package/dist/utils/host-capabilities.d.ts.map +1 -0
- package/dist/utils/host-capabilities.js +59 -0
- package/dist/utils/host-capabilities.js.map +1 -0
- package/dist/utils/inferSyntheticOutputSchema.d.ts +20 -0
- package/dist/utils/inferSyntheticOutputSchema.d.ts.map +1 -0
- package/dist/utils/inferSyntheticOutputSchema.js +151 -0
- package/dist/utils/inferSyntheticOutputSchema.js.map +1 -0
- package/dist/utils/outputSchema.d.ts +26 -0
- package/dist/utils/outputSchema.d.ts.map +1 -0
- package/dist/utils/outputSchema.js +297 -0
- package/dist/utils/outputSchema.js.map +1 -0
- package/dist/utils/validateAndRepair.d.ts +41 -0
- package/dist/utils/validateAndRepair.d.ts.map +1 -0
- package/dist/utils/validateAndRepair.js +483 -0
- package/dist/utils/validateAndRepair.js.map +1 -0
- package/dist/utils/workflow-prompts/actionResponse.d.ts +2 -0
- package/dist/utils/workflow-prompts/actionResponse.d.ts.map +1 -0
- package/dist/utils/workflow-prompts/actionResponse.js +17 -0
- package/dist/utils/workflow-prompts/actionResponse.js.map +1 -0
- package/dist/utils/workflow-prompts/draftIntent.d.ts +2 -0
- package/dist/utils/workflow-prompts/draftIntent.d.ts.map +1 -0
- package/dist/utils/workflow-prompts/draftIntent.js +23 -0
- package/dist/utils/workflow-prompts/draftIntent.js.map +1 -0
- package/dist/utils/workflow-prompts/feasibilityCheck.d.ts +2 -0
- package/dist/utils/workflow-prompts/feasibilityCheck.d.ts.map +1 -0
- package/dist/utils/workflow-prompts/feasibilityCheck.js +21 -0
- package/dist/utils/workflow-prompts/feasibilityCheck.js.map +1 -0
- package/dist/utils/workflow-prompts/fieldCorrection.d.ts +3 -0
- package/dist/utils/workflow-prompts/fieldCorrection.d.ts.map +1 -0
- package/dist/utils/workflow-prompts/fieldCorrection.js +20 -0
- package/dist/utils/workflow-prompts/fieldCorrection.js.map +1 -0
- package/dist/utils/workflow-prompts/index.d.ts +8 -0
- package/dist/utils/workflow-prompts/index.d.ts.map +1 -0
- package/dist/utils/workflow-prompts/index.js +8 -0
- package/dist/utils/workflow-prompts/index.js.map +1 -0
- package/dist/utils/workflow-prompts/keywordExtraction.d.ts +2 -0
- package/dist/utils/workflow-prompts/keywordExtraction.d.ts.map +1 -0
- package/dist/utils/workflow-prompts/keywordExtraction.js +21 -0
- package/dist/utils/workflow-prompts/keywordExtraction.js.map +1 -0
- package/dist/utils/workflow-prompts/parameterCorrection.d.ts +3 -0
- package/dist/utils/workflow-prompts/parameterCorrection.d.ts.map +1 -0
- package/dist/utils/workflow-prompts/parameterCorrection.js +29 -0
- package/dist/utils/workflow-prompts/parameterCorrection.js.map +1 -0
- package/dist/utils/workflow-prompts/workflowGeneration.d.ts +2 -0
- package/dist/utils/workflow-prompts/workflowGeneration.d.ts.map +1 -0
- package/dist/utils/workflow-prompts/workflowGeneration.js +529 -0
- package/dist/utils/workflow-prompts/workflowGeneration.js.map +1 -0
- package/dist/utils/workflow-prompts/workflowMatching.d.ts +2 -0
- package/dist/utils/workflow-prompts/workflowMatching.d.ts.map +1 -0
- package/dist/utils/workflow-prompts/workflowMatching.js +23 -0
- package/dist/utils/workflow-prompts/workflowMatching.js.map +1 -0
- package/dist/utils/workflow.d.ts +62 -0
- package/dist/utils/workflow.d.ts.map +1 -0
- package/dist/utils/workflow.js +712 -0
- package/dist/utils/workflow.js.map +1 -0
- package/package.json +87 -0
- package/src/actions/index.ts +1 -0
- package/src/actions/workflow.ts +494 -0
- package/src/data/defaultNodes.json +9887 -0
- package/src/data/schemaIndex.json +1 -0
- package/src/data/triggerSchemaIndex.json +1 -0
- package/src/db/index.ts +8 -0
- package/src/db/schema.ts +94 -0
- package/src/index.ts +179 -0
- package/src/lib/automations-builder.ts +679 -0
- package/src/lib/automations-types.ts +391 -0
- package/src/lib/index.ts +8 -0
- package/src/lib/legacy-task-migration.ts +143 -0
- package/src/lib/legacy-text-trigger-migration.ts +178 -0
- package/src/lib/workflow-clarification.ts +497 -0
- package/src/plugin-routes.ts +164 -0
- package/src/providers/activeWorkflows.ts +81 -0
- package/src/providers/index.ts +3 -0
- package/src/providers/pendingDraft.ts +55 -0
- package/src/providers/workflowStatus.ts +88 -0
- package/src/register-routes.ts +6 -0
- package/src/routes/_helpers.ts +27 -0
- package/src/routes/automations.ts +46 -0
- package/src/routes/embedded-webhooks.ts +64 -0
- package/src/routes/executions.ts +75 -0
- package/src/routes/index.ts +16 -0
- package/src/routes/nodes.ts +211 -0
- package/src/routes/validation.ts +51 -0
- package/src/routes/workflow-routes.ts +469 -0
- package/src/routes/workflows.ts +310 -0
- package/src/schemas/draftIntent.ts +21 -0
- package/src/schemas/feasibility.ts +8 -0
- package/src/schemas/index.ts +4 -0
- package/src/schemas/keywordExtraction.ts +11 -0
- package/src/schemas/workflowMatching.ts +29 -0
- package/src/services/embedded-workflow-service.ts +2224 -0
- package/src/services/index.ts +17 -0
- package/src/services/workflow-credential-store.ts +132 -0
- package/src/services/workflow-dispatch.ts +121 -0
- package/src/services/workflow-service.ts +839 -0
- package/src/trigger-routes.ts +714 -0
- package/src/types/index.ts +562 -0
- package/src/utils/catalog.ts +260 -0
- package/src/utils/clarification.ts +52 -0
- package/src/utils/context.ts +22 -0
- package/src/utils/credentialResolver.ts +234 -0
- package/src/utils/generation.ts +987 -0
- package/src/utils/host-capabilities.ts +81 -0
- package/src/utils/inferSyntheticOutputSchema.ts +163 -0
- package/src/utils/outputSchema.ts +372 -0
- package/src/utils/validateAndRepair.ts +610 -0
- package/src/utils/workflow-prompts/actionResponse.ts +16 -0
- package/src/utils/workflow-prompts/draftIntent.ts +22 -0
- package/src/utils/workflow-prompts/feasibilityCheck.ts +20 -0
- package/src/utils/workflow-prompts/fieldCorrection.ts +20 -0
- package/src/utils/workflow-prompts/index.ts +10 -0
- package/src/utils/workflow-prompts/keywordExtraction.ts +20 -0
- package/src/utils/workflow-prompts/parameterCorrection.ts +29 -0
- package/src/utils/workflow-prompts/workflowGeneration.ts +528 -0
- package/src/utils/workflow-prompts/workflowMatching.ts +22 -0
- package/src/utils/workflow.ts +895 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import defaultNodesData from '../data/defaultNodes.json';
|
|
2
|
+
import type {
|
|
3
|
+
IntegrationFilterResult,
|
|
4
|
+
NodeDefinition,
|
|
5
|
+
NodeProperty,
|
|
6
|
+
NodeSearchResult,
|
|
7
|
+
} from '../types/index';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* workflows node catalog with keyword-based search
|
|
11
|
+
* @note Uses embedded catalog (457 nodes as of April 2025)
|
|
12
|
+
* @todo Add dynamic refresh via GET /node-types in v2
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const NODE_CATALOG = defaultNodesData as NodeDefinition[];
|
|
16
|
+
|
|
17
|
+
/** Get all nodes in the catalog. Used by route handlers for unfiltered listing. */
|
|
18
|
+
export function getAllNodes(): NodeDefinition[] {
|
|
19
|
+
return NODE_CATALOG;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Look up a node definition by its type name.
|
|
24
|
+
*
|
|
25
|
+
* Handles full names ("workflows-nodes-base.httpRequest") and bare names ("httpRequest").
|
|
26
|
+
*/
|
|
27
|
+
export function getNodeDefinition(typeName: string): NodeDefinition | undefined {
|
|
28
|
+
const exact = NODE_CATALOG.find((n) => n.name === typeName);
|
|
29
|
+
if (exact) {
|
|
30
|
+
return exact;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const bare = typeName.replace(/^workflows-nodes-base\./, '');
|
|
34
|
+
return NODE_CATALOG.find((n) => {
|
|
35
|
+
const catalogBare = n.name.replace(/^workflows-nodes-base\./, '');
|
|
36
|
+
return catalogBare === bare || n.name === bare;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Split a name into lowercase tokens on camelCase / dot / hyphen / underscore / @ / slash boundaries */
|
|
41
|
+
function tokenize(name: string): string[] {
|
|
42
|
+
return name
|
|
43
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2') // camelCase → words
|
|
44
|
+
.split(/[\s.\-_@/]+/)
|
|
45
|
+
.map((t) => t.toLowerCase())
|
|
46
|
+
.filter(Boolean);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Scoring: exact name 10, word-boundary 7, substring 3, category 3, description 2, word 1
|
|
51
|
+
*/
|
|
52
|
+
export function searchNodes(keywords: string[], limit = 15): NodeSearchResult[] {
|
|
53
|
+
if (keywords.length === 0) {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const normalizedKeywords = keywords.map((kw) => kw.toLowerCase().trim());
|
|
58
|
+
|
|
59
|
+
const scoredNodes: NodeSearchResult[] = NODE_CATALOG.filter(
|
|
60
|
+
(node) => node.name && node.displayName
|
|
61
|
+
).map((node) => {
|
|
62
|
+
let score = 0;
|
|
63
|
+
const matchReasons: string[] = [];
|
|
64
|
+
|
|
65
|
+
const nodeName = node.name.toLowerCase();
|
|
66
|
+
const nodeDisplayName = node.displayName.toLowerCase();
|
|
67
|
+
const nodeDescription = node.description?.toLowerCase() || '';
|
|
68
|
+
const nameTokens = tokenize(node.name);
|
|
69
|
+
const displayTokens = tokenize(node.displayName);
|
|
70
|
+
|
|
71
|
+
for (const keyword of normalizedKeywords) {
|
|
72
|
+
if (nodeName === keyword || nodeDisplayName === keyword) {
|
|
73
|
+
score += 10;
|
|
74
|
+
matchReasons.push(`exact match: "${keyword}"`);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Word-boundary match: keyword equals a token in the name
|
|
79
|
+
const isWordMatch =
|
|
80
|
+
nameTokens.some((t) => t === keyword) || displayTokens.some((t) => t === keyword);
|
|
81
|
+
|
|
82
|
+
if (isWordMatch) {
|
|
83
|
+
score += 7;
|
|
84
|
+
matchReasons.push(`word match: "${keyword}"`);
|
|
85
|
+
} else if (nodeName.includes(keyword) || nodeDisplayName.includes(keyword)) {
|
|
86
|
+
score += 3;
|
|
87
|
+
matchReasons.push(`name contains: "${keyword}"`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (nodeDescription.includes(keyword)) {
|
|
91
|
+
score += 2;
|
|
92
|
+
matchReasons.push(`description contains: "${keyword}"`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const descriptionWords = nodeDescription.split(/\s+/);
|
|
96
|
+
if (descriptionWords.some((word) => word.includes(keyword))) {
|
|
97
|
+
score += 1;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (node.group.some((group) => group.toLowerCase().includes(keyword))) {
|
|
101
|
+
score += 3;
|
|
102
|
+
matchReasons.push(`category: "${keyword}"`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
node,
|
|
108
|
+
score,
|
|
109
|
+
matchReason: matchReasons.join(', ') || 'no strong match',
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return scoredNodes
|
|
114
|
+
.filter((result) => result.score > 0)
|
|
115
|
+
.sort((a, b) => b.score - a.score)
|
|
116
|
+
.slice(0, limit);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function filterNodesByIntegrationSupport(
|
|
120
|
+
nodes: NodeSearchResult[],
|
|
121
|
+
supportedCredTypes: Set<string>
|
|
122
|
+
): IntegrationFilterResult {
|
|
123
|
+
const remaining: NodeSearchResult[] = [];
|
|
124
|
+
const removed: NodeSearchResult[] = [];
|
|
125
|
+
|
|
126
|
+
for (const result of nodes) {
|
|
127
|
+
const creds = result.node.credentials;
|
|
128
|
+
|
|
129
|
+
// No credentials → utility node → always keep
|
|
130
|
+
if (!creds || creds.length === 0) {
|
|
131
|
+
remaining.push(result);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Service node: keep if ANY credential type is supported
|
|
136
|
+
const hasSupported = creds.some((c) => supportedCredTypes.has(c.name));
|
|
137
|
+
if (hasSupported) {
|
|
138
|
+
remaining.push(result);
|
|
139
|
+
} else {
|
|
140
|
+
removed.push(result);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return { remaining, removed };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const NOISE_TYPES = new Set(['notice', 'hidden']);
|
|
148
|
+
const STRIP_KEYS = new Set([
|
|
149
|
+
'routing',
|
|
150
|
+
'displayOptions',
|
|
151
|
+
'typeOptions',
|
|
152
|
+
'hint',
|
|
153
|
+
'isNodeSetting',
|
|
154
|
+
'noDataExpression',
|
|
155
|
+
'validateType',
|
|
156
|
+
'ignoreValidationDuringExecution',
|
|
157
|
+
'requiresDataPath',
|
|
158
|
+
'disabledOptions',
|
|
159
|
+
'credentialTypes',
|
|
160
|
+
'modes',
|
|
161
|
+
]);
|
|
162
|
+
|
|
163
|
+
type NodePropertyOption = NonNullable<NodeProperty['options']>[number];
|
|
164
|
+
|
|
165
|
+
function isPropertyCollectionOption(
|
|
166
|
+
option: NodePropertyOption
|
|
167
|
+
): option is Extract<NodePropertyOption, { values: NodeProperty[] }> {
|
|
168
|
+
return Array.isArray(option.values);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function simplifyProperty(prop: NodeProperty): NodeProperty | null {
|
|
172
|
+
if (NOISE_TYPES.has(prop.type)) {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const slim: NodeProperty = { ...prop };
|
|
177
|
+
for (const key of STRIP_KEYS) {
|
|
178
|
+
delete slim[key];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (prop.type === 'resourceLocator') {
|
|
182
|
+
slim.type = 'string';
|
|
183
|
+
slim.default = '';
|
|
184
|
+
slim.description = slim.description || `${prop.displayName} ID`;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (prop.options && Array.isArray(prop.options)) {
|
|
188
|
+
slim.options = prop.options.map((opt) => {
|
|
189
|
+
if (isPropertyCollectionOption(opt)) {
|
|
190
|
+
return {
|
|
191
|
+
name: opt.name,
|
|
192
|
+
displayName: opt.displayName,
|
|
193
|
+
values: opt.values.map(simplifyProperty).filter((v): v is NodeProperty => v !== null),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
const { description: _d, ...rest } = opt;
|
|
197
|
+
return rest;
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return slim;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Derive a `{ credType: requiredAuthValue }` map from a node's catalog
|
|
206
|
+
* credential entries. So Gmail's catalog produces
|
|
207
|
+
* `{ gmailOAuth2: "oAuth2", googleApi: "serviceAccount" }`. The LLM uses
|
|
208
|
+
* this to set `parameters.authentication` correctly when attaching a
|
|
209
|
+
* credentials block (Session 21 anti-hallucination Layer 2).
|
|
210
|
+
*
|
|
211
|
+
* Returns undefined when no credential entries gate on `authentication`.
|
|
212
|
+
*/
|
|
213
|
+
function buildCredentialAuthMatrix(node: NodeDefinition): Record<string, string> | undefined {
|
|
214
|
+
if (!node.credentials?.length) {
|
|
215
|
+
return undefined;
|
|
216
|
+
}
|
|
217
|
+
const out: Record<string, string> = {};
|
|
218
|
+
for (const cred of node.credentials) {
|
|
219
|
+
const authValues = (cred.displayOptions as { show?: { authentication?: string[] } } | undefined)
|
|
220
|
+
?.show?.authentication;
|
|
221
|
+
if (Array.isArray(authValues) && authValues.length === 1) {
|
|
222
|
+
out[cred.name] = authValues[0];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function simplifyNodeForLLM(node: NodeDefinition): NodeDefinition {
|
|
229
|
+
const cleaned = node.properties
|
|
230
|
+
.map(simplifyProperty)
|
|
231
|
+
.filter((p): p is NodeProperty => p !== null);
|
|
232
|
+
|
|
233
|
+
const seen = new Set<string>();
|
|
234
|
+
const deduped: NodeProperty[] = [];
|
|
235
|
+
for (const prop of cleaned) {
|
|
236
|
+
if (seen.has(prop.name)) {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
seen.add(prop.name);
|
|
240
|
+
deduped.push(prop);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Layer 2 (Session 21): always emit `version` as an array so the LLM
|
|
244
|
+
// sees the EXACT set of valid values (catches typeVersion hallucinations
|
|
245
|
+
// like 2.2 when only [1, 2, 2.1] exist). Pair with the prompt rule
|
|
246
|
+
// "pick the highest from version[]; never invent versions".
|
|
247
|
+
const versions: number[] = Array.isArray(node.version) ? [...node.version] : [node.version];
|
|
248
|
+
|
|
249
|
+
// Layer 2 (Session 21): expose the credential→authentication mapping
|
|
250
|
+
// so the LLM sets `parameters.authentication` correctly when it
|
|
251
|
+
// attaches a credentials block.
|
|
252
|
+
const credentialAuthMatrix = buildCredentialAuthMatrix(node);
|
|
253
|
+
|
|
254
|
+
return {
|
|
255
|
+
...node,
|
|
256
|
+
version: versions,
|
|
257
|
+
properties: deduped,
|
|
258
|
+
...(credentialAuthMatrix ? { credentialAuthMatrix } : {}),
|
|
259
|
+
} as NodeDefinition & { credentialAuthMatrix?: Record<string, string> };
|
|
260
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ClarificationRequest } from '../types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Marker used by the service to flag clarifications produced by post-LLM
|
|
5
|
+
* catalog validation (vs. clarifications emitted by the LLM itself). Hosts
|
|
6
|
+
* may surface these differently if needed.
|
|
7
|
+
*/
|
|
8
|
+
export const CATALOG_CLARIFICATION_SUFFIX =
|
|
9
|
+
'— please provide this value or clarify your requirements';
|
|
10
|
+
|
|
11
|
+
export function isCatalogClarificationString(value: string): boolean {
|
|
12
|
+
return value.endsWith(CATALOG_CLARIFICATION_SUFFIX);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function isCatalogClarification(item: string | ClarificationRequest): boolean {
|
|
16
|
+
return typeof item === 'string'
|
|
17
|
+
? isCatalogClarificationString(item)
|
|
18
|
+
: isCatalogClarificationString(item.question);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Normalize a mixed-shape clarifications array into structured
|
|
23
|
+
* `ClarificationRequest` objects. Legacy strings become `kind: 'free_text'`
|
|
24
|
+
* with an empty `paramPath` (host renders a free-form input instead of a
|
|
25
|
+
* picker). Structured items pass through unchanged.
|
|
26
|
+
*/
|
|
27
|
+
export function coerceClarificationRequests(
|
|
28
|
+
items: ReadonlyArray<string | ClarificationRequest> | undefined | null
|
|
29
|
+
): ClarificationRequest[] {
|
|
30
|
+
if (!items || items.length === 0) {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
const out: ClarificationRequest[] = [];
|
|
34
|
+
for (const item of items) {
|
|
35
|
+
if (typeof item === 'string') {
|
|
36
|
+
const trimmed = item.trim();
|
|
37
|
+
if (trimmed.length === 0) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
out.push({ kind: 'free_text', question: trimmed, paramPath: '' });
|
|
41
|
+
} else if (item && typeof item === 'object' && typeof item.question === 'string') {
|
|
42
|
+
out.push({
|
|
43
|
+
kind: item.kind ?? 'free_text',
|
|
44
|
+
platform: item.platform,
|
|
45
|
+
scope: item.scope,
|
|
46
|
+
question: item.question,
|
|
47
|
+
paramPath: typeof item.paramPath === 'string' ? item.paramPath : '',
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { IAgentRuntime, Memory, State, UUID } from '@elizaos/core';
|
|
2
|
+
|
|
3
|
+
export function buildConversationContext(message: Memory, state: State | undefined): string {
|
|
4
|
+
const raw = state?.values?.recentMessages;
|
|
5
|
+
const recentMessages = typeof raw === 'string' ? raw : '';
|
|
6
|
+
const currentText = message.content?.text ?? '';
|
|
7
|
+
|
|
8
|
+
if (!recentMessages) {
|
|
9
|
+
return currentText;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return `${recentMessages}\n\nCurrent request: ${currentText}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function getUserTagName(runtime: IAgentRuntime, userId: string): Promise<string> {
|
|
16
|
+
const entity = await runtime.getEntityById(userId as UUID);
|
|
17
|
+
const shortId = userId.replace(/-/g, '').slice(0, 8);
|
|
18
|
+
const name = entity?.names?.[0];
|
|
19
|
+
// ElizaOS default name is "User" + UUID — not useful for a tag
|
|
20
|
+
const isRealName = name && !name.includes(userId.slice(0, 8));
|
|
21
|
+
return isRealName ? `${name}_${shortId}` : `user_${shortId}`;
|
|
22
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { logger } from '@elizaos/core';
|
|
2
|
+
import type {
|
|
3
|
+
CredentialProvider,
|
|
4
|
+
CredentialResolutionResult,
|
|
5
|
+
MissingConnection,
|
|
6
|
+
WorkflowCredentialStoreApi,
|
|
7
|
+
WorkflowDefinition,
|
|
8
|
+
WorkflowPluginConfig,
|
|
9
|
+
} from '../types/index';
|
|
10
|
+
|
|
11
|
+
interface CredentialApiClient {
|
|
12
|
+
createCredential(credential: {
|
|
13
|
+
name: string;
|
|
14
|
+
type: string;
|
|
15
|
+
data: Record<string, unknown>;
|
|
16
|
+
}): Promise<{ id: string }>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resolve and inject credentials into workflow.
|
|
21
|
+
*
|
|
22
|
+
* Resolution chain (first match wins):
|
|
23
|
+
* 1. Credential store DB — cached mappings from previous resolutions
|
|
24
|
+
* 2. Static config — character.settings.workflows.credentials
|
|
25
|
+
* 3. External provider — registered CredentialProvider service (e.g. cloud OAuth)
|
|
26
|
+
* 4. Missing — reported for manual configuration in workflows
|
|
27
|
+
*/
|
|
28
|
+
export async function resolveCredentials(
|
|
29
|
+
workflow: WorkflowDefinition,
|
|
30
|
+
userId: string,
|
|
31
|
+
config: WorkflowPluginConfig,
|
|
32
|
+
credStore: WorkflowCredentialStoreApi | null,
|
|
33
|
+
credProvider: CredentialProvider | null,
|
|
34
|
+
apiClient: CredentialApiClient | null,
|
|
35
|
+
tagName: string
|
|
36
|
+
): Promise<CredentialResolutionResult> {
|
|
37
|
+
const requiredCredTypes = extractRequiredCredentialTypes(workflow);
|
|
38
|
+
|
|
39
|
+
if (requiredCredTypes.size === 0) {
|
|
40
|
+
return {
|
|
41
|
+
workflow,
|
|
42
|
+
missingConnections: [],
|
|
43
|
+
injectedCredentials: new Map(),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const injectedCredentials = new Map<string, string>();
|
|
48
|
+
const missingConnections: MissingConnection[] = [];
|
|
49
|
+
|
|
50
|
+
for (const credType of requiredCredTypes) {
|
|
51
|
+
const credId = await resolveOneCredential(
|
|
52
|
+
credType,
|
|
53
|
+
userId,
|
|
54
|
+
config,
|
|
55
|
+
credStore,
|
|
56
|
+
credProvider,
|
|
57
|
+
apiClient,
|
|
58
|
+
missingConnections,
|
|
59
|
+
tagName
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
if (credId) {
|
|
63
|
+
injectedCredentials.set(credType, credId);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const resolvedWorkflow = injectCredentialIds(workflow, injectedCredentials);
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
workflow: resolvedWorkflow,
|
|
71
|
+
missingConnections,
|
|
72
|
+
injectedCredentials,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async function resolveOneCredential(
|
|
77
|
+
credType: string,
|
|
78
|
+
userId: string,
|
|
79
|
+
config: WorkflowPluginConfig,
|
|
80
|
+
credStore: WorkflowCredentialStoreApi | null,
|
|
81
|
+
credProvider: CredentialProvider | null,
|
|
82
|
+
apiClient: CredentialApiClient | null,
|
|
83
|
+
missingConnections: MissingConnection[],
|
|
84
|
+
tagName: string
|
|
85
|
+
): Promise<string | null> {
|
|
86
|
+
// 1. Credential store DB
|
|
87
|
+
const cachedId = await credStore?.get(userId, credType);
|
|
88
|
+
if (cachedId) {
|
|
89
|
+
logger.debug(
|
|
90
|
+
{ src: 'plugin:workflow:utils:credentials' },
|
|
91
|
+
`Resolved ${credType} from credential store`
|
|
92
|
+
);
|
|
93
|
+
return cachedId;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 2. Static config
|
|
97
|
+
if (config.credentials) {
|
|
98
|
+
const configId = findCredentialId(config.credentials, credType);
|
|
99
|
+
if (configId) {
|
|
100
|
+
return configId;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// 3. External provider
|
|
105
|
+
if (credProvider) {
|
|
106
|
+
try {
|
|
107
|
+
const result = await credProvider.resolve(userId, credType);
|
|
108
|
+
|
|
109
|
+
if (result?.status === 'credential_data') {
|
|
110
|
+
if (!apiClient) {
|
|
111
|
+
logger.error(
|
|
112
|
+
{ src: 'plugin:workflow:utils:credentials' },
|
|
113
|
+
`Received credential_data for ${credType} but no apiClient available`
|
|
114
|
+
);
|
|
115
|
+
missingConnections.push({ credType });
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
const credName = `${credType}_${tagName}`;
|
|
119
|
+
const workflowsCred = await apiClient.createCredential({
|
|
120
|
+
name: credName,
|
|
121
|
+
type: credType,
|
|
122
|
+
data: result.data,
|
|
123
|
+
});
|
|
124
|
+
try {
|
|
125
|
+
await credStore?.set(userId, credType, workflowsCred.id);
|
|
126
|
+
} catch (cacheError) {
|
|
127
|
+
logger.warn(
|
|
128
|
+
{ src: 'plugin:workflow:utils:credentials' },
|
|
129
|
+
`Failed to cache credential mapping for ${credType} (credential still usable): ${cacheError instanceof Error ? cacheError.message : String(cacheError)}`
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
logger.info(
|
|
133
|
+
{ src: 'plugin:workflow:utils:credentials' },
|
|
134
|
+
`Created workflows credential for ${credType}: ${workflowsCred.id}`
|
|
135
|
+
);
|
|
136
|
+
return workflowsCred.id;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (result?.status === 'needs_auth') {
|
|
140
|
+
missingConnections.push({ credType, authUrl: result.authUrl });
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
} catch (error) {
|
|
144
|
+
logger.error(
|
|
145
|
+
{ src: 'plugin:workflow:utils:credentials' },
|
|
146
|
+
`Credential provider failed for ${credType}: ${error instanceof Error ? error.message : String(error)}`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// 4. Missing
|
|
152
|
+
missingConnections.push({ credType });
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Look up a credential ID from config, tolerating naming mismatches
|
|
158
|
+
* (e.g. LLM generates "gmailOAuth2Api" but config has "gmailOAuth2", or vice-versa).
|
|
159
|
+
*/
|
|
160
|
+
function findCredentialId(credentials: Record<string, string>, credType: string): string | null {
|
|
161
|
+
if (credentials[credType]) {
|
|
162
|
+
return credentials[credType];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Fuzzy: try without "Api" suffix (e.g. "gmailOAuth2Api" → "gmailOAuth2")
|
|
166
|
+
const withoutApi = credType.replace(/Api$/, '');
|
|
167
|
+
if (withoutApi !== credType && credentials[withoutApi]) {
|
|
168
|
+
logger.debug(
|
|
169
|
+
{ src: 'plugin:workflow:utils:credentials' },
|
|
170
|
+
`Fuzzy credential match: "${credType}" → "${withoutApi}" (removed Api suffix)`
|
|
171
|
+
);
|
|
172
|
+
return credentials[withoutApi];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Fuzzy: try with "Api" suffix (e.g. "gmailOAuth2" → "gmailOAuth2Api")
|
|
176
|
+
const withApi = `${credType}Api`;
|
|
177
|
+
if (credentials[withApi]) {
|
|
178
|
+
logger.debug(
|
|
179
|
+
{ src: 'plugin:workflow:utils:credentials' },
|
|
180
|
+
`Fuzzy credential match: "${credType}" → "${withApi}" (added Api suffix)`
|
|
181
|
+
);
|
|
182
|
+
return credentials[withApi];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function extractRequiredCredentialTypes(workflow: WorkflowDefinition): Set<string> {
|
|
189
|
+
const credTypes = new Set<string>();
|
|
190
|
+
|
|
191
|
+
for (const node of workflow.nodes) {
|
|
192
|
+
if (node.credentials) {
|
|
193
|
+
for (const credType of Object.keys(node.credentials)) {
|
|
194
|
+
credTypes.add(credType);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return credTypes;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function injectCredentialIds(
|
|
203
|
+
workflow: WorkflowDefinition,
|
|
204
|
+
credentialMap: Map<string, string>
|
|
205
|
+
): WorkflowDefinition {
|
|
206
|
+
const injected = { ...workflow };
|
|
207
|
+
injected.nodes = workflow.nodes.map((node) => {
|
|
208
|
+
if (!node.credentials) {
|
|
209
|
+
return node;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const updatedCredentials: typeof node.credentials = {};
|
|
213
|
+
|
|
214
|
+
for (const [credType, credRef] of Object.entries(node.credentials)) {
|
|
215
|
+
const credId = credentialMap.get(credType);
|
|
216
|
+
|
|
217
|
+
if (credId) {
|
|
218
|
+
updatedCredentials[credType] = {
|
|
219
|
+
id: credId,
|
|
220
|
+
name: credRef.name,
|
|
221
|
+
};
|
|
222
|
+
} else {
|
|
223
|
+
updatedCredentials[credType] = credRef;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
...node,
|
|
229
|
+
credentials: updatedCredentials,
|
|
230
|
+
};
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
return injected;
|
|
234
|
+
}
|