@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.js CHANGED
@@ -286,6 +286,19 @@ var ActionNode = class extends BaseNode {
286
286
  });
287
287
  const status = await this.executeTick(context);
288
288
  this._status = status;
289
+ if (status === "FAILURE" /* FAILURE */ && this._lastError) {
290
+ context.eventEmitter?.emit({
291
+ type: "error" /* ERROR */,
292
+ nodeId: this.id,
293
+ nodeName: this.name,
294
+ nodeType: this.type,
295
+ timestamp: Date.now(),
296
+ data: {
297
+ error: { message: this._lastError },
298
+ blackboard: context.blackboard?.toJSON?.() ?? {}
299
+ }
300
+ });
301
+ }
289
302
  context.eventEmitter?.emit({
290
303
  type: "tick_end" /* TICK_END */,
291
304
  nodeId: this.id,
@@ -352,6 +365,19 @@ var ConditionNode = class extends BaseNode {
352
365
  });
353
366
  const status = await this.executeTick(context);
354
367
  this._status = status;
368
+ if (status === "FAILURE" /* FAILURE */ && this._lastError) {
369
+ context.eventEmitter?.emit({
370
+ type: "error" /* ERROR */,
371
+ nodeId: this.id,
372
+ nodeName: this.name,
373
+ nodeType: this.type,
374
+ timestamp: Date.now(),
375
+ data: {
376
+ error: { message: this._lastError },
377
+ blackboard: context.blackboard?.toJSON?.() ?? {}
378
+ }
379
+ });
380
+ }
355
381
  context.eventEmitter?.emit({
356
382
  type: "tick_end" /* TICK_END */,
357
383
  nodeId: this.id,
@@ -830,9 +856,9 @@ var BehaviorTree = class _BehaviorTree {
830
856
  *
831
857
  * @example
832
858
  * ```typescript
833
- * import { BehaviorTree } from '@wayfarer-ai/btree';
834
- * import { Sequence } from '@wayfarer-ai/btree';
835
- * import { PrintAction } from '@wayfarer-ai/btree';
859
+ * import { BehaviorTree } from '@q1k-oss/behaviour-tree-workflows';
860
+ * import { Sequence } from '@q1k-oss/behaviour-tree-workflows';
861
+ * import { PrintAction } from '@q1k-oss/behaviour-tree-workflows';
836
862
  *
837
863
  * const root = new Sequence({ id: 'root' });
838
864
  * root.addChild(new PrintAction({ id: 'step1', message: 'Hello' }));
@@ -2414,8 +2440,63 @@ var memorySequenceConfigurationSchema = nodeConfigurationSchema;
2414
2440
  // src/composites/recovery.schema.ts
2415
2441
  var recoveryConfigurationSchema = nodeConfigurationSchema;
2416
2442
 
2417
- // src/schemas/validation.ts
2443
+ // src/actions/llm-chat.schema.ts
2418
2444
  import { z as z3 } from "zod";
2445
+ var messageSchema = z3.object({
2446
+ role: z3.enum(["system", "user", "assistant"]),
2447
+ content: z3.string().min(1, "Message content cannot be empty")
2448
+ });
2449
+ var llmChatSchema = createNodeSchema("LLMChat", {
2450
+ provider: z3.enum(["anthropic", "openai", "google", "ollama"]),
2451
+ model: z3.string().min(1, "Model is required"),
2452
+ messages: z3.array(messageSchema).min(1, "At least one message is required"),
2453
+ systemPrompt: z3.string().optional(),
2454
+ temperature: z3.number().min(0).max(2).optional(),
2455
+ maxTokens: z3.number().int().positive().optional(),
2456
+ responseFormat: z3.enum(["text", "json"]).optional().default("text"),
2457
+ jsonSchema: z3.record(z3.string(), z3.unknown()).optional(),
2458
+ timeout: z3.number().int().positive().optional().default(6e4),
2459
+ baseUrl: z3.string().url().optional(),
2460
+ outputKey: z3.string().min(1, "outputKey is required")
2461
+ });
2462
+
2463
+ // src/actions/browser-agent.schema.ts
2464
+ import { z as z4 } from "zod";
2465
+ var browserAgentSchema = createNodeSchema("BrowserAgent", {
2466
+ goal: z4.string().min(1, "Goal is required"),
2467
+ startUrl: z4.string().optional(),
2468
+ contextKey: z4.string().optional(),
2469
+ persistContext: z4.boolean().optional().default(false),
2470
+ timeout: z4.number().int().positive().optional().default(6e4),
2471
+ maxSteps: z4.number().int().positive().optional().default(20),
2472
+ llmProvider: z4.enum(["anthropic", "openai", "google", "ollama"]).optional(),
2473
+ llmModel: z4.string().optional(),
2474
+ outputKey: z4.string().min(1, "outputKey is required")
2475
+ });
2476
+
2477
+ // src/actions/human-task.schema.ts
2478
+ import { z as z5 } from "zod";
2479
+ var a2uiComponentSchema = z5.object({
2480
+ id: z5.string().min(1, "Component ID cannot be empty"),
2481
+ component: z5.record(z5.string(), z5.unknown()),
2482
+ weight: z5.number().optional()
2483
+ });
2484
+ var humanTaskSchema = createNodeSchema("HumanTask", {
2485
+ title: z5.string().min(1, "Title is required"),
2486
+ description: z5.string().optional(),
2487
+ assignee: z5.string().optional(),
2488
+ assigneeRole: z5.string().optional(),
2489
+ a2ui: z5.object({
2490
+ components: z5.array(a2uiComponentSchema).min(1, "At least one A2UI component is required"),
2491
+ dataBindings: z5.record(z5.string(), z5.string()).optional()
2492
+ }),
2493
+ timeoutMs: z5.number().int().positive().optional().default(864e5),
2494
+ onTimeout: z5.enum(["expire", "approve", "reject"]).optional().default("expire"),
2495
+ outputKey: z5.string().optional()
2496
+ });
2497
+
2498
+ // src/schemas/validation.ts
2499
+ import { z as z6 } from "zod";
2419
2500
  function zodErrorToConfigurationError(error, nodeType, nodeId) {
2420
2501
  const nodeIdentifier = nodeId ? `${nodeType}:${nodeId}` : nodeType;
2421
2502
  const issues = error.issues.map((issue) => {
@@ -2431,7 +2512,7 @@ function validateConfiguration(schema, config, nodeType, nodeId) {
2431
2512
  try {
2432
2513
  return schema.parse(config);
2433
2514
  } catch (error) {
2434
- if (error instanceof z3.ZodError) {
2515
+ if (error instanceof z6.ZodError) {
2435
2516
  throw zodErrorToConfigurationError(error, nodeType, nodeId);
2436
2517
  }
2437
2518
  throw error;
@@ -2450,14 +2531,14 @@ function safeValidateConfiguration(schema, config, nodeType, nodeId) {
2450
2531
  }
2451
2532
 
2452
2533
  // src/schemas/tree-definition.schema.ts
2453
- import { z as z4 } from "zod";
2454
- var treeDefSchemaObject = z4.object({
2455
- type: z4.string().min(1, "Node type is required"),
2456
- id: z4.string().optional(),
2457
- name: z4.string().optional(),
2458
- props: z4.record(z4.string(), z4.unknown()).optional(),
2459
- children: z4.array(
2460
- z4.lazy(() => treeDefinitionSchema)
2534
+ import { z as z7 } from "zod";
2535
+ var treeDefSchemaObject = z7.object({
2536
+ type: z7.string().min(1, "Node type is required"),
2537
+ id: z7.string().optional(),
2538
+ name: z7.string().optional(),
2539
+ props: z7.record(z7.string(), z7.unknown()).optional(),
2540
+ children: z7.array(
2541
+ z7.lazy(() => treeDefinitionSchema)
2461
2542
  ).optional()
2462
2543
  });
2463
2544
  var treeDefinitionSchema = treeDefSchemaObject;
@@ -2536,6 +2617,9 @@ var SchemaRegistry = class {
2536
2617
  this.register("ReactiveSequence", reactiveSequenceConfigurationSchema);
2537
2618
  this.register("MemorySequence", memorySequenceConfigurationSchema);
2538
2619
  this.register("Recovery", recoveryConfigurationSchema);
2620
+ this.register("LLMChat", llmChatSchema);
2621
+ this.register("BrowserAgent", browserAgentSchema);
2622
+ this.register("HumanTask", humanTaskSchema);
2539
2623
  }
2540
2624
  /**
2541
2625
  * Register a validation schema for a node type
@@ -3889,6 +3973,481 @@ var CodeExecution = class extends ActionNode {
3889
3973
  }
3890
3974
  };
3891
3975
 
3976
+ // src/actions/llm-chat.ts
3977
+ var LLMChat = class extends ActionNode {
3978
+ provider;
3979
+ model;
3980
+ messages;
3981
+ systemPrompt;
3982
+ temperature;
3983
+ maxTokens;
3984
+ responseFormat;
3985
+ jsonSchema;
3986
+ timeout;
3987
+ baseUrl;
3988
+ outputKey;
3989
+ constructor(config) {
3990
+ super(config);
3991
+ if (!config.provider) {
3992
+ throw new ConfigurationError("LLMChat requires provider");
3993
+ }
3994
+ if (!config.model) {
3995
+ throw new ConfigurationError("LLMChat requires model");
3996
+ }
3997
+ if (!config.messages || config.messages.length === 0) {
3998
+ throw new ConfigurationError(
3999
+ "LLMChat requires at least one message"
4000
+ );
4001
+ }
4002
+ if (!config.outputKey) {
4003
+ throw new ConfigurationError("LLMChat requires outputKey");
4004
+ }
4005
+ this.provider = config.provider;
4006
+ this.model = config.model;
4007
+ this.messages = config.messages;
4008
+ this.systemPrompt = config.systemPrompt;
4009
+ this.temperature = config.temperature;
4010
+ this.maxTokens = config.maxTokens;
4011
+ this.responseFormat = config.responseFormat || "text";
4012
+ this.jsonSchema = config.jsonSchema;
4013
+ this.timeout = config.timeout;
4014
+ this.baseUrl = config.baseUrl;
4015
+ this.outputKey = config.outputKey;
4016
+ }
4017
+ async executeTick(context) {
4018
+ if (!context.activities?.llmChat) {
4019
+ this._lastError = "LLMChat requires activities.llmChat to be configured. This activity handles LLM API calls outside the workflow sandbox.";
4020
+ this.log(`Error: ${this._lastError}`);
4021
+ return "FAILURE" /* FAILURE */;
4022
+ }
4023
+ try {
4024
+ const varCtx = {
4025
+ blackboard: context.blackboard,
4026
+ input: context.input,
4027
+ testData: context.testData
4028
+ };
4029
+ const resolvedMessages = this.messages.map((msg) => ({
4030
+ role: msg.role,
4031
+ content: resolveValue(msg.content, varCtx)
4032
+ }));
4033
+ const resolvedSystemPrompt = this.systemPrompt ? resolveValue(this.systemPrompt, varCtx) : void 0;
4034
+ const resolvedModel = resolveValue(this.model, varCtx);
4035
+ const request = {
4036
+ provider: this.provider,
4037
+ model: resolvedModel,
4038
+ messages: resolvedMessages,
4039
+ systemPrompt: resolvedSystemPrompt,
4040
+ temperature: this.temperature,
4041
+ maxTokens: this.maxTokens,
4042
+ responseFormat: this.responseFormat,
4043
+ jsonSchema: this.jsonSchema,
4044
+ timeout: this.timeout,
4045
+ baseUrl: this.baseUrl
4046
+ };
4047
+ this.log(
4048
+ `LLM ${this.provider}/${resolvedModel} - ${resolvedMessages.length} messages`
4049
+ );
4050
+ const result = await context.activities.llmChat(request);
4051
+ context.blackboard.set(this.outputKey, result);
4052
+ if (result.finishReason === "error") {
4053
+ this._lastError = `LLM returned error: ${result.content}`;
4054
+ this.log(`Error: ${this._lastError}`);
4055
+ return "FAILURE" /* FAILURE */;
4056
+ }
4057
+ this.log(
4058
+ `LLM ${this.provider}/${resolvedModel} completed: ${result.usage.totalTokens} tokens, finish: ${result.finishReason}`
4059
+ );
4060
+ return "SUCCESS" /* SUCCESS */;
4061
+ } catch (error) {
4062
+ this._lastError = error instanceof Error ? error.message : String(error);
4063
+ this.log(`LLM chat failed: ${this._lastError}`);
4064
+ return "FAILURE" /* FAILURE */;
4065
+ }
4066
+ }
4067
+ };
4068
+
4069
+ // src/actions/browser-agent.ts
4070
+ var BrowserAgent = class extends ActionNode {
4071
+ goal;
4072
+ startUrl;
4073
+ contextKey;
4074
+ persistContext;
4075
+ timeout;
4076
+ maxSteps;
4077
+ llmProvider;
4078
+ llmModel;
4079
+ outputKey;
4080
+ constructor(config) {
4081
+ super(config);
4082
+ if (!config.goal) {
4083
+ throw new ConfigurationError("BrowserAgent requires goal");
4084
+ }
4085
+ if (!config.outputKey) {
4086
+ throw new ConfigurationError("BrowserAgent requires outputKey");
4087
+ }
4088
+ this.goal = config.goal;
4089
+ this.startUrl = config.startUrl;
4090
+ this.contextKey = config.contextKey;
4091
+ this.persistContext = config.persistContext ?? false;
4092
+ this.timeout = config.timeout;
4093
+ this.maxSteps = config.maxSteps;
4094
+ this.llmProvider = config.llmProvider;
4095
+ this.llmModel = config.llmModel;
4096
+ this.outputKey = config.outputKey;
4097
+ }
4098
+ async executeTick(context) {
4099
+ if (!context.activities?.browserAgent) {
4100
+ this._lastError = "BrowserAgent requires activities.browserAgent to be configured. This activity handles browser automation via Browserbase + Stagehand.";
4101
+ this.log(`Error: ${this._lastError}`);
4102
+ return "FAILURE" /* FAILURE */;
4103
+ }
4104
+ try {
4105
+ const varCtx = {
4106
+ blackboard: context.blackboard,
4107
+ input: context.input,
4108
+ testData: context.testData
4109
+ };
4110
+ const resolvedGoal = resolveValue(this.goal, varCtx);
4111
+ const resolvedStartUrl = this.startUrl ? resolveValue(this.startUrl, varCtx) : void 0;
4112
+ const contextId = this.contextKey ? context.blackboard.get(this.contextKey) : void 0;
4113
+ const request = {
4114
+ goal: resolvedGoal,
4115
+ startUrl: resolvedStartUrl,
4116
+ contextId,
4117
+ persistContext: this.persistContext,
4118
+ timeout: this.timeout,
4119
+ maxSteps: this.maxSteps,
4120
+ llmProvider: this.llmProvider,
4121
+ llmModel: this.llmModel
4122
+ };
4123
+ this.log(
4124
+ `Browser agent: ${resolvedGoal.substring(0, 50)}${resolvedGoal.length > 50 ? "..." : ""}`
4125
+ );
4126
+ const result = await context.activities.browserAgent(request);
4127
+ if (this.contextKey && result.contextId) {
4128
+ context.blackboard.set(this.contextKey, result.contextId);
4129
+ }
4130
+ context.blackboard.set(this.outputKey, result);
4131
+ if (!result.success) {
4132
+ this._lastError = `Browser agent failed to achieve goal: ${result.message}`;
4133
+ this.log(`Error: ${this._lastError}`);
4134
+ this.log(`Debug session: ${result.debugUrl}`);
4135
+ return "FAILURE" /* FAILURE */;
4136
+ }
4137
+ if (!result.completed) {
4138
+ this._lastError = `Browser agent hit step limit before completing: ${result.message}`;
4139
+ this.log(`Error: ${this._lastError}`);
4140
+ this.log(`Debug session: ${result.debugUrl}`);
4141
+ return "FAILURE" /* FAILURE */;
4142
+ }
4143
+ this.log(`Browser agent succeeded: ${result.message}`);
4144
+ this.log(`Debug session: ${result.debugUrl}`);
4145
+ return "SUCCESS" /* SUCCESS */;
4146
+ } catch (error) {
4147
+ this._lastError = error instanceof Error ? error.message : String(error);
4148
+ this.log(`Browser agent failed: ${this._lastError}`);
4149
+ return "FAILURE" /* FAILURE */;
4150
+ }
4151
+ }
4152
+ };
4153
+
4154
+ // src/actions/claude-agent.ts
4155
+ var ClaudeAgent = class extends ActionNode {
4156
+ prompt;
4157
+ model;
4158
+ systemPrompt;
4159
+ allowedTools;
4160
+ permissionMode;
4161
+ maxTurns;
4162
+ maxBudgetUsd;
4163
+ agentCwd;
4164
+ mcpServers;
4165
+ agents;
4166
+ outputKey;
4167
+ constructor(config) {
4168
+ super(config);
4169
+ if (!config.prompt) {
4170
+ throw new ConfigurationError("ClaudeAgent requires prompt");
4171
+ }
4172
+ if (!config.outputKey) {
4173
+ throw new ConfigurationError("ClaudeAgent requires outputKey");
4174
+ }
4175
+ this.prompt = config.prompt;
4176
+ this.model = config.model;
4177
+ this.systemPrompt = config.systemPrompt;
4178
+ this.allowedTools = config.allowedTools;
4179
+ this.permissionMode = config.permissionMode ?? "default";
4180
+ this.maxTurns = config.maxTurns ?? 50;
4181
+ this.maxBudgetUsd = config.maxBudgetUsd;
4182
+ this.agentCwd = config.cwd;
4183
+ this.mcpServers = config.mcpServers;
4184
+ this.agents = config.agents;
4185
+ this.outputKey = config.outputKey;
4186
+ }
4187
+ async executeTick(context) {
4188
+ if (!context.activities?.claudeAgent) {
4189
+ this._lastError = "ClaudeAgent requires activities.claudeAgent to be configured. This activity handles autonomous agent execution via the Claude Agent SDK.";
4190
+ this.log(`Error: ${this._lastError}`);
4191
+ return "FAILURE" /* FAILURE */;
4192
+ }
4193
+ try {
4194
+ const varCtx = {
4195
+ blackboard: context.blackboard,
4196
+ input: context.input,
4197
+ testData: context.testData
4198
+ };
4199
+ const resolvedPrompt = resolveValue(this.prompt, varCtx);
4200
+ const resolvedSystemPrompt = this.systemPrompt ? resolveValue(this.systemPrompt, varCtx) : void 0;
4201
+ const resolvedModel = this.model ? resolveValue(this.model, varCtx) : void 0;
4202
+ const resolvedCwd = this.agentCwd ? resolveValue(this.agentCwd, varCtx) : void 0;
4203
+ const request = {
4204
+ prompt: resolvedPrompt,
4205
+ model: resolvedModel,
4206
+ systemPrompt: resolvedSystemPrompt,
4207
+ allowedTools: this.allowedTools,
4208
+ permissionMode: this.permissionMode,
4209
+ maxTurns: this.maxTurns,
4210
+ maxBudgetUsd: this.maxBudgetUsd,
4211
+ cwd: resolvedCwd,
4212
+ mcpServers: this.mcpServers,
4213
+ agents: this.agents
4214
+ };
4215
+ this.log(
4216
+ `Claude agent: ${resolvedPrompt.substring(0, 80)}${resolvedPrompt.length > 80 ? "..." : ""}`
4217
+ );
4218
+ const result = await context.activities.claudeAgent(request);
4219
+ context.blackboard.set(this.outputKey, result);
4220
+ if (!result.success) {
4221
+ this._lastError = `Claude agent failed: ${result.errors?.join(", ") || "unknown error"}`;
4222
+ this.log(`Error: ${this._lastError}`);
4223
+ return "FAILURE" /* FAILURE */;
4224
+ }
4225
+ this.log(
4226
+ `Claude agent completed in ${result.numTurns} turns, $${result.totalCostUsd.toFixed(4)}, ${result.durationMs}ms`
4227
+ );
4228
+ return "SUCCESS" /* SUCCESS */;
4229
+ } catch (error) {
4230
+ this._lastError = error instanceof Error ? error.message : String(error);
4231
+ this.log(`Claude agent failed: ${this._lastError}`);
4232
+ return "FAILURE" /* FAILURE */;
4233
+ }
4234
+ }
4235
+ };
4236
+
4237
+ // src/actions/github-action.ts
4238
+ var VALID_OPERATIONS = [
4239
+ "createBranch",
4240
+ "createPullRequest",
4241
+ "getPullRequest",
4242
+ "mergePullRequest",
4243
+ "closePullRequest",
4244
+ "createReview",
4245
+ "listIssues",
4246
+ "addLabels",
4247
+ "createComment",
4248
+ "createRelease"
4249
+ ];
4250
+ var GitHubAction = class extends ActionNode {
4251
+ operation;
4252
+ repo;
4253
+ params;
4254
+ outputKey;
4255
+ constructor(config) {
4256
+ super(config);
4257
+ if (!config.operation) {
4258
+ throw new ConfigurationError("GitHubAction requires operation");
4259
+ }
4260
+ if (!VALID_OPERATIONS.includes(config.operation)) {
4261
+ throw new ConfigurationError(
4262
+ `GitHubAction: invalid operation "${config.operation}". Valid operations: ${VALID_OPERATIONS.join(", ")}`
4263
+ );
4264
+ }
4265
+ if (!config.repo) {
4266
+ throw new ConfigurationError("GitHubAction requires repo");
4267
+ }
4268
+ if (!config.outputKey) {
4269
+ throw new ConfigurationError("GitHubAction requires outputKey");
4270
+ }
4271
+ this.operation = config.operation;
4272
+ this.repo = config.repo;
4273
+ this.params = config.params ?? {};
4274
+ this.outputKey = config.outputKey;
4275
+ }
4276
+ async executeTick(context) {
4277
+ if (!context.activities?.githubAction) {
4278
+ this._lastError = "GitHubAction requires activities.githubAction to be configured. This activity handles GitHub API operations.";
4279
+ this.log(`Error: ${this._lastError}`);
4280
+ return "FAILURE" /* FAILURE */;
4281
+ }
4282
+ try {
4283
+ const varCtx = {
4284
+ blackboard: context.blackboard,
4285
+ input: context.input,
4286
+ testData: context.testData
4287
+ };
4288
+ const resolvedRepo = resolveValue(this.repo, varCtx);
4289
+ const resolvedParams = {};
4290
+ for (const [key, value] of Object.entries(this.params)) {
4291
+ if (typeof value === "string") {
4292
+ resolvedParams[key] = resolveValue(value, varCtx);
4293
+ } else {
4294
+ resolvedParams[key] = value;
4295
+ }
4296
+ }
4297
+ const request = {
4298
+ operation: this.operation,
4299
+ repo: resolvedRepo,
4300
+ params: resolvedParams
4301
+ };
4302
+ this.log(
4303
+ `GitHub ${this.operation}: ${resolvedRepo}`
4304
+ );
4305
+ const result = await context.activities.githubAction(request);
4306
+ context.blackboard.set(this.outputKey, result.data);
4307
+ if (!result.success) {
4308
+ this._lastError = `GitHub ${this.operation} failed`;
4309
+ this.log(`Error: ${this._lastError}`);
4310
+ return "FAILURE" /* FAILURE */;
4311
+ }
4312
+ this.log(`GitHub ${this.operation} completed successfully`);
4313
+ return "SUCCESS" /* SUCCESS */;
4314
+ } catch (error) {
4315
+ this._lastError = error instanceof Error ? error.message : String(error);
4316
+ this.log(`GitHub ${this.operation} failed: ${this._lastError}`);
4317
+ return "FAILURE" /* FAILURE */;
4318
+ }
4319
+ }
4320
+ };
4321
+
4322
+ // src/actions/human-task.ts
4323
+ var HumanTask = class extends ActionNode {
4324
+ title;
4325
+ description;
4326
+ assignee;
4327
+ assigneeRole;
4328
+ a2ui;
4329
+ timeoutMs;
4330
+ onTimeout;
4331
+ outputKey;
4332
+ constructor(config) {
4333
+ super(config);
4334
+ if (!config.title) {
4335
+ throw new ConfigurationError("HumanTask requires title");
4336
+ }
4337
+ if (!config.a2ui?.components || config.a2ui.components.length === 0) {
4338
+ throw new ConfigurationError(
4339
+ "HumanTask requires a2ui.components with at least one component"
4340
+ );
4341
+ }
4342
+ this.title = config.title;
4343
+ this.description = config.description;
4344
+ this.assignee = config.assignee;
4345
+ this.assigneeRole = config.assigneeRole;
4346
+ this.a2ui = config.a2ui;
4347
+ this.timeoutMs = config.timeoutMs ?? 864e5;
4348
+ this.onTimeout = config.onTimeout ?? "expire";
4349
+ this.outputKey = config.outputKey;
4350
+ }
4351
+ async executeTick(context) {
4352
+ if (!context.activities?.createHumanTask) {
4353
+ this._lastError = "HumanTask requires activities.createHumanTask to be configured. This activity creates a task record in the database.";
4354
+ this.log(`Error: ${this._lastError}`);
4355
+ return "FAILURE" /* FAILURE */;
4356
+ }
4357
+ if (!context.activities?.waitForHumanTask) {
4358
+ this._lastError = "HumanTask requires activities.waitForHumanTask to be configured. This activity waits for the user to complete the task.";
4359
+ this.log(`Error: ${this._lastError}`);
4360
+ return "FAILURE" /* FAILURE */;
4361
+ }
4362
+ try {
4363
+ const varCtx = {
4364
+ blackboard: context.blackboard,
4365
+ input: context.input,
4366
+ testData: context.testData
4367
+ };
4368
+ const a2uiDataModel = {};
4369
+ if (this.a2ui.dataBindings) {
4370
+ for (const [a2uiPath, expression] of Object.entries(
4371
+ this.a2ui.dataBindings
4372
+ )) {
4373
+ const resolved = resolveValue(expression, varCtx);
4374
+ setNestedPath(a2uiDataModel, a2uiPath, resolved);
4375
+ }
4376
+ }
4377
+ const resolvedTitle = resolveValue(this.title, varCtx);
4378
+ const resolvedDescription = this.description ? resolveValue(this.description, varCtx) : void 0;
4379
+ const resolvedAssignee = this.assignee ? resolveValue(this.assignee, varCtx) : void 0;
4380
+ const tenantId = context.blackboard.get("__tenantId") || "";
4381
+ const executionId = context.blackboard.get("__executionId") || context.workflowInfo?.workflowId || "";
4382
+ const request = {
4383
+ nodeId: this.id,
4384
+ tenantId,
4385
+ executionId,
4386
+ title: resolvedTitle,
4387
+ description: resolvedDescription,
4388
+ assigneeEmail: resolvedAssignee,
4389
+ assigneeRole: this.assigneeRole,
4390
+ a2uiComponents: this.a2ui.components,
4391
+ a2uiDataModel,
4392
+ timeoutMs: this.timeoutMs,
4393
+ onTimeout: this.onTimeout
4394
+ };
4395
+ this.log(
4396
+ `Creating human task: "${resolvedTitle}" (timeout: ${this.timeoutMs}ms)`
4397
+ );
4398
+ const createResult = await context.activities.createHumanTask(request);
4399
+ this.log(`Task created: ${createResult.taskId}`);
4400
+ this.log(
4401
+ `Waiting for human task ${createResult.taskId} on node ${this.id}`
4402
+ );
4403
+ const waitResult = await context.activities.waitForHumanTask({
4404
+ taskId: createResult.taskId,
4405
+ nodeId: this.id,
4406
+ timeoutMs: this.timeoutMs,
4407
+ onTimeout: this.onTimeout
4408
+ });
4409
+ const prefix = this.outputKey || this.id;
4410
+ context.blackboard.set(`${prefix}.taskId`, createResult.taskId);
4411
+ context.blackboard.set(`${prefix}.completed`, waitResult.completed);
4412
+ context.blackboard.set(`${prefix}.decision`, waitResult.decision);
4413
+ context.blackboard.set(
4414
+ `${prefix}.submittedData`,
4415
+ waitResult.submittedData
4416
+ );
4417
+ context.blackboard.set(`${prefix}.completedBy`, waitResult.completedBy);
4418
+ context.blackboard.set(`${prefix}.timedOut`, waitResult.timedOut);
4419
+ if (waitResult.timedOut) {
4420
+ this._lastError = `Task timed out after ${this.timeoutMs}ms`;
4421
+ this.log(`Task timed out, onTimeout=${this.onTimeout}`);
4422
+ return this.onTimeout === "approve" ? "SUCCESS" /* SUCCESS */ : "FAILURE" /* FAILURE */;
4423
+ }
4424
+ this.log(
4425
+ `Task completed: decision=${waitResult.decision}, completedBy=${waitResult.completedBy}`
4426
+ );
4427
+ return waitResult.completed ? "SUCCESS" /* SUCCESS */ : "FAILURE" /* FAILURE */;
4428
+ } catch (error) {
4429
+ this._lastError = error instanceof Error ? error.message : String(error);
4430
+ this.log(`HumanTask failed: ${this._lastError}`);
4431
+ return "FAILURE" /* FAILURE */;
4432
+ }
4433
+ }
4434
+ };
4435
+ function setNestedPath(obj, path2, value) {
4436
+ const parts = path2.split("/").filter(Boolean);
4437
+ let current = obj;
4438
+ for (let i = 0; i < parts.length - 1; i++) {
4439
+ const key = parts[i];
4440
+ if (!(key in current) || typeof current[key] !== "object") {
4441
+ current[key] = {};
4442
+ }
4443
+ current = current[key];
4444
+ }
4445
+ if (parts.length > 0) {
4446
+ const lastKey = parts[parts.length - 1];
4447
+ current[lastKey] = value;
4448
+ }
4449
+ }
4450
+
3892
4451
  // src/registry-utils.ts
3893
4452
  function registerStandardNodes(registry) {
3894
4453
  registry.register("Sequence", Sequence, { category: "composite" });
@@ -3948,6 +4507,11 @@ function registerStandardNodes(registry) {
3948
4507
  registry.register("GenerateFile", GenerateFile, { category: "action" });
3949
4508
  registry.register("HttpRequest", HttpRequest, { category: "action" });
3950
4509
  registry.register("CodeExecution", CodeExecution, { category: "action" });
4510
+ registry.register("LLMChat", LLMChat, { category: "action" });
4511
+ registry.register("BrowserAgent", BrowserAgent, { category: "action" });
4512
+ registry.register("ClaudeAgent", ClaudeAgent, { category: "action" });
4513
+ registry.register("GitHubAction", GitHubAction, { category: "action" });
4514
+ registry.register("HumanTask", HumanTask, { category: "action" });
3951
4515
  }
3952
4516
 
3953
4517
  // src/data-store/memory-store.ts
@@ -4784,7 +5348,9 @@ export {
4784
5348
  AlwaysCondition,
4785
5349
  BaseNode,
4786
5350
  BehaviorTree,
5351
+ BrowserAgent,
4787
5352
  CheckCondition,
5353
+ ClaudeAgent,
4788
5354
  CodeExecution,
4789
5355
  CompositeNode,
4790
5356
  ConditionNode,
@@ -4801,10 +5367,13 @@ export {
4801
5367
  ForceFailure,
4802
5368
  ForceSuccess,
4803
5369
  GenerateFile,
5370
+ GitHubAction,
4804
5371
  HttpRequest,
5372
+ HumanTask,
4805
5373
  IntegrationAction,
4806
5374
  Invert,
4807
5375
  KeepRunningUntilFailure,
5376
+ LLMChat,
4808
5377
  LogMessage,
4809
5378
  MemoryDataStore,
4810
5379
  MemorySequence,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@q1k-oss/behaviour-tree-workflows",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Behavior tree library for TypeScript — 30+ production-ready nodes, YAML workflows, Temporal integration, and built-in observability",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",