@loopthink/n8n-nodes-loopthink 0.13.0 → 0.14.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.
- package/README.md +29 -13
- package/dist/nodes/Loopthink/result.operation.js +22 -6
- package/dist/nodes/Loopthink/result.operation.js.map +1 -1
- package/dist/nodes/LoopthinkRunner/workflowTools.d.ts +0 -1
- package/dist/nodes/LoopthinkRunner/workflowTools.js +0 -3
- package/dist/nodes/LoopthinkRunner/workflowTools.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -125,11 +125,12 @@ past the last id it was given by passing `id_after`. Both are ordinary filters i
|
|
|
125
125
|
already understands, so nothing opaque travels back and forth and the model can
|
|
126
126
|
also bisect a large range instead of only walking forward.
|
|
127
127
|
|
|
128
|
-
**`$json.
|
|
129
|
-
ready to use. That node cannot take its conditions from an expression:
|
|
130
|
-
rows in the editor, fixed when the workflow is built, and the list as a
|
|
131
|
-
cannot be computed, because n8n walks a string handed to a multi-value
|
|
132
|
-
character by character and quietly produces one empty condition per
|
|
128
|
+
**`$json.params`** is what fills a Data Table node's condition rows, and it
|
|
129
|
+
arrives ready to use. That node cannot take its conditions from an expression:
|
|
130
|
+
they are rows in the editor, fixed when the workflow is built, and the list as a
|
|
131
|
+
whole cannot be computed, because n8n walks a string handed to a multi-value
|
|
132
|
+
collection character by character and quietly produces one empty condition per
|
|
133
|
+
character.
|
|
133
134
|
|
|
134
135
|
So every row has to hold a value on every call, including the ones the model left
|
|
135
136
|
empty. The platform sends them, keyed by the tool's parameter name: a bound so
|
|
@@ -138,14 +139,20 @@ match. One key, one plain value:
|
|
|
138
139
|
|
|
139
140
|
| Tool parameter | Column | Comparison | Value |
|
|
140
141
|
|---|---|---|---|
|
|
141
|
-
| `created_after` | `createdAt` | Or Later | `{{ $json.
|
|
142
|
-
| `created_before` | `createdAt` | Or Earlier | `{{ $json.
|
|
143
|
-
| `status` | `status` | Contains | `{{ $json.
|
|
144
|
-
| `id_after` | `id` | Greater Than | `{{ $json.
|
|
142
|
+
| `created_after` | `createdAt` | Or Later | `{{ $json.params.created_after }}` |
|
|
143
|
+
| `created_before` | `createdAt` | Or Earlier | `{{ $json.params.created_before }}` |
|
|
144
|
+
| `status` | `status` | Contains | `{{ $json.params.status }}` |
|
|
145
|
+
| `id_after` | `id` | Greater Than | `{{ $json.params.id_after }}` |
|
|
145
146
|
|
|
146
147
|
The comparison is chosen once from the dropdown and never changes, so it is not
|
|
147
|
-
in the data.
|
|
148
|
-
|
|
148
|
+
in the data.
|
|
149
|
+
|
|
150
|
+
Every key under `params` is a parameter the tool declared, under the name its
|
|
151
|
+
author typed. Nothing is added on the way. A tool that wants a cap declares
|
|
152
|
+
`limit` like any other parameter, and then the reading node's **Limit** is
|
|
153
|
+
`{{ $json.params.limit + 1 }}` — one more than the answer carries, which is where
|
|
154
|
+
`truncated` comes from. A tool that declares `sort` gets `ASC` or `DESC` under
|
|
155
|
+
that name, ready for **Order**.
|
|
149
156
|
|
|
150
157
|
`id_after` is what lets a model read on, and it is an ordinary parameter like any
|
|
151
158
|
other. Compare it with **Greater Than** rather than Or Later, so that it means
|
|
@@ -153,10 +160,19 @@ what it says and the boundary row is not returned twice.
|
|
|
153
160
|
|
|
154
161
|

|
|
155
162
|
|
|
156
|
-
Paging is by **cursor**, not offset, so the source does the work: `id < c` with a
|
|
157
|
-
Limit is one comparison it expresses natively and it hands back only the page.
|
|
158
163
|
See [examples/](examples) for three sources worked through.
|
|
159
164
|
|
|
165
|
+
### When an answer is too large
|
|
166
|
+
|
|
167
|
+
One answer carries 300 KB. Past that **Send Result** does not send the rows at
|
|
168
|
+
all: it answers with a sentence naming the size and the row count and saying to
|
|
169
|
+
narrow the filters or pass a smaller limit, which a model acts on by splitting
|
|
170
|
+
its question and asking again.
|
|
171
|
+
|
|
172
|
+
Measured before the POST on purpose. Sent anyway, an oversized body is rejected
|
|
173
|
+
by whichever layer notices first, the call stays unanswered, and the caller waits
|
|
174
|
+
out its timeout to learn nothing at all.
|
|
175
|
+
|
|
160
176
|
## Masking
|
|
161
177
|
|
|
162
178
|
Masking runs **here**, before anything travels back. Only masked data ever passes
|
|
@@ -16,6 +16,20 @@ function pagePayload(ctx, respondWith, items) {
|
|
|
16
16
|
const capped = Number.isFinite(limit) && limit > 0;
|
|
17
17
|
return { items: capped ? rows.slice(0, limit) : rows, truncated: capped && rows.length > limit };
|
|
18
18
|
}
|
|
19
|
+
const MAX_RESULT_BYTES = 300 * 1024;
|
|
20
|
+
function tooLargeMessage(bytes, rows) {
|
|
21
|
+
const kb = (n) => `${Math.round(n / 1024)} KB`;
|
|
22
|
+
const counted = rows === undefined ? '' : `${rows.toLocaleString('en-US')} rows, `;
|
|
23
|
+
return (`The result was too large to return: ${counted}${kb(bytes)}, and one answer can carry ${kb(MAX_RESULT_BYTES)}. ` +
|
|
24
|
+
'Nothing was returned. Ask for a smaller slice and combine the answers: narrow the filters, for instance a ' +
|
|
25
|
+
'shorter date range or a more specific match, or pass a smaller limit if this tool takes one.');
|
|
26
|
+
}
|
|
27
|
+
function countRows(payload) {
|
|
28
|
+
if (Array.isArray(payload))
|
|
29
|
+
return payload.length;
|
|
30
|
+
const items = payload?.items;
|
|
31
|
+
return Array.isArray(items) ? items.length : undefined;
|
|
32
|
+
}
|
|
19
33
|
function parseRequest(value) {
|
|
20
34
|
if (typeof value === 'string') {
|
|
21
35
|
try {
|
|
@@ -67,9 +81,9 @@ exports.resultFields = [
|
|
|
67
81
|
displayName: 'Limit',
|
|
68
82
|
name: 'pageSize',
|
|
69
83
|
type: 'number',
|
|
70
|
-
default: "={{ $('loopthink Runner').first().json.
|
|
84
|
+
default: "={{ $('loopthink Runner').first().json.params.limit }}",
|
|
71
85
|
displayOptions: { show: { respondWith: ['page'] } },
|
|
72
|
-
description: 'How many rows to answer with.
|
|
86
|
+
description: 'How many rows to answer with. Set the reading node\'s own limit to {{ $json.params.limit + 1 }}: if that extra row arrives, the answer is marked truncated.',
|
|
73
87
|
},
|
|
74
88
|
{
|
|
75
89
|
displayName: 'Status',
|
|
@@ -110,10 +124,12 @@ async function executeResult() {
|
|
|
110
124
|
}
|
|
111
125
|
else {
|
|
112
126
|
const payload = pagePayload(this, respondWith, items);
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
127
|
+
const data = (0, masking_1.applyMasking)(payload, (0, masking_1.rulesForScope)(request.masking ?? [], request.scope ?? undefined));
|
|
128
|
+
const size = Buffer.byteLength(JSON.stringify(data ?? null), 'utf8');
|
|
129
|
+
body =
|
|
130
|
+
size > MAX_RESULT_BYTES
|
|
131
|
+
? { error: tooLargeMessage(size, countRows(data)) }
|
|
132
|
+
: { status: this.getNodeParameter('status', 0), data };
|
|
117
133
|
}
|
|
118
134
|
const response = await this.helpers.httpRequest({
|
|
119
135
|
method: 'POST',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result.operation.js","sourceRoot":"","sources":["../../../nodes/Loopthink/result.operation.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"result.operation.js","sourceRoot":"","sources":["../../../nodes/Loopthink/result.operation.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,12 +19,9 @@ function emitJob(ctx, job) {
|
|
|
19
19
|
{
|
|
20
20
|
requestId: job.requestId,
|
|
21
21
|
tool: job.tool,
|
|
22
|
-
request: job.request,
|
|
23
22
|
params: isParamsRequest(job.request) || isStatementRequest(job.request)
|
|
24
23
|
? job.request.params
|
|
25
24
|
: {},
|
|
26
|
-
statement: isStatementRequest(job.request) ? job.request.statement : null,
|
|
27
|
-
q: isParamsRequest(job.request) ? (job.request.q ?? {}) : {},
|
|
28
25
|
masking: job.masking ?? [],
|
|
29
26
|
scope: job.scope ?? null,
|
|
30
27
|
leaseUntil: job.leaseUntil,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflowTools.js","sourceRoot":"","sources":["../../../nodes/LoopthinkRunner/workflowTools.ts"],"names":[],"mappings":";;;AAiFA,0CAEC;AAED,gDAIC;AAyBD,
|
|
1
|
+
{"version":3,"file":"workflowTools.js","sourceRoot":"","sources":["../../../nodes/LoopthinkRunner/workflowTools.ts"],"names":[],"mappings":";;;AAiFA,0CAEC;AAED,gDAIC;AAyBD,0BAkBC;AAnDD,SAAgB,eAAe,CAAC,OAAiC;IAChE,OAAQ,OAAyB,EAAE,IAAI,KAAK,QAAQ,CAAC;AACtD,CAAC;AAED,SAAgB,kBAAkB,CACjC,OAAiC;IAEjC,OAAQ,OAA4B,EAAE,IAAI,KAAK,WAAW,CAAC;AAC5D,CAAC;AAWY,QAAA,cAAc,GAA+B;IAGzD,EAAE,IAAI,EAAE,MAA0C,EAAE;CACpD,CAAC;AAUF,SAAgB,OAAO,CAAC,GAAsB,EAAE,GAAkB;IACjE,GAAG,CAAC,IAAI,CAAC;QACR,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC;YAC3B;gBACC,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,IAAI,EAAE,GAAG,CAAC,IAAI;gBAId,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC;oBACtE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM;oBACpB,CAAC,CAAC,EAAE;gBACL,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE;gBAC1B,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,IAAI;gBACxB,UAAU,EAAE,GAAG,CAAC,UAAU;aAC1B;SACD,CAAC;KACF,CAAC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loopthink/n8n-nodes-loopthink",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Run loopthink MCP tools from inside your own network. The node reaches out to loopthink, claims tool calls, executes them against your internal HTTP APIs and returns masked results \u2014 no inbound connection required.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"n8n-community-node-package",
|