n8n-nodes-tendem 0.1.2 → 0.2.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 +50 -2
- package/dist/credentials/TendemApi.credentials.js +1 -1
- package/dist/credentials/TendemApi.credentials.js.map +1 -1
- package/dist/nodes/Tendem/Tendem.node.json +2 -2
- package/dist/nodes/Tendem/tools.d.ts +1 -0
- package/dist/nodes/Tendem/tools.js +28 -1
- package/dist/nodes/Tendem/tools.js.map +1 -1
- package/dist/nodes/Tendem/transport.d.ts +1 -1
- package/dist/nodes/Tendem/transport.js +1 -1
- package/dist/nodes/TendemExpert/TendemExpert.node.d.ts +5 -0
- package/dist/nodes/TendemExpert/TendemExpert.node.js +145 -0
- package/dist/nodes/TendemExpert/TendemExpert.node.js.map +1 -0
- package/dist/nodes/TendemExpert/TendemExpert.node.json +18 -0
- package/dist/nodes/TendemExpert/descriptions.d.ts +3 -0
- package/dist/nodes/TendemExpert/descriptions.js +159 -0
- package/dist/nodes/TendemExpert/descriptions.js.map +1 -0
- package/dist/nodes/TendemExpert/engine.d.ts +42 -0
- package/dist/nodes/TendemExpert/engine.js +248 -0
- package/dist/nodes/TendemExpert/engine.js.map +1 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# n8n-nodes-tendem
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
n8n community nodes for [Tendem](https://tendem.ai) — a hybrid
|
|
4
4
|
AI + human task service. You submit a task in plain English, Tendem's orchestrator
|
|
5
5
|
scopes it in a chat and quotes a transparent price, and once a **human** approves
|
|
6
6
|
the spend, a vetted expert executes it and returns verified results as markdown
|
|
@@ -14,6 +14,8 @@ policy.
|
|
|
14
14
|
|
|
15
15
|
- [Installation](#installation)
|
|
16
16
|
- [Credentials](#credentials)
|
|
17
|
+
- [The two nodes](#the-two-nodes)
|
|
18
|
+
- [Tendem Expert: the high-level node](#tendem-expert-the-high-level-node)
|
|
17
19
|
- [Operations](#operations)
|
|
18
20
|
- [Approving a task spends real money](#approving-a-task-spends-real-money)
|
|
19
21
|
- [Worked example](#worked-example-research-brief-end-to-end)
|
|
@@ -52,8 +54,54 @@ Tendem also supports interactive OAuth, which is what the Claude Code / Cursor /
|
|
|
52
54
|
Gemini plugins use. n8n workflows run unattended, so this node deliberately does
|
|
53
55
|
API keys only.
|
|
54
56
|
|
|
57
|
+
## The two nodes
|
|
58
|
+
|
|
59
|
+
The package installs two nodes sharing one credential:
|
|
60
|
+
|
|
61
|
+
- **Tendem Expert** — the high-level node. Five lifecycle operations with the delegation
|
|
62
|
+
choreography built in; the one to reach for first, and the one to hand to AI Agents.
|
|
63
|
+
- **Tendem** — the raw protocol node. All 11 Tendem MCP tools as granular operations, for
|
|
64
|
+
workflows that want full control over each step.
|
|
65
|
+
|
|
66
|
+
## Tendem Expert: the high-level node
|
|
67
|
+
|
|
68
|
+
Each operation returns an **outcome envelope** — branch on `outcome`, everything else rides
|
|
69
|
+
along as data:
|
|
70
|
+
|
|
71
|
+
| Operation | Spends money | Outcomes it returns |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| Delegate | no | `created` (with the `task_id` everything else needs) |
|
|
74
|
+
| Check & Advance | no | `question`, `quote`, `result`, `pending`, `topup_required`, `closed` |
|
|
75
|
+
| Reply | no | same as Check — it answers, then keeps advancing |
|
|
76
|
+
| **Approve (Spends Money)** | **yes** | `approved`, `quote` (refused, nothing charged), `topup_required` |
|
|
77
|
+
| Wait for Result | no | `result` (markdown + file URLs), `pending`, `quote`, `question` |
|
|
78
|
+
|
|
79
|
+
What the node does for you, so neither workflows nor agents have to:
|
|
80
|
+
|
|
81
|
+
- **Waiting is server-side.** Polling long-polls on Tendem's side and honours its pacing hints;
|
|
82
|
+
`pending` is always resumable — call again with the same `task_id`.
|
|
83
|
+
- **The chat choreography is built in.** `await_input` becomes a `question` outcome with
|
|
84
|
+
Tendem's text; Reply answers at the live conversation offset and absorbs the race the
|
|
85
|
+
protocol allows.
|
|
86
|
+
- **File upload is one field.** Name the binary properties in *Input Binary Fields* on
|
|
87
|
+
Delegate; the node mints the upload URL, does the host-swapped PUTs, and announces the
|
|
88
|
+
files to the expert.
|
|
89
|
+
- **Money is one operation with a policy.** Approve is the only spending path, and its
|
|
90
|
+
*Approval Policy* says where consent comes from: **Never** (default — quotes stay data),
|
|
91
|
+
**Under Max Price** (auto-approve at or under a cap you set), **From Decision Field**
|
|
92
|
+
(a boolean driven by any upstream approval — Slack, form, IF), or **Always**. Whatever the
|
|
93
|
+
policy, the engine re-reads the live quote at approval time and never pays a price it
|
|
94
|
+
cannot parse.
|
|
95
|
+
|
|
96
|
+
As an **AI Agent tool**, this is the node to attach: each operation's description tells the
|
|
97
|
+
model when to reach for it, so no system-prompt choreography is needed. Give an agent
|
|
98
|
+
Delegate + Check + Reply and it can drive a task end to end without ever being able to spend;
|
|
99
|
+
add Approve with a policy only when the workflow's spend rules are settled.
|
|
100
|
+
|
|
55
101
|
## Operations
|
|
56
102
|
|
|
103
|
+
The raw **Tendem** node, one operation per protocol tool:
|
|
104
|
+
|
|
57
105
|
| Resource | Operation | Tendem tool | Spends money |
|
|
58
106
|
|---|---|---|---|
|
|
59
107
|
| Task | Create | `create_task` | no |
|
|
@@ -264,7 +312,7 @@ is expected, and the confirming chat message settles it.
|
|
|
264
312
|
|
|
265
313
|
## Support
|
|
266
314
|
|
|
267
|
-
- Issues: <https://github.com/Toloka/tendem
|
|
315
|
+
- Issues: <https://github.com/Toloka/n8n-nodes-tendem/issues>
|
|
268
316
|
- Email: <support@tendem.ai>
|
|
269
317
|
|
|
270
318
|
## License
|
|
@@ -7,7 +7,7 @@ class TendemApi {
|
|
|
7
7
|
this.name = 'tendemApi';
|
|
8
8
|
this.displayName = 'Tendem API';
|
|
9
9
|
this.icon = 'file:../nodes/Tendem/tendem.svg';
|
|
10
|
-
this.documentationUrl = 'https://github.com/Toloka/tendem
|
|
10
|
+
this.documentationUrl = 'https://github.com/Toloka/n8n-nodes-tendem';
|
|
11
11
|
this.properties = [
|
|
12
12
|
{
|
|
13
13
|
displayName: 'API Key',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TendemApi.credentials.js","sourceRoot":"","sources":["../../credentials/TendemApi.credentials.ts"],"names":[],"mappings":";;;AAQA,yDAKmC;AAEnC,MAAa,SAAS;IAAtB;QACC,SAAI,GAAG,WAAW,CAAC;QAEnB,gBAAW,GAAG,YAAY,CAAC;QAO3B,SAAI,GAAS,iCAAiC,CAAC;QAE/C,qBAAgB,GAAG,
|
|
1
|
+
{"version":3,"file":"TendemApi.credentials.js","sourceRoot":"","sources":["../../credentials/TendemApi.credentials.ts"],"names":[],"mappings":";;;AAQA,yDAKmC;AAEnC,MAAa,SAAS;IAAtB;QACC,SAAI,GAAG,WAAW,CAAC;QAEnB,gBAAW,GAAG,YAAY,CAAC;QAO3B,SAAI,GAAS,iCAAiC,CAAC;QAE/C,qBAAgB,GAAG,4CAA4C,CAAC;QAEhE,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,SAAS;gBACtB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EACV,6IAA6I;aAC9I;YACD;gBACC,WAAW,EAAE,cAAc;gBAC3B,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,mCAAuB;gBAChC,QAAQ,EAAE,IAAI;gBACd,WAAW,EACV,uGAAuG;aACxG;SACD,CAAC;QAEF,iBAAY,GAAyB;YACpC,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACX,OAAO,EAAE;oBACR,aAAa,EAAE,iCAAiC;iBAChD;aACD;SACD,CAAC;QAGF,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,GAAG,EAAE,4BAA4B;gBACjC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACR,MAAM,EAAE,qCAAqC;oBAC7C,cAAc,EAAE,kBAAkB;iBAClC;gBACD,IAAI,EAAE;oBACL,OAAO,EAAE,KAAK;oBACd,EAAE,EAAE,CAAC;oBACL,MAAM,EAAE,YAAY;oBACpB,MAAM,EAAE;wBACP,eAAe,EAAE,gCAAoB;wBACrC,YAAY,EAAE,EAAE;wBAChB,UAAU,EAAE,EAAE,IAAI,EAAE,2BAAe,EAAE,OAAO,EAAE,8BAAkB,EAAE;qBAClE;iBACD;aACD;SACD,CAAC;IACH,CAAC;CAAA;AAlED,8BAkEC"}
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
"resources": {
|
|
7
7
|
"credentialDocumentation": [
|
|
8
8
|
{
|
|
9
|
-
"url": "https://github.com/Toloka/
|
|
9
|
+
"url": "https://github.com/Toloka/n8n-nodes-tendem#credentials"
|
|
10
10
|
}
|
|
11
11
|
],
|
|
12
12
|
"primaryDocumentation": [
|
|
13
13
|
{
|
|
14
|
-
"url": "https://github.com/Toloka/
|
|
14
|
+
"url": "https://github.com/Toloka/n8n-nodes-tendem"
|
|
15
15
|
}
|
|
16
16
|
]
|
|
17
17
|
}
|
|
@@ -14,6 +14,7 @@ export declare const TENDEM_TOOLS: {
|
|
|
14
14
|
};
|
|
15
15
|
export type TendemToolName = (typeof TENDEM_TOOLS)[keyof typeof TENDEM_TOOLS];
|
|
16
16
|
export declare const SPEND_COMMITTING_TOOLS: readonly TendemToolName[];
|
|
17
|
+
export declare const SPEND_OPERATION_KEYS: readonly string[];
|
|
17
18
|
export declare const SPEND_OPERATION_KEY = "task:approve";
|
|
18
19
|
export declare const IDEMPOTENT_TOOLS: readonly TendemToolName[];
|
|
19
20
|
export declare const OPERATION_TOOL_ALLOWLIST: Readonly<Record<string, readonly TendemToolName[]>>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GuardedToolCaller = exports.ToolNotPermittedError = exports.OPERATION_TOOL_ALLOWLIST = exports.IDEMPOTENT_TOOLS = exports.SPEND_OPERATION_KEY = exports.SPEND_COMMITTING_TOOLS = exports.TENDEM_TOOLS = void 0;
|
|
3
|
+
exports.GuardedToolCaller = exports.ToolNotPermittedError = exports.OPERATION_TOOL_ALLOWLIST = exports.IDEMPOTENT_TOOLS = exports.SPEND_OPERATION_KEY = exports.SPEND_OPERATION_KEYS = exports.SPEND_COMMITTING_TOOLS = exports.TENDEM_TOOLS = void 0;
|
|
4
4
|
exports.operationKey = operationKey;
|
|
5
5
|
exports.guardFor = guardFor;
|
|
6
6
|
exports.TENDEM_TOOLS = {
|
|
@@ -17,6 +17,7 @@ exports.TENDEM_TOOLS = {
|
|
|
17
17
|
GET_FILE_UPLOAD_URL: 'get_file_upload_url',
|
|
18
18
|
};
|
|
19
19
|
exports.SPEND_COMMITTING_TOOLS = [exports.TENDEM_TOOLS.APPROVE_TASK];
|
|
20
|
+
exports.SPEND_OPERATION_KEYS = ['task:approve', 'expert:approve'];
|
|
20
21
|
exports.SPEND_OPERATION_KEY = 'task:approve';
|
|
21
22
|
exports.IDEMPOTENT_TOOLS = [
|
|
22
23
|
exports.TENDEM_TOOLS.GET_TASK,
|
|
@@ -41,6 +42,32 @@ exports.OPERATION_TOOL_ALLOWLIST = {
|
|
|
41
42
|
'chat:send': [exports.TENDEM_TOOLS.SEND_MESSAGE, exports.TENDEM_TOOLS.READ_CHAT],
|
|
42
43
|
'account:get': [exports.TENDEM_TOOLS.GET_ACCOUNT],
|
|
43
44
|
'file:getUploadUrl': [exports.TENDEM_TOOLS.GET_FILE_UPLOAD_URL],
|
|
45
|
+
'expert:delegate': [
|
|
46
|
+
exports.TENDEM_TOOLS.CREATE_TASK,
|
|
47
|
+
exports.TENDEM_TOOLS.GET_FILE_UPLOAD_URL,
|
|
48
|
+
exports.TENDEM_TOOLS.SEND_MESSAGE,
|
|
49
|
+
exports.TENDEM_TOOLS.READ_CHAT,
|
|
50
|
+
],
|
|
51
|
+
'expert:check': [
|
|
52
|
+
exports.TENDEM_TOOLS.GET_TASK,
|
|
53
|
+
exports.TENDEM_TOOLS.READ_CHAT,
|
|
54
|
+
exports.TENDEM_TOOLS.GET_CONTRACT,
|
|
55
|
+
exports.TENDEM_TOOLS.GET_TASK_RESULT,
|
|
56
|
+
],
|
|
57
|
+
'expert:reply': [
|
|
58
|
+
exports.TENDEM_TOOLS.SEND_MESSAGE,
|
|
59
|
+
exports.TENDEM_TOOLS.GET_TASK,
|
|
60
|
+
exports.TENDEM_TOOLS.READ_CHAT,
|
|
61
|
+
exports.TENDEM_TOOLS.GET_CONTRACT,
|
|
62
|
+
exports.TENDEM_TOOLS.GET_TASK_RESULT,
|
|
63
|
+
],
|
|
64
|
+
'expert:approve': [exports.TENDEM_TOOLS.GET_TASK, exports.TENDEM_TOOLS.GET_CONTRACT, exports.TENDEM_TOOLS.APPROVE_TASK],
|
|
65
|
+
'expert:waitResult': [
|
|
66
|
+
exports.TENDEM_TOOLS.GET_TASK,
|
|
67
|
+
exports.TENDEM_TOOLS.READ_CHAT,
|
|
68
|
+
exports.TENDEM_TOOLS.GET_CONTRACT,
|
|
69
|
+
exports.TENDEM_TOOLS.GET_TASK_RESULT,
|
|
70
|
+
],
|
|
44
71
|
};
|
|
45
72
|
class ToolNotPermittedError extends Error {
|
|
46
73
|
constructor(message) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../nodes/Tendem/tools.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../nodes/Tendem/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { IDataObject } from 'n8n-workflow';
|
|
2
2
|
export declare const MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
3
3
|
export declare const MCP_CLIENT_NAME = "n8n-nodes-tendem";
|
|
4
|
-
export declare const MCP_CLIENT_VERSION = "0.
|
|
4
|
+
export declare const MCP_CLIENT_VERSION = "0.2.0";
|
|
5
5
|
export declare const TENDEM_DEFAULT_ENDPOINT = "https://mcp.tendem.ai/mcp?utm_hash=83dad40a52";
|
|
6
6
|
export interface McpHttpRequestOptions {
|
|
7
7
|
method: 'POST';
|
|
@@ -6,7 +6,7 @@ exports.toolResultIsError = toolResultIsError;
|
|
|
6
6
|
exports.unwrapToolResult = unwrapToolResult;
|
|
7
7
|
exports.MCP_PROTOCOL_VERSION = '2025-06-18';
|
|
8
8
|
exports.MCP_CLIENT_NAME = 'n8n-nodes-tendem';
|
|
9
|
-
exports.MCP_CLIENT_VERSION = '0.
|
|
9
|
+
exports.MCP_CLIENT_VERSION = '0.2.0';
|
|
10
10
|
exports.TENDEM_DEFAULT_ENDPOINT = 'https://mcp.tendem.ai/mcp?utm_hash=83dad40a52';
|
|
11
11
|
class McpError extends Error {
|
|
12
12
|
constructor(message, code, data, httpStatus) {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type IExecuteFunctions, type INodeExecutionData, type INodeType, type INodeTypeDescription } from 'n8n-workflow';
|
|
2
|
+
export declare class TendemExpert implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
5
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TendemExpert = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const descriptions_1 = require("./descriptions");
|
|
6
|
+
const engine_1 = require("./engine");
|
|
7
|
+
const transport_1 = require("../Tendem/transport");
|
|
8
|
+
const retry_1 = require("../Tendem/retry");
|
|
9
|
+
const tools_1 = require("../Tendem/tools");
|
|
10
|
+
class TendemExpert {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.description = {
|
|
13
|
+
displayName: 'Tendem Expert',
|
|
14
|
+
name: 'tendemExpert',
|
|
15
|
+
icon: 'file:../Tendem/tendem.svg',
|
|
16
|
+
group: ['transform'],
|
|
17
|
+
version: 1,
|
|
18
|
+
subtitle: '={{$parameter["operation"]}}',
|
|
19
|
+
description: 'Involve a vetted human expert via Tendem: delegate work AI cannot reliably finish, drive the scoping conversation, and collect the verified result — with spend capped at a price you set in advance',
|
|
20
|
+
defaults: { name: 'Tendem Expert' },
|
|
21
|
+
usableAsTool: true,
|
|
22
|
+
inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
23
|
+
outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
24
|
+
credentials: [{ name: 'tendemApi', required: true }],
|
|
25
|
+
properties: [descriptions_1.expertOperations, ...descriptions_1.expertFields],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async execute() {
|
|
29
|
+
const items = this.getInputData();
|
|
30
|
+
const returnData = [];
|
|
31
|
+
const credentials = await this.getCredentials('tendemApi');
|
|
32
|
+
const endpoint = typeof credentials.endpoint === 'string' && credentials.endpoint.trim() !== ''
|
|
33
|
+
? credentials.endpoint.trim()
|
|
34
|
+
: transport_1.TENDEM_DEFAULT_ENDPOINT;
|
|
35
|
+
const requester = async (options) => (await this.helpers.httpRequestWithAuthentication.call(this, 'tendemApi', options));
|
|
36
|
+
const session = new transport_1.McpSession(requester, { endpoint });
|
|
37
|
+
const retrying = new retry_1.RetryingToolCaller(session, { sleep: n8n_workflow_1.sleep });
|
|
38
|
+
for (let i = 0; i < items.length; i += 1) {
|
|
39
|
+
try {
|
|
40
|
+
const operation = this.getNodeParameter('operation', i);
|
|
41
|
+
const key = (0, tools_1.operationKey)('expert', operation);
|
|
42
|
+
const guarded = (0, tools_1.guardFor)(retrying, key);
|
|
43
|
+
const deps = { caller: guarded, sleep: n8n_workflow_1.sleep, now: () => Date.now() };
|
|
44
|
+
const payload = await runExpertOperation.call(this, deps, operation, i);
|
|
45
|
+
returnData.push(...this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(payload), {
|
|
46
|
+
itemData: { item: i },
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (this.continueOnFail()) {
|
|
51
|
+
returnData.push({
|
|
52
|
+
json: { error: error instanceof Error ? error.message : String(error) },
|
|
53
|
+
pairedItem: { item: i },
|
|
54
|
+
});
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
throw asNodeError.call(this, error, i);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return [returnData];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.TendemExpert = TendemExpert;
|
|
64
|
+
function asNodeError(error, itemIndex) {
|
|
65
|
+
if (error instanceof n8n_workflow_1.NodeOperationError || error instanceof n8n_workflow_1.NodeApiError)
|
|
66
|
+
return error;
|
|
67
|
+
return new n8n_workflow_1.NodeApiError(this.getNode(), error, {
|
|
68
|
+
itemIndex,
|
|
69
|
+
message: error instanceof Error ? error.message : String(error),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async function runExpertOperation(deps, operation, i) {
|
|
73
|
+
var _a;
|
|
74
|
+
switch (operation) {
|
|
75
|
+
case 'delegate': {
|
|
76
|
+
const request = this.getNodeParameter('request', i);
|
|
77
|
+
const taskName = this.getNodeParameter('taskName', i, '');
|
|
78
|
+
const conversationId = this.getNodeParameter('conversationId', i, '');
|
|
79
|
+
const binaryFields = this.getNodeParameter('inputBinaryFields', i, '')
|
|
80
|
+
.split(',')
|
|
81
|
+
.map((name) => name.trim())
|
|
82
|
+
.filter((name) => name !== '');
|
|
83
|
+
const files = {};
|
|
84
|
+
for (const field of binaryFields) {
|
|
85
|
+
const binary = this.helpers.assertBinaryData(i, field);
|
|
86
|
+
const data = await this.helpers.getBinaryDataBuffer(i, field);
|
|
87
|
+
files[(_a = binary.fileName) !== null && _a !== void 0 ? _a : field] = data;
|
|
88
|
+
}
|
|
89
|
+
return await (0, engine_1.delegate)(deps, {
|
|
90
|
+
request,
|
|
91
|
+
taskName,
|
|
92
|
+
conversationId,
|
|
93
|
+
files,
|
|
94
|
+
putFile: async (url, data) => {
|
|
95
|
+
await this.helpers.httpRequest({
|
|
96
|
+
method: 'PUT',
|
|
97
|
+
url,
|
|
98
|
+
body: data,
|
|
99
|
+
headers: { 'x-ms-blob-type': 'BlockBlob' },
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
case 'check':
|
|
105
|
+
return await (0, engine_1.advance)(deps, {
|
|
106
|
+
taskId: this.getNodeParameter('taskId', i),
|
|
107
|
+
maxRounds: this.getNodeParameter('maxRounds', i, 20),
|
|
108
|
+
});
|
|
109
|
+
case 'reply':
|
|
110
|
+
return await (0, engine_1.reply)(deps, {
|
|
111
|
+
taskId: this.getNodeParameter('taskId', i),
|
|
112
|
+
reply: this.getNodeParameter('replyText', i),
|
|
113
|
+
maxRounds: this.getNodeParameter('maxRounds', i, 20),
|
|
114
|
+
});
|
|
115
|
+
case 'approve': {
|
|
116
|
+
const policy = this.getNodeParameter('approvalPolicy', i, 'never');
|
|
117
|
+
let cap = 0;
|
|
118
|
+
if (policy === 'underMaxPrice') {
|
|
119
|
+
cap = this.getNodeParameter('maxPrice', i, 0);
|
|
120
|
+
}
|
|
121
|
+
else if (policy === 'decision') {
|
|
122
|
+
cap = this.getNodeParameter('approveDecision', i, false)
|
|
123
|
+
? Number.POSITIVE_INFINITY
|
|
124
|
+
: 0;
|
|
125
|
+
}
|
|
126
|
+
else if (policy === 'always') {
|
|
127
|
+
cap = Number.POSITIVE_INFINITY;
|
|
128
|
+
}
|
|
129
|
+
return await (0, engine_1.approve)(deps, {
|
|
130
|
+
taskId: this.getNodeParameter('taskId', i),
|
|
131
|
+
maxPrice: cap,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
case 'waitResult':
|
|
135
|
+
return await (0, engine_1.waitForResult)(deps, {
|
|
136
|
+
taskId: this.getNodeParameter('taskId', i),
|
|
137
|
+
maxRounds: this.getNodeParameter('maxRounds', i, 20),
|
|
138
|
+
});
|
|
139
|
+
default:
|
|
140
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unsupported Tendem Expert operation "${operation}"`, {
|
|
141
|
+
itemIndex: i,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=TendemExpert.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TendemExpert.node.js","sourceRoot":"","sources":["../../../nodes/TendemExpert/TendemExpert.node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"node": "n8n-nodes-tendem.tendemExpert",
|
|
3
|
+
"nodeVersion": "1.0",
|
|
4
|
+
"codexVersion": "1.0",
|
|
5
|
+
"categories": ["Development", "Productivity"],
|
|
6
|
+
"resources": {
|
|
7
|
+
"credentialDocumentation": [
|
|
8
|
+
{
|
|
9
|
+
"url": "https://github.com/Toloka/n8n-nodes-tendem#credentials"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"primaryDocumentation": [
|
|
13
|
+
{
|
|
14
|
+
"url": "https://github.com/Toloka/n8n-nodes-tendem"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.expertFields = exports.expertOperations = void 0;
|
|
4
|
+
const showFor = (operations) => ({
|
|
5
|
+
show: { operation: operations },
|
|
6
|
+
});
|
|
7
|
+
exports.expertOperations = {
|
|
8
|
+
displayName: 'Operation',
|
|
9
|
+
name: 'operation',
|
|
10
|
+
type: 'options',
|
|
11
|
+
noDataExpression: true,
|
|
12
|
+
default: 'delegate',
|
|
13
|
+
options: [
|
|
14
|
+
{
|
|
15
|
+
name: 'Approve (Spends Money)',
|
|
16
|
+
value: 'approve',
|
|
17
|
+
description: 'Approve the current quote so the human expert starts work — the ONLY operation that charges the Tendem account. It re-reads the live quote and approves only when it is at or under Max Price; anything else returns the quote as data with nothing charged. Call this only after a human or workflow policy has accepted a "quote" outcome.',
|
|
18
|
+
action: 'Approve the quote under a price cap',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'Check & Advance',
|
|
22
|
+
value: 'check',
|
|
23
|
+
description: 'Poll a delegated task until it needs something, and say what as data: a scoping question from Tendem (outcome "question"), a quote to decide on (outcome "quote"), or the finished result. Never spends money. Call this after delegating, and again whenever the outcome is "pending".',
|
|
24
|
+
action: 'Check a delegated task and advance it',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'Delegate',
|
|
28
|
+
value: 'delegate',
|
|
29
|
+
description: 'Create a Tendem task for a vetted human expert from a plain-language request, optionally attaching input files. Nothing is charged: Tendem scopes the work and quotes a price first. Returns the task_id every later call needs. Call this exactly once per piece of work.',
|
|
30
|
+
action: 'Delegate work to a human expert',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'Reply',
|
|
34
|
+
value: 'reply',
|
|
35
|
+
description: 'Answer Tendem\'s scoping question (from a "question" outcome), then keep advancing the task in the same call. Use the task_id from this conversation.',
|
|
36
|
+
action: 'Reply to the expert service and continue',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Wait for Result',
|
|
40
|
+
value: 'waitResult',
|
|
41
|
+
description: 'Block until the verified result is ready and return it: markdown plus downloadable file URLs. Never spends money. Outcome "pending" means the work is still running — call again with the same task_id.',
|
|
42
|
+
action: 'Wait for the verified result',
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
exports.expertFields = [
|
|
47
|
+
{
|
|
48
|
+
displayName: 'Request',
|
|
49
|
+
name: 'request',
|
|
50
|
+
type: 'string',
|
|
51
|
+
typeOptions: { rows: 5 },
|
|
52
|
+
default: '',
|
|
53
|
+
required: true,
|
|
54
|
+
displayOptions: showFor(['delegate']),
|
|
55
|
+
description: 'The work to delegate, in plain language: what to do and what the deliverable looks like. Pass the requester\'s intent faithfully — Tendem\'s orchestrator does the scoping and asks follow-up questions. Tendem declines data-scraping work by policy.',
|
|
56
|
+
placeholder: 'Research the top 5 competitors in EU freight brokerage and summarise their pricing models in a one-page brief',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
displayName: 'Task Name',
|
|
60
|
+
name: 'taskName',
|
|
61
|
+
type: 'string',
|
|
62
|
+
default: '',
|
|
63
|
+
displayOptions: showFor(['delegate']),
|
|
64
|
+
description: 'Optional short name shown in Tendem lists. Left empty, one is derived from the request.',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
displayName: 'Conversation ID',
|
|
68
|
+
name: 'conversationId',
|
|
69
|
+
type: 'string',
|
|
70
|
+
default: '',
|
|
71
|
+
displayOptions: showFor(['delegate']),
|
|
72
|
+
description: 'Optional stable identifier letting Tendem correlate several tasks from one conversation',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
displayName: 'Input Binary Fields',
|
|
76
|
+
name: 'inputBinaryFields',
|
|
77
|
+
type: 'string',
|
|
78
|
+
default: '',
|
|
79
|
+
displayOptions: showFor(['delegate']),
|
|
80
|
+
description: 'Comma-separated names of binary properties on the input item to upload as task input files. Uploaded after creation and announced to the expert automatically.',
|
|
81
|
+
placeholder: 'data, attachment_1',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
displayName: 'Task ID',
|
|
85
|
+
name: 'taskId',
|
|
86
|
+
type: 'string',
|
|
87
|
+
default: '',
|
|
88
|
+
required: true,
|
|
89
|
+
displayOptions: showFor(['approve', 'check', 'reply', 'waitResult']),
|
|
90
|
+
description: 'The task UUID returned by Delegate. Always the one from this conversation — never invent or reuse an ID from elsewhere.',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
displayName: 'Reply Text',
|
|
94
|
+
name: 'replyText',
|
|
95
|
+
type: 'string',
|
|
96
|
+
typeOptions: { rows: 4 },
|
|
97
|
+
default: '',
|
|
98
|
+
required: true,
|
|
99
|
+
displayOptions: showFor(['reply']),
|
|
100
|
+
description: 'The answer to Tendem\'s scoping question. Answer from the conversation\'s context when it contains the answer; otherwise relay the question to the user first.',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
displayName: 'Approval Policy',
|
|
104
|
+
name: 'approvalPolicy',
|
|
105
|
+
type: 'options',
|
|
106
|
+
default: 'never',
|
|
107
|
+
displayOptions: showFor(['approve']),
|
|
108
|
+
description: 'Where the spend decision comes from. Whatever the policy, the engine re-reads the LIVE quote at approval time and an unparsable price is never paid.',
|
|
109
|
+
options: [
|
|
110
|
+
{
|
|
111
|
+
name: 'Always Approve',
|
|
112
|
+
value: 'always',
|
|
113
|
+
description: 'Approve whatever the current quote is. For fully trusted flows only.',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'From Decision Field',
|
|
117
|
+
value: 'decision',
|
|
118
|
+
description: 'Approve only when the Decision field below is true — drive it by expression from any upstream node: a Slack approval, a Wait-for-form, an IF branch',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'Never (Report Quote Only)',
|
|
122
|
+
value: 'never',
|
|
123
|
+
description: 'Never approve — return the current quote as data and charge nothing',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: 'Under Max Price',
|
|
127
|
+
value: 'underMaxPrice',
|
|
128
|
+
description: 'Approve automatically when the live quote is at or under Max Price',
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
displayName: 'Max Price',
|
|
134
|
+
name: 'maxPrice',
|
|
135
|
+
type: 'number',
|
|
136
|
+
default: 0,
|
|
137
|
+
typeOptions: { minValue: 0 },
|
|
138
|
+
displayOptions: { show: { operation: ['approve'], approvalPolicy: ['underMaxPrice'] } },
|
|
139
|
+
description: 'Spend cap in USD, set by the workflow author. The live quote is approved only when it is at or under this; a higher quote returns as data and charges nothing. This is the consent to spend — set it deliberately.',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
displayName: 'Decision',
|
|
143
|
+
name: 'approveDecision',
|
|
144
|
+
type: 'boolean',
|
|
145
|
+
default: false,
|
|
146
|
+
displayOptions: { show: { operation: ['approve'], approvalPolicy: ['decision'] } },
|
|
147
|
+
description: 'Whether to commit the spend. Drive it from an expression carrying an upstream decision — a Slack approval, a Wait-for-form answer, an IF branch.',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
displayName: 'Max Rounds',
|
|
151
|
+
name: 'maxRounds',
|
|
152
|
+
type: 'number',
|
|
153
|
+
default: 20,
|
|
154
|
+
typeOptions: { minValue: 1, maxValue: 240 },
|
|
155
|
+
displayOptions: showFor(['check', 'reply', 'waitResult']),
|
|
156
|
+
description: 'How many 30-second server-side waits to spend before returning outcome "pending". Waiting is server-side long-polling — no busy loop, and pending is resumable: call again with the same task_id.',
|
|
157
|
+
},
|
|
158
|
+
];
|
|
159
|
+
//# sourceMappingURL=descriptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descriptions.js","sourceRoot":"","sources":["../../../nodes/TendemExpert/descriptions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { IDataObject } from 'n8n-workflow';
|
|
2
|
+
import { type ToolCaller } from '../Tendem/tools';
|
|
3
|
+
export type ExpertOutcome = 'created' | 'question' | 'quote' | 'approved' | 'topup_required' | 'result' | 'pending' | 'closed';
|
|
4
|
+
export interface ExpertEnvelope extends IDataObject {
|
|
5
|
+
outcome: ExpertOutcome;
|
|
6
|
+
task_id: string;
|
|
7
|
+
}
|
|
8
|
+
export interface EngineDeps {
|
|
9
|
+
caller: ToolCaller;
|
|
10
|
+
sleep(ms: number): Promise<void>;
|
|
11
|
+
now(): number;
|
|
12
|
+
}
|
|
13
|
+
export interface AdvanceParams {
|
|
14
|
+
taskId: string;
|
|
15
|
+
maxRounds?: number;
|
|
16
|
+
waitForChangeSeconds?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare const DEFAULT_ADVANCE_ROUNDS = 20;
|
|
19
|
+
export declare const DEFAULT_WAIT_SECONDS = 30;
|
|
20
|
+
export declare function parsePrice(raw: unknown): number | undefined;
|
|
21
|
+
export declare function deriveTaskName(request: string): string;
|
|
22
|
+
export declare function sendAtLiveOffset(caller: ToolCaller, taskId: string, text: string): Promise<IDataObject>;
|
|
23
|
+
export interface DelegateParams {
|
|
24
|
+
request: string;
|
|
25
|
+
taskName?: string;
|
|
26
|
+
conversationId?: string;
|
|
27
|
+
files?: Record<string, Buffer>;
|
|
28
|
+
putFile?(url: string, data: Buffer): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
export declare function blobUploadUrl(uploadUrl: string, name: string): string;
|
|
31
|
+
export declare function delegate(deps: EngineDeps, params: DelegateParams): Promise<ExpertEnvelope>;
|
|
32
|
+
export declare function advance(deps: EngineDeps, params: AdvanceParams): Promise<ExpertEnvelope>;
|
|
33
|
+
export interface ApproveParams {
|
|
34
|
+
taskId: string;
|
|
35
|
+
maxPrice: number;
|
|
36
|
+
}
|
|
37
|
+
export declare function approve(deps: EngineDeps, params: ApproveParams): Promise<ExpertEnvelope>;
|
|
38
|
+
export interface ReplyParams extends AdvanceParams {
|
|
39
|
+
reply: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function reply(deps: EngineDeps, params: ReplyParams): Promise<ExpertEnvelope>;
|
|
42
|
+
export declare function waitForResult(deps: EngineDeps, params: AdvanceParams): Promise<ExpertEnvelope>;
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_WAIT_SECONDS = exports.DEFAULT_ADVANCE_ROUNDS = void 0;
|
|
4
|
+
exports.parsePrice = parsePrice;
|
|
5
|
+
exports.deriveTaskName = deriveTaskName;
|
|
6
|
+
exports.sendAtLiveOffset = sendAtLiveOffset;
|
|
7
|
+
exports.blobUploadUrl = blobUploadUrl;
|
|
8
|
+
exports.delegate = delegate;
|
|
9
|
+
exports.advance = advance;
|
|
10
|
+
exports.approve = approve;
|
|
11
|
+
exports.reply = reply;
|
|
12
|
+
exports.waitForResult = waitForResult;
|
|
13
|
+
const tools_1 = require("../Tendem/tools");
|
|
14
|
+
const waitForTask_1 = require("../Tendem/waitForTask");
|
|
15
|
+
exports.DEFAULT_ADVANCE_ROUNDS = 20;
|
|
16
|
+
exports.DEFAULT_WAIT_SECONDS = 30;
|
|
17
|
+
function readString(obj, key) {
|
|
18
|
+
const value = obj[key];
|
|
19
|
+
return typeof value === 'string' ? value : '';
|
|
20
|
+
}
|
|
21
|
+
function readNextAction(task) {
|
|
22
|
+
return readString(task, 'next_action').trim().toLowerCase();
|
|
23
|
+
}
|
|
24
|
+
function parsePrice(raw) {
|
|
25
|
+
if (typeof raw === 'number' && Number.isFinite(raw))
|
|
26
|
+
return raw;
|
|
27
|
+
if (typeof raw !== 'string')
|
|
28
|
+
return undefined;
|
|
29
|
+
const match = raw.replace(/,/g, '').match(/\d+(?:\.\d+)?/);
|
|
30
|
+
if (!match)
|
|
31
|
+
return undefined;
|
|
32
|
+
const value = Number(match[0]);
|
|
33
|
+
return Number.isFinite(value) ? value : undefined;
|
|
34
|
+
}
|
|
35
|
+
function deriveTaskName(request) {
|
|
36
|
+
const words = request.trim().split(/\s+/).slice(0, 8).join(' ');
|
|
37
|
+
const name = words.length > 100 ? `${words.slice(0, 97)}...` : words;
|
|
38
|
+
return name === '' ? 'Delegated task' : name;
|
|
39
|
+
}
|
|
40
|
+
function collectMessages(chat) {
|
|
41
|
+
const messages = chat.messages;
|
|
42
|
+
if (!Array.isArray(messages))
|
|
43
|
+
return '';
|
|
44
|
+
const parts = [];
|
|
45
|
+
for (const entry of messages) {
|
|
46
|
+
if (!entry || typeof entry !== 'object')
|
|
47
|
+
continue;
|
|
48
|
+
const text = entry.text;
|
|
49
|
+
if (typeof text === 'string' && text.trim() !== '')
|
|
50
|
+
parts.push(text.trim());
|
|
51
|
+
}
|
|
52
|
+
return parts.join('\n\n').trim();
|
|
53
|
+
}
|
|
54
|
+
async function latestOffset(caller, taskId) {
|
|
55
|
+
const chat = await caller.callTool(tools_1.TENDEM_TOOLS.READ_CHAT, {
|
|
56
|
+
task_id: taskId,
|
|
57
|
+
from_offset: 0,
|
|
58
|
+
});
|
|
59
|
+
return typeof chat.last_seen_offset === 'number' ? chat.last_seen_offset : 0;
|
|
60
|
+
}
|
|
61
|
+
async function sendAtLiveOffset(caller, taskId, text) {
|
|
62
|
+
let offset = await latestOffset(caller, taskId);
|
|
63
|
+
let response = await caller.callTool(tools_1.TENDEM_TOOLS.SEND_MESSAGE, {
|
|
64
|
+
task_id: taskId,
|
|
65
|
+
text,
|
|
66
|
+
last_seen_offset: offset,
|
|
67
|
+
});
|
|
68
|
+
if (response.response_type === 'race') {
|
|
69
|
+
offset =
|
|
70
|
+
typeof response.last_seen_offset === 'number'
|
|
71
|
+
? response.last_seen_offset
|
|
72
|
+
: await latestOffset(caller, taskId);
|
|
73
|
+
response = await caller.callTool(tools_1.TENDEM_TOOLS.SEND_MESSAGE, {
|
|
74
|
+
task_id: taskId,
|
|
75
|
+
text,
|
|
76
|
+
last_seen_offset: offset,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return response;
|
|
80
|
+
}
|
|
81
|
+
function blobUploadUrl(uploadUrl, name) {
|
|
82
|
+
const [base = '', query = ''] = uploadUrl.split('?');
|
|
83
|
+
const swapped = base.replace('.dfs.core.windows.net', '.blob.core.windows.net');
|
|
84
|
+
return `${swapped.replace(/\/+$/, '')}/${name}${query === '' ? '' : `?${query}`}`;
|
|
85
|
+
}
|
|
86
|
+
async function delegate(deps, params) {
|
|
87
|
+
var _a, _b;
|
|
88
|
+
const args = {
|
|
89
|
+
name: ((_a = params.taskName) === null || _a === void 0 ? void 0 : _a.trim()) !== '' && params.taskName !== undefined
|
|
90
|
+
? params.taskName
|
|
91
|
+
: deriveTaskName(params.request),
|
|
92
|
+
description: params.request,
|
|
93
|
+
};
|
|
94
|
+
if (params.conversationId !== undefined && params.conversationId !== '') {
|
|
95
|
+
args.conversation_id = params.conversationId;
|
|
96
|
+
}
|
|
97
|
+
const created = await deps.caller.callTool(tools_1.TENDEM_TOOLS.CREATE_TASK, args);
|
|
98
|
+
const taskId = readString(created, 'task_id');
|
|
99
|
+
const fileNames = Object.keys((_b = params.files) !== null && _b !== void 0 ? _b : {});
|
|
100
|
+
if (fileNames.length > 0 && params.files && params.putFile) {
|
|
101
|
+
const minted = await deps.caller.callTool(tools_1.TENDEM_TOOLS.GET_FILE_UPLOAD_URL, {
|
|
102
|
+
task_id: taskId,
|
|
103
|
+
});
|
|
104
|
+
const uploadUrl = readString(minted, 'upload_url');
|
|
105
|
+
for (const name of fileNames) {
|
|
106
|
+
await params.putFile(blobUploadUrl(uploadUrl, name), params.files[name]);
|
|
107
|
+
}
|
|
108
|
+
await sendAtLiveOffset(deps.caller, taskId, `I've uploaded ${fileNames.join(', ')} for this task.`);
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
outcome: 'created',
|
|
112
|
+
task_id: taskId,
|
|
113
|
+
status: readString(created, 'status'),
|
|
114
|
+
files_attached: fileNames,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
async function advance(deps, params) {
|
|
118
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
119
|
+
const rounds = Math.max(1, Math.trunc((_a = params.maxRounds) !== null && _a !== void 0 ? _a : exports.DEFAULT_ADVANCE_ROUNDS));
|
|
120
|
+
const waitSeconds = (_b = params.waitForChangeSeconds) !== null && _b !== void 0 ? _b : exports.DEFAULT_WAIT_SECONDS;
|
|
121
|
+
let task = {};
|
|
122
|
+
for (let round = 0; round < rounds; round += 1) {
|
|
123
|
+
const startedAt = deps.now();
|
|
124
|
+
task = await deps.caller.callTool(tools_1.TENDEM_TOOLS.GET_TASK, {
|
|
125
|
+
task_id: params.taskId,
|
|
126
|
+
wait_for_change_seconds: waitSeconds,
|
|
127
|
+
});
|
|
128
|
+
const nextAction = readNextAction(task);
|
|
129
|
+
if (nextAction === 'await_input' || nextAction === 'resolve_race') {
|
|
130
|
+
const chat = await deps.caller.callTool(tools_1.TENDEM_TOOLS.READ_CHAT, {
|
|
131
|
+
task_id: params.taskId,
|
|
132
|
+
from_offset: 0,
|
|
133
|
+
});
|
|
134
|
+
return {
|
|
135
|
+
outcome: 'question',
|
|
136
|
+
task_id: params.taskId,
|
|
137
|
+
question: collectMessages(chat),
|
|
138
|
+
last_seen_offset: (_c = chat.last_seen_offset) !== null && _c !== void 0 ? _c : 0,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
if (nextAction === 'await_user_approval') {
|
|
142
|
+
const contract = await deps.caller.callTool(tools_1.TENDEM_TOOLS.GET_CONTRACT, {
|
|
143
|
+
task_id: params.taskId,
|
|
144
|
+
});
|
|
145
|
+
const priceRaw = (_d = contract.price) !== null && _d !== void 0 ? _d : task.price;
|
|
146
|
+
return {
|
|
147
|
+
outcome: 'quote',
|
|
148
|
+
task_id: params.taskId,
|
|
149
|
+
price: priceRaw !== null && priceRaw !== void 0 ? priceRaw : null,
|
|
150
|
+
price_value: (_e = parsePrice(priceRaw)) !== null && _e !== void 0 ? _e : null,
|
|
151
|
+
contract: (_f = contract.contract) !== null && _f !== void 0 ? _f : null,
|
|
152
|
+
charged: false,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (nextAction === 'await_user_topup') {
|
|
156
|
+
return {
|
|
157
|
+
outcome: 'topup_required',
|
|
158
|
+
task_id: params.taskId,
|
|
159
|
+
topup_url: readString(task, 'topup_url'),
|
|
160
|
+
price: (_g = task.price) !== null && _g !== void 0 ? _g : null,
|
|
161
|
+
charged: false,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (nextAction === 'fetch_result' || nextAction === 'done') {
|
|
165
|
+
return await fetchResult(deps, params.taskId, nextAction);
|
|
166
|
+
}
|
|
167
|
+
if (round < rounds - 1 && deps.now() - startedAt < waitForTask_1.MIN_SERVER_BLOCK_MS) {
|
|
168
|
+
await deps.sleep((0, waitForTask_1.backoffMs)(task, waitSeconds));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
outcome: 'pending',
|
|
173
|
+
task_id: params.taskId,
|
|
174
|
+
status: readString(task, 'status'),
|
|
175
|
+
next_action: readNextAction(task),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
async function approve(deps, params) {
|
|
179
|
+
var _a, _b, _c;
|
|
180
|
+
const task = await deps.caller.callTool(tools_1.TENDEM_TOOLS.GET_TASK, {
|
|
181
|
+
task_id: params.taskId,
|
|
182
|
+
wait_for_change_seconds: 0,
|
|
183
|
+
});
|
|
184
|
+
const contract = await deps.caller.callTool(tools_1.TENDEM_TOOLS.GET_CONTRACT, {
|
|
185
|
+
task_id: params.taskId,
|
|
186
|
+
});
|
|
187
|
+
const priceRaw = (_a = contract.price) !== null && _a !== void 0 ? _a : task.price;
|
|
188
|
+
const price = parsePrice(priceRaw);
|
|
189
|
+
const cap = params.maxPrice;
|
|
190
|
+
if (cap <= 0 || price === undefined || price > cap) {
|
|
191
|
+
return {
|
|
192
|
+
outcome: 'quote',
|
|
193
|
+
task_id: params.taskId,
|
|
194
|
+
price: priceRaw !== null && priceRaw !== void 0 ? priceRaw : null,
|
|
195
|
+
price_value: price !== null && price !== void 0 ? price : null,
|
|
196
|
+
max_price: Number.isFinite(cap) && cap > 0 ? cap : null,
|
|
197
|
+
over_cap: price !== undefined && cap > 0 && price > cap,
|
|
198
|
+
contract: (_b = contract.contract) !== null && _b !== void 0 ? _b : null,
|
|
199
|
+
charged: false,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
const approval = await deps.caller.callTool(tools_1.TENDEM_TOOLS.APPROVE_TASK, {
|
|
203
|
+
task_id: params.taskId,
|
|
204
|
+
name: readString(task, 'name') || 'Delegated task',
|
|
205
|
+
price: typeof priceRaw === 'string' ? priceRaw : String(priceRaw),
|
|
206
|
+
});
|
|
207
|
+
if (approval.approved !== true) {
|
|
208
|
+
return {
|
|
209
|
+
outcome: 'topup_required',
|
|
210
|
+
task_id: params.taskId,
|
|
211
|
+
topup_url: readString(approval, 'topup_url'),
|
|
212
|
+
price: priceRaw !== null && priceRaw !== void 0 ? priceRaw : null,
|
|
213
|
+
charged: false,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
outcome: 'approved',
|
|
218
|
+
task_id: params.taskId,
|
|
219
|
+
price: priceRaw !== null && priceRaw !== void 0 ? priceRaw : null,
|
|
220
|
+
approved_under_cap: cap,
|
|
221
|
+
contract: (_c = contract.contract) !== null && _c !== void 0 ? _c : null,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
async function fetchResult(deps, taskId, nextAction) {
|
|
225
|
+
const result = await deps.caller.callTool(tools_1.TENDEM_TOOLS.GET_TASK_RESULT, { task_id: taskId });
|
|
226
|
+
if (result.content === null || result.content === undefined) {
|
|
227
|
+
return {
|
|
228
|
+
outcome: nextAction === 'done' ? 'closed' : 'pending',
|
|
229
|
+
task_id: taskId,
|
|
230
|
+
status: readString(result, 'status'),
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
outcome: 'result',
|
|
235
|
+
task_id: taskId,
|
|
236
|
+
content: result.content,
|
|
237
|
+
files: Array.isArray(result.files) ? result.files : [],
|
|
238
|
+
status: readString(result, 'status'),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
async function reply(deps, params) {
|
|
242
|
+
await sendAtLiveOffset(deps.caller, params.taskId, params.reply);
|
|
243
|
+
return await advance(deps, params);
|
|
244
|
+
}
|
|
245
|
+
async function waitForResult(deps, params) {
|
|
246
|
+
return await advance(deps, params);
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../nodes/TendemExpert/engine.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n8n-nodes-tendem",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Delegate tasks to vetted human experts with Tendem — create a task, read the priced contract, approve the spend, poll, and fetch the result.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"homepage": "https://tendem
|
|
6
|
+
"homepage": "https://github.com/Toloka/n8n-nodes-tendem#readme",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"n8n-community-node-package",
|
|
9
9
|
"n8n",
|
|
@@ -20,11 +20,10 @@
|
|
|
20
20
|
},
|
|
21
21
|
"repository": {
|
|
22
22
|
"type": "git",
|
|
23
|
-
"url": "git+https://github.com/Toloka/tendem
|
|
24
|
-
"directory": "integrations/n8n-nodes-tendem"
|
|
23
|
+
"url": "git+https://github.com/Toloka/n8n-nodes-tendem.git"
|
|
25
24
|
},
|
|
26
25
|
"bugs": {
|
|
27
|
-
"url": "https://github.com/Toloka/tendem
|
|
26
|
+
"url": "https://github.com/Toloka/n8n-nodes-tendem/issues"
|
|
28
27
|
},
|
|
29
28
|
"engines": {
|
|
30
29
|
"node": ">=20.19"
|
|
@@ -50,7 +49,8 @@
|
|
|
50
49
|
"dist/credentials/TendemApi.credentials.js"
|
|
51
50
|
],
|
|
52
51
|
"nodes": [
|
|
53
|
-
"dist/nodes/Tendem/Tendem.node.js"
|
|
52
|
+
"dist/nodes/Tendem/Tendem.node.js",
|
|
53
|
+
"dist/nodes/TendemExpert/TendemExpert.node.js"
|
|
54
54
|
]
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|