@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 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 '@wayfarer-ai/btree';
965
- * import { Sequence } from '@wayfarer-ai/btree';
966
- * import { PrintAction } from '@wayfarer-ai/btree';
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/schemas/validation.ts
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 import_zod3.z.ZodError) {
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 import_zod4 = require("zod");
2585
- var treeDefSchemaObject = import_zod4.z.object({
2586
- type: import_zod4.z.string().min(1, "Node type is required"),
2587
- id: import_zod4.z.string().optional(),
2588
- name: import_zod4.z.string().optional(),
2589
- props: import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()).optional(),
2590
- children: import_zod4.z.array(
2591
- import_zod4.z.lazy(() => treeDefinitionSchema)
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,