Support define is tool logic function (#17926)

- supports isTool and timeout settings in defineLogicFunction in apps
and in setting tabs definition
- compute for all toolInputSchema for logic funciton, in settings and in
code steps

<img width="991" height="802" alt="image"
src="https://github.com/user-attachments/assets/05dc1221-cac9-45a3-87b0-3b13161446fd"
/>
This commit is contained in:
martmull
2026-02-16 10:43:29 +01:00
committed by GitHub
parent f694bb99b3
commit da064d5e88
138 changed files with 4839 additions and 367 deletions
@@ -0,0 +1,67 @@
import { getFunctionInputSchema } from '@/logic-function/get-function-input-schema';
describe('getFunctionInputSchema', () => {
it('should analyze a simple function correctly', () => {
const fileContent = `
function testFunction(param1: string, param2: number): void {
return;
}
`;
const result = getFunctionInputSchema(fileContent);
expect(result).toEqual([{ type: 'string' }, { type: 'number' }]);
});
it('should analyze a arrow function correctly', () => {
const fileContent = `
export const main = async (
param1: string,
param2: number,
): Promise<object> => {
return param1;
};
`;
const result = getFunctionInputSchema(fileContent);
expect(result).toEqual([{ type: 'string' }, { type: 'number' }]);
});
it('should analyze a complex function correctly', () => {
const fileContent = `
function testFunction(
params: {
param1: string;
param2: number;
param3: boolean;
param4: object;
param5: { subParam1: string };
param6: "my" | "enum";
param7: string[];
}
): void {
return
}
`;
const result = getFunctionInputSchema(fileContent);
expect(result).toEqual([
{
type: 'object',
properties: {
param1: { type: 'string' },
param2: { type: 'number' },
param3: { type: 'boolean' },
param4: { type: 'object' },
param5: {
type: 'object',
properties: {
subParam1: { type: 'string' },
},
},
param6: { type: 'string', enum: ['my', 'enum'] },
param7: { type: 'array', items: { type: 'string' } },
},
},
]);
});
});
@@ -0,0 +1,75 @@
import { getInputSchemaFromSourceCode } from '@/logic-function/get-input-schema-from-source-code';
import { DEFAULT_TOOL_INPUT_SCHEMA } from '@/logic-function/constants/default-tool-input-schema';
describe('getInputSchemaFromSourceCode', () => {
it('should return empty input if not parameter', async () => {
const fileContent = 'function testFunction() { return }';
const result = await getInputSchemaFromSourceCode(fileContent);
expect(result).toEqual(DEFAULT_TOOL_INPUT_SCHEMA);
});
it('should return first input if multiple parameters', async () => {
const fileContent =
'function testFunction(params1: {}, params2: {}) { return }';
const result = await getInputSchemaFromSourceCode(fileContent);
expect(result).toEqual(DEFAULT_TOOL_INPUT_SCHEMA);
});
it('should return empty input if wrong parameter', async () => {
const fileContent = 'function testFunction(params: string) { return }';
const result = await getInputSchemaFromSourceCode(fileContent);
expect(result).toEqual(DEFAULT_TOOL_INPUT_SCHEMA);
});
it('should return input from source code', async () => {
const fileContent = `
function testFunction(
params: {
param1: string;
param2: number;
param3: boolean;
param4: object;
param5: { subParam1: string };
param6: "my" | "enum";
param7: string[];
}
): void {
return
}
`;
const result = await getInputSchemaFromSourceCode(fileContent);
expect(result).toEqual({
properties: {
param1: {
type: 'string',
},
param2: {
type: 'number',
},
param3: {
type: 'boolean',
},
param4: {
type: 'object',
},
param5: {
properties: {
subParam1: {
type: 'string',
},
},
type: 'object',
},
param6: {
enum: ['my', 'enum'],
type: 'string',
},
param7: {
items: {
type: 'string',
},
type: 'array',
},
},
type: 'object',
});
});
});
@@ -0,0 +1,104 @@
import { getOutputSchemaFromValue } from '@/logic-function/get-output-schema-from-value';
describe('getOutputSchemaFromValue', () => {
it('should compute outputSchema properly for mixed types', () => {
const testResult = {
a: null,
b: 'b',
c: { cc: 1 },
d: true,
e: [1, 2, 3],
};
const expectedOutputSchema = {
a: {
isLeaf: true,
type: 'unknown',
value: null,
label: 'a',
},
b: {
isLeaf: true,
type: 'string',
value: 'b',
label: 'b',
},
c: {
isLeaf: false,
type: 'object',
label: 'c',
value: {
cc: {
isLeaf: true,
type: 'number',
value: 1,
label: 'cc',
},
},
},
d: {
isLeaf: true,
type: 'boolean',
value: true,
label: 'd',
},
e: {
isLeaf: true,
type: 'array',
value: [1, 2, 3],
label: 'e',
},
};
expect(getOutputSchemaFromValue(testResult)).toEqual(expectedOutputSchema);
});
it('should handle nested objects', () => {
const testResult = {
user: {
name: 'John',
address: {
street: '123 Main St',
city: 'New York',
},
},
};
const result = getOutputSchemaFromValue(testResult);
expect(result.user).toEqual({
isLeaf: false,
type: 'object',
label: 'user',
value: {
name: {
isLeaf: true,
type: 'string',
value: 'John',
label: 'name',
},
address: {
isLeaf: false,
type: 'object',
label: 'address',
value: {
street: {
isLeaf: true,
type: 'string',
value: '123 Main St',
label: 'street',
},
city: {
isLeaf: true,
type: 'string',
value: 'New York',
label: 'city',
},
},
},
},
});
});
it('should return empty object for empty input', () => {
expect(getOutputSchemaFromValue({})).toEqual({});
});
});