mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-19 16:55:02 +02:00
fix(editor): Show AI Gateway hints for supported nodes used as tools (backport to release-candidate/2.29.x) (#33472)
Co-authored-by: Alexander Gekov <40495748+alexander-gekov@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
4d8304a7c6
commit
2b895252db
|
|
@ -343,6 +343,20 @@ describe('aiGateway.store', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('should fall back to the base node name for Tool-suffixed node types', async () => {
|
||||
mockGetGatewayConfig.mockResolvedValue(MOCK_CONFIG);
|
||||
const store = useAiGatewayStore();
|
||||
await store.fetchConfig();
|
||||
|
||||
// "openAiTool" is not a config key, but its base "openAi" is.
|
||||
expect(
|
||||
store.isActionSupported('@n8n/n8n-nodes-langchain.openAiTool', 'text', 'message'),
|
||||
).toBe(true);
|
||||
expect(store.isActionSupported('@n8n/n8n-nodes-langchain.openAiTool', 'file', 'upload')).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
describe('operation-only nodes (no resource)', () => {
|
||||
it('should return true when operation is in the OPERATION_ONLY list', async () => {
|
||||
mockGetGatewayConfig.mockResolvedValue(MOCK_CONFIG);
|
||||
|
|
@ -456,6 +470,19 @@ describe('aiGateway.store', () => {
|
|||
|
||||
expect(store.isNodePropertyHidden(null, 'modelSource')).toBe(false);
|
||||
});
|
||||
|
||||
it('should fall back to the base node name for Tool-suffixed node types', async () => {
|
||||
mockGetGatewayConfig.mockResolvedValue(MOCK_CONFIG);
|
||||
const store = useAiGatewayStore();
|
||||
await store.fetchConfig();
|
||||
|
||||
const toolNode = {
|
||||
type: 'n8n-nodes-browserbase.browserbaseTool',
|
||||
credentials: { browserbaseApi: { id: null, name: '', __aiGatewayManaged: true } },
|
||||
} as unknown as INode;
|
||||
|
||||
expect(store.isNodePropertyHidden(toolNode, 'modelSource')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNodeTypeVersionSupported()', () => {
|
||||
|
|
@ -516,5 +543,15 @@ describe('aiGateway.store', () => {
|
|||
// node support when config is unloaded is handled by isCredentialTypeSupported / isNodeSupported
|
||||
expect(store.isNodeTypeVersionSupported('some-package.SomeNode', 1.1)).toBe(true);
|
||||
});
|
||||
|
||||
it('should fall back to the base node name for Tool-suffixed node types', async () => {
|
||||
mockGetGatewayConfig.mockResolvedValue(CONFIG_WITH_VERSION_REQ);
|
||||
const store = useAiGatewayStore();
|
||||
await store.fetchConfig();
|
||||
|
||||
// "SomeNodeTool" has no entry, but the base "SomeNode" requires >= 1.1.
|
||||
expect(store.isNodeTypeVersionSupported('some-package.SomeNodeTool', 1.1)).toBe(true);
|
||||
expect(store.isNodeTypeVersionSupported('some-package.SomeNodeTool', 1.0)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ function toError(e: unknown): Error {
|
|||
return e instanceof Error ? e : new Error(String(e));
|
||||
}
|
||||
|
||||
// Tool-variant node types carry a "Tool"/"HitlTool" suffix (e.g. "openAiTool"),
|
||||
// but the gateway config is keyed by the base node name ("openAi").
|
||||
const stripToolSuffix = (nodeName: string) =>
|
||||
nodeName.replace(/HitlTool$/, '').replace(/Tool$/, '');
|
||||
|
||||
export const useAiGatewayStore = defineStore(STORES.AI_GATEWAY, () => {
|
||||
const rootStore = useRootStore();
|
||||
|
||||
|
|
@ -98,7 +103,9 @@ export const useAiGatewayStore = defineStore(STORES.AI_GATEWAY, () => {
|
|||
operation: string,
|
||||
): boolean {
|
||||
if (!config.value) return true;
|
||||
const nodeActions = config.value.supportedActions?.[nodeName];
|
||||
const nodeActions =
|
||||
config.value.supportedActions?.[nodeName] ??
|
||||
config.value.supportedActions?.[stripToolSuffix(nodeName)];
|
||||
if (!nodeActions) return true;
|
||||
const ops = nodeActions[resource ?? OPERATION_ONLY];
|
||||
if (!ops) return false;
|
||||
|
|
@ -106,7 +113,9 @@ export const useAiGatewayStore = defineStore(STORES.AI_GATEWAY, () => {
|
|||
}
|
||||
|
||||
function isNodeTypeVersionSupported(nodeName: string, typeVersion: number): boolean {
|
||||
const minVersion = config.value?.minNodeTypeVersion?.[nodeName];
|
||||
const minVersion =
|
||||
config.value?.minNodeTypeVersion?.[nodeName] ??
|
||||
config.value?.minNodeTypeVersion?.[stripToolSuffix(nodeName)];
|
||||
if (minVersion === undefined) return true;
|
||||
return typeVersion >= minVersion;
|
||||
}
|
||||
|
|
@ -119,7 +128,9 @@ export const useAiGatewayStore = defineStore(STORES.AI_GATEWAY, () => {
|
|||
);
|
||||
if (!hasGatewayCredential) return false;
|
||||
|
||||
const properties = config.value?.hiddenNodeProperties?.[node.type];
|
||||
const properties =
|
||||
config.value?.hiddenNodeProperties?.[node.type] ??
|
||||
config.value?.hiddenNodeProperties?.[stripToolSuffix(node.type)];
|
||||
if (!properties) return false;
|
||||
return properties.includes(propertyName);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user