@loomcycle/n8n-nodes-loomcycle 1.0.0

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 (99) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +190 -0
  3. package/dist/credentials/LoomCycleApi.credentials.d.ts +21 -0
  4. package/dist/credentials/LoomCycleApi.credentials.js +81 -0
  5. package/dist/credentials/LoomCycleApi.credentials.js.map +1 -0
  6. package/dist/nodes/LoomCycle/LoomCycle.node.d.ts +22 -0
  7. package/dist/nodes/LoomCycle/LoomCycle.node.js +403 -0
  8. package/dist/nodes/LoomCycle/LoomCycle.node.js.map +1 -0
  9. package/dist/nodes/LoomCycle/LoomCycle.node.json +13 -0
  10. package/dist/nodes/LoomCycle/LoomCycle.svg +13 -0
  11. package/dist/nodes/LoomCycle/descriptions/agentdef.d.ts +21 -0
  12. package/dist/nodes/LoomCycle/descriptions/agentdef.js +155 -0
  13. package/dist/nodes/LoomCycle/descriptions/agentdef.js.map +1 -0
  14. package/dist/nodes/LoomCycle/descriptions/channels.d.ts +19 -0
  15. package/dist/nodes/LoomCycle/descriptions/channels.js +164 -0
  16. package/dist/nodes/LoomCycle/descriptions/channels.js.map +1 -0
  17. package/dist/nodes/LoomCycle/descriptions/index.d.ts +6 -0
  18. package/dist/nodes/LoomCycle/descriptions/index.js +16 -0
  19. package/dist/nodes/LoomCycle/descriptions/index.js.map +1 -0
  20. package/dist/nodes/LoomCycle/descriptions/mcpserverdef.d.ts +29 -0
  21. package/dist/nodes/LoomCycle/descriptions/mcpserverdef.js +241 -0
  22. package/dist/nodes/LoomCycle/descriptions/mcpserverdef.js.map +1 -0
  23. package/dist/nodes/LoomCycle/descriptions/memory.d.ts +20 -0
  24. package/dist/nodes/LoomCycle/descriptions/memory.js +119 -0
  25. package/dist/nodes/LoomCycle/descriptions/memory.js.map +1 -0
  26. package/dist/nodes/LoomCycle/descriptions/runs.d.ts +17 -0
  27. package/dist/nodes/LoomCycle/descriptions/runs.js +226 -0
  28. package/dist/nodes/LoomCycle/descriptions/runs.js.map +1 -0
  29. package/dist/nodes/LoomCycle/descriptions/skilldef.d.ts +10 -0
  30. package/dist/nodes/LoomCycle/descriptions/skilldef.js +144 -0
  31. package/dist/nodes/LoomCycle/descriptions/skilldef.js.map +1 -0
  32. package/dist/nodes/LoomCycle/helpers/capability.d.ts +42 -0
  33. package/dist/nodes/LoomCycle/helpers/capability.js +54 -0
  34. package/dist/nodes/LoomCycle/helpers/capability.js.map +1 -0
  35. package/dist/nodes/LoomCycle/helpers/client.d.ts +15 -0
  36. package/dist/nodes/LoomCycle/helpers/client.js +30 -0
  37. package/dist/nodes/LoomCycle/helpers/client.js.map +1 -0
  38. package/dist/nodes/LoomCycle/helpers/envVarHints.d.ts +30 -0
  39. package/dist/nodes/LoomCycle/helpers/envVarHints.js +67 -0
  40. package/dist/nodes/LoomCycle/helpers/envVarHints.js.map +1 -0
  41. package/dist/nodes/LoomCycle/helpers/errors.d.ts +23 -0
  42. package/dist/nodes/LoomCycle/helpers/errors.js +189 -0
  43. package/dist/nodes/LoomCycle/helpers/errors.js.map +1 -0
  44. package/dist/nodes/LoomCycle/helpers/loadOptions.d.ts +24 -0
  45. package/dist/nodes/LoomCycle/helpers/loadOptions.js +89 -0
  46. package/dist/nodes/LoomCycle/helpers/loadOptions.js.map +1 -0
  47. package/dist/nodes/LoomCycle/helpers/segments.d.ts +13 -0
  48. package/dist/nodes/LoomCycle/helpers/segments.js +31 -0
  49. package/dist/nodes/LoomCycle/helpers/segments.js.map +1 -0
  50. package/dist/nodes/LoomCycle/helpers/staticData.d.ts +5 -0
  51. package/dist/nodes/LoomCycle/helpers/staticData.js +31 -0
  52. package/dist/nodes/LoomCycle/helpers/staticData.js.map +1 -0
  53. package/dist/nodes/LoomCycle/helpers/streaming.d.ts +31 -0
  54. package/dist/nodes/LoomCycle/helpers/streaming.js +48 -0
  55. package/dist/nodes/LoomCycle/helpers/streaming.js.map +1 -0
  56. package/dist/nodes/LoomCycleChannelMessage/LoomCycleChannelMessage.node.d.ts +24 -0
  57. package/dist/nodes/LoomCycleChannelMessage/LoomCycleChannelMessage.node.js +162 -0
  58. package/dist/nodes/LoomCycleChannelMessage/LoomCycleChannelMessage.node.js.map +1 -0
  59. package/dist/nodes/LoomCycleChannelMessage/LoomCycleChannelMessage.node.json +13 -0
  60. package/dist/nodes/LoomCycleChannelMessage/LoomCycleChannelMessage.svg +9 -0
  61. package/dist/nodes/LoomCycleChannelMessage/helpers/subscribe.d.ts +20 -0
  62. package/dist/nodes/LoomCycleChannelMessage/helpers/subscribe.js +106 -0
  63. package/dist/nodes/LoomCycleChannelMessage/helpers/subscribe.js.map +1 -0
  64. package/dist/nodes/LoomCycleChannelTool/LoomCycleChannelTool.node.d.ts +5 -0
  65. package/dist/nodes/LoomCycleChannelTool/LoomCycleChannelTool.node.js +114 -0
  66. package/dist/nodes/LoomCycleChannelTool/LoomCycleChannelTool.node.js.map +1 -0
  67. package/dist/nodes/LoomCycleChannelTool/LoomCycleChannelTool.node.json +13 -0
  68. package/dist/nodes/LoomCycleChannelTool/LoomCycleChannelTool.svg +13 -0
  69. package/dist/nodes/LoomCycleMcpServerTool/LoomCycleMcpServerTool.node.d.ts +5 -0
  70. package/dist/nodes/LoomCycleMcpServerTool/LoomCycleMcpServerTool.node.js +259 -0
  71. package/dist/nodes/LoomCycleMcpServerTool/LoomCycleMcpServerTool.node.js.map +1 -0
  72. package/dist/nodes/LoomCycleMcpServerTool/LoomCycleMcpServerTool.node.json +13 -0
  73. package/dist/nodes/LoomCycleMcpServerTool/LoomCycleMcpServerTool.svg +14 -0
  74. package/dist/nodes/LoomCycleMemoryTool/LoomCycleMemoryTool.node.d.ts +5 -0
  75. package/dist/nodes/LoomCycleMemoryTool/LoomCycleMemoryTool.node.js +108 -0
  76. package/dist/nodes/LoomCycleMemoryTool/LoomCycleMemoryTool.node.js.map +1 -0
  77. package/dist/nodes/LoomCycleMemoryTool/LoomCycleMemoryTool.node.json +13 -0
  78. package/dist/nodes/LoomCycleMemoryTool/LoomCycleMemoryTool.svg +11 -0
  79. package/dist/nodes/LoomCycleRunCompleted/LoomCycleRunCompleted.node.d.ts +18 -0
  80. package/dist/nodes/LoomCycleRunCompleted/LoomCycleRunCompleted.node.js +188 -0
  81. package/dist/nodes/LoomCycleRunCompleted/LoomCycleRunCompleted.node.js.map +1 -0
  82. package/dist/nodes/LoomCycleRunCompleted/LoomCycleRunCompleted.node.json +13 -0
  83. package/dist/nodes/LoomCycleRunCompleted/LoomCycleRunCompleted.svg +10 -0
  84. package/dist/nodes/LoomCycleRunCompleted/helpers/poll.d.ts +12 -0
  85. package/dist/nodes/LoomCycleRunCompleted/helpers/poll.js +69 -0
  86. package/dist/nodes/LoomCycleRunCompleted/helpers/poll.js.map +1 -0
  87. package/dist/nodes/LoomCycleRunCompleted/helpers/sse.d.ts +29 -0
  88. package/dist/nodes/LoomCycleRunCompleted/helpers/sse.js +61 -0
  89. package/dist/nodes/LoomCycleRunCompleted/helpers/sse.js.map +1 -0
  90. package/dist/nodes/LoomCycleSubAgentTool/LoomCycleSubAgentTool.node.d.ts +5 -0
  91. package/dist/nodes/LoomCycleSubAgentTool/LoomCycleSubAgentTool.node.js +131 -0
  92. package/dist/nodes/LoomCycleSubAgentTool/LoomCycleSubAgentTool.node.js.map +1 -0
  93. package/dist/nodes/LoomCycleSubAgentTool/LoomCycleSubAgentTool.node.json +13 -0
  94. package/dist/nodes/LoomCycleSubAgentTool/LoomCycleSubAgentTool.svg +12 -0
  95. package/dist/nodes/_shared/clusterTool.d.ts +19 -0
  96. package/dist/nodes/_shared/clusterTool.js +36 -0
  97. package/dist/nodes/_shared/clusterTool.js.map +1 -0
  98. package/dist/tsconfig.tsbuildinfo +1 -0
  99. package/package.json +86 -0
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LoomCycleChannelMessage = void 0;
4
+ const client_1 = require("../LoomCycle/helpers/client");
5
+ const errors_1 = require("../LoomCycle/helpers/errors");
6
+ const loadOptions_1 = require("../LoomCycle/helpers/loadOptions");
7
+ const subscribe_1 = require("./helpers/subscribe");
8
+ /**
9
+ * `LoomCycle: Channel Message` — trigger that fires when a new
10
+ * message lands on a watched loomcycle channel.
11
+ *
12
+ * Two delivery modes:
13
+ * - `auto-ack`: direct long-poll subscribeChannel (at-most-once;
14
+ * fastest path)
15
+ * - `peek-ack`: peekChannel + explicit ackChannel after emit (at-
16
+ * least-once; survives workflow crashes mid-processing)
17
+ *
18
+ * Both modes ride the v0.9.2 PR #180 Channel CRUD wire surface — no
19
+ * one-shot agents.
20
+ */
21
+ class LoomCycleChannelMessage {
22
+ constructor() {
23
+ this.description = {
24
+ displayName: 'LoomCycle: Channel Message',
25
+ name: 'loomCycleChannelMessage',
26
+ icon: 'file:LoomCycleChannelMessage.svg',
27
+ group: ['trigger'],
28
+ version: 1,
29
+ description: 'Fires when a new message arrives on a loomcycle channel',
30
+ defaults: { name: 'LoomCycle: Channel Message' },
31
+ // eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node
32
+ inputs: [],
33
+ outputs: ['main'],
34
+ credentials: [{ name: 'loomCycleApi', required: true }],
35
+ properties: [
36
+ {
37
+ displayName: 'Channel Name or ID',
38
+ name: 'channel',
39
+ type: 'options',
40
+ typeOptions: { loadOptionsMethod: 'loadChannels' },
41
+ default: '',
42
+ required: true,
43
+ description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
44
+ },
45
+ {
46
+ displayName: 'Scope',
47
+ name: 'scope',
48
+ type: 'options',
49
+ default: 'global',
50
+ options: [
51
+ { name: 'Global (Admin)', value: 'global', description: 'Single global queue for the channel' },
52
+ { name: 'User (Per-User)', value: 'user', description: 'Per-user queue; userId required' },
53
+ ],
54
+ },
55
+ {
56
+ displayName: 'User ID',
57
+ name: 'userId',
58
+ type: 'string',
59
+ default: '',
60
+ displayOptions: { show: { scope: ['user'] } },
61
+ description: 'User_id for the per-user scope. Empty = use the credential\'s Default User ID.',
62
+ },
63
+ {
64
+ displayName: 'Delivery Mode',
65
+ name: 'deliveryMode',
66
+ type: 'options',
67
+ default: 'auto-ack',
68
+ options: [
69
+ {
70
+ name: 'Auto-Ack (At-Most-Once)',
71
+ value: 'auto-ack',
72
+ description: 'Direct long-poll subscribe; substrate auto-commits the cursor',
73
+ },
74
+ {
75
+ name: 'Peek + Explicit Ack (At-Least-Once)',
76
+ value: 'peek-ack',
77
+ description: 'Peek non-destructively, emit, then ack — survives crashes mid-processing',
78
+ },
79
+ ],
80
+ },
81
+ {
82
+ displayName: 'Additional Fields',
83
+ name: 'additionalFields',
84
+ type: 'collection',
85
+ placeholder: 'Add Field',
86
+ default: {},
87
+ options: [
88
+ {
89
+ displayName: 'Max Messages per Batch',
90
+ name: 'maxMessages',
91
+ type: 'number',
92
+ default: 10,
93
+ typeOptions: { minValue: 1, maxValue: 1000 },
94
+ description: 'Maximum number of messages to return per long-poll round',
95
+ },
96
+ {
97
+ displayName: 'Wait Ms',
98
+ name: 'waitMs',
99
+ type: 'number',
100
+ default: 30000,
101
+ typeOptions: { minValue: 0, maxValue: 60000 },
102
+ description: 'Long-poll wait timeout for auto-ack mode (server cap typically 30s). For peek-ack mode, sleep between empty peeks.',
103
+ },
104
+ {
105
+ displayName: 'Error Backoff (Ms)',
106
+ name: 'backoffMs',
107
+ type: 'number',
108
+ default: 5000,
109
+ typeOptions: { minValue: 500, maxValue: 60000 },
110
+ description: 'How long to wait after an error before retrying',
111
+ },
112
+ ],
113
+ },
114
+ ],
115
+ };
116
+ this.methods = {
117
+ loadOptions: {
118
+ loadChannels: loadOptions_1.loadChannels,
119
+ },
120
+ };
121
+ }
122
+ async trigger() {
123
+ const channel = this.getNodeParameter('channel', '');
124
+ const scope = this.getNodeParameter('scope', 'global') ?? 'global';
125
+ const userIdParam = this.getNodeParameter('userId', '') ?? '';
126
+ const deliveryMode = this.getNodeParameter('deliveryMode', 'auto-ack') ?? 'auto-ack';
127
+ const additionalFields = this.getNodeParameter('additionalFields', {}) ?? {};
128
+ if (!channel) {
129
+ throw (0, errors_1.wrapLoomcycleError)(new Error('Channel name is required'), this.getNode());
130
+ }
131
+ const userId = scope === 'user' ? userIdParam || (await (0, client_1.getCredentialDefault)(this, 'userId')) : undefined;
132
+ if (scope === 'user' && !userId) {
133
+ throw (0, errors_1.wrapLoomcycleError)(new Error('User ID is required when scope=user — set per-node or as Default User ID on the credential'), this.getNode());
134
+ }
135
+ const client = await (0, client_1.getClient)(this);
136
+ const ac = new AbortController();
137
+ const loopOpts = {
138
+ client,
139
+ channel,
140
+ scope,
141
+ userId,
142
+ deliveryMode,
143
+ maxMessages: additionalFields.maxMessages ?? 10,
144
+ waitMs: additionalFields.waitMs ?? 30000,
145
+ backoffMs: additionalFields.backoffMs ?? 5000,
146
+ signal: ac.signal,
147
+ };
148
+ void subscribe_1.runSubscribeLoop.call(this, loopOpts);
149
+ async function manualTriggerFunction() {
150
+ const oneShotAc = new AbortController();
151
+ await subscribe_1.subscribeOnce.call(this, { ...loopOpts, signal: oneShotAc.signal });
152
+ }
153
+ return {
154
+ closeFunction: async () => {
155
+ ac.abort();
156
+ },
157
+ manualTriggerFunction: manualTriggerFunction.bind(this),
158
+ };
159
+ }
160
+ }
161
+ exports.LoomCycleChannelMessage = LoomCycleChannelMessage;
162
+ //# sourceMappingURL=LoomCycleChannelMessage.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoomCycleChannelMessage.node.js","sourceRoot":"","sources":["../../../nodes/LoomCycleChannelMessage/LoomCycleChannelMessage.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ {
2
+ "node": "@loomcycle/n8n-nodes-loomcycle.loomCycleChannelMessage",
3
+ "nodeVersion": "1.0",
4
+ "codexVersion": "1.0",
5
+ "categories": ["AI"],
6
+ "resources": {
7
+ "primaryDocumentation": [
8
+ {
9
+ "url": "https://github.com/denn-gubsky/n8n-nodes-loomcycle#trigger-nodes"
10
+ }
11
+ ]
12
+ }
13
+ }
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" width="60" height="60">
3
+ <title>LoomCycle: Channel Message</title>
4
+ <circle cx="30" cy="30" r="28" fill="#0f172a"/>
5
+ <g fill="none" stroke="#22d3ee" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
6
+ <rect x="15" y="20" width="30" height="20" rx="4"/>
7
+ <path d="M15 24 L30 32 L45 24"/>
8
+ </g>
9
+ </svg>
@@ -0,0 +1,20 @@
1
+ import type { ITriggerFunctions } from 'n8n-workflow';
2
+ import type { ChannelScope, LoomcycleClient } from '@loomcycle/client';
3
+ export interface SubscribeOptions {
4
+ client: LoomcycleClient;
5
+ channel: string;
6
+ scope: ChannelScope;
7
+ userId?: string;
8
+ deliveryMode: 'auto-ack' | 'peek-ack';
9
+ maxMessages: number;
10
+ waitMs: number;
11
+ backoffMs: number;
12
+ signal: AbortSignal;
13
+ }
14
+ export declare function runSubscribeLoop(this: ITriggerFunctions, opts: SubscribeOptions): Promise<void>;
15
+ /**
16
+ * Single long-poll round. Returns the number of messages emitted.
17
+ * Exposed as a separate function so manualTriggerFunction can do a
18
+ * one-shot listen.
19
+ */
20
+ export declare function subscribeOnce(this: ITriggerFunctions, opts: SubscribeOptions): Promise<number>;
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runSubscribeLoop = runSubscribeLoop;
4
+ exports.subscribeOnce = subscribeOnce;
5
+ const staticData_1 = require("../../LoomCycle/helpers/staticData");
6
+ /**
7
+ * Long-poll subscribe loop for the LoomCycleChannelMessage trigger.
8
+ *
9
+ * Two delivery shapes:
10
+ * - `auto-ack` (default): direct subscribeChannel — substrate
11
+ * auto-commits the cursor on a non-empty batch (at-most-once).
12
+ * - `peek-ack`: peekChannel + ackChannel-after-emit. Survives
13
+ * workflow crashes between "loomcycle returned the batch" and
14
+ * "downstream node finished processing" (at-least-once).
15
+ *
16
+ * On any error, surfaces via emitError and waits one backoff before
17
+ * retrying. The outer abort signal breaks both error-retry sleep and
18
+ * the next long-poll round-trip.
19
+ */
20
+ const CURSOR_KEY = 'channelMessageCursor';
21
+ const MAX_CONSECUTIVE_FAILURES = 5;
22
+ async function runSubscribeLoop(opts) {
23
+ let consecutiveFailures = 0;
24
+ while (!opts.signal.aborted) {
25
+ try {
26
+ const emitted = await subscribeOnce.call(this, opts);
27
+ consecutiveFailures = 0;
28
+ if (emitted === 0) {
29
+ // long-poll returned empty (timed out); loop immediately
30
+ continue;
31
+ }
32
+ }
33
+ catch (err) {
34
+ if (opts.signal.aborted)
35
+ return;
36
+ consecutiveFailures += 1;
37
+ if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
38
+ // Terminal — bail out so n8n's trigger lifecycle deactivates
39
+ // rather than spinning indefinitely on (e.g.) a permanent
40
+ // ChannelCursorRegressionError on ack.
41
+ this.emitError(err);
42
+ return;
43
+ }
44
+ await sleep(opts.backoffMs, opts.signal);
45
+ }
46
+ }
47
+ }
48
+ /**
49
+ * Single long-poll round. Returns the number of messages emitted.
50
+ * Exposed as a separate function so manualTriggerFunction can do a
51
+ * one-shot listen.
52
+ */
53
+ async function subscribeOnce(opts) {
54
+ if (opts.deliveryMode === 'peek-ack') {
55
+ const persistedCursor = (0, staticData_1.readCursor)(this, CURSOR_KEY);
56
+ const resp = await opts.client.peekChannel(opts.channel, {
57
+ scope: opts.scope,
58
+ userId: opts.userId,
59
+ fromCursor: persistedCursor || undefined,
60
+ maxMessages: opts.maxMessages,
61
+ signal: opts.signal,
62
+ });
63
+ const messages = resp.messages ?? [];
64
+ if (messages.length === 0) {
65
+ // Peek doesn't long-poll; sleep waitMs before next iteration
66
+ // so we don't spin.
67
+ await sleep(opts.waitMs, opts.signal);
68
+ return 0;
69
+ }
70
+ this.emit([this.helpers.returnJsonArray(messages.map((m) => m))]);
71
+ const lastCursor = messages[messages.length - 1].id;
72
+ await opts.client.ackChannel(opts.channel, {
73
+ scope: opts.scope,
74
+ userId: opts.userId,
75
+ cursor: lastCursor,
76
+ signal: opts.signal,
77
+ });
78
+ (0, staticData_1.writeCursor)(this, CURSOR_KEY, lastCursor);
79
+ return messages.length;
80
+ }
81
+ // auto-ack — direct subscribe
82
+ const resp = await opts.client.subscribeChannel(opts.channel, {
83
+ scope: opts.scope,
84
+ userId: opts.userId,
85
+ maxMessages: opts.maxMessages,
86
+ waitMs: opts.waitMs,
87
+ signal: opts.signal,
88
+ });
89
+ const messages = resp.messages ?? [];
90
+ if (messages.length === 0)
91
+ return 0;
92
+ this.emit([this.helpers.returnJsonArray(messages.map((m) => m))]);
93
+ return messages.length;
94
+ }
95
+ function sleep(ms, signal) {
96
+ return new Promise((resolve) => {
97
+ if (signal.aborted)
98
+ return resolve();
99
+ const t = setTimeout(resolve, ms);
100
+ signal.addEventListener('abort', () => {
101
+ clearTimeout(t);
102
+ resolve();
103
+ });
104
+ });
105
+ }
106
+ //# sourceMappingURL=subscribe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscribe.js","sourceRoot":"","sources":["../../../../nodes/LoomCycleChannelMessage/helpers/subscribe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { INodeType, INodeTypeDescription, ISupplyDataFunctions, SupplyData } from 'n8n-workflow';
2
+ export declare class LoomCycleChannelTool implements INodeType {
3
+ description: INodeTypeDescription;
4
+ supplyData(this: ISupplyDataFunctions): Promise<SupplyData>;
5
+ }
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LoomCycleChannelTool = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const zod_1 = require("zod");
6
+ const client_1 = require("../LoomCycle/helpers/client");
7
+ const clusterTool_1 = require("../_shared/clusterTool");
8
+ /**
9
+ * `LoomCycle Channel Tool` — cluster sub-node exposing Channel Publish +
10
+ * Peek as a tool the AI Agent can call. (Subscribe is intentionally a
11
+ * trigger node, not a tool; Ack would couple to durable cursor state
12
+ * better handled by the action node.)
13
+ */
14
+ const ChannelInputSchema = zod_1.z.object({
15
+ op: zod_1.z.enum(['publish', 'peek']).describe('Channel operation to invoke'),
16
+ channel: zod_1.z.string().describe('Channel name'),
17
+ scope: zod_1.z.enum(['global', 'user']).default('global').describe('Channel scope'),
18
+ userId: zod_1.z
19
+ .string()
20
+ .optional()
21
+ .describe('User_id for scope=user. Falls through to the credential default if empty.'),
22
+ payload: zod_1.z
23
+ .unknown()
24
+ .optional()
25
+ .describe('JSON-serialisable payload (publish only). Required for publish.'),
26
+ deliverAt: zod_1.z
27
+ .string()
28
+ .optional()
29
+ .describe('Optional RFC3339 deferred-delivery timestamp (publish only)'),
30
+ fromCursor: zod_1.z.string().optional().describe('Resume cursor (peek only). Empty = oldest non-expired row.'),
31
+ maxMessages: zod_1.z
32
+ .number()
33
+ .int()
34
+ .positive()
35
+ .optional()
36
+ .describe('Max messages to return (peek only). Defaults to 10 substrate-side.'),
37
+ });
38
+ class LoomCycleChannelTool {
39
+ constructor() {
40
+ this.description = {
41
+ displayName: 'LoomCycle Channel Tool',
42
+ name: 'loomCycleChannelTool',
43
+ icon: 'file:LoomCycleChannelTool.svg',
44
+ group: ['transform'],
45
+ version: 1,
46
+ description: 'Loomcycle Channel ops (publish + peek) as a tool the AI Agent can call',
47
+ defaults: { name: 'LoomCycle Channel Tool' },
48
+ codex: { categories: ['AI'], subcategories: { AI: ['Tools'] } },
49
+ // eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node
50
+ inputs: [],
51
+ // eslint-disable-next-line n8n-nodes-base/node-class-description-outputs-wrong
52
+ outputs: [n8n_workflow_1.NodeConnectionTypes.AiTool],
53
+ outputNames: ['Tool'],
54
+ credentials: [{ name: 'loomCycleApi', required: true }],
55
+ properties: [
56
+ {
57
+ displayName: 'Tool Name',
58
+ name: 'toolName',
59
+ type: 'string',
60
+ default: 'loomcycle_channel',
61
+ required: true,
62
+ description: 'Name of the tool surfaced to the parent AI Agent',
63
+ },
64
+ {
65
+ displayName: 'Tool Description',
66
+ name: 'toolDescription',
67
+ type: 'string',
68
+ typeOptions: { rows: 3 },
69
+ default: 'Publish or peek at loomcycle channel messages. Use op=publish+channel+payload to publish; op=peek+channel to non-destructively read.',
70
+ description: 'Description the AI Agent sees when deciding whether to call the tool',
71
+ },
72
+ ],
73
+ };
74
+ }
75
+ async supplyData() {
76
+ const toolName = this.getNodeParameter('toolName', 0, 'loomcycle_channel');
77
+ const toolDescription = this.getNodeParameter('toolDescription', 0, '');
78
+ const client = await (0, client_1.getClient)(this);
79
+ const credentialUserIdDefault = await (0, client_1.getCredentialDefault)(this, 'userId');
80
+ const tool = (0, clusterTool_1.buildTool)({
81
+ name: toolName,
82
+ description: toolDescription,
83
+ schema: ChannelInputSchema,
84
+ fn: async (args) => {
85
+ const scope = args.scope ?? 'global';
86
+ const userId = scope === 'user' ? args.userId || credentialUserIdDefault : undefined;
87
+ if (scope === 'user' && !userId) {
88
+ throw new Error('userId required when scope=user (set on tool args or as credential default)');
89
+ }
90
+ if (args.op === 'publish') {
91
+ if (args.payload === undefined) {
92
+ throw new Error('payload is required for publish');
93
+ }
94
+ return client.publishChannel(args.channel, {
95
+ scope,
96
+ userId,
97
+ payload: args.payload,
98
+ deliverAt: args.deliverAt,
99
+ });
100
+ }
101
+ // peek
102
+ return client.peekChannel(args.channel, {
103
+ scope,
104
+ userId,
105
+ fromCursor: args.fromCursor,
106
+ maxMessages: args.maxMessages,
107
+ });
108
+ },
109
+ });
110
+ return { response: tool };
111
+ }
112
+ }
113
+ exports.LoomCycleChannelTool = LoomCycleChannelTool;
114
+ //# sourceMappingURL=LoomCycleChannelTool.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoomCycleChannelTool.node.js","sourceRoot":"","sources":["../../../nodes/LoomCycleChannelTool/LoomCycleChannelTool.node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ {
2
+ "node": "@loomcycle/n8n-nodes-loomcycle.loomCycleChannelTool",
3
+ "nodeVersion": "1.0",
4
+ "codexVersion": "1.0",
5
+ "categories": ["AI"],
6
+ "resources": {
7
+ "primaryDocumentation": [
8
+ {
9
+ "url": "https://github.com/denn-gubsky/n8n-nodes-loomcycle#cluster-sub-nodes"
10
+ }
11
+ ]
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" width="60" height="60">
3
+ <title>LoomCycle Channel Tool</title>
4
+ <circle cx="30" cy="30" r="28" fill="#0f172a"/>
5
+ <g fill="none" stroke="#22d3ee" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
6
+ <path d="M16 22 L44 22"/>
7
+ <path d="M16 30 L44 30"/>
8
+ <path d="M16 38 L44 38"/>
9
+ <circle cx="14" cy="22" r="2" fill="#22d3ee"/>
10
+ <circle cx="46" cy="30" r="2" fill="#22d3ee"/>
11
+ <circle cx="14" cy="38" r="2" fill="#22d3ee"/>
12
+ </g>
13
+ </svg>
@@ -0,0 +1,5 @@
1
+ import type { INodeType, INodeTypeDescription, ISupplyDataFunctions, SupplyData } from 'n8n-workflow';
2
+ export declare class LoomCycleMcpServerTool implements INodeType {
3
+ description: INodeTypeDescription;
4
+ supplyData(this: ISupplyDataFunctions): Promise<SupplyData>;
5
+ }