@q1k-oss/behaviour-tree-workflows 0.0.1 → 0.0.2
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/dist/index.cjs +587 -13
- package/dist/index.d.cts +790 -10
- package/dist/index.d.ts +790 -10
- package/dist/index.js +582 -13
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -34,7 +34,9 @@ __export(index_exports, {
|
|
|
34
34
|
AlwaysCondition: () => AlwaysCondition,
|
|
35
35
|
BaseNode: () => BaseNode,
|
|
36
36
|
BehaviorTree: () => BehaviorTree,
|
|
37
|
+
BrowserAgent: () => BrowserAgent,
|
|
37
38
|
CheckCondition: () => CheckCondition,
|
|
39
|
+
ClaudeAgent: () => ClaudeAgent,
|
|
38
40
|
CodeExecution: () => CodeExecution,
|
|
39
41
|
CompositeNode: () => CompositeNode,
|
|
40
42
|
ConditionNode: () => ConditionNode,
|
|
@@ -51,10 +53,13 @@ __export(index_exports, {
|
|
|
51
53
|
ForceFailure: () => ForceFailure,
|
|
52
54
|
ForceSuccess: () => ForceSuccess,
|
|
53
55
|
GenerateFile: () => GenerateFile,
|
|
56
|
+
GitHubAction: () => GitHubAction,
|
|
54
57
|
HttpRequest: () => HttpRequest,
|
|
58
|
+
HumanTask: () => HumanTask,
|
|
55
59
|
IntegrationAction: () => IntegrationAction,
|
|
56
60
|
Invert: () => Invert,
|
|
57
61
|
KeepRunningUntilFailure: () => KeepRunningUntilFailure,
|
|
62
|
+
LLMChat: () => LLMChat,
|
|
58
63
|
LogMessage: () => LogMessage,
|
|
59
64
|
MemoryDataStore: () => MemoryDataStore,
|
|
60
65
|
MemorySequence: () => MemorySequence,
|
|
@@ -417,6 +422,19 @@ var ActionNode = class extends BaseNode {
|
|
|
417
422
|
});
|
|
418
423
|
const status = await this.executeTick(context);
|
|
419
424
|
this._status = status;
|
|
425
|
+
if (status === "FAILURE" /* FAILURE */ && this._lastError) {
|
|
426
|
+
context.eventEmitter?.emit({
|
|
427
|
+
type: "error" /* ERROR */,
|
|
428
|
+
nodeId: this.id,
|
|
429
|
+
nodeName: this.name,
|
|
430
|
+
nodeType: this.type,
|
|
431
|
+
timestamp: Date.now(),
|
|
432
|
+
data: {
|
|
433
|
+
error: { message: this._lastError },
|
|
434
|
+
blackboard: context.blackboard?.toJSON?.() ?? {}
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
}
|
|
420
438
|
context.eventEmitter?.emit({
|
|
421
439
|
type: "tick_end" /* TICK_END */,
|
|
422
440
|
nodeId: this.id,
|
|
@@ -483,6 +501,19 @@ var ConditionNode = class extends BaseNode {
|
|
|
483
501
|
});
|
|
484
502
|
const status = await this.executeTick(context);
|
|
485
503
|
this._status = status;
|
|
504
|
+
if (status === "FAILURE" /* FAILURE */ && this._lastError) {
|
|
505
|
+
context.eventEmitter?.emit({
|
|
506
|
+
type: "error" /* ERROR */,
|
|
507
|
+
nodeId: this.id,
|
|
508
|
+
nodeName: this.name,
|
|
509
|
+
nodeType: this.type,
|
|
510
|
+
timestamp: Date.now(),
|
|
511
|
+
data: {
|
|
512
|
+
error: { message: this._lastError },
|
|
513
|
+
blackboard: context.blackboard?.toJSON?.() ?? {}
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
}
|
|
486
517
|
context.eventEmitter?.emit({
|
|
487
518
|
type: "tick_end" /* TICK_END */,
|
|
488
519
|
nodeId: this.id,
|
|
@@ -961,9 +992,9 @@ var BehaviorTree = class _BehaviorTree {
|
|
|
961
992
|
*
|
|
962
993
|
* @example
|
|
963
994
|
* ```typescript
|
|
964
|
-
* import { BehaviorTree } from '@
|
|
965
|
-
* import { Sequence } from '@
|
|
966
|
-
* import { PrintAction } from '@
|
|
995
|
+
* import { BehaviorTree } from '@q1k-oss/behaviour-tree-workflows';
|
|
996
|
+
* import { Sequence } from '@q1k-oss/behaviour-tree-workflows';
|
|
997
|
+
* import { PrintAction } from '@q1k-oss/behaviour-tree-workflows';
|
|
967
998
|
*
|
|
968
999
|
* const root = new Sequence({ id: 'root' });
|
|
969
1000
|
* root.addChild(new PrintAction({ id: 'step1', message: 'Hello' }));
|
|
@@ -2545,8 +2576,63 @@ var memorySequenceConfigurationSchema = nodeConfigurationSchema;
|
|
|
2545
2576
|
// src/composites/recovery.schema.ts
|
|
2546
2577
|
var recoveryConfigurationSchema = nodeConfigurationSchema;
|
|
2547
2578
|
|
|
2548
|
-
// src/
|
|
2579
|
+
// src/actions/llm-chat.schema.ts
|
|
2549
2580
|
var import_zod3 = require("zod");
|
|
2581
|
+
var messageSchema = import_zod3.z.object({
|
|
2582
|
+
role: import_zod3.z.enum(["system", "user", "assistant"]),
|
|
2583
|
+
content: import_zod3.z.string().min(1, "Message content cannot be empty")
|
|
2584
|
+
});
|
|
2585
|
+
var llmChatSchema = createNodeSchema("LLMChat", {
|
|
2586
|
+
provider: import_zod3.z.enum(["anthropic", "openai", "google", "ollama"]),
|
|
2587
|
+
model: import_zod3.z.string().min(1, "Model is required"),
|
|
2588
|
+
messages: import_zod3.z.array(messageSchema).min(1, "At least one message is required"),
|
|
2589
|
+
systemPrompt: import_zod3.z.string().optional(),
|
|
2590
|
+
temperature: import_zod3.z.number().min(0).max(2).optional(),
|
|
2591
|
+
maxTokens: import_zod3.z.number().int().positive().optional(),
|
|
2592
|
+
responseFormat: import_zod3.z.enum(["text", "json"]).optional().default("text"),
|
|
2593
|
+
jsonSchema: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional(),
|
|
2594
|
+
timeout: import_zod3.z.number().int().positive().optional().default(6e4),
|
|
2595
|
+
baseUrl: import_zod3.z.string().url().optional(),
|
|
2596
|
+
outputKey: import_zod3.z.string().min(1, "outputKey is required")
|
|
2597
|
+
});
|
|
2598
|
+
|
|
2599
|
+
// src/actions/browser-agent.schema.ts
|
|
2600
|
+
var import_zod4 = require("zod");
|
|
2601
|
+
var browserAgentSchema = createNodeSchema("BrowserAgent", {
|
|
2602
|
+
goal: import_zod4.z.string().min(1, "Goal is required"),
|
|
2603
|
+
startUrl: import_zod4.z.string().optional(),
|
|
2604
|
+
contextKey: import_zod4.z.string().optional(),
|
|
2605
|
+
persistContext: import_zod4.z.boolean().optional().default(false),
|
|
2606
|
+
timeout: import_zod4.z.number().int().positive().optional().default(6e4),
|
|
2607
|
+
maxSteps: import_zod4.z.number().int().positive().optional().default(20),
|
|
2608
|
+
llmProvider: import_zod4.z.enum(["anthropic", "openai", "google", "ollama"]).optional(),
|
|
2609
|
+
llmModel: import_zod4.z.string().optional(),
|
|
2610
|
+
outputKey: import_zod4.z.string().min(1, "outputKey is required")
|
|
2611
|
+
});
|
|
2612
|
+
|
|
2613
|
+
// src/actions/human-task.schema.ts
|
|
2614
|
+
var import_zod5 = require("zod");
|
|
2615
|
+
var a2uiComponentSchema = import_zod5.z.object({
|
|
2616
|
+
id: import_zod5.z.string().min(1, "Component ID cannot be empty"),
|
|
2617
|
+
component: import_zod5.z.record(import_zod5.z.string(), import_zod5.z.unknown()),
|
|
2618
|
+
weight: import_zod5.z.number().optional()
|
|
2619
|
+
});
|
|
2620
|
+
var humanTaskSchema = createNodeSchema("HumanTask", {
|
|
2621
|
+
title: import_zod5.z.string().min(1, "Title is required"),
|
|
2622
|
+
description: import_zod5.z.string().optional(),
|
|
2623
|
+
assignee: import_zod5.z.string().optional(),
|
|
2624
|
+
assigneeRole: import_zod5.z.string().optional(),
|
|
2625
|
+
a2ui: import_zod5.z.object({
|
|
2626
|
+
components: import_zod5.z.array(a2uiComponentSchema).min(1, "At least one A2UI component is required"),
|
|
2627
|
+
dataBindings: import_zod5.z.record(import_zod5.z.string(), import_zod5.z.string()).optional()
|
|
2628
|
+
}),
|
|
2629
|
+
timeoutMs: import_zod5.z.number().int().positive().optional().default(864e5),
|
|
2630
|
+
onTimeout: import_zod5.z.enum(["expire", "approve", "reject"]).optional().default("expire"),
|
|
2631
|
+
outputKey: import_zod5.z.string().optional()
|
|
2632
|
+
});
|
|
2633
|
+
|
|
2634
|
+
// src/schemas/validation.ts
|
|
2635
|
+
var import_zod6 = require("zod");
|
|
2550
2636
|
function zodErrorToConfigurationError(error, nodeType, nodeId) {
|
|
2551
2637
|
const nodeIdentifier = nodeId ? `${nodeType}:${nodeId}` : nodeType;
|
|
2552
2638
|
const issues = error.issues.map((issue) => {
|
|
@@ -2562,7 +2648,7 @@ function validateConfiguration(schema, config, nodeType, nodeId) {
|
|
|
2562
2648
|
try {
|
|
2563
2649
|
return schema.parse(config);
|
|
2564
2650
|
} catch (error) {
|
|
2565
|
-
if (error instanceof
|
|
2651
|
+
if (error instanceof import_zod6.z.ZodError) {
|
|
2566
2652
|
throw zodErrorToConfigurationError(error, nodeType, nodeId);
|
|
2567
2653
|
}
|
|
2568
2654
|
throw error;
|
|
@@ -2581,14 +2667,14 @@ function safeValidateConfiguration(schema, config, nodeType, nodeId) {
|
|
|
2581
2667
|
}
|
|
2582
2668
|
|
|
2583
2669
|
// src/schemas/tree-definition.schema.ts
|
|
2584
|
-
var
|
|
2585
|
-
var treeDefSchemaObject =
|
|
2586
|
-
type:
|
|
2587
|
-
id:
|
|
2588
|
-
name:
|
|
2589
|
-
props:
|
|
2590
|
-
children:
|
|
2591
|
-
|
|
2670
|
+
var import_zod7 = require("zod");
|
|
2671
|
+
var treeDefSchemaObject = import_zod7.z.object({
|
|
2672
|
+
type: import_zod7.z.string().min(1, "Node type is required"),
|
|
2673
|
+
id: import_zod7.z.string().optional(),
|
|
2674
|
+
name: import_zod7.z.string().optional(),
|
|
2675
|
+
props: import_zod7.z.record(import_zod7.z.string(), import_zod7.z.unknown()).optional(),
|
|
2676
|
+
children: import_zod7.z.array(
|
|
2677
|
+
import_zod7.z.lazy(() => treeDefinitionSchema)
|
|
2592
2678
|
).optional()
|
|
2593
2679
|
});
|
|
2594
2680
|
var treeDefinitionSchema = treeDefSchemaObject;
|
|
@@ -2667,6 +2753,9 @@ var SchemaRegistry = class {
|
|
|
2667
2753
|
this.register("ReactiveSequence", reactiveSequenceConfigurationSchema);
|
|
2668
2754
|
this.register("MemorySequence", memorySequenceConfigurationSchema);
|
|
2669
2755
|
this.register("Recovery", recoveryConfigurationSchema);
|
|
2756
|
+
this.register("LLMChat", llmChatSchema);
|
|
2757
|
+
this.register("BrowserAgent", browserAgentSchema);
|
|
2758
|
+
this.register("HumanTask", humanTaskSchema);
|
|
2670
2759
|
}
|
|
2671
2760
|
/**
|
|
2672
2761
|
* Register a validation schema for a node type
|
|
@@ -4020,6 +4109,481 @@ var CodeExecution = class extends ActionNode {
|
|
|
4020
4109
|
}
|
|
4021
4110
|
};
|
|
4022
4111
|
|
|
4112
|
+
// src/actions/llm-chat.ts
|
|
4113
|
+
var LLMChat = class extends ActionNode {
|
|
4114
|
+
provider;
|
|
4115
|
+
model;
|
|
4116
|
+
messages;
|
|
4117
|
+
systemPrompt;
|
|
4118
|
+
temperature;
|
|
4119
|
+
maxTokens;
|
|
4120
|
+
responseFormat;
|
|
4121
|
+
jsonSchema;
|
|
4122
|
+
timeout;
|
|
4123
|
+
baseUrl;
|
|
4124
|
+
outputKey;
|
|
4125
|
+
constructor(config) {
|
|
4126
|
+
super(config);
|
|
4127
|
+
if (!config.provider) {
|
|
4128
|
+
throw new ConfigurationError("LLMChat requires provider");
|
|
4129
|
+
}
|
|
4130
|
+
if (!config.model) {
|
|
4131
|
+
throw new ConfigurationError("LLMChat requires model");
|
|
4132
|
+
}
|
|
4133
|
+
if (!config.messages || config.messages.length === 0) {
|
|
4134
|
+
throw new ConfigurationError(
|
|
4135
|
+
"LLMChat requires at least one message"
|
|
4136
|
+
);
|
|
4137
|
+
}
|
|
4138
|
+
if (!config.outputKey) {
|
|
4139
|
+
throw new ConfigurationError("LLMChat requires outputKey");
|
|
4140
|
+
}
|
|
4141
|
+
this.provider = config.provider;
|
|
4142
|
+
this.model = config.model;
|
|
4143
|
+
this.messages = config.messages;
|
|
4144
|
+
this.systemPrompt = config.systemPrompt;
|
|
4145
|
+
this.temperature = config.temperature;
|
|
4146
|
+
this.maxTokens = config.maxTokens;
|
|
4147
|
+
this.responseFormat = config.responseFormat || "text";
|
|
4148
|
+
this.jsonSchema = config.jsonSchema;
|
|
4149
|
+
this.timeout = config.timeout;
|
|
4150
|
+
this.baseUrl = config.baseUrl;
|
|
4151
|
+
this.outputKey = config.outputKey;
|
|
4152
|
+
}
|
|
4153
|
+
async executeTick(context) {
|
|
4154
|
+
if (!context.activities?.llmChat) {
|
|
4155
|
+
this._lastError = "LLMChat requires activities.llmChat to be configured. This activity handles LLM API calls outside the workflow sandbox.";
|
|
4156
|
+
this.log(`Error: ${this._lastError}`);
|
|
4157
|
+
return "FAILURE" /* FAILURE */;
|
|
4158
|
+
}
|
|
4159
|
+
try {
|
|
4160
|
+
const varCtx = {
|
|
4161
|
+
blackboard: context.blackboard,
|
|
4162
|
+
input: context.input,
|
|
4163
|
+
testData: context.testData
|
|
4164
|
+
};
|
|
4165
|
+
const resolvedMessages = this.messages.map((msg) => ({
|
|
4166
|
+
role: msg.role,
|
|
4167
|
+
content: resolveValue(msg.content, varCtx)
|
|
4168
|
+
}));
|
|
4169
|
+
const resolvedSystemPrompt = this.systemPrompt ? resolveValue(this.systemPrompt, varCtx) : void 0;
|
|
4170
|
+
const resolvedModel = resolveValue(this.model, varCtx);
|
|
4171
|
+
const request = {
|
|
4172
|
+
provider: this.provider,
|
|
4173
|
+
model: resolvedModel,
|
|
4174
|
+
messages: resolvedMessages,
|
|
4175
|
+
systemPrompt: resolvedSystemPrompt,
|
|
4176
|
+
temperature: this.temperature,
|
|
4177
|
+
maxTokens: this.maxTokens,
|
|
4178
|
+
responseFormat: this.responseFormat,
|
|
4179
|
+
jsonSchema: this.jsonSchema,
|
|
4180
|
+
timeout: this.timeout,
|
|
4181
|
+
baseUrl: this.baseUrl
|
|
4182
|
+
};
|
|
4183
|
+
this.log(
|
|
4184
|
+
`LLM ${this.provider}/${resolvedModel} - ${resolvedMessages.length} messages`
|
|
4185
|
+
);
|
|
4186
|
+
const result = await context.activities.llmChat(request);
|
|
4187
|
+
context.blackboard.set(this.outputKey, result);
|
|
4188
|
+
if (result.finishReason === "error") {
|
|
4189
|
+
this._lastError = `LLM returned error: ${result.content}`;
|
|
4190
|
+
this.log(`Error: ${this._lastError}`);
|
|
4191
|
+
return "FAILURE" /* FAILURE */;
|
|
4192
|
+
}
|
|
4193
|
+
this.log(
|
|
4194
|
+
`LLM ${this.provider}/${resolvedModel} completed: ${result.usage.totalTokens} tokens, finish: ${result.finishReason}`
|
|
4195
|
+
);
|
|
4196
|
+
return "SUCCESS" /* SUCCESS */;
|
|
4197
|
+
} catch (error) {
|
|
4198
|
+
this._lastError = error instanceof Error ? error.message : String(error);
|
|
4199
|
+
this.log(`LLM chat failed: ${this._lastError}`);
|
|
4200
|
+
return "FAILURE" /* FAILURE */;
|
|
4201
|
+
}
|
|
4202
|
+
}
|
|
4203
|
+
};
|
|
4204
|
+
|
|
4205
|
+
// src/actions/browser-agent.ts
|
|
4206
|
+
var BrowserAgent = class extends ActionNode {
|
|
4207
|
+
goal;
|
|
4208
|
+
startUrl;
|
|
4209
|
+
contextKey;
|
|
4210
|
+
persistContext;
|
|
4211
|
+
timeout;
|
|
4212
|
+
maxSteps;
|
|
4213
|
+
llmProvider;
|
|
4214
|
+
llmModel;
|
|
4215
|
+
outputKey;
|
|
4216
|
+
constructor(config) {
|
|
4217
|
+
super(config);
|
|
4218
|
+
if (!config.goal) {
|
|
4219
|
+
throw new ConfigurationError("BrowserAgent requires goal");
|
|
4220
|
+
}
|
|
4221
|
+
if (!config.outputKey) {
|
|
4222
|
+
throw new ConfigurationError("BrowserAgent requires outputKey");
|
|
4223
|
+
}
|
|
4224
|
+
this.goal = config.goal;
|
|
4225
|
+
this.startUrl = config.startUrl;
|
|
4226
|
+
this.contextKey = config.contextKey;
|
|
4227
|
+
this.persistContext = config.persistContext ?? false;
|
|
4228
|
+
this.timeout = config.timeout;
|
|
4229
|
+
this.maxSteps = config.maxSteps;
|
|
4230
|
+
this.llmProvider = config.llmProvider;
|
|
4231
|
+
this.llmModel = config.llmModel;
|
|
4232
|
+
this.outputKey = config.outputKey;
|
|
4233
|
+
}
|
|
4234
|
+
async executeTick(context) {
|
|
4235
|
+
if (!context.activities?.browserAgent) {
|
|
4236
|
+
this._lastError = "BrowserAgent requires activities.browserAgent to be configured. This activity handles browser automation via Browserbase + Stagehand.";
|
|
4237
|
+
this.log(`Error: ${this._lastError}`);
|
|
4238
|
+
return "FAILURE" /* FAILURE */;
|
|
4239
|
+
}
|
|
4240
|
+
try {
|
|
4241
|
+
const varCtx = {
|
|
4242
|
+
blackboard: context.blackboard,
|
|
4243
|
+
input: context.input,
|
|
4244
|
+
testData: context.testData
|
|
4245
|
+
};
|
|
4246
|
+
const resolvedGoal = resolveValue(this.goal, varCtx);
|
|
4247
|
+
const resolvedStartUrl = this.startUrl ? resolveValue(this.startUrl, varCtx) : void 0;
|
|
4248
|
+
const contextId = this.contextKey ? context.blackboard.get(this.contextKey) : void 0;
|
|
4249
|
+
const request = {
|
|
4250
|
+
goal: resolvedGoal,
|
|
4251
|
+
startUrl: resolvedStartUrl,
|
|
4252
|
+
contextId,
|
|
4253
|
+
persistContext: this.persistContext,
|
|
4254
|
+
timeout: this.timeout,
|
|
4255
|
+
maxSteps: this.maxSteps,
|
|
4256
|
+
llmProvider: this.llmProvider,
|
|
4257
|
+
llmModel: this.llmModel
|
|
4258
|
+
};
|
|
4259
|
+
this.log(
|
|
4260
|
+
`Browser agent: ${resolvedGoal.substring(0, 50)}${resolvedGoal.length > 50 ? "..." : ""}`
|
|
4261
|
+
);
|
|
4262
|
+
const result = await context.activities.browserAgent(request);
|
|
4263
|
+
if (this.contextKey && result.contextId) {
|
|
4264
|
+
context.blackboard.set(this.contextKey, result.contextId);
|
|
4265
|
+
}
|
|
4266
|
+
context.blackboard.set(this.outputKey, result);
|
|
4267
|
+
if (!result.success) {
|
|
4268
|
+
this._lastError = `Browser agent failed to achieve goal: ${result.message}`;
|
|
4269
|
+
this.log(`Error: ${this._lastError}`);
|
|
4270
|
+
this.log(`Debug session: ${result.debugUrl}`);
|
|
4271
|
+
return "FAILURE" /* FAILURE */;
|
|
4272
|
+
}
|
|
4273
|
+
if (!result.completed) {
|
|
4274
|
+
this._lastError = `Browser agent hit step limit before completing: ${result.message}`;
|
|
4275
|
+
this.log(`Error: ${this._lastError}`);
|
|
4276
|
+
this.log(`Debug session: ${result.debugUrl}`);
|
|
4277
|
+
return "FAILURE" /* FAILURE */;
|
|
4278
|
+
}
|
|
4279
|
+
this.log(`Browser agent succeeded: ${result.message}`);
|
|
4280
|
+
this.log(`Debug session: ${result.debugUrl}`);
|
|
4281
|
+
return "SUCCESS" /* SUCCESS */;
|
|
4282
|
+
} catch (error) {
|
|
4283
|
+
this._lastError = error instanceof Error ? error.message : String(error);
|
|
4284
|
+
this.log(`Browser agent failed: ${this._lastError}`);
|
|
4285
|
+
return "FAILURE" /* FAILURE */;
|
|
4286
|
+
}
|
|
4287
|
+
}
|
|
4288
|
+
};
|
|
4289
|
+
|
|
4290
|
+
// src/actions/claude-agent.ts
|
|
4291
|
+
var ClaudeAgent = class extends ActionNode {
|
|
4292
|
+
prompt;
|
|
4293
|
+
model;
|
|
4294
|
+
systemPrompt;
|
|
4295
|
+
allowedTools;
|
|
4296
|
+
permissionMode;
|
|
4297
|
+
maxTurns;
|
|
4298
|
+
maxBudgetUsd;
|
|
4299
|
+
agentCwd;
|
|
4300
|
+
mcpServers;
|
|
4301
|
+
agents;
|
|
4302
|
+
outputKey;
|
|
4303
|
+
constructor(config) {
|
|
4304
|
+
super(config);
|
|
4305
|
+
if (!config.prompt) {
|
|
4306
|
+
throw new ConfigurationError("ClaudeAgent requires prompt");
|
|
4307
|
+
}
|
|
4308
|
+
if (!config.outputKey) {
|
|
4309
|
+
throw new ConfigurationError("ClaudeAgent requires outputKey");
|
|
4310
|
+
}
|
|
4311
|
+
this.prompt = config.prompt;
|
|
4312
|
+
this.model = config.model;
|
|
4313
|
+
this.systemPrompt = config.systemPrompt;
|
|
4314
|
+
this.allowedTools = config.allowedTools;
|
|
4315
|
+
this.permissionMode = config.permissionMode ?? "default";
|
|
4316
|
+
this.maxTurns = config.maxTurns ?? 50;
|
|
4317
|
+
this.maxBudgetUsd = config.maxBudgetUsd;
|
|
4318
|
+
this.agentCwd = config.cwd;
|
|
4319
|
+
this.mcpServers = config.mcpServers;
|
|
4320
|
+
this.agents = config.agents;
|
|
4321
|
+
this.outputKey = config.outputKey;
|
|
4322
|
+
}
|
|
4323
|
+
async executeTick(context) {
|
|
4324
|
+
if (!context.activities?.claudeAgent) {
|
|
4325
|
+
this._lastError = "ClaudeAgent requires activities.claudeAgent to be configured. This activity handles autonomous agent execution via the Claude Agent SDK.";
|
|
4326
|
+
this.log(`Error: ${this._lastError}`);
|
|
4327
|
+
return "FAILURE" /* FAILURE */;
|
|
4328
|
+
}
|
|
4329
|
+
try {
|
|
4330
|
+
const varCtx = {
|
|
4331
|
+
blackboard: context.blackboard,
|
|
4332
|
+
input: context.input,
|
|
4333
|
+
testData: context.testData
|
|
4334
|
+
};
|
|
4335
|
+
const resolvedPrompt = resolveValue(this.prompt, varCtx);
|
|
4336
|
+
const resolvedSystemPrompt = this.systemPrompt ? resolveValue(this.systemPrompt, varCtx) : void 0;
|
|
4337
|
+
const resolvedModel = this.model ? resolveValue(this.model, varCtx) : void 0;
|
|
4338
|
+
const resolvedCwd = this.agentCwd ? resolveValue(this.agentCwd, varCtx) : void 0;
|
|
4339
|
+
const request = {
|
|
4340
|
+
prompt: resolvedPrompt,
|
|
4341
|
+
model: resolvedModel,
|
|
4342
|
+
systemPrompt: resolvedSystemPrompt,
|
|
4343
|
+
allowedTools: this.allowedTools,
|
|
4344
|
+
permissionMode: this.permissionMode,
|
|
4345
|
+
maxTurns: this.maxTurns,
|
|
4346
|
+
maxBudgetUsd: this.maxBudgetUsd,
|
|
4347
|
+
cwd: resolvedCwd,
|
|
4348
|
+
mcpServers: this.mcpServers,
|
|
4349
|
+
agents: this.agents
|
|
4350
|
+
};
|
|
4351
|
+
this.log(
|
|
4352
|
+
`Claude agent: ${resolvedPrompt.substring(0, 80)}${resolvedPrompt.length > 80 ? "..." : ""}`
|
|
4353
|
+
);
|
|
4354
|
+
const result = await context.activities.claudeAgent(request);
|
|
4355
|
+
context.blackboard.set(this.outputKey, result);
|
|
4356
|
+
if (!result.success) {
|
|
4357
|
+
this._lastError = `Claude agent failed: ${result.errors?.join(", ") || "unknown error"}`;
|
|
4358
|
+
this.log(`Error: ${this._lastError}`);
|
|
4359
|
+
return "FAILURE" /* FAILURE */;
|
|
4360
|
+
}
|
|
4361
|
+
this.log(
|
|
4362
|
+
`Claude agent completed in ${result.numTurns} turns, $${result.totalCostUsd.toFixed(4)}, ${result.durationMs}ms`
|
|
4363
|
+
);
|
|
4364
|
+
return "SUCCESS" /* SUCCESS */;
|
|
4365
|
+
} catch (error) {
|
|
4366
|
+
this._lastError = error instanceof Error ? error.message : String(error);
|
|
4367
|
+
this.log(`Claude agent failed: ${this._lastError}`);
|
|
4368
|
+
return "FAILURE" /* FAILURE */;
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
};
|
|
4372
|
+
|
|
4373
|
+
// src/actions/github-action.ts
|
|
4374
|
+
var VALID_OPERATIONS = [
|
|
4375
|
+
"createBranch",
|
|
4376
|
+
"createPullRequest",
|
|
4377
|
+
"getPullRequest",
|
|
4378
|
+
"mergePullRequest",
|
|
4379
|
+
"closePullRequest",
|
|
4380
|
+
"createReview",
|
|
4381
|
+
"listIssues",
|
|
4382
|
+
"addLabels",
|
|
4383
|
+
"createComment",
|
|
4384
|
+
"createRelease"
|
|
4385
|
+
];
|
|
4386
|
+
var GitHubAction = class extends ActionNode {
|
|
4387
|
+
operation;
|
|
4388
|
+
repo;
|
|
4389
|
+
params;
|
|
4390
|
+
outputKey;
|
|
4391
|
+
constructor(config) {
|
|
4392
|
+
super(config);
|
|
4393
|
+
if (!config.operation) {
|
|
4394
|
+
throw new ConfigurationError("GitHubAction requires operation");
|
|
4395
|
+
}
|
|
4396
|
+
if (!VALID_OPERATIONS.includes(config.operation)) {
|
|
4397
|
+
throw new ConfigurationError(
|
|
4398
|
+
`GitHubAction: invalid operation "${config.operation}". Valid operations: ${VALID_OPERATIONS.join(", ")}`
|
|
4399
|
+
);
|
|
4400
|
+
}
|
|
4401
|
+
if (!config.repo) {
|
|
4402
|
+
throw new ConfigurationError("GitHubAction requires repo");
|
|
4403
|
+
}
|
|
4404
|
+
if (!config.outputKey) {
|
|
4405
|
+
throw new ConfigurationError("GitHubAction requires outputKey");
|
|
4406
|
+
}
|
|
4407
|
+
this.operation = config.operation;
|
|
4408
|
+
this.repo = config.repo;
|
|
4409
|
+
this.params = config.params ?? {};
|
|
4410
|
+
this.outputKey = config.outputKey;
|
|
4411
|
+
}
|
|
4412
|
+
async executeTick(context) {
|
|
4413
|
+
if (!context.activities?.githubAction) {
|
|
4414
|
+
this._lastError = "GitHubAction requires activities.githubAction to be configured. This activity handles GitHub API operations.";
|
|
4415
|
+
this.log(`Error: ${this._lastError}`);
|
|
4416
|
+
return "FAILURE" /* FAILURE */;
|
|
4417
|
+
}
|
|
4418
|
+
try {
|
|
4419
|
+
const varCtx = {
|
|
4420
|
+
blackboard: context.blackboard,
|
|
4421
|
+
input: context.input,
|
|
4422
|
+
testData: context.testData
|
|
4423
|
+
};
|
|
4424
|
+
const resolvedRepo = resolveValue(this.repo, varCtx);
|
|
4425
|
+
const resolvedParams = {};
|
|
4426
|
+
for (const [key, value] of Object.entries(this.params)) {
|
|
4427
|
+
if (typeof value === "string") {
|
|
4428
|
+
resolvedParams[key] = resolveValue(value, varCtx);
|
|
4429
|
+
} else {
|
|
4430
|
+
resolvedParams[key] = value;
|
|
4431
|
+
}
|
|
4432
|
+
}
|
|
4433
|
+
const request = {
|
|
4434
|
+
operation: this.operation,
|
|
4435
|
+
repo: resolvedRepo,
|
|
4436
|
+
params: resolvedParams
|
|
4437
|
+
};
|
|
4438
|
+
this.log(
|
|
4439
|
+
`GitHub ${this.operation}: ${resolvedRepo}`
|
|
4440
|
+
);
|
|
4441
|
+
const result = await context.activities.githubAction(request);
|
|
4442
|
+
context.blackboard.set(this.outputKey, result.data);
|
|
4443
|
+
if (!result.success) {
|
|
4444
|
+
this._lastError = `GitHub ${this.operation} failed`;
|
|
4445
|
+
this.log(`Error: ${this._lastError}`);
|
|
4446
|
+
return "FAILURE" /* FAILURE */;
|
|
4447
|
+
}
|
|
4448
|
+
this.log(`GitHub ${this.operation} completed successfully`);
|
|
4449
|
+
return "SUCCESS" /* SUCCESS */;
|
|
4450
|
+
} catch (error) {
|
|
4451
|
+
this._lastError = error instanceof Error ? error.message : String(error);
|
|
4452
|
+
this.log(`GitHub ${this.operation} failed: ${this._lastError}`);
|
|
4453
|
+
return "FAILURE" /* FAILURE */;
|
|
4454
|
+
}
|
|
4455
|
+
}
|
|
4456
|
+
};
|
|
4457
|
+
|
|
4458
|
+
// src/actions/human-task.ts
|
|
4459
|
+
var HumanTask = class extends ActionNode {
|
|
4460
|
+
title;
|
|
4461
|
+
description;
|
|
4462
|
+
assignee;
|
|
4463
|
+
assigneeRole;
|
|
4464
|
+
a2ui;
|
|
4465
|
+
timeoutMs;
|
|
4466
|
+
onTimeout;
|
|
4467
|
+
outputKey;
|
|
4468
|
+
constructor(config) {
|
|
4469
|
+
super(config);
|
|
4470
|
+
if (!config.title) {
|
|
4471
|
+
throw new ConfigurationError("HumanTask requires title");
|
|
4472
|
+
}
|
|
4473
|
+
if (!config.a2ui?.components || config.a2ui.components.length === 0) {
|
|
4474
|
+
throw new ConfigurationError(
|
|
4475
|
+
"HumanTask requires a2ui.components with at least one component"
|
|
4476
|
+
);
|
|
4477
|
+
}
|
|
4478
|
+
this.title = config.title;
|
|
4479
|
+
this.description = config.description;
|
|
4480
|
+
this.assignee = config.assignee;
|
|
4481
|
+
this.assigneeRole = config.assigneeRole;
|
|
4482
|
+
this.a2ui = config.a2ui;
|
|
4483
|
+
this.timeoutMs = config.timeoutMs ?? 864e5;
|
|
4484
|
+
this.onTimeout = config.onTimeout ?? "expire";
|
|
4485
|
+
this.outputKey = config.outputKey;
|
|
4486
|
+
}
|
|
4487
|
+
async executeTick(context) {
|
|
4488
|
+
if (!context.activities?.createHumanTask) {
|
|
4489
|
+
this._lastError = "HumanTask requires activities.createHumanTask to be configured. This activity creates a task record in the database.";
|
|
4490
|
+
this.log(`Error: ${this._lastError}`);
|
|
4491
|
+
return "FAILURE" /* FAILURE */;
|
|
4492
|
+
}
|
|
4493
|
+
if (!context.activities?.waitForHumanTask) {
|
|
4494
|
+
this._lastError = "HumanTask requires activities.waitForHumanTask to be configured. This activity waits for the user to complete the task.";
|
|
4495
|
+
this.log(`Error: ${this._lastError}`);
|
|
4496
|
+
return "FAILURE" /* FAILURE */;
|
|
4497
|
+
}
|
|
4498
|
+
try {
|
|
4499
|
+
const varCtx = {
|
|
4500
|
+
blackboard: context.blackboard,
|
|
4501
|
+
input: context.input,
|
|
4502
|
+
testData: context.testData
|
|
4503
|
+
};
|
|
4504
|
+
const a2uiDataModel = {};
|
|
4505
|
+
if (this.a2ui.dataBindings) {
|
|
4506
|
+
for (const [a2uiPath, expression] of Object.entries(
|
|
4507
|
+
this.a2ui.dataBindings
|
|
4508
|
+
)) {
|
|
4509
|
+
const resolved = resolveValue(expression, varCtx);
|
|
4510
|
+
setNestedPath(a2uiDataModel, a2uiPath, resolved);
|
|
4511
|
+
}
|
|
4512
|
+
}
|
|
4513
|
+
const resolvedTitle = resolveValue(this.title, varCtx);
|
|
4514
|
+
const resolvedDescription = this.description ? resolveValue(this.description, varCtx) : void 0;
|
|
4515
|
+
const resolvedAssignee = this.assignee ? resolveValue(this.assignee, varCtx) : void 0;
|
|
4516
|
+
const tenantId = context.blackboard.get("__tenantId") || "";
|
|
4517
|
+
const executionId = context.blackboard.get("__executionId") || context.workflowInfo?.workflowId || "";
|
|
4518
|
+
const request = {
|
|
4519
|
+
nodeId: this.id,
|
|
4520
|
+
tenantId,
|
|
4521
|
+
executionId,
|
|
4522
|
+
title: resolvedTitle,
|
|
4523
|
+
description: resolvedDescription,
|
|
4524
|
+
assigneeEmail: resolvedAssignee,
|
|
4525
|
+
assigneeRole: this.assigneeRole,
|
|
4526
|
+
a2uiComponents: this.a2ui.components,
|
|
4527
|
+
a2uiDataModel,
|
|
4528
|
+
timeoutMs: this.timeoutMs,
|
|
4529
|
+
onTimeout: this.onTimeout
|
|
4530
|
+
};
|
|
4531
|
+
this.log(
|
|
4532
|
+
`Creating human task: "${resolvedTitle}" (timeout: ${this.timeoutMs}ms)`
|
|
4533
|
+
);
|
|
4534
|
+
const createResult = await context.activities.createHumanTask(request);
|
|
4535
|
+
this.log(`Task created: ${createResult.taskId}`);
|
|
4536
|
+
this.log(
|
|
4537
|
+
`Waiting for human task ${createResult.taskId} on node ${this.id}`
|
|
4538
|
+
);
|
|
4539
|
+
const waitResult = await context.activities.waitForHumanTask({
|
|
4540
|
+
taskId: createResult.taskId,
|
|
4541
|
+
nodeId: this.id,
|
|
4542
|
+
timeoutMs: this.timeoutMs,
|
|
4543
|
+
onTimeout: this.onTimeout
|
|
4544
|
+
});
|
|
4545
|
+
const prefix = this.outputKey || this.id;
|
|
4546
|
+
context.blackboard.set(`${prefix}.taskId`, createResult.taskId);
|
|
4547
|
+
context.blackboard.set(`${prefix}.completed`, waitResult.completed);
|
|
4548
|
+
context.blackboard.set(`${prefix}.decision`, waitResult.decision);
|
|
4549
|
+
context.blackboard.set(
|
|
4550
|
+
`${prefix}.submittedData`,
|
|
4551
|
+
waitResult.submittedData
|
|
4552
|
+
);
|
|
4553
|
+
context.blackboard.set(`${prefix}.completedBy`, waitResult.completedBy);
|
|
4554
|
+
context.blackboard.set(`${prefix}.timedOut`, waitResult.timedOut);
|
|
4555
|
+
if (waitResult.timedOut) {
|
|
4556
|
+
this._lastError = `Task timed out after ${this.timeoutMs}ms`;
|
|
4557
|
+
this.log(`Task timed out, onTimeout=${this.onTimeout}`);
|
|
4558
|
+
return this.onTimeout === "approve" ? "SUCCESS" /* SUCCESS */ : "FAILURE" /* FAILURE */;
|
|
4559
|
+
}
|
|
4560
|
+
this.log(
|
|
4561
|
+
`Task completed: decision=${waitResult.decision}, completedBy=${waitResult.completedBy}`
|
|
4562
|
+
);
|
|
4563
|
+
return waitResult.completed ? "SUCCESS" /* SUCCESS */ : "FAILURE" /* FAILURE */;
|
|
4564
|
+
} catch (error) {
|
|
4565
|
+
this._lastError = error instanceof Error ? error.message : String(error);
|
|
4566
|
+
this.log(`HumanTask failed: ${this._lastError}`);
|
|
4567
|
+
return "FAILURE" /* FAILURE */;
|
|
4568
|
+
}
|
|
4569
|
+
}
|
|
4570
|
+
};
|
|
4571
|
+
function setNestedPath(obj, path2, value) {
|
|
4572
|
+
const parts = path2.split("/").filter(Boolean);
|
|
4573
|
+
let current = obj;
|
|
4574
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
4575
|
+
const key = parts[i];
|
|
4576
|
+
if (!(key in current) || typeof current[key] !== "object") {
|
|
4577
|
+
current[key] = {};
|
|
4578
|
+
}
|
|
4579
|
+
current = current[key];
|
|
4580
|
+
}
|
|
4581
|
+
if (parts.length > 0) {
|
|
4582
|
+
const lastKey = parts[parts.length - 1];
|
|
4583
|
+
current[lastKey] = value;
|
|
4584
|
+
}
|
|
4585
|
+
}
|
|
4586
|
+
|
|
4023
4587
|
// src/registry-utils.ts
|
|
4024
4588
|
function registerStandardNodes(registry) {
|
|
4025
4589
|
registry.register("Sequence", Sequence, { category: "composite" });
|
|
@@ -4079,6 +4643,11 @@ function registerStandardNodes(registry) {
|
|
|
4079
4643
|
registry.register("GenerateFile", GenerateFile, { category: "action" });
|
|
4080
4644
|
registry.register("HttpRequest", HttpRequest, { category: "action" });
|
|
4081
4645
|
registry.register("CodeExecution", CodeExecution, { category: "action" });
|
|
4646
|
+
registry.register("LLMChat", LLMChat, { category: "action" });
|
|
4647
|
+
registry.register("BrowserAgent", BrowserAgent, { category: "action" });
|
|
4648
|
+
registry.register("ClaudeAgent", ClaudeAgent, { category: "action" });
|
|
4649
|
+
registry.register("GitHubAction", GitHubAction, { category: "action" });
|
|
4650
|
+
registry.register("HumanTask", HumanTask, { category: "action" });
|
|
4082
4651
|
}
|
|
4083
4652
|
|
|
4084
4653
|
// src/data-store/memory-store.ts
|
|
@@ -4916,7 +5485,9 @@ function createObservabilitySinkHandler(config = {}) {
|
|
|
4916
5485
|
AlwaysCondition,
|
|
4917
5486
|
BaseNode,
|
|
4918
5487
|
BehaviorTree,
|
|
5488
|
+
BrowserAgent,
|
|
4919
5489
|
CheckCondition,
|
|
5490
|
+
ClaudeAgent,
|
|
4920
5491
|
CodeExecution,
|
|
4921
5492
|
CompositeNode,
|
|
4922
5493
|
ConditionNode,
|
|
@@ -4933,10 +5504,13 @@ function createObservabilitySinkHandler(config = {}) {
|
|
|
4933
5504
|
ForceFailure,
|
|
4934
5505
|
ForceSuccess,
|
|
4935
5506
|
GenerateFile,
|
|
5507
|
+
GitHubAction,
|
|
4936
5508
|
HttpRequest,
|
|
5509
|
+
HumanTask,
|
|
4937
5510
|
IntegrationAction,
|
|
4938
5511
|
Invert,
|
|
4939
5512
|
KeepRunningUntilFailure,
|
|
5513
|
+
LLMChat,
|
|
4940
5514
|
LogMessage,
|
|
4941
5515
|
MemoryDataStore,
|
|
4942
5516
|
MemorySequence,
|