@atom8n/n8n-nodes-langchain 2.5.5 → 2.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/credentials/NineRouterApi.credentials.js +67 -0
- package/dist/credentials/NineRouterApi.credentials.js.map +1 -0
- package/dist/known/credentials.json +7 -0
- package/dist/known/nodes.json +12 -0
- package/dist/nodes/llms/LmChat9Router/9router.dark.svg +10 -0
- package/dist/nodes/llms/LmChat9Router/9router.svg +10 -0
- package/dist/nodes/llms/LmChat9Router/LmChat9Router.node.js +248 -0
- package/dist/nodes/llms/LmChat9Router/LmChat9Router.node.js.map +1 -0
- package/dist/nodes/llms/LmChatCodexCli/LmChatCodexCli.node.js +456 -0
- package/dist/nodes/llms/LmChatCodexCli/LmChatCodexCli.node.js.map +1 -0
- package/dist/nodes/llms/LmChatCodexCli/codexCli.svg +1 -0
- package/dist/nodes/llms/LmChatCursorAgent/LmChatCursorAgent.node.js +136 -15
- package/dist/nodes/llms/LmChatCursorAgent/LmChatCursorAgent.node.js.map +1 -1
- package/dist/nodes/llms/LmChatOpenCodeCli/LmChatOpenCodeCli.node.js +443 -0
- package/dist/nodes/llms/LmChatOpenCodeCli/LmChatOpenCodeCli.node.js.map +1 -0
- package/dist/nodes/llms/LmChatOpenCodeCli/openCodeCli.svg +1 -0
- package/dist/types/credentials.json +1 -0
- package/dist/types/nodes.json +4 -1
- package/package.json +15 -11
|
@@ -27,6 +27,7 @@ var import_n8n_workflow = require("n8n-workflow");
|
|
|
27
27
|
var import_sharedFields = require("../../../utils/sharedFields");
|
|
28
28
|
var import_N8nLlmTracing = require("../N8nLlmTracing");
|
|
29
29
|
var import_child_process = require("child_process");
|
|
30
|
+
var import_fs = require("fs");
|
|
30
31
|
const TOOL_CALL_SYSTEM_PROMPT = `You have access to the following tools. When you need to call a tool, respond ONLY with a JSON block in this exact format (no other text before or after):
|
|
31
32
|
|
|
32
33
|
\`\`\`tool_calls
|
|
@@ -126,9 +127,15 @@ class ChatCursorAgentCLI extends import_chat_models.BaseChatModel {
|
|
|
126
127
|
if (this.model && this.model !== "auto") {
|
|
127
128
|
args.push("--model", this.model);
|
|
128
129
|
}
|
|
130
|
+
const cwd = this.workingDirectory?.trim() || void 0;
|
|
131
|
+
console.log("[LmChatCursorAgent] spawning cursor-agent", {
|
|
132
|
+
binaryPath: this.binaryPath,
|
|
133
|
+
model: this.model,
|
|
134
|
+
cwd
|
|
135
|
+
});
|
|
129
136
|
return await new Promise((resolve, reject) => {
|
|
130
137
|
const child = (0, import_child_process.spawn)(this.binaryPath, args, {
|
|
131
|
-
cwd
|
|
138
|
+
cwd,
|
|
132
139
|
stdio: ["pipe", "pipe", "pipe"],
|
|
133
140
|
env: { ...process.env }
|
|
134
141
|
});
|
|
@@ -143,7 +150,7 @@ class ChatCursorAgentCLI extends import_chat_models.BaseChatModel {
|
|
|
143
150
|
child.on("error", (err) => {
|
|
144
151
|
reject(
|
|
145
152
|
new Error(
|
|
146
|
-
`Failed to spawn cursor-agent: ${err.message}. Make sure cursor-agent CLI is installed and accessible
|
|
153
|
+
`Failed to spawn cursor-agent: ${err.message}. Make sure cursor-agent CLI is installed and accessible. Working directory: ${cwd ?? "<default>"}`
|
|
147
154
|
)
|
|
148
155
|
);
|
|
149
156
|
});
|
|
@@ -214,23 +221,104 @@ class LmChatCursorAgent {
|
|
|
214
221
|
displayName: "Model",
|
|
215
222
|
name: "model",
|
|
216
223
|
type: "options",
|
|
217
|
-
description: "The model to use via cursor-agent CLI
|
|
224
|
+
description: "The model to use via cursor-agent CLI",
|
|
218
225
|
// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items
|
|
219
226
|
options: [
|
|
220
227
|
{ name: "Auto", value: "auto" },
|
|
221
|
-
|
|
228
|
+
// Composer models
|
|
229
|
+
{ name: "Composer 2 Fast", value: "composer-2-fast" },
|
|
230
|
+
{ name: "Composer 2", value: "composer-2" },
|
|
222
231
|
{ name: "Composer 1.5", value: "composer-1.5" },
|
|
232
|
+
// Claude 4.6 models
|
|
233
|
+
{ name: "Claude 4.6 Opus High", value: "claude-4.6-opus-high" },
|
|
234
|
+
{ name: "Claude 4.6 Opus High Thinking", value: "claude-4.6-opus-high-thinking" },
|
|
235
|
+
{ name: "Claude 4.6 Opus Max", value: "claude-4.6-opus-max" },
|
|
236
|
+
{ name: "Claude 4.6 Opus Max Thinking", value: "claude-4.6-opus-max-thinking" },
|
|
237
|
+
{ name: "Claude 4.6 Sonnet Medium", value: "claude-4.6-sonnet-medium" },
|
|
238
|
+
{ name: "Claude 4.6 Sonnet Medium Thinking", value: "claude-4.6-sonnet-medium-thinking" },
|
|
239
|
+
// Claude 4.5 models
|
|
240
|
+
{ name: "Claude 4.5 Opus High", value: "claude-4.5-opus-high" },
|
|
241
|
+
{ name: "Claude 4.5 Opus High Thinking", value: "claude-4.5-opus-high-thinking" },
|
|
242
|
+
{ name: "Claude 4.5 Sonnet", value: "claude-4.5-sonnet" },
|
|
243
|
+
{ name: "Claude 4.5 Sonnet Thinking", value: "claude-4.5-sonnet-thinking" },
|
|
244
|
+
// Claude 4 models
|
|
245
|
+
{ name: "Claude 4 Sonnet", value: "claude-4-sonnet" },
|
|
246
|
+
{ name: "Claude 4 Sonnet 1M", value: "claude-4-sonnet-1m" },
|
|
247
|
+
{ name: "Claude 4 Sonnet Thinking", value: "claude-4-sonnet-thinking" },
|
|
248
|
+
{ name: "Claude 4 Sonnet 1M Thinking", value: "claude-4-sonnet-1m-thinking" },
|
|
249
|
+
// Gemini models
|
|
250
|
+
{ name: "Gemini 3.1 Pro", value: "gemini-3.1-pro" },
|
|
223
251
|
{ name: "Gemini 3 Flash", value: "gemini-3-flash" },
|
|
224
|
-
|
|
225
|
-
{ name: "GPT-5.
|
|
226
|
-
{ name: "GPT-5.
|
|
252
|
+
// GPT-5.4 models
|
|
253
|
+
{ name: "GPT-5.4 Low", value: "gpt-5.4-low" },
|
|
254
|
+
{ name: "GPT-5.4 Medium", value: "gpt-5.4-medium" },
|
|
255
|
+
{ name: "GPT-5.4 Medium Fast", value: "gpt-5.4-medium-fast" },
|
|
256
|
+
{ name: "GPT-5.4 High", value: "gpt-5.4-high" },
|
|
257
|
+
{ name: "GPT-5.4 High Fast", value: "gpt-5.4-high-fast" },
|
|
258
|
+
{ name: "GPT-5.4 XHigh", value: "gpt-5.4-xhigh" },
|
|
259
|
+
{ name: "GPT-5.4 XHigh Fast", value: "gpt-5.4-xhigh-fast" },
|
|
260
|
+
{ name: "GPT-5.4 Mini None", value: "gpt-5.4-mini-none" },
|
|
261
|
+
{ name: "GPT-5.4 Mini Low", value: "gpt-5.4-mini-low" },
|
|
262
|
+
{ name: "GPT-5.4 Mini Medium", value: "gpt-5.4-mini-medium" },
|
|
263
|
+
{ name: "GPT-5.4 Mini High", value: "gpt-5.4-mini-high" },
|
|
264
|
+
{ name: "GPT-5.4 Mini XHigh", value: "gpt-5.4-mini-xhigh" },
|
|
265
|
+
{ name: "GPT-5.4 Nano None", value: "gpt-5.4-nano-none" },
|
|
266
|
+
{ name: "GPT-5.4 Nano Low", value: "gpt-5.4-nano-low" },
|
|
267
|
+
{ name: "GPT-5.4 Nano Medium", value: "gpt-5.4-nano-medium" },
|
|
268
|
+
{ name: "GPT-5.4 Nano High", value: "gpt-5.4-nano-high" },
|
|
269
|
+
{ name: "GPT-5.4 Nano XHigh", value: "gpt-5.4-nano-xhigh" },
|
|
270
|
+
// GPT-5.3 Codex models
|
|
271
|
+
{ name: "GPT-5.3 Codex Low", value: "gpt-5.3-codex-low" },
|
|
272
|
+
{ name: "GPT-5.3 Codex Low Fast", value: "gpt-5.3-codex-low-fast" },
|
|
273
|
+
{ name: "GPT-5.3 Codex", value: "gpt-5.3-codex" },
|
|
274
|
+
{ name: "GPT-5.3 Codex Fast", value: "gpt-5.3-codex-fast" },
|
|
275
|
+
{ name: "GPT-5.3 Codex High", value: "gpt-5.3-codex-high" },
|
|
276
|
+
{ name: "GPT-5.3 Codex High Fast", value: "gpt-5.3-codex-high-fast" },
|
|
277
|
+
{ name: "GPT-5.3 Codex XHigh", value: "gpt-5.3-codex-xhigh" },
|
|
278
|
+
{ name: "GPT-5.3 Codex XHigh Fast", value: "gpt-5.3-codex-xhigh-fast" },
|
|
279
|
+
{ name: "GPT-5.3 Codex Spark Preview Low", value: "gpt-5.3-codex-spark-preview-low" },
|
|
280
|
+
{ name: "GPT-5.3 Codex Spark Preview", value: "gpt-5.3-codex-spark-preview" },
|
|
281
|
+
{ name: "GPT-5.3 Codex Spark Preview High", value: "gpt-5.3-codex-spark-preview-high" },
|
|
282
|
+
{ name: "GPT-5.3 Codex Spark Preview XHigh", value: "gpt-5.3-codex-spark-preview-xhigh" },
|
|
283
|
+
// GPT-5.2 models
|
|
284
|
+
{ name: "GPT-5.2 Low", value: "gpt-5.2-low" },
|
|
285
|
+
{ name: "GPT-5.2 Low Fast", value: "gpt-5.2-low-fast" },
|
|
227
286
|
{ name: "GPT-5.2", value: "gpt-5.2" },
|
|
287
|
+
{ name: "GPT-5.2 Fast", value: "gpt-5.2-fast" },
|
|
228
288
|
{ name: "GPT-5.2 High", value: "gpt-5.2-high" },
|
|
229
|
-
{ name: "
|
|
230
|
-
{ name: "
|
|
231
|
-
{ name: "
|
|
232
|
-
{ name: "
|
|
233
|
-
{ name: "
|
|
289
|
+
{ name: "GPT-5.2 High Fast", value: "gpt-5.2-high-fast" },
|
|
290
|
+
{ name: "GPT-5.2 XHigh", value: "gpt-5.2-xhigh" },
|
|
291
|
+
{ name: "GPT-5.2 XHigh Fast", value: "gpt-5.2-xhigh-fast" },
|
|
292
|
+
{ name: "GPT-5.2 Codex Low", value: "gpt-5.2-codex-low" },
|
|
293
|
+
{ name: "GPT-5.2 Codex Low Fast", value: "gpt-5.2-codex-low-fast" },
|
|
294
|
+
{ name: "GPT-5.2 Codex", value: "gpt-5.2-codex" },
|
|
295
|
+
{ name: "GPT-5.2 Codex Fast", value: "gpt-5.2-codex-fast" },
|
|
296
|
+
{ name: "GPT-5.2 Codex High", value: "gpt-5.2-codex-high" },
|
|
297
|
+
{ name: "GPT-5.2 Codex High Fast", value: "gpt-5.2-codex-high-fast" },
|
|
298
|
+
{ name: "GPT-5.2 Codex XHigh", value: "gpt-5.2-codex-xhigh" },
|
|
299
|
+
{ name: "GPT-5.2 Codex XHigh Fast", value: "gpt-5.2-codex-xhigh-fast" },
|
|
300
|
+
// GPT-5.1 models
|
|
301
|
+
{ name: "GPT-5.1 Low", value: "gpt-5.1-low" },
|
|
302
|
+
{ name: "GPT-5.1", value: "gpt-5.1" },
|
|
303
|
+
{ name: "GPT-5.1 High", value: "gpt-5.1-high" },
|
|
304
|
+
{ name: "GPT-5.1 Codex Max Low", value: "gpt-5.1-codex-max-low" },
|
|
305
|
+
{ name: "GPT-5.1 Codex Max Low Fast", value: "gpt-5.1-codex-max-low-fast" },
|
|
306
|
+
{ name: "GPT-5.1 Codex Max Medium", value: "gpt-5.1-codex-max-medium" },
|
|
307
|
+
{ name: "GPT-5.1 Codex Max Medium Fast", value: "gpt-5.1-codex-max-medium-fast" },
|
|
308
|
+
{ name: "GPT-5.1 Codex Max High", value: "gpt-5.1-codex-max-high" },
|
|
309
|
+
{ name: "GPT-5.1 Codex Max High Fast", value: "gpt-5.1-codex-max-high-fast" },
|
|
310
|
+
{ name: "GPT-5.1 Codex Max XHigh", value: "gpt-5.1-codex-max-xhigh" },
|
|
311
|
+
{ name: "GPT-5.1 Codex Max XHigh Fast", value: "gpt-5.1-codex-max-xhigh-fast" },
|
|
312
|
+
{ name: "GPT-5.1 Codex Mini Low", value: "gpt-5.1-codex-mini-low" },
|
|
313
|
+
{ name: "GPT-5.1 Codex Mini", value: "gpt-5.1-codex-mini" },
|
|
314
|
+
{ name: "GPT-5.1 Codex Mini High", value: "gpt-5.1-codex-mini-high" },
|
|
315
|
+
// GPT-5 models
|
|
316
|
+
{ name: "GPT-5 Mini", value: "gpt-5-mini" },
|
|
317
|
+
// Grok models
|
|
318
|
+
{ name: "Grok 4 20", value: "grok-4-20" },
|
|
319
|
+
{ name: "Grok 4 20 Thinking", value: "grok-4-20-thinking" },
|
|
320
|
+
// Kimi models
|
|
321
|
+
{ name: "Kimi K2.5", value: "kimi-k2.5" }
|
|
234
322
|
],
|
|
235
323
|
default: "auto"
|
|
236
324
|
},
|
|
@@ -263,11 +351,44 @@ class LmChatCursorAgent {
|
|
|
263
351
|
}
|
|
264
352
|
async supplyData(itemIndex) {
|
|
265
353
|
const modelName = this.getNodeParameter("model", itemIndex);
|
|
266
|
-
const
|
|
354
|
+
const binaryPath = this.getNodeParameter(
|
|
355
|
+
"options.binaryPath",
|
|
356
|
+
itemIndex,
|
|
357
|
+
"cursor-agent"
|
|
358
|
+
);
|
|
359
|
+
const rawWorkingDirectory = this.getNodeParameter("options.workingDirectory", itemIndex, "", {
|
|
360
|
+
rawExpressions: true
|
|
361
|
+
});
|
|
362
|
+
const workingDirectory = this.getNodeParameter("options.workingDirectory", itemIndex, "");
|
|
363
|
+
const normalizedWorkingDirectory = (workingDirectory ?? "").trim();
|
|
364
|
+
const rawWorkingDirectoryValue = rawWorkingDirectory ?? "";
|
|
365
|
+
const isWorkingDirectoryExpression = rawWorkingDirectoryValue.startsWith("=") || rawWorkingDirectoryValue.includes("{{") || rawWorkingDirectoryValue.includes("$workspace");
|
|
366
|
+
console.log("[LmChatCursorAgent] resolved Cursor Agent options", {
|
|
367
|
+
itemIndex,
|
|
368
|
+
modelName,
|
|
369
|
+
binaryPath,
|
|
370
|
+
rawWorkingDirectory,
|
|
371
|
+
workingDirectory: normalizedWorkingDirectory
|
|
372
|
+
});
|
|
373
|
+
if (isWorkingDirectoryExpression && !normalizedWorkingDirectory) {
|
|
374
|
+
throw new import_n8n_workflow.ApplicationError(
|
|
375
|
+
`Cursor Agent working directory expression resolved to an empty value: ${rawWorkingDirectoryValue}`
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
if (normalizedWorkingDirectory.includes("{{") || normalizedWorkingDirectory.includes("$workspace")) {
|
|
379
|
+
throw new import_n8n_workflow.ApplicationError(
|
|
380
|
+
`Cursor Agent working directory was not resolved before execution: ${normalizedWorkingDirectory}`
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
if (normalizedWorkingDirectory && (!(0, import_fs.existsSync)(normalizedWorkingDirectory) || !(0, import_fs.statSync)(normalizedWorkingDirectory).isDirectory())) {
|
|
384
|
+
throw new import_n8n_workflow.ApplicationError(
|
|
385
|
+
`Cursor Agent working directory does not exist or is not a directory: ${normalizedWorkingDirectory}`
|
|
386
|
+
);
|
|
387
|
+
}
|
|
267
388
|
const model = new ChatCursorAgentCLI({
|
|
268
389
|
model: modelName,
|
|
269
|
-
binaryPath
|
|
270
|
-
workingDirectory:
|
|
390
|
+
binaryPath,
|
|
391
|
+
workingDirectory: normalizedWorkingDirectory
|
|
271
392
|
});
|
|
272
393
|
model.callbacks = [new import_N8nLlmTracing.N8nLlmTracing(this)];
|
|
273
394
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../nodes/llms/LmChatCursorAgent/LmChatCursorAgent.node.ts"],"sourcesContent":["import { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport { AIMessage, HumanMessage, SystemMessage } from '@langchain/core/messages';\nimport type { ChatResult } from '@langchain/core/outputs';\nimport type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';\nimport type { BindToolsInput } from '@langchain/core/language_models/chat_models';\nimport {\n\tNodeConnectionTypes,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n\ttype ISupplyDataFunctions,\n\ttype SupplyData,\n} from 'n8n-workflow';\n\nimport { getConnectionHintNoticeField } from '@utils/sharedFields';\n\nimport { N8nLlmTracing } from '../N8nLlmTracing';\nimport { spawn } from 'child_process';\n\ninterface CursorAgentFields {\n\tmodel: string;\n\tbinaryPath: string;\n\tworkingDirectory: string;\n}\n\ninterface ParsedToolCall {\n\tid: string;\n\tname: string;\n\targs: Record<string, unknown>;\n}\n\nconst TOOL_CALL_SYSTEM_PROMPT = `You have access to the following tools. When you need to call a tool, respond ONLY with a JSON block in this exact format (no other text before or after):\n\n\\`\\`\\`tool_calls\n[{\"id\": \"call_1\", \"name\": \"tool_name\", \"args\": {\"param\": \"value\"}}]\n\\`\\`\\`\n\nWhen you do NOT need to call a tool, respond normally with text. Never mix tool calls and text in the same response.\n\nAvailable tools:\n`;\n\n/**\n * Custom LangChain chat model that wraps the cursor-agent CLI binary.\n * Supports tool calling by injecting tool schemas into the prompt\n * and parsing structured JSON responses for tool calls.\n */\nclass ChatCursorAgentCLI extends BaseChatModel {\n\tmodel: string;\n\n\tbinaryPath: string;\n\n\tworkingDirectory: string;\n\n\tboundTools: BindToolsInput[] = [];\n\n\tconstructor(fields: CursorAgentFields) {\n\t\tsuper({});\n\t\tthis.model = fields.model;\n\t\tthis.binaryPath = fields.binaryPath;\n\t\tthis.workingDirectory = fields.workingDirectory;\n\t}\n\n\t_llmType(): string {\n\t\treturn 'cursor-agent-cli';\n\t}\n\n\toverride bindTools(tools: BindToolsInput[], kwargs?: Partial<this['ParsedCallOptions']>) {\n\t\tconst clone = new ChatCursorAgentCLI({\n\t\t\tmodel: this.model,\n\t\t\tbinaryPath: this.binaryPath,\n\t\t\tworkingDirectory: this.workingDirectory,\n\t\t});\n\t\tclone.boundTools = tools;\n\t\tclone.callbacks = this.callbacks;\n\t\tif (kwargs) {\n\t\t\treturn clone.bind(kwargs);\n\t\t}\n\t\treturn clone;\n\t}\n\n\tasync _generate(\n\t\tmessages: BaseMessage[],\n\t\t_options: this['ParsedCallOptions'],\n\t\t_runManager?: CallbackManagerForLLMRun,\n\t): Promise<ChatResult> {\n\t\t// If tools are bound, inject tool schemas into a system message\n\t\tconst processedMessages = [...messages];\n\t\tif (this.boundTools.length > 0) {\n\t\t\tconst toolDescriptions = this.boundTools\n\t\t\t\t.map((tool) => {\n\t\t\t\t\tconst t = tool as Record<string, unknown>;\n\t\t\t\t\tconst name = (t.name as string) ?? '';\n\t\t\t\t\tconst description = (t.description as string) ?? '';\n\t\t\t\t\tconst schema = t.parameters ?? t.schema ?? {};\n\t\t\t\t\treturn `- ${name}: ${description}\\n Parameters: ${JSON.stringify(schema)}`;\n\t\t\t\t})\n\t\t\t\t.join('\\n\\n');\n\n\t\t\tconst systemPrompt = TOOL_CALL_SYSTEM_PROMPT + toolDescriptions;\n\t\t\tprocessedMessages.unshift(new SystemMessage(systemPrompt));\n\t\t}\n\n\t\t// Build prompt from messages\n\t\tconst prompt = processedMessages\n\t\t\t.map((m) => {\n\t\t\t\tconst content = typeof m.content === 'string' ? m.content : JSON.stringify(m.content);\n\t\t\t\tif (m instanceof SystemMessage) return `[system]: ${content}`;\n\t\t\t\tif (m instanceof HumanMessage) return `[user]: ${content}`;\n\t\t\t\tif (m instanceof AIMessage) return `[assistant]: ${content}`;\n\t\t\t\treturn `[${m._getType()}]: ${content}`;\n\t\t\t})\n\t\t\t.join('\\n\\n');\n\n\t\t// Execute cursor-agent CLI\n\t\tconst rawResponse = await this.executeCursorAgent(prompt);\n\n\t\t// Check for tool calls in response\n\t\tif (this.boundTools.length > 0) {\n\t\t\tconst toolCalls = this.extractToolCalls(rawResponse);\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tconst aiMessage = new AIMessage({\n\t\t\t\t\tcontent: '',\n\t\t\t\t\ttool_calls: toolCalls.map((tc) => ({\n\t\t\t\t\t\tid: tc.id,\n\t\t\t\t\t\tname: tc.name,\n\t\t\t\t\t\targs: tc.args,\n\t\t\t\t\t\ttype: 'tool_call' as const,\n\t\t\t\t\t})),\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\tgenerations: [{ message: aiMessage, text: '' }],\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\t// Normal text response\n\t\tconst aiMessage = new AIMessage({ content: rawResponse });\n\t\treturn {\n\t\t\tgenerations: [{ message: aiMessage, text: rawResponse }],\n\t\t};\n\t}\n\n\tprivate extractToolCalls(text: string): ParsedToolCall[] {\n\t\t// Look for tool_calls JSON block\n\t\tconst toolCallRegex = /```tool_calls\\s*\\n([\\s\\S]*?)\\n```/;\n\t\tconst match = toolCallRegex.exec(text);\n\t\tif (!match) return [];\n\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(match[1]) as Array<{\n\t\t\t\tid?: string;\n\t\t\t\tname: string;\n\t\t\t\targs: Record<string, unknown>;\n\t\t\t}>;\n\t\t\tif (!Array.isArray(parsed)) return [];\n\n\t\t\treturn parsed.map((tc, i) => ({\n\t\t\t\tid: tc.id ?? `call_${i}`,\n\t\t\t\tname: tc.name,\n\t\t\t\targs: tc.args ?? {},\n\t\t\t}));\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t}\n\n\tprivate async executeCursorAgent(prompt: string): Promise<string> {\n\t\tconst args = ['-p', '--output-format=stream-json', '--trust'];\n\t\tif (this.model && this.model !== 'auto') {\n\t\t\targs.push('--model', this.model);\n\t\t}\n\n\t\treturn await new Promise<string>((resolve, reject) => {\n\t\t\tconst child = spawn(this.binaryPath, args, {\n\t\t\t\tcwd: this.workingDirectory || undefined,\n\t\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\t\tenv: { ...process.env },\n\t\t\t});\n\n\t\t\tlet stdout = '';\n\t\t\tlet stderr = '';\n\n\t\t\tchild.stdout.on('data', (data: Buffer) => {\n\t\t\t\tstdout += data.toString();\n\t\t\t});\n\n\t\t\tchild.stderr.on('data', (data: Buffer) => {\n\t\t\t\tstderr += data.toString();\n\t\t\t});\n\n\t\t\tchild.on('error', (err: Error) => {\n\t\t\t\treject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`Failed to spawn cursor-agent: ${err.message}. Make sure cursor-agent CLI is installed and accessible.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tchild.on('close', (code: number | null) => {\n\t\t\t\tif (code !== 0 && !stdout) {\n\t\t\t\t\tconst errorMsg = stderr.trim() || `cursor-agent exited with code ${code}`;\n\t\t\t\t\treject(new Error(errorMsg));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst assistantContent = this.parseStreamJsonOutput(stdout);\n\n\t\t\t\tif (!assistantContent) {\n\t\t\t\t\treject(new Error('No assistant response received from cursor-agent'));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tresolve(assistantContent);\n\t\t\t});\n\n\t\t\tif (child.stdin) {\n\t\t\t\tchild.stdin.write(prompt);\n\t\t\t\tchild.stdin.end();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate parseStreamJsonOutput(output: string): string {\n\t\tconst lines = output.split('\\n').filter((line) => line.trim());\n\t\tconst assistantParts: string[] = [];\n\n\t\tfor (const line of lines) {\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(line) as {\n\t\t\t\t\ttype?: string;\n\t\t\t\t\tmessage?: {\n\t\t\t\t\t\tcontent?: Array<{ type?: string; text?: string }>;\n\t\t\t\t\t};\n\t\t\t\t\ttext?: string;\n\t\t\t\t};\n\n\t\t\t\tif (parsed.type === 'assistant' && parsed.message?.content) {\n\t\t\t\t\tfor (const item of parsed.message.content) {\n\t\t\t\t\t\tif (item.type === 'text' && item.text) {\n\t\t\t\t\t\t\tassistantParts.push(item.text);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Skip non-JSON lines\n\t\t\t}\n\t\t}\n\n\t\treturn assistantParts.join('');\n\t}\n}\n\nexport class LmChatCursorAgent implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Cursor Agent CLI Chat Model',\n\n\t\tname: 'lmChatCursorAgent',\n\t\ticon: 'file:cursorAgent.svg',\n\t\tgroup: ['transform'],\n\t\tversion: [1],\n\t\tdescription:\n\t\t\t'Chat model powered by the Cursor Agent CLI. Requires cursor-agent to be installed locally.',\n\t\tdefaults: {\n\t\t\tname: 'Cursor Agent CLI Chat Model',\n\t\t},\n\t\tcodex: {\n\t\t\tcategories: ['AI'],\n\t\t\tsubcategories: {\n\t\t\t\tAI: ['Language Models', 'Root Nodes'],\n\t\t\t\t'Language Models': ['Chat Models (Recommended)'],\n\t\t\t},\n\t\t\tresources: {},\n\t\t},\n\n\t\tinputs: [],\n\n\t\toutputs: [NodeConnectionTypes.AiLanguageModel],\n\t\toutputNames: ['Model'],\n\t\tproperties: [\n\t\t\tgetConnectionHintNoticeField([NodeConnectionTypes.AiChain, NodeConnectionTypes.AiAgent]),\n\t\t\t{\n\t\t\t\tdisplayName: 'Model',\n\t\t\t\tname: 'model',\n\t\t\t\ttype: 'options',\n\t\t\t\tdescription: 'The model to use via cursor-agent CLI.',\n\t\t\t\t// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: 'Auto', value: 'auto' },\n\t\t\t\t\t{ name: 'Composer 1', value: 'composer-1' },\n\t\t\t\t\t{ name: 'Composer 1.5', value: 'composer-1.5' },\n\t\t\t\t\t{ name: 'Gemini 3 Flash', value: 'gemini-3-flash' },\n\t\t\t\t\t{ name: 'Gemini 3 Pro', value: 'gemini-3-pro' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Max', value: 'gpt-5.1-codex-max' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Max High', value: 'gpt-5.1-codex-max-high' },\n\t\t\t\t\t{ name: 'GPT-5.2', value: 'gpt-5.2' },\n\t\t\t\t\t{ name: 'GPT-5.2 High', value: 'gpt-5.2-high' },\n\t\t\t\t\t{ name: 'Grok', value: 'grok' },\n\t\t\t\t\t{ name: 'Opus 4.5', value: 'opus-4.5' },\n\t\t\t\t\t{ name: 'Opus 4.5 Thinking', value: 'opus-4.5-thinking' },\n\t\t\t\t\t{ name: 'Sonnet 4.5', value: 'sonnet-4.5' },\n\t\t\t\t\t{ name: 'Sonnet 4.5 Thinking', value: 'sonnet-4.5-thinking' },\n\t\t\t\t],\n\t\t\t\tdefault: 'auto',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\tdescription: 'Additional options to configure',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Binary Path',\n\t\t\t\t\t\tname: 'binaryPath',\n\t\t\t\t\t\tdefault: 'cursor-agent',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Path to the cursor-agent binary. Defaults to \"cursor-agent\" (must be in PATH).',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Working Directory',\n\t\t\t\t\t\tname: 'workingDirectory',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Working directory for the cursor-agent process. Leave empty to use the default.',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n\n\tasync supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData> {\n\t\tconst modelName = this.getNodeParameter('model', itemIndex) as string;\n\n\t\tconst options = this.getNodeParameter('options', itemIndex, {}) as {\n\t\t\tbinaryPath?: string;\n\t\t\tworkingDirectory?: string;\n\t\t};\n\n\t\tconst model = new ChatCursorAgentCLI({\n\t\t\tmodel: modelName,\n\t\t\tbinaryPath: options.binaryPath ?? 'cursor-agent',\n\t\t\tworkingDirectory: options.workingDirectory ?? '',\n\t\t});\n\n\t\tmodel.callbacks = [new N8nLlmTracing(this)];\n\n\t\treturn {\n\t\t\tresponse: model,\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["aiMessage"]}
|
|
1
|
+
{"version":3,"sources":["../../../../nodes/llms/LmChatCursorAgent/LmChatCursorAgent.node.ts"],"sourcesContent":["import { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport { AIMessage, HumanMessage, SystemMessage } from '@langchain/core/messages';\nimport type { ChatResult } from '@langchain/core/outputs';\nimport type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';\nimport type { BindToolsInput } from '@langchain/core/language_models/chat_models';\nimport {\n\tApplicationError,\n\tNodeConnectionTypes,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n\ttype ISupplyDataFunctions,\n\ttype SupplyData,\n} from 'n8n-workflow';\n\nimport { getConnectionHintNoticeField } from '@utils/sharedFields';\n\nimport { N8nLlmTracing } from '../N8nLlmTracing';\nimport { spawn } from 'child_process';\nimport { existsSync, statSync } from 'fs';\n\ninterface CursorAgentFields {\n\tmodel: string;\n\tbinaryPath: string;\n\tworkingDirectory: string;\n}\n\ninterface ParsedToolCall {\n\tid: string;\n\tname: string;\n\targs: Record<string, unknown>;\n}\n\nconst TOOL_CALL_SYSTEM_PROMPT = `You have access to the following tools. When you need to call a tool, respond ONLY with a JSON block in this exact format (no other text before or after):\n\n\\`\\`\\`tool_calls\n[{\"id\": \"call_1\", \"name\": \"tool_name\", \"args\": {\"param\": \"value\"}}]\n\\`\\`\\`\n\nWhen you do NOT need to call a tool, respond normally with text. Never mix tool calls and text in the same response.\n\nAvailable tools:\n`;\n\n/**\n * Custom LangChain chat model that wraps the cursor-agent CLI binary.\n * Supports tool calling by injecting tool schemas into the prompt\n * and parsing structured JSON responses for tool calls.\n */\nclass ChatCursorAgentCLI extends BaseChatModel {\n\tmodel: string;\n\n\tbinaryPath: string;\n\n\tworkingDirectory: string;\n\n\tboundTools: BindToolsInput[] = [];\n\n\tconstructor(fields: CursorAgentFields) {\n\t\tsuper({});\n\t\tthis.model = fields.model;\n\t\tthis.binaryPath = fields.binaryPath;\n\t\tthis.workingDirectory = fields.workingDirectory;\n\t}\n\n\t_llmType(): string {\n\t\treturn 'cursor-agent-cli';\n\t}\n\n\toverride bindTools(tools: BindToolsInput[], kwargs?: Partial<this['ParsedCallOptions']>) {\n\t\tconst clone = new ChatCursorAgentCLI({\n\t\t\tmodel: this.model,\n\t\t\tbinaryPath: this.binaryPath,\n\t\t\tworkingDirectory: this.workingDirectory,\n\t\t});\n\t\tclone.boundTools = tools;\n\t\tclone.callbacks = this.callbacks;\n\t\tif (kwargs) {\n\t\t\treturn (\n\t\t\t\tclone as unknown as {\n\t\t\t\t\tbind: (kwargs: Record<string, unknown>) => ChatCursorAgentCLI;\n\t\t\t\t}\n\t\t\t).bind(kwargs as Record<string, unknown>);\n\t\t}\n\t\treturn clone;\n\t}\n\n\tasync _generate(\n\t\tmessages: BaseMessage[],\n\t\t_options: this['ParsedCallOptions'],\n\t\t_runManager?: CallbackManagerForLLMRun,\n\t): Promise<ChatResult> {\n\t\t// If tools are bound, inject tool schemas into a system message\n\t\tconst processedMessages = [...messages];\n\t\tif (this.boundTools.length > 0) {\n\t\t\tconst toolDescriptions = this.boundTools\n\t\t\t\t.map((tool) => {\n\t\t\t\t\tconst t = tool as Record<string, unknown>;\n\t\t\t\t\tconst name = (t.name as string) ?? '';\n\t\t\t\t\tconst description = (t.description as string) ?? '';\n\t\t\t\t\tconst schema = t.parameters ?? t.schema ?? {};\n\t\t\t\t\treturn `- ${name}: ${description}\\n Parameters: ${JSON.stringify(schema)}`;\n\t\t\t\t})\n\t\t\t\t.join('\\n\\n');\n\n\t\t\tconst systemPrompt = TOOL_CALL_SYSTEM_PROMPT + toolDescriptions;\n\t\t\tprocessedMessages.unshift(new SystemMessage(systemPrompt));\n\t\t}\n\n\t\t// Build prompt from messages\n\t\tconst prompt = processedMessages\n\t\t\t.map((m) => {\n\t\t\t\tconst content = typeof m.content === 'string' ? m.content : JSON.stringify(m.content);\n\t\t\t\tif (m instanceof SystemMessage) return `[system]: ${content}`;\n\t\t\t\tif (m instanceof HumanMessage) return `[user]: ${content}`;\n\t\t\t\tif (m instanceof AIMessage) return `[assistant]: ${content}`;\n\t\t\t\treturn `[${m._getType()}]: ${content}`;\n\t\t\t})\n\t\t\t.join('\\n\\n');\n\n\t\t// Execute cursor-agent CLI\n\t\tconst rawResponse = await this.executeCursorAgent(prompt);\n\n\t\t// Check for tool calls in response\n\t\tif (this.boundTools.length > 0) {\n\t\t\tconst toolCalls = this.extractToolCalls(rawResponse);\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tconst aiMessage = new AIMessage({\n\t\t\t\t\tcontent: '',\n\t\t\t\t\ttool_calls: toolCalls.map((tc) => ({\n\t\t\t\t\t\tid: tc.id,\n\t\t\t\t\t\tname: tc.name,\n\t\t\t\t\t\targs: tc.args,\n\t\t\t\t\t\ttype: 'tool_call' as const,\n\t\t\t\t\t})),\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\tgenerations: [{ message: aiMessage, text: '' }],\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\t// Normal text response\n\t\tconst aiMessage = new AIMessage({ content: rawResponse });\n\t\treturn {\n\t\t\tgenerations: [{ message: aiMessage, text: rawResponse }],\n\t\t};\n\t}\n\n\tprivate extractToolCalls(text: string): ParsedToolCall[] {\n\t\t// Look for tool_calls JSON block\n\t\tconst toolCallRegex = /```tool_calls\\s*\\n([\\s\\S]*?)\\n```/;\n\t\tconst match = toolCallRegex.exec(text);\n\t\tif (!match) return [];\n\n\t\ttry {\n\t\t\tconst parsed = JSON.parse(match[1]) as Array<{\n\t\t\t\tid?: string;\n\t\t\t\tname: string;\n\t\t\t\targs: Record<string, unknown>;\n\t\t\t}>;\n\t\t\tif (!Array.isArray(parsed)) return [];\n\n\t\t\treturn parsed.map((tc, i) => ({\n\t\t\t\tid: tc.id ?? `call_${i}`,\n\t\t\t\tname: tc.name,\n\t\t\t\targs: tc.args ?? {},\n\t\t\t}));\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t}\n\n\tprivate async executeCursorAgent(prompt: string): Promise<string> {\n\t\tconst args = ['-p', '--output-format=stream-json', '--trust'];\n\t\tif (this.model && this.model !== 'auto') {\n\t\t\targs.push('--model', this.model);\n\t\t}\n\t\tconst cwd = this.workingDirectory?.trim() || undefined;\n\n\t\tconsole.log('[LmChatCursorAgent] spawning cursor-agent', {\n\t\t\tbinaryPath: this.binaryPath,\n\t\t\tmodel: this.model,\n\t\t\tcwd,\n\t\t});\n\n\t\treturn await new Promise<string>((resolve, reject) => {\n\t\t\tconst child = spawn(this.binaryPath, args, {\n\t\t\t\tcwd,\n\t\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\t\tenv: { ...process.env },\n\t\t\t});\n\n\t\t\tlet stdout = '';\n\t\t\tlet stderr = '';\n\n\t\t\tchild.stdout.on('data', (data: Buffer) => {\n\t\t\t\tstdout += data.toString();\n\t\t\t});\n\n\t\t\tchild.stderr.on('data', (data: Buffer) => {\n\t\t\t\tstderr += data.toString();\n\t\t\t});\n\n\t\t\tchild.on('error', (err: Error) => {\n\t\t\t\treject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`Failed to spawn cursor-agent: ${err.message}. Make sure cursor-agent CLI is installed and accessible. Working directory: ${cwd ?? '<default>'}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tchild.on('close', (code: number | null) => {\n\t\t\t\tif (code !== 0 && !stdout) {\n\t\t\t\t\tconst errorMsg = stderr.trim() || `cursor-agent exited with code ${code}`;\n\t\t\t\t\treject(new Error(errorMsg));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst assistantContent = this.parseStreamJsonOutput(stdout);\n\n\t\t\t\tif (!assistantContent) {\n\t\t\t\t\treject(new Error('No assistant response received from cursor-agent'));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tresolve(assistantContent);\n\t\t\t});\n\n\t\t\tif (child.stdin) {\n\t\t\t\tchild.stdin.write(prompt);\n\t\t\t\tchild.stdin.end();\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate parseStreamJsonOutput(output: string): string {\n\t\tconst lines = output.split('\\n').filter((line) => line.trim());\n\t\tconst assistantParts: string[] = [];\n\n\t\tfor (const line of lines) {\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(line) as {\n\t\t\t\t\ttype?: string;\n\t\t\t\t\tmessage?: {\n\t\t\t\t\t\tcontent?: Array<{ type?: string; text?: string }>;\n\t\t\t\t\t};\n\t\t\t\t\ttext?: string;\n\t\t\t\t};\n\n\t\t\t\tif (parsed.type === 'assistant' && parsed.message?.content) {\n\t\t\t\t\tfor (const item of parsed.message.content) {\n\t\t\t\t\t\tif (item.type === 'text' && item.text) {\n\t\t\t\t\t\t\tassistantParts.push(item.text);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Skip non-JSON lines\n\t\t\t}\n\t\t}\n\n\t\treturn assistantParts.join('');\n\t}\n}\n\nexport class LmChatCursorAgent implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Cursor Agent CLI Chat Model',\n\n\t\tname: 'lmChatCursorAgent',\n\t\ticon: 'file:cursorAgent.svg',\n\t\tgroup: ['transform'],\n\t\tversion: [1],\n\t\tdescription:\n\t\t\t'Chat model powered by the Cursor Agent CLI. Requires cursor-agent to be installed locally.',\n\t\tdefaults: {\n\t\t\tname: 'Cursor Agent CLI Chat Model',\n\t\t},\n\t\tcodex: {\n\t\t\tcategories: ['AI'],\n\t\t\tsubcategories: {\n\t\t\t\tAI: ['Language Models', 'Root Nodes'],\n\t\t\t\t'Language Models': ['Chat Models (Recommended)'],\n\t\t\t},\n\t\t\tresources: {},\n\t\t},\n\n\t\tinputs: [],\n\n\t\toutputs: [NodeConnectionTypes.AiLanguageModel],\n\t\toutputNames: ['Model'],\n\t\tproperties: [\n\t\t\tgetConnectionHintNoticeField([NodeConnectionTypes.AiChain, NodeConnectionTypes.AiAgent]),\n\t\t\t{\n\t\t\t\tdisplayName: 'Model',\n\t\t\t\tname: 'model',\n\t\t\t\ttype: 'options',\n\t\t\t\tdescription: 'The model to use via cursor-agent CLI',\n\t\t\t\t// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items\n\t\t\t\toptions: [\n\t\t\t\t\t{ name: 'Auto', value: 'auto' },\n\t\t\t\t\t// Composer models\n\t\t\t\t\t{ name: 'Composer 2 Fast', value: 'composer-2-fast' },\n\t\t\t\t\t{ name: 'Composer 2', value: 'composer-2' },\n\t\t\t\t\t{ name: 'Composer 1.5', value: 'composer-1.5' },\n\t\t\t\t\t// Claude 4.6 models\n\t\t\t\t\t{ name: 'Claude 4.6 Opus High', value: 'claude-4.6-opus-high' },\n\t\t\t\t\t{ name: 'Claude 4.6 Opus High Thinking', value: 'claude-4.6-opus-high-thinking' },\n\t\t\t\t\t{ name: 'Claude 4.6 Opus Max', value: 'claude-4.6-opus-max' },\n\t\t\t\t\t{ name: 'Claude 4.6 Opus Max Thinking', value: 'claude-4.6-opus-max-thinking' },\n\t\t\t\t\t{ name: 'Claude 4.6 Sonnet Medium', value: 'claude-4.6-sonnet-medium' },\n\t\t\t\t\t{ name: 'Claude 4.6 Sonnet Medium Thinking', value: 'claude-4.6-sonnet-medium-thinking' },\n\t\t\t\t\t// Claude 4.5 models\n\t\t\t\t\t{ name: 'Claude 4.5 Opus High', value: 'claude-4.5-opus-high' },\n\t\t\t\t\t{ name: 'Claude 4.5 Opus High Thinking', value: 'claude-4.5-opus-high-thinking' },\n\t\t\t\t\t{ name: 'Claude 4.5 Sonnet', value: 'claude-4.5-sonnet' },\n\t\t\t\t\t{ name: 'Claude 4.5 Sonnet Thinking', value: 'claude-4.5-sonnet-thinking' },\n\t\t\t\t\t// Claude 4 models\n\t\t\t\t\t{ name: 'Claude 4 Sonnet', value: 'claude-4-sonnet' },\n\t\t\t\t\t{ name: 'Claude 4 Sonnet 1M', value: 'claude-4-sonnet-1m' },\n\t\t\t\t\t{ name: 'Claude 4 Sonnet Thinking', value: 'claude-4-sonnet-thinking' },\n\t\t\t\t\t{ name: 'Claude 4 Sonnet 1M Thinking', value: 'claude-4-sonnet-1m-thinking' },\n\t\t\t\t\t// Gemini models\n\t\t\t\t\t{ name: 'Gemini 3.1 Pro', value: 'gemini-3.1-pro' },\n\t\t\t\t\t{ name: 'Gemini 3 Flash', value: 'gemini-3-flash' },\n\t\t\t\t\t// GPT-5.4 models\n\t\t\t\t\t{ name: 'GPT-5.4 Low', value: 'gpt-5.4-low' },\n\t\t\t\t\t{ name: 'GPT-5.4 Medium', value: 'gpt-5.4-medium' },\n\t\t\t\t\t{ name: 'GPT-5.4 Medium Fast', value: 'gpt-5.4-medium-fast' },\n\t\t\t\t\t{ name: 'GPT-5.4 High', value: 'gpt-5.4-high' },\n\t\t\t\t\t{ name: 'GPT-5.4 High Fast', value: 'gpt-5.4-high-fast' },\n\t\t\t\t\t{ name: 'GPT-5.4 XHigh', value: 'gpt-5.4-xhigh' },\n\t\t\t\t\t{ name: 'GPT-5.4 XHigh Fast', value: 'gpt-5.4-xhigh-fast' },\n\t\t\t\t\t{ name: 'GPT-5.4 Mini None', value: 'gpt-5.4-mini-none' },\n\t\t\t\t\t{ name: 'GPT-5.4 Mini Low', value: 'gpt-5.4-mini-low' },\n\t\t\t\t\t{ name: 'GPT-5.4 Mini Medium', value: 'gpt-5.4-mini-medium' },\n\t\t\t\t\t{ name: 'GPT-5.4 Mini High', value: 'gpt-5.4-mini-high' },\n\t\t\t\t\t{ name: 'GPT-5.4 Mini XHigh', value: 'gpt-5.4-mini-xhigh' },\n\t\t\t\t\t{ name: 'GPT-5.4 Nano None', value: 'gpt-5.4-nano-none' },\n\t\t\t\t\t{ name: 'GPT-5.4 Nano Low', value: 'gpt-5.4-nano-low' },\n\t\t\t\t\t{ name: 'GPT-5.4 Nano Medium', value: 'gpt-5.4-nano-medium' },\n\t\t\t\t\t{ name: 'GPT-5.4 Nano High', value: 'gpt-5.4-nano-high' },\n\t\t\t\t\t{ name: 'GPT-5.4 Nano XHigh', value: 'gpt-5.4-nano-xhigh' },\n\t\t\t\t\t// GPT-5.3 Codex models\n\t\t\t\t\t{ name: 'GPT-5.3 Codex Low', value: 'gpt-5.3-codex-low' },\n\t\t\t\t\t{ name: 'GPT-5.3 Codex Low Fast', value: 'gpt-5.3-codex-low-fast' },\n\t\t\t\t\t{ name: 'GPT-5.3 Codex', value: 'gpt-5.3-codex' },\n\t\t\t\t\t{ name: 'GPT-5.3 Codex Fast', value: 'gpt-5.3-codex-fast' },\n\t\t\t\t\t{ name: 'GPT-5.3 Codex High', value: 'gpt-5.3-codex-high' },\n\t\t\t\t\t{ name: 'GPT-5.3 Codex High Fast', value: 'gpt-5.3-codex-high-fast' },\n\t\t\t\t\t{ name: 'GPT-5.3 Codex XHigh', value: 'gpt-5.3-codex-xhigh' },\n\t\t\t\t\t{ name: 'GPT-5.3 Codex XHigh Fast', value: 'gpt-5.3-codex-xhigh-fast' },\n\t\t\t\t\t{ name: 'GPT-5.3 Codex Spark Preview Low', value: 'gpt-5.3-codex-spark-preview-low' },\n\t\t\t\t\t{ name: 'GPT-5.3 Codex Spark Preview', value: 'gpt-5.3-codex-spark-preview' },\n\t\t\t\t\t{ name: 'GPT-5.3 Codex Spark Preview High', value: 'gpt-5.3-codex-spark-preview-high' },\n\t\t\t\t\t{ name: 'GPT-5.3 Codex Spark Preview XHigh', value: 'gpt-5.3-codex-spark-preview-xhigh' },\n\t\t\t\t\t// GPT-5.2 models\n\t\t\t\t\t{ name: 'GPT-5.2 Low', value: 'gpt-5.2-low' },\n\t\t\t\t\t{ name: 'GPT-5.2 Low Fast', value: 'gpt-5.2-low-fast' },\n\t\t\t\t\t{ name: 'GPT-5.2', value: 'gpt-5.2' },\n\t\t\t\t\t{ name: 'GPT-5.2 Fast', value: 'gpt-5.2-fast' },\n\t\t\t\t\t{ name: 'GPT-5.2 High', value: 'gpt-5.2-high' },\n\t\t\t\t\t{ name: 'GPT-5.2 High Fast', value: 'gpt-5.2-high-fast' },\n\t\t\t\t\t{ name: 'GPT-5.2 XHigh', value: 'gpt-5.2-xhigh' },\n\t\t\t\t\t{ name: 'GPT-5.2 XHigh Fast', value: 'gpt-5.2-xhigh-fast' },\n\t\t\t\t\t{ name: 'GPT-5.2 Codex Low', value: 'gpt-5.2-codex-low' },\n\t\t\t\t\t{ name: 'GPT-5.2 Codex Low Fast', value: 'gpt-5.2-codex-low-fast' },\n\t\t\t\t\t{ name: 'GPT-5.2 Codex', value: 'gpt-5.2-codex' },\n\t\t\t\t\t{ name: 'GPT-5.2 Codex Fast', value: 'gpt-5.2-codex-fast' },\n\t\t\t\t\t{ name: 'GPT-5.2 Codex High', value: 'gpt-5.2-codex-high' },\n\t\t\t\t\t{ name: 'GPT-5.2 Codex High Fast', value: 'gpt-5.2-codex-high-fast' },\n\t\t\t\t\t{ name: 'GPT-5.2 Codex XHigh', value: 'gpt-5.2-codex-xhigh' },\n\t\t\t\t\t{ name: 'GPT-5.2 Codex XHigh Fast', value: 'gpt-5.2-codex-xhigh-fast' },\n\t\t\t\t\t// GPT-5.1 models\n\t\t\t\t\t{ name: 'GPT-5.1 Low', value: 'gpt-5.1-low' },\n\t\t\t\t\t{ name: 'GPT-5.1', value: 'gpt-5.1' },\n\t\t\t\t\t{ name: 'GPT-5.1 High', value: 'gpt-5.1-high' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Max Low', value: 'gpt-5.1-codex-max-low' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Max Low Fast', value: 'gpt-5.1-codex-max-low-fast' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Max Medium', value: 'gpt-5.1-codex-max-medium' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Max Medium Fast', value: 'gpt-5.1-codex-max-medium-fast' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Max High', value: 'gpt-5.1-codex-max-high' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Max High Fast', value: 'gpt-5.1-codex-max-high-fast' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Max XHigh', value: 'gpt-5.1-codex-max-xhigh' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Max XHigh Fast', value: 'gpt-5.1-codex-max-xhigh-fast' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Mini Low', value: 'gpt-5.1-codex-mini-low' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Mini', value: 'gpt-5.1-codex-mini' },\n\t\t\t\t\t{ name: 'GPT-5.1 Codex Mini High', value: 'gpt-5.1-codex-mini-high' },\n\t\t\t\t\t// GPT-5 models\n\t\t\t\t\t{ name: 'GPT-5 Mini', value: 'gpt-5-mini' },\n\t\t\t\t\t// Grok models\n\t\t\t\t\t{ name: 'Grok 4 20', value: 'grok-4-20' },\n\t\t\t\t\t{ name: 'Grok 4 20 Thinking', value: 'grok-4-20-thinking' },\n\t\t\t\t\t// Kimi models\n\t\t\t\t\t{ name: 'Kimi K2.5', value: 'kimi-k2.5' },\n\t\t\t\t],\n\t\t\t\tdefault: 'auto',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\tdescription: 'Additional options to configure',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdefault: {},\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Binary Path',\n\t\t\t\t\t\tname: 'binaryPath',\n\t\t\t\t\t\tdefault: 'cursor-agent',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Path to the cursor-agent binary. Defaults to \"cursor-agent\" (must be in PATH).',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Working Directory',\n\t\t\t\t\t\tname: 'workingDirectory',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Working directory for the cursor-agent process. Leave empty to use the default.',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n\n\tasync supplyData(this: ISupplyDataFunctions, itemIndex: number): Promise<SupplyData> {\n\t\tconst modelName = this.getNodeParameter('model', itemIndex) as string;\n\n\t\tconst binaryPath = this.getNodeParameter(\n\t\t\t'options.binaryPath',\n\t\t\titemIndex,\n\t\t\t'cursor-agent',\n\t\t) as string;\n\t\tconst rawWorkingDirectory = this.getNodeParameter('options.workingDirectory', itemIndex, '', {\n\t\t\trawExpressions: true,\n\t\t}) as string | undefined;\n\t\tconst workingDirectory = this.getNodeParameter('options.workingDirectory', itemIndex, '') as\n\t\t\t| string\n\t\t\t| undefined;\n\t\tconst normalizedWorkingDirectory = (workingDirectory ?? '').trim();\n\t\tconst rawWorkingDirectoryValue = rawWorkingDirectory ?? '';\n\t\tconst isWorkingDirectoryExpression =\n\t\t\trawWorkingDirectoryValue.startsWith('=') ||\n\t\t\trawWorkingDirectoryValue.includes('{{') ||\n\t\t\trawWorkingDirectoryValue.includes('$workspace');\n\n\t\tconsole.log('[LmChatCursorAgent] resolved Cursor Agent options', {\n\t\t\titemIndex,\n\t\t\tmodelName,\n\t\t\tbinaryPath,\n\t\t\trawWorkingDirectory,\n\t\t\tworkingDirectory: normalizedWorkingDirectory,\n\t\t});\n\n\t\tif (isWorkingDirectoryExpression && !normalizedWorkingDirectory) {\n\t\t\tthrow new ApplicationError(\n\t\t\t\t`Cursor Agent working directory expression resolved to an empty value: ${rawWorkingDirectoryValue}`,\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\tnormalizedWorkingDirectory.includes('{{') ||\n\t\t\tnormalizedWorkingDirectory.includes('$workspace')\n\t\t) {\n\t\t\tthrow new ApplicationError(\n\t\t\t\t`Cursor Agent working directory was not resolved before execution: ${normalizedWorkingDirectory}`,\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\tnormalizedWorkingDirectory &&\n\t\t\t(!existsSync(normalizedWorkingDirectory) ||\n\t\t\t\t!statSync(normalizedWorkingDirectory).isDirectory())\n\t\t) {\n\t\t\tthrow new ApplicationError(\n\t\t\t\t`Cursor Agent working directory does not exist or is not a directory: ${normalizedWorkingDirectory}`,\n\t\t\t);\n\t\t}\n\n\t\tconst model = new ChatCursorAgentCLI({\n\t\t\tmodel: modelName,\n\t\t\tbinaryPath,\n\t\t\tworkingDirectory: normalizedWorkingDirectory,\n\t\t});\n\n\t\tmodel.callbacks = [new N8nLlmTracing(this)];\n\n\t\treturn {\n\t\t\tresponse: model,\n\t\t};\n\t}\n}\n"],"mappings":"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","names":["aiMessage"]}
|