@atom8n/n8n-nodes-langchain 2.5.7 → 2.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/known/nodes.json +24 -0
  2. package/dist/methods/defined.json +3 -0
  3. package/dist/methods/referenced.json +3 -0
  4. package/dist/nodes/agents/OpenClawAgent/OpenClawAgent.node.js +62 -0
  5. package/dist/nodes/agents/OpenClawAgent/OpenClawAgent.node.js.map +1 -0
  6. package/dist/nodes/agents/OpenClawAgent/V1/OpenClawAgentV1.node.js +821 -0
  7. package/dist/nodes/agents/OpenClawAgent/V1/OpenClawAgentV1.node.js.map +1 -0
  8. package/dist/nodes/agents/OpenClawAgent/V2/OpenClawAgentV2.node.js +2059 -0
  9. package/dist/nodes/agents/OpenClawAgent/V2/OpenClawAgentV2.node.js.map +1 -0
  10. package/dist/nodes/agents/OpenClawAgent/channels/TelegramChannel/TelegramChannel.node.js +329 -0
  11. package/dist/nodes/agents/OpenClawAgent/channels/TelegramChannel/TelegramChannel.node.js.map +1 -0
  12. package/dist/nodes/agents/OpenClawAgent/channels/TelegramChannel/telegram-channel.svg +4 -0
  13. package/dist/nodes/agents/OpenClawAgent/channels/WhatsAppChannel/WhatsAppChannel.node.js +108 -0
  14. package/dist/nodes/agents/OpenClawAgent/channels/WhatsAppChannel/WhatsAppChannel.node.js.map +1 -0
  15. package/dist/nodes/agents/OpenClawAgent/channels/WhatsAppChannel/whatsapp-channel.svg +3 -0
  16. package/dist/nodes/agents/OpenClawAgent/mcpServers/OpenClawMcpServer/OpenClawMcpServer.node.js +228 -0
  17. package/dist/nodes/agents/OpenClawAgent/mcpServers/OpenClawMcpServer/OpenClawMcpServer.node.js.map +1 -0
  18. package/dist/nodes/agents/OpenClawAgent/mcpServers/OpenClawMcpServer/openclaw-mcp-server.svg +9 -0
  19. package/dist/nodes/agents/OpenClawAgent/models/OpenCodeFreeModel/OpenCodeFreeModel.node.js +97 -0
  20. package/dist/nodes/agents/OpenClawAgent/models/OpenCodeFreeModel/OpenCodeFreeModel.node.js.map +1 -0
  21. package/dist/nodes/agents/OpenClawAgent/models/OpenCodeFreeModel/opencode-free-model.svg +1 -0
  22. package/dist/nodes/agents/OpenClawAgent/openclaw.svg +8 -0
  23. package/dist/nodes/agents/OpenClawAgent/plugins/OpenClawPlugin/OpenClawPlugin.node.js +261 -0
  24. package/dist/nodes/agents/OpenClawAgent/plugins/OpenClawPlugin/OpenClawPlugin.node.js.map +1 -0
  25. package/dist/nodes/agents/OpenClawAgent/plugins/OpenClawPlugin/openclaw-plugin.svg +3 -0
  26. package/dist/nodes/llms/LmChat9Router/LmChat9Router.node.js +40 -3
  27. package/dist/nodes/llms/LmChat9Router/LmChat9Router.node.js.map +1 -1
  28. package/dist/types/nodes.json +8 -1
  29. package/package.json +17 -11
@@ -0,0 +1,821 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var OpenClawAgentV1_node_exports = {};
20
+ __export(OpenClawAgentV1_node_exports, {
21
+ OpenClawAgentV1: () => OpenClawAgentV1
22
+ });
23
+ module.exports = __toCommonJS(OpenClawAgentV1_node_exports);
24
+ var import_child_process = require("child_process");
25
+ var import_crypto = require("crypto");
26
+ var import_fs = require("fs");
27
+ var import_path = require("path");
28
+ var import_n8n_workflow = require("n8n-workflow");
29
+ const selectorTypeToParameterName = {
30
+ agent: "agentId",
31
+ sessionId: "sessionId",
32
+ recipient: "to"
33
+ };
34
+ const selectorTypeToCliFlag = {
35
+ agent: "--agent",
36
+ sessionId: "--session-id",
37
+ recipient: "--to"
38
+ };
39
+ const DEFAULT_TIMEOUT_SECONDS = 300;
40
+ const CLI_SHUTDOWN_GRACE_SECONDS = 90;
41
+ const GATEWAY_RESTART_TIMEOUT_SECONDS = 60;
42
+ const TELEGRAM_CREDENTIAL_TYPE = "telegramApi";
43
+ const OPENCLAW_CONFIG_PATH_ENV = "OPENCLAW_CONFIG_PATH";
44
+ const OPENCLAW_DEFAULT_ACCOUNT_ID = "default";
45
+ function isObject(value) {
46
+ return typeof value === "object" && value !== null && !Array.isArray(value);
47
+ }
48
+ function getErrorMessage(error) {
49
+ if (error instanceof Error) {
50
+ return error.message;
51
+ }
52
+ return String(error);
53
+ }
54
+ function normalizeOptionalString(value) {
55
+ if (typeof value !== "string") {
56
+ return void 0;
57
+ }
58
+ const trimmed = value.trim();
59
+ return trimmed || void 0;
60
+ }
61
+ function getOpenClawConfigPath() {
62
+ const configuredPath = normalizeOptionalString(process.env[OPENCLAW_CONFIG_PATH_ENV]);
63
+ if (configuredPath) {
64
+ return configuredPath;
65
+ }
66
+ const home = getHomeDirectory();
67
+ return home ? (0, import_path.join)(home, ".openclaw", "openclaw.json") : void 0;
68
+ }
69
+ function ensureDataObject(parent, key) {
70
+ const existing = parent[key];
71
+ if (isObject(existing)) {
72
+ return existing;
73
+ }
74
+ const next = {};
75
+ parent[key] = next;
76
+ return next;
77
+ }
78
+ function setConfigValue(target, key, value) {
79
+ if (target[key] === value) {
80
+ return false;
81
+ }
82
+ target[key] = value;
83
+ return true;
84
+ }
85
+ function setDefaultConfigValue(target, key, value) {
86
+ if (target[key] !== void 0) {
87
+ return false;
88
+ }
89
+ target[key] = value;
90
+ return true;
91
+ }
92
+ function normalizeOpenClawAccountId(value) {
93
+ const trimmed = normalizeOptionalString(value)?.toLowerCase();
94
+ if (!trimmed) {
95
+ return void 0;
96
+ }
97
+ const normalized = trimmed.replace(/[^a-z0-9_-]+/g, "-").replace(/^-+/, "").replace(/-+$/, "").slice(0, 64);
98
+ if (!normalized || ["__proto__", "constructor", "prototype"].includes(normalized)) {
99
+ return void 0;
100
+ }
101
+ return normalized;
102
+ }
103
+ function readOpenClawConfig(configPath) {
104
+ if (!(0, import_fs.existsSync)(configPath)) {
105
+ return {};
106
+ }
107
+ const rawConfig = (0, import_fs.readFileSync)(configPath, "utf8").trim();
108
+ if (!rawConfig) {
109
+ return {};
110
+ }
111
+ const parsed = (0, import_n8n_workflow.jsonParse)(rawConfig, { acceptJSObject: true, repairJSON: true });
112
+ if (!isObject(parsed)) {
113
+ throw new import_n8n_workflow.ApplicationError(`OpenClaw config is not an object: ${configPath}`);
114
+ }
115
+ return parsed;
116
+ }
117
+ function syncTelegramChannelConfig(params) {
118
+ const configPath = getOpenClawConfigPath();
119
+ if (!configPath) {
120
+ throw new import_n8n_workflow.ApplicationError(
121
+ `Could not determine OpenClaw config path. Set ${OPENCLAW_CONFIG_PATH_ENV} or HOME for the n8n process.`
122
+ );
123
+ }
124
+ const config = readOpenClawConfig(configPath);
125
+ const channels = ensureDataObject(config, "channels");
126
+ const telegram = ensureDataObject(channels, "telegram");
127
+ const accountId = normalizeOpenClawAccountId(params.replyAccount);
128
+ let changed = false;
129
+ changed = setConfigValue(telegram, "enabled", true) || changed;
130
+ changed = setDefaultConfigValue(telegram, "dmPolicy", "pairing") || changed;
131
+ changed = setDefaultConfigValue(telegram, "groupPolicy", "allowlist") || changed;
132
+ if (accountId && accountId !== OPENCLAW_DEFAULT_ACCOUNT_ID) {
133
+ const accounts = ensureDataObject(telegram, "accounts");
134
+ const account = ensureDataObject(accounts, accountId);
135
+ changed = setConfigValue(account, "enabled", true) || changed;
136
+ changed = setConfigValue(account, "botToken", params.botToken) || changed;
137
+ } else {
138
+ changed = setConfigValue(telegram, "botToken", params.botToken) || changed;
139
+ }
140
+ if (changed) {
141
+ (0, import_fs.mkdirSync)((0, import_path.dirname)(configPath), { recursive: true });
142
+ (0, import_fs.writeFileSync)(configPath, `${JSON.stringify(config, null, 2)}
143
+ `, "utf8");
144
+ }
145
+ return { accountId, changed, configPath };
146
+ }
147
+ function parseOpenClawOutput(stdout) {
148
+ const trimmed = stdout.trim();
149
+ if (!trimmed) {
150
+ return {};
151
+ }
152
+ const parsed = (0, import_n8n_workflow.jsonParse)(trimmed);
153
+ if (isObject(parsed)) {
154
+ return parsed;
155
+ }
156
+ return { result: parsed };
157
+ }
158
+ function isUsableFile(filePath) {
159
+ try {
160
+ return (0, import_fs.existsSync)(filePath) && (0, import_fs.statSync)(filePath).isFile();
161
+ } catch {
162
+ return false;
163
+ }
164
+ }
165
+ function getHomeDirectory() {
166
+ return normalizeOptionalString(process.env.HOME) ?? normalizeOptionalString(process.env.USERPROFILE);
167
+ }
168
+ function getDefaultBinarySearchPaths(binaryName) {
169
+ const home = getHomeDirectory();
170
+ const homeCandidates = home ? [
171
+ (0, import_path.join)(home, ".volta", "bin", binaryName),
172
+ (0, import_path.join)(home, ".local", "bin", binaryName),
173
+ (0, import_path.join)(home, ".npm-global", "bin", binaryName),
174
+ (0, import_path.join)(home, ".bun", "bin", binaryName),
175
+ (0, import_path.join)(home, "Library", "pnpm", binaryName)
176
+ ] : [];
177
+ return [
178
+ normalizeOptionalString(process.env.OPENCLAW_BINARY_PATH),
179
+ normalizeOptionalString(process.env.OPENCLAW_BIN),
180
+ ...(process.env.PATH ?? "").split(import_path.delimiter).filter(Boolean).map((pathDirectory) => (0, import_path.join)(pathDirectory, binaryName)),
181
+ ...homeCandidates,
182
+ (0, import_path.join)("/opt/homebrew/bin", binaryName),
183
+ (0, import_path.join)("/usr/local/bin", binaryName)
184
+ ].filter((candidate) => typeof candidate === "string");
185
+ }
186
+ function resolveOpenClawBinary(binaryPath) {
187
+ if (binaryPath.includes("/") || binaryPath.includes("\\")) {
188
+ return {
189
+ binaryPath,
190
+ pathDirectories: [(0, import_path.dirname)(binaryPath)]
191
+ };
192
+ }
193
+ for (const candidate of getDefaultBinarySearchPaths(binaryPath)) {
194
+ if (isUsableFile(candidate)) {
195
+ return {
196
+ binaryPath: candidate,
197
+ pathDirectories: [(0, import_path.dirname)(candidate)]
198
+ };
199
+ }
200
+ }
201
+ return {
202
+ binaryPath,
203
+ pathDirectories: []
204
+ };
205
+ }
206
+ function createOpenClawProcessEnv(pathDirectories, additionalEnv = {}) {
207
+ const existingPath = process.env.PATH ?? "";
208
+ const prependedPath = pathDirectories.filter(Boolean).join(import_path.delimiter);
209
+ const nextPath = prependedPath ? `${prependedPath}${import_path.delimiter}${existingPath}` : existingPath;
210
+ return {
211
+ ...process.env,
212
+ ...additionalEnv,
213
+ PATH: nextPath
214
+ };
215
+ }
216
+ function killOpenClawProcess(child, signal) {
217
+ try {
218
+ if (child.pid && process.platform !== "win32") {
219
+ process.kill(-child.pid, signal);
220
+ return;
221
+ }
222
+ } catch {
223
+ }
224
+ try {
225
+ child.kill(signal);
226
+ } catch {
227
+ }
228
+ }
229
+ function summarizeProcessOutput(output) {
230
+ const trimmed = output.trim();
231
+ if (!trimmed) {
232
+ return "";
233
+ }
234
+ const maxLength = 2e3;
235
+ if (trimmed.length <= maxLength) {
236
+ return trimmed;
237
+ }
238
+ return `${trimmed.slice(0, maxLength)}...`;
239
+ }
240
+ function getWatchdogTimeoutMs(timeoutSeconds) {
241
+ return (timeoutSeconds + CLI_SHUTDOWN_GRACE_SECONDS) * 1e3;
242
+ }
243
+ function getGatewayCallArgs(params, rpcTimeoutMs) {
244
+ return [
245
+ "gateway",
246
+ "call",
247
+ "agent",
248
+ "--expect-final",
249
+ "--json",
250
+ "--timeout",
251
+ String(rpcTimeoutMs),
252
+ "--params",
253
+ JSON.stringify(params)
254
+ ];
255
+ }
256
+ function quoteCommandArgument(value) {
257
+ if (/^[A-Za-z0-9_/:=-]+$/.test(value)) {
258
+ return value;
259
+ }
260
+ return `'${value.replaceAll("'", "'\\''")}'`;
261
+ }
262
+ function getOpenClawCommand(binaryPath, args) {
263
+ return [binaryPath, ...args].map(quoteCommandArgument).join(" ");
264
+ }
265
+ async function runOpenClawCli(params) {
266
+ return await new Promise((resolve, reject) => {
267
+ const resolvedBinary = resolveOpenClawBinary(params.binaryPath);
268
+ const command = getOpenClawCommand(resolvedBinary.binaryPath, params.args);
269
+ const child = (0, import_child_process.spawn)(resolvedBinary.binaryPath, params.args, {
270
+ cwd: params.cwd,
271
+ detached: process.platform !== "win32",
272
+ stdio: ["ignore", "pipe", "pipe"],
273
+ env: createOpenClawProcessEnv(resolvedBinary.pathDirectories, params.env)
274
+ });
275
+ let stdout = "";
276
+ let stderr = "";
277
+ let aborted = false;
278
+ let timedOut = false;
279
+ let forceKillTimer;
280
+ const abortHandler = () => {
281
+ aborted = true;
282
+ killOpenClawProcess(child, "SIGTERM");
283
+ };
284
+ const timeoutTimer = setTimeout(() => {
285
+ timedOut = true;
286
+ killOpenClawProcess(child, "SIGTERM");
287
+ forceKillTimer = setTimeout(() => {
288
+ killOpenClawProcess(child, "SIGKILL");
289
+ }, 5e3);
290
+ }, params.timeoutMs);
291
+ params.abortSignal?.addEventListener("abort", abortHandler, { once: true });
292
+ child.stdout.on("data", (data) => {
293
+ stdout += data.toString();
294
+ });
295
+ child.stderr.on("data", (data) => {
296
+ stderr += data.toString();
297
+ });
298
+ child.on("error", (error) => {
299
+ clearTimeout(timeoutTimer);
300
+ if (forceKillTimer) {
301
+ clearTimeout(forceKillTimer);
302
+ }
303
+ params.abortSignal?.removeEventListener("abort", abortHandler);
304
+ reject(
305
+ new Error(
306
+ `Failed to spawn OpenClaw CLI at "${resolvedBinary.binaryPath}": ${error.message}. Set Options > Binary Path to the full path of the openclaw executable, or set OPENCLAW_BINARY_PATH in the n8n process environment.`
307
+ )
308
+ );
309
+ });
310
+ child.on("close", (exitCode, signal) => {
311
+ clearTimeout(timeoutTimer);
312
+ if (forceKillTimer) {
313
+ clearTimeout(forceKillTimer);
314
+ }
315
+ params.abortSignal?.removeEventListener("abort", abortHandler);
316
+ if (aborted) {
317
+ reject(new Error("OpenClaw CLI execution was cancelled"));
318
+ return;
319
+ }
320
+ if (timedOut) {
321
+ const stderrSummary = summarizeProcessOutput(stderr);
322
+ const stdoutSummary = summarizeProcessOutput(stdout);
323
+ const details = stderrSummary || stdoutSummary ? ` Last output: ${stderrSummary || stdoutSummary}` : "";
324
+ reject(
325
+ new Error(
326
+ `OpenClaw CLI did not finish within ${Math.ceil(params.timeoutMs / 1e3)} seconds and was stopped.${details}`
327
+ )
328
+ );
329
+ return;
330
+ }
331
+ resolve({ stdout, stderr, exitCode, signal, command });
332
+ });
333
+ });
334
+ }
335
+ class OpenClawAgentV1 {
336
+ constructor(baseDescription) {
337
+ this.description = {
338
+ ...baseDescription,
339
+ version: 1,
340
+ subtitle: '={{$parameter.selectorType === "agent" ? "Agent: " + $parameter.agentId : $parameter.selectorType === "sessionId" ? "Session: " + $parameter.sessionId : $parameter.selectorType === "recipient" ? "To: " + $parameter.to : "Default route"}}',
341
+ defaults: {
342
+ name: "OpenClaw AI Agent"
343
+ },
344
+ codex: {
345
+ alias: ["OpenClaw", "Agent", "Gateway", "Assistant"],
346
+ categories: ["AI"],
347
+ subcategories: {
348
+ AI: ["Agents", "Root Nodes"]
349
+ },
350
+ resources: {
351
+ primaryDocumentation: [
352
+ {
353
+ url: "https://docs.openclaw.ai/cli/agent"
354
+ }
355
+ ]
356
+ }
357
+ },
358
+ inputs: [import_n8n_workflow.NodeConnectionTypes.Main],
359
+ outputs: [import_n8n_workflow.NodeConnectionTypes.Main],
360
+ credentials: [
361
+ {
362
+ name: TELEGRAM_CREDENTIAL_TYPE,
363
+ displayName: "Telegram Credential",
364
+ required: false
365
+ }
366
+ ],
367
+ properties: [
368
+ {
369
+ displayName: "Requires the OpenClaw CLI to be installed and configured on the n8n host. The node runs <code>openclaw agent --json</code> and returns OpenClaw payloads and metadata.",
370
+ name: "openClawNotice",
371
+ type: "notice",
372
+ default: ""
373
+ },
374
+ {
375
+ displayName: "Message",
376
+ name: "message",
377
+ type: "string",
378
+ required: true,
379
+ default: '={{ $json.chatInput || $json.chat_input || $json.message || $json.text || "" }}',
380
+ description: "Message body to send to the OpenClaw agent",
381
+ typeOptions: {
382
+ rows: 5
383
+ }
384
+ },
385
+ {
386
+ displayName: "Route By",
387
+ name: "selectorType",
388
+ type: "options",
389
+ default: "agent",
390
+ noDataExpression: true,
391
+ description: "How to target the OpenClaw agent turn",
392
+ options: [
393
+ {
394
+ name: "Agent ID",
395
+ value: "agent",
396
+ description: "Run against a configured OpenClaw agent"
397
+ },
398
+ {
399
+ name: "Existing Session ID",
400
+ value: "sessionId",
401
+ description: "Continue an existing OpenClaw session"
402
+ },
403
+ {
404
+ name: "Recipient",
405
+ value: "recipient",
406
+ description: "Use a recipient/channel target to derive the session"
407
+ },
408
+ {
409
+ name: "OpenClaw Default",
410
+ value: "default",
411
+ description: "Let OpenClaw choose its default route"
412
+ }
413
+ ]
414
+ },
415
+ {
416
+ displayName: "Agent ID",
417
+ name: "agentId",
418
+ type: "string",
419
+ default: "main",
420
+ description: "Configured OpenClaw agent ID",
421
+ displayOptions: {
422
+ show: {
423
+ selectorType: ["agent"]
424
+ }
425
+ }
426
+ },
427
+ {
428
+ displayName: "Session ID",
429
+ name: "sessionId",
430
+ type: "string",
431
+ default: "",
432
+ description: "OpenClaw session ID to continue",
433
+ displayOptions: {
434
+ show: {
435
+ selectorType: ["sessionId"]
436
+ }
437
+ }
438
+ },
439
+ {
440
+ displayName: "Recipient",
441
+ name: "to",
442
+ type: "string",
443
+ default: "",
444
+ description: "Recipient or channel target passed to OpenClaw as --to",
445
+ displayOptions: {
446
+ show: {
447
+ selectorType: ["recipient"]
448
+ }
449
+ }
450
+ },
451
+ {
452
+ displayName: "Model",
453
+ name: "model",
454
+ type: "string",
455
+ default: "openai-codex/gpt-5.5",
456
+ description: "Model override for this run. Use an OpenClaw model reference such as openai-codex/gpt-5.5."
457
+ },
458
+ {
459
+ displayName: "Thinking Level",
460
+ name: "thinking",
461
+ type: "options",
462
+ default: "",
463
+ description: "Optional OpenClaw thinking level override for this run",
464
+ options: [
465
+ { name: "Adaptive", value: "adaptive" },
466
+ { name: "Extra High", value: "xhigh" },
467
+ { name: "High", value: "high" },
468
+ { name: "Low", value: "low" },
469
+ { name: "Max", value: "max" },
470
+ { name: "Medium", value: "medium" },
471
+ { name: "Minimal", value: "minimal" },
472
+ { name: "Off", value: "off" },
473
+ { name: "Use OpenClaw Default", value: "" }
474
+ ]
475
+ },
476
+ {
477
+ displayName: "Run Locally",
478
+ name: "local",
479
+ type: "boolean",
480
+ default: false,
481
+ description: "Whether to force OpenClaw embedded local runtime instead of Gateway mode"
482
+ },
483
+ {
484
+ displayName: "Deliver Reply",
485
+ name: "deliver",
486
+ type: "boolean",
487
+ default: false,
488
+ description: "Whether OpenClaw should deliver the reply back to the selected channel/target"
489
+ },
490
+ {
491
+ displayName: "Options",
492
+ name: "options",
493
+ type: "collection",
494
+ placeholder: "Add Option",
495
+ default: {},
496
+ options: [
497
+ {
498
+ displayName: "System Message",
499
+ name: "systemMessage",
500
+ type: "string",
501
+ default: "",
502
+ description: "Additional system instructions for this OpenClaw run. When set, the node sends the run through the OpenClaw Gateway agent RPC so the instructions are passed as extraSystemPrompt.",
503
+ typeOptions: {
504
+ rows: 5
505
+ }
506
+ },
507
+ {
508
+ displayName: "Binary Path",
509
+ name: "binaryPath",
510
+ type: "string",
511
+ default: "openclaw",
512
+ description: 'Path to the openclaw binary. Defaults to "openclaw" in PATH.'
513
+ },
514
+ {
515
+ displayName: "Working Directory",
516
+ name: "workingDirectory",
517
+ type: "string",
518
+ default: "",
519
+ description: "Working directory for the OpenClaw process. Leave empty to use n8n default."
520
+ },
521
+ {
522
+ displayName: "Timeout",
523
+ name: "timeout",
524
+ type: "number",
525
+ default: DEFAULT_TIMEOUT_SECONDS,
526
+ description: "OpenClaw agent timeout in seconds. The node allows extra time for the CLI to return the final gateway result before stopping the process.",
527
+ typeOptions: {
528
+ minValue: 1
529
+ }
530
+ },
531
+ {
532
+ displayName: "Channel",
533
+ name: "channel",
534
+ type: "string",
535
+ default: "",
536
+ description: "Delivery channel passed to OpenClaw as --channel"
537
+ },
538
+ {
539
+ displayName: "Reply To",
540
+ name: "replyTo",
541
+ type: "string",
542
+ default: "",
543
+ description: "Delivery target override passed to OpenClaw as --reply-to"
544
+ },
545
+ {
546
+ displayName: "Reply Channel",
547
+ name: "replyChannel",
548
+ type: "string",
549
+ default: "",
550
+ description: "Delivery channel override passed to OpenClaw as --reply-channel"
551
+ },
552
+ {
553
+ displayName: "Reply Account",
554
+ name: "replyAccount",
555
+ type: "string",
556
+ default: "",
557
+ description: "Delivery account ID override passed to OpenClaw as --reply-account"
558
+ },
559
+ {
560
+ displayName: "Verbose",
561
+ name: "verbose",
562
+ type: "options",
563
+ default: "",
564
+ description: "Optional OpenClaw verbose setting to persist for the session",
565
+ options: [
566
+ { name: "Full", value: "full" },
567
+ { name: "Leave Unchanged", value: "" },
568
+ { name: "Off", value: "off" },
569
+ { name: "On", value: "on" }
570
+ ]
571
+ },
572
+ {
573
+ displayName: "Include Raw Output",
574
+ name: "includeRawOutput",
575
+ type: "boolean",
576
+ default: false,
577
+ description: "Whether to include raw stdout and stderr from the OpenClaw CLI in the output"
578
+ }
579
+ ]
580
+ }
581
+ ]
582
+ };
583
+ }
584
+ async trigger() {
585
+ const node = this.getNode();
586
+ console.log("[OpenClawAgentV1] trigger activation registered", {
587
+ nodeName: node.name,
588
+ workflowId: this.getWorkflow().id,
589
+ activationMode: this.getActivationMode()
590
+ });
591
+ return {
592
+ closeFunction: async () => {
593
+ console.log("[OpenClawAgentV1] trigger activation closed", {
594
+ nodeName: node.name,
595
+ workflowId: this.getWorkflow().id
596
+ });
597
+ }
598
+ };
599
+ }
600
+ async execute() {
601
+ const items = this.getInputData();
602
+ const returnData = [];
603
+ for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
604
+ try {
605
+ const message = normalizeOptionalString(this.getNodeParameter("message", itemIndex));
606
+ if (!message) {
607
+ throw new import_n8n_workflow.NodeOperationError(this.getNode(), "Message must not be empty", { itemIndex });
608
+ }
609
+ const openClawEnv = {};
610
+ let telegramBotToken;
611
+ const telegramCredentialSelection = this.getNode().credentials?.[TELEGRAM_CREDENTIAL_TYPE];
612
+ if (telegramCredentialSelection) {
613
+ const telegramCredential = await this.getCredentials(
614
+ TELEGRAM_CREDENTIAL_TYPE,
615
+ itemIndex
616
+ );
617
+ const accessToken = normalizeOptionalString(telegramCredential.accessToken);
618
+ if (!accessToken) {
619
+ throw new import_n8n_workflow.NodeOperationError(
620
+ this.getNode(),
621
+ "Telegram Credential access token must not be empty",
622
+ { itemIndex }
623
+ );
624
+ }
625
+ telegramBotToken = accessToken;
626
+ openClawEnv.TELEGRAM_BOT_TOKEN = accessToken;
627
+ }
628
+ let args = ["agent", "--message", message, "--json"];
629
+ let processTimeoutMs;
630
+ let telegramConfigChanged = false;
631
+ const gatewayParams = {
632
+ message,
633
+ idempotencyKey: (0, import_crypto.randomUUID)()
634
+ };
635
+ const selectorType = this.getNodeParameter("selectorType", itemIndex);
636
+ if (selectorType !== "default") {
637
+ const parameterName = selectorTypeToParameterName[selectorType];
638
+ const value = normalizeOptionalString(this.getNodeParameter(parameterName, itemIndex));
639
+ if (!value) {
640
+ throw new import_n8n_workflow.NodeOperationError(
641
+ this.getNode(),
642
+ `${parameterName} must not be empty when Route By is ${selectorType}`,
643
+ { itemIndex }
644
+ );
645
+ }
646
+ args.push(selectorTypeToCliFlag[selectorType], value);
647
+ if (selectorType === "agent") {
648
+ gatewayParams.agentId = value;
649
+ } else if (selectorType === "sessionId") {
650
+ gatewayParams.sessionId = value;
651
+ } else {
652
+ gatewayParams.to = value;
653
+ }
654
+ }
655
+ const model = normalizeOptionalString(this.getNodeParameter("model", itemIndex));
656
+ if (model) {
657
+ args.push("--model", model);
658
+ gatewayParams.model = model;
659
+ }
660
+ const thinking = normalizeOptionalString(this.getNodeParameter("thinking", itemIndex));
661
+ if (thinking) {
662
+ args.push("--thinking", thinking);
663
+ gatewayParams.thinking = thinking;
664
+ }
665
+ const runLocally = this.getNodeParameter("local", itemIndex, false) === true;
666
+ if (runLocally) {
667
+ args.push("--local");
668
+ }
669
+ const deliverReply = this.getNodeParameter("deliver", itemIndex, false) === true;
670
+ if (deliverReply) {
671
+ args.push("--deliver");
672
+ gatewayParams.deliver = true;
673
+ }
674
+ const timeout = Number(
675
+ this.getNodeParameter("options.timeout", itemIndex, DEFAULT_TIMEOUT_SECONDS)
676
+ );
677
+ const timeoutSeconds = Number.isFinite(timeout) && timeout > 0 ? Math.floor(timeout) : DEFAULT_TIMEOUT_SECONDS;
678
+ args.push("--timeout", String(timeoutSeconds));
679
+ gatewayParams.timeout = timeoutSeconds;
680
+ const channel = normalizeOptionalString(
681
+ this.getNodeParameter("options.channel", itemIndex, "")
682
+ );
683
+ if (channel) {
684
+ args.push("--channel", channel);
685
+ gatewayParams.channel = channel;
686
+ }
687
+ const replyTo = normalizeOptionalString(
688
+ this.getNodeParameter("options.replyTo", itemIndex, "")
689
+ );
690
+ if (replyTo) {
691
+ args.push("--reply-to", replyTo);
692
+ gatewayParams.replyTo = replyTo;
693
+ }
694
+ let replyChannel = normalizeOptionalString(
695
+ this.getNodeParameter("options.replyChannel", itemIndex, "")
696
+ );
697
+ if (!replyChannel && !channel && deliverReply && telegramBotToken) {
698
+ replyChannel = "telegram";
699
+ }
700
+ if (replyChannel) {
701
+ args.push("--reply-channel", replyChannel);
702
+ gatewayParams.replyChannel = replyChannel;
703
+ }
704
+ const configuredReplyAccount = normalizeOptionalString(
705
+ this.getNodeParameter("options.replyAccount", itemIndex, "")
706
+ );
707
+ const deliveryChannel = normalizeOptionalString(replyChannel ?? channel)?.toLowerCase();
708
+ const replyAccount = configuredReplyAccount;
709
+ let effectiveReplyAccount = replyAccount;
710
+ if (telegramBotToken) {
711
+ const telegramConfigSync = syncTelegramChannelConfig({
712
+ botToken: telegramBotToken,
713
+ replyAccount: deliveryChannel === "telegram" ? replyAccount : void 0
714
+ });
715
+ telegramConfigChanged = telegramConfigSync.changed || telegramConfigChanged;
716
+ if (telegramConfigSync.accountId && deliveryChannel === "telegram") {
717
+ effectiveReplyAccount = telegramConfigSync.accountId;
718
+ }
719
+ }
720
+ if (effectiveReplyAccount) {
721
+ args.push("--reply-account", effectiveReplyAccount);
722
+ gatewayParams.replyAccountId = effectiveReplyAccount;
723
+ }
724
+ const verbose = normalizeOptionalString(
725
+ this.getNodeParameter("options.verbose", itemIndex, "")
726
+ );
727
+ if (verbose) {
728
+ args.push("--verbose", verbose);
729
+ }
730
+ const binaryPath = normalizeOptionalString(this.getNodeParameter("options.binaryPath", itemIndex, "")) ?? "openclaw";
731
+ const workingDirectory = normalizeOptionalString(
732
+ this.getNodeParameter("options.workingDirectory", itemIndex, "")
733
+ );
734
+ if (workingDirectory && (!(0, import_fs.existsSync)(workingDirectory) || !(0, import_fs.statSync)(workingDirectory).isDirectory())) {
735
+ throw new import_n8n_workflow.NodeOperationError(
736
+ this.getNode(),
737
+ `Working directory does not exist or is not a directory: ${workingDirectory}`,
738
+ { itemIndex }
739
+ );
740
+ }
741
+ if (telegramConfigChanged && !runLocally) {
742
+ const restartResult = await runOpenClawCli({
743
+ binaryPath,
744
+ args: ["gateway", "restart"],
745
+ cwd: workingDirectory,
746
+ timeoutMs: GATEWAY_RESTART_TIMEOUT_SECONDS * 1e3,
747
+ env: openClawEnv,
748
+ abortSignal: this.getExecutionCancelSignal()
749
+ });
750
+ if (restartResult.exitCode !== 0) {
751
+ throw new import_n8n_workflow.NodeOperationError(
752
+ this.getNode(),
753
+ restartResult.stderr.trim() || restartResult.stdout.trim() || `OpenClaw Gateway restart exited with code ${restartResult.exitCode ?? `signal ${restartResult.signal}`}`,
754
+ { itemIndex }
755
+ );
756
+ }
757
+ }
758
+ const systemMessage = normalizeOptionalString(
759
+ this.getNodeParameter("options.systemMessage", itemIndex, "")
760
+ );
761
+ if (systemMessage) {
762
+ if (runLocally) {
763
+ throw new import_n8n_workflow.NodeOperationError(
764
+ this.getNode(),
765
+ "System Message is only supported in OpenClaw Gateway mode. Disable Run Locally to use it.",
766
+ { itemIndex }
767
+ );
768
+ }
769
+ gatewayParams.extraSystemPrompt = systemMessage;
770
+ const rpcTimeoutMs = getWatchdogTimeoutMs(timeoutSeconds);
771
+ args = getGatewayCallArgs(gatewayParams, rpcTimeoutMs);
772
+ processTimeoutMs = rpcTimeoutMs + 1e4;
773
+ }
774
+ const result = await runOpenClawCli({
775
+ binaryPath,
776
+ args,
777
+ cwd: workingDirectory,
778
+ timeoutMs: processTimeoutMs ?? getWatchdogTimeoutMs(timeoutSeconds),
779
+ env: openClawEnv,
780
+ abortSignal: this.getExecutionCancelSignal()
781
+ });
782
+ if (result.exitCode !== 0) {
783
+ const messageFromStderr = result.stderr.trim();
784
+ const messageFromStdout = result.stdout.trim();
785
+ throw new import_n8n_workflow.NodeOperationError(
786
+ this.getNode(),
787
+ messageFromStderr || messageFromStdout || `OpenClaw CLI exited with code ${result.exitCode ?? `signal ${result.signal}`}`,
788
+ { itemIndex }
789
+ );
790
+ }
791
+ const json = parseOpenClawOutput(result.stdout);
792
+ json.command = result.command;
793
+ if (this.getNodeParameter("options.includeRawOutput", itemIndex, false) === true) {
794
+ json.rawOutput = {
795
+ stdout: result.stdout,
796
+ stderr: result.stderr
797
+ };
798
+ }
799
+ returnData.push({
800
+ json,
801
+ pairedItem: { item: itemIndex }
802
+ });
803
+ } catch (error) {
804
+ if (this.continueOnFail()) {
805
+ returnData.push({
806
+ json: { error: getErrorMessage(error) },
807
+ pairedItem: { item: itemIndex }
808
+ });
809
+ continue;
810
+ }
811
+ throw error;
812
+ }
813
+ }
814
+ return [returnData];
815
+ }
816
+ }
817
+ // Annotate the CommonJS export names for ESM import in node:
818
+ 0 && (module.exports = {
819
+ OpenClawAgentV1
820
+ });
821
+ //# sourceMappingURL=OpenClawAgentV1.node.js.map