mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-14 08:34:07 -08:00
setup for local testing
This commit is contained in:
parent
cb7c4d29a6
commit
6b4959fc76
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { ApplicationError, type INodeProperties, type NodePropertyAction } from 'n8n-workflow';
|
||||
import { type IDataObject, type INodeProperties, type NodePropertyAction } from 'n8n-workflow';
|
||||
import type { INodeUi, IUpdateInformation } from '@/Interface';
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { N8nButton, N8nInput, N8nTooltip } from 'n8n-design-system/components';
|
||||
|
@ -10,6 +10,7 @@ import { getSchemas, getParentNodes } from './utils';
|
|||
import { useRootStore } from '@/stores/root.store';
|
||||
import { useTelemetry } from '@/composables/useTelemetry';
|
||||
import { generateCodeForPrompt } from '@/api/ai';
|
||||
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||
|
||||
import { format } from 'prettier';
|
||||
import jsParser from 'prettier/plugins/babel';
|
||||
|
@ -29,6 +30,7 @@ const props = defineProps<{
|
|||
|
||||
const rootStore = useRootStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
|
||||
const i18n = useI18n();
|
||||
|
||||
|
@ -88,7 +90,7 @@ async function onSubmit() {
|
|||
value: prompt.value,
|
||||
});
|
||||
|
||||
const { type, target } = action;
|
||||
const { type, handler, target } = action;
|
||||
|
||||
startLoading();
|
||||
|
||||
|
@ -113,7 +115,20 @@ async function onSubmit() {
|
|||
const { code } = await generateCodeForPrompt(restApiContext, payload);
|
||||
value = code;
|
||||
} else {
|
||||
throw new ApplicationError('AI code generation is not enabled');
|
||||
if (handler) {
|
||||
const currentNodeParameters = activeNode.parameters;
|
||||
value = await nodeTypesStore.getNodeParameterActionResult({
|
||||
nodeTypeAndVersion: {
|
||||
name: activeNode.type,
|
||||
version: activeNode.typeVersion,
|
||||
},
|
||||
path: props.path,
|
||||
currentNodeParameters,
|
||||
credentials: activeNode.credentials,
|
||||
handler,
|
||||
payload: payload as unknown as IDataObject,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (value === undefined) return;
|
||||
|
|
|
@ -5,6 +5,8 @@ import {
|
|||
type INodeExecutionData,
|
||||
type INodeType,
|
||||
type INodeTypeDescription,
|
||||
type ILoadOptionsFunctions,
|
||||
type IDataObject,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import set from 'lodash/set';
|
||||
|
@ -12,6 +14,7 @@ import set from 'lodash/set';
|
|||
import { JavaScriptSandbox } from '../Code/JavaScriptSandbox';
|
||||
import { getSandboxContext } from '../Code/Sandbox';
|
||||
import { standardizeOutput } from '../Code/utils';
|
||||
import { generateMessage, type RequestPayload } from './test-setup';
|
||||
|
||||
const { CODE_ENABLE_STDOUT } = process.env;
|
||||
|
||||
|
@ -30,6 +33,16 @@ export class AiTransform implements INodeType {
|
|||
outputs: [NodeConnectionType.Main],
|
||||
parameterPane: 'wide',
|
||||
properties: [
|
||||
{
|
||||
displayName: 'OpenAI API Key',
|
||||
name: 'openAiApiKey',
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
password: true,
|
||||
},
|
||||
default: '',
|
||||
isNodeSetting: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Instructions',
|
||||
name: 'instructions',
|
||||
|
@ -47,6 +60,7 @@ export class AiTransform implements INodeType {
|
|||
action: {
|
||||
type: 'askAiCodeGeneration',
|
||||
target: 'jsCode',
|
||||
handler: 'generateCode',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -79,6 +93,22 @@ export class AiTransform implements INodeType {
|
|||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
actionHandler: {
|
||||
async generateCode(this: ILoadOptionsFunctions, payload: IDataObject | string | undefined) {
|
||||
const apiKey = this.getNodeParameter('openAiApiKey', 0) as string;
|
||||
|
||||
const code = await generateMessage.call(
|
||||
this,
|
||||
[{ role: 'user', content: (payload as unknown as RequestPayload)?.question || '' }],
|
||||
apiKey,
|
||||
);
|
||||
|
||||
return code;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions) {
|
||||
const workflowMode = this.getMode();
|
||||
|
||||
|
|
54
packages/nodes-base/nodes/AiTransform/test-setup.ts
Normal file
54
packages/nodes-base/nodes/AiTransform/test-setup.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
import axios from 'axios';
|
||||
import { type IDataObject, type ILoadOptionsFunctions, NodeApiError } from 'n8n-workflow';
|
||||
|
||||
interface Message {
|
||||
role: 'user' | 'assistant' | 'system';
|
||||
content: string;
|
||||
}
|
||||
|
||||
interface ChatResponse {
|
||||
choices: Array<{ message: Message }>;
|
||||
}
|
||||
|
||||
export interface RequestPayload {
|
||||
question: string;
|
||||
context: {
|
||||
schema: NodeExecutionSchema[];
|
||||
inputSchema: NodeExecutionSchema;
|
||||
pushRef: string;
|
||||
ndvPushRef: string;
|
||||
};
|
||||
forNode: 'code' | 'transform';
|
||||
}
|
||||
|
||||
export interface NodeExecutionSchema {
|
||||
nodeName: string;
|
||||
schema: IDataObject;
|
||||
}
|
||||
|
||||
export async function generateMessage(
|
||||
this: ILoadOptionsFunctions,
|
||||
messages: Message[],
|
||||
API_KEY: string,
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
const response = await axios.post<ChatResponse>(
|
||||
'https://api.openai.com/v1/chat/completions',
|
||||
{
|
||||
model: 'gpt-4o',
|
||||
messages,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${API_KEY}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const message = response.data.choices[0]?.message.content;
|
||||
return message || null;
|
||||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue