Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: update toolset configuration display name and other style settings #5343

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/backend/base/langflow/base/tools/component_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ def _format_tool_name(name: str):
return re.sub(r"[^a-zA-Z0-9_-]", "-", name)


def _add_commands_to_tool_description(tool_description: str, commands: str):
return f"very_time you see one of those commands {commands} run the tool. tool description is {tool_description}"


class ComponentToolkit:
def __init__(self, component: Component, metadata: pd.DataFrame | None = None):
self.component = component
Expand Down Expand Up @@ -276,6 +280,10 @@ def update_tools_metadata(
tool_metadata = metadata_dict[tag]
tool.name = tool_metadata.get("name", tool.name)
tool.description = tool_metadata.get("description", tool.description)
if tool_metadata.get("commands"):
tool.description = _add_commands_to_tool_description(
tool.description, tool_metadata.get("commands")
)
else:
msg = f"Expected a StructuredTool or BaseTool, got {type(tool)}"
raise TypeError(msg)
Expand Down
17 changes: 15 additions & 2 deletions src/backend/base/langflow/base/tools/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"description": "Describe the purpose of the tool.",
"sortable": False,
"filterable": False,
"edit_mode": EditMode.INLINE,
"edit_mode": EditMode.POPOVER,
},
{
"name": "tags",
Expand All @@ -35,6 +35,19 @@
"filterable": False,
"edit_mode": EditMode.INLINE,
},
{
"name": "commands",
"display_name": "Commands",
"type": "str",
"description": (
"Add commands to the tool. These commands will be used to run the tool. Start all commands with a `/`. "
"You can add multiple commands separated by a comma. "
"Example: `/command1`, `/command2`, `/command3`"
),
"sortable": False,
"filterable": False,
"edit_mode": EditMode.INLINE,
},
]

TOOLS_METADATA_INFO = "Use the table to configure the tools."
TOOLS_METADATA_INFO = "Modify tool names and descriptions to help agents understand when to use each tool."
12 changes: 8 additions & 4 deletions src/backend/base/langflow/custom/custom_component/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -1197,13 +1197,13 @@ def _build_tools_metadata_input(self):

return TableInput(
name=TOOLS_METADATA_INPUT_NAME,
info=TOOLS_METADATA_INFO,
display_name="Toolset configuration",
display_name="Edit tools",
real_time_refresh=True,
table_schema=TOOL_TABLE_SCHEMA,
value=tool_data,
table_icon="Hammer",
trigger_icon="Hammer",
trigger_text="Open toolset",
trigger_text="",
table_options=TableOptions(
block_add=True,
block_delete=True,
Expand All @@ -1213,6 +1213,10 @@ def _build_tools_metadata_input(self):
block_hide=True,
block_select=True,
hide_options=True,
field_parsers={"name": FieldParserType.SNAKE_CASE},
field_parsers={
"name": [FieldParserType.SNAKE_CASE, FieldParserType.NO_BLANK],
"commands": FieldParserType.COMMANDS,
},
description=TOOLS_METADATA_INFO,
),
)
1 change: 1 addition & 0 deletions src/backend/base/langflow/inputs/input_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ class TableMixin(BaseModel):
table_schema: TableSchema | list[Column] | None = None
trigger_text: str = Field(default="Open table")
trigger_icon: str = Field(default="Table")
table_icon: str = Field(default="Table")
table_options: TableOptions | None = None

@field_validator("table_schema")
Expand Down
5 changes: 5 additions & 0 deletions src/backend/base/langflow/schema/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class FormatterType(str, Enum):

class EditMode(str, Enum):
MODAL = "modal"
POPOVER = "popover"
INLINE = "inline"


Expand Down Expand Up @@ -83,6 +84,9 @@ class FieldParserType(str, Enum):
KEBAB_CASE = "kebab_case"
LOWERCASE = "lowercase"
UPPERCASE = "uppercase"
NO_BLANK = "no_blank"
VALID_CSV = ("valid_csv",)
COMMANDS = "commands"


class TableOptions(BaseModel):
Expand All @@ -96,3 +100,4 @@ class TableOptions(BaseModel):
hide_options: bool = Field(default=False)
field_validators: dict[str, list[FieldValidatorType] | FieldValidatorType] | None = Field(default=None)
field_parsers: dict[str, list[FieldParserType] | FieldParserType] | None = Field(default=None)
description: str | None = Field(default=None)
11 changes: 11 additions & 0 deletions src/frontend/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,14 @@ code {
resize: none !important;
height: 100% !important;
}

.cell-disable-edit {
cursor: not-allowed;
}

.cell-disable-edit.ag-cell-focus {
outline: none !important;
border: 0px !important;
box-shadow: none !important;
border-radius: 0px !important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default function TableNodeComponent({
table_options,
trigger_icon = "Table",
trigger_text = "Open Table",
table_icon,
}: InputProps<any[], TableComponentType>): JSX.Element {
const dataTypeDefinitions: {
[cellDataType: string]: DataTypeDefinition<any>;
Expand Down Expand Up @@ -107,7 +108,7 @@ export default function TableNodeComponent({
.map((column) => {
const isCustomEdit =
column.formatter &&
((column.formatter === "text" && column.edit_mode !== "inline") ||
((column.formatter === "text" && column.edit_mode === "modal") ||
column.formatter === "json");
return {
field: column.name,
Expand All @@ -128,6 +129,8 @@ export default function TableNodeComponent({
>
<div className="flex w-full items-center gap-3" data-testid={"div-" + id}>
<TableModal
stopEditingWhenCellsLoseFocus={true}
tableIcon={table_icon}
tableOptions={table_options}
dataTypeDefinitions={dataTypeDefinitions}
autoSizeStrategy={{ type: "fitGridWidth", defaultMinWidth: 100 }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export function ParameterRenderComponent({
table_options={templateData?.table_options}
trigger_icon={templateData?.trigger_icon}
trigger_text={templateData?.trigger_text}
table_icon={templateData?.table_icon}
/>
);
case "slider":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export type TableComponentType = {
table_options?: TableOptionsTypeAPI;
trigger_text?: string;
trigger_icon?: string;
table_icon?: string;
};

export type FloatComponentType = {
Expand Down
19 changes: 16 additions & 3 deletions src/frontend/src/modals/tableModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,19 @@ interface TableModalProps extends TableComponentProps {
children: React.ReactNode;
tableOptions?: TableOptionsTypeAPI;
hideColumns?: boolean | string[];
tableIcon?: string;
}

const TableModal = forwardRef<AgGridReact, TableModalProps>(
(
{ tableTitle, description, children, disabled, ...props }: TableModalProps,
{
tableTitle,
description,
children,
disabled,
tableIcon,
...props
}: TableModalProps,
ref: ForwardedRef<AgGridReact>,
) => {
return (
Expand All @@ -37,9 +45,14 @@ const TableModal = forwardRef<AgGridReact, TableModalProps>(
disable={disabled}
>
<BaseModal.Trigger asChild>{children}</BaseModal.Trigger>
<BaseModal.Header description={description}>
<BaseModal.Header
description={props.tableOptions?.description ?? description}
>
<span className="pr-2">{tableTitle}</span>
<ForwardedIconComponent name="Table" className="mr-2 h-4 w-4" />
<ForwardedIconComponent
name={tableIcon ?? "Table"}
className="mr-2 h-4 w-4"
/>
</BaseModal.Header>
<BaseModal.Content>
<TableComponent
Expand Down
6 changes: 5 additions & 1 deletion src/frontend/src/types/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,10 @@ export type FieldParserType =
| "pascal_case"
| "kebab_case"
| "lowercase"
| "uppercase";
| "uppercase"
| "no_blank"
| "valid_csv"
| "commands";

export type TableOptionsTypeAPI = {
block_add?: boolean;
Expand All @@ -326,4 +329,5 @@ export type TableOptionsTypeAPI = {
FieldValidatorType | { [key: string]: FieldValidatorType }
>;
field_parsers?: Array<FieldParserType | { [key: string]: FieldParserType }>;
description?: string;
};
2 changes: 1 addition & 1 deletion src/frontend/src/types/utils/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ export interface ColumnField {
description?: string;
disable_edit?: boolean;
default?: any; // Add this line
edit_mode?: "modal" | "inline";
edit_mode?: "modal" | "inline" | "popover";
}
79 changes: 60 additions & 19 deletions src/frontend/src/utils/stringManipulation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,34 @@ function toUpperCase(str: string): string {
return str.toUpperCase();
}

function noBlank(str: string): string {
const trim = str.trim();
if (trim === "") {
throw new Error("String is blank");
}
return trim;
}

function validCsv(str: string): string {
return str.trim().replace(/\s+/g, ",");
}

function validCommands(str: string): string {
return str
.trim()
.split(/[\s,]+/)
.flatMap((cmd) => {
cmd = cmd.trim();
cmd = cmd.replace(/\\/g, "/");
return cmd
.split("/")
.filter((part) => part.length > 0)
.map((part) => `/${part}`);
})
.filter((cmd) => cmd.length > 1)
.join(", ");
}

export function parseString(
str: string,
parsers: FieldParserType[] | FieldParserType,
Expand All @@ -48,25 +76,38 @@ export function parseString(
}

for (const parser of parsersArray) {
switch (parser) {
case "snake_case":
result = toSnakeCase(result);
break;
case "camel_case":
result = toCamelCase(result);
break;
case "pascal_case":
result = toPascalCase(result);
break;
case "kebab_case":
result = toKebabCase(result);
break;
case "lowercase":
result = toLowerCase(result);
break;
case "uppercase":
result = toUpperCase(result);
break;
try {
switch (parser) {
case "snake_case":
result = toSnakeCase(result);
break;
case "camel_case":
result = toCamelCase(result);
break;
case "pascal_case":
result = toPascalCase(result);
break;
case "kebab_case":
result = toKebabCase(result);
break;
case "lowercase":
result = toLowerCase(result);
break;
case "uppercase":
result = toUpperCase(result);
break;
case "no_blank":
result = noBlank(result);
break;
case "valid_csv":
result = validCsv(result);
break;
case "commands":
result = validCommands(result);
break;
}
} catch (error) {
throw new Error(`Error in parser ${parser}`);
}
}

Expand Down
41 changes: 26 additions & 15 deletions src/frontend/src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import TableAutoCellRender from "@/components/core/parameterRenderComponent/components/tableComponent/components/tableAutoCellRender";
import useAlertStore from "@/stores/alertStore";
import { ColumnField, FormatterType } from "@/types/utils/functions";
import { ColDef, ColGroupDef, ValueParserParams } from "ag-grid-community";
import clsx, { ClassValue } from "clsx";
Expand Down Expand Up @@ -526,17 +527,25 @@ export function FormatColumns(columns: ColumnField[]): ColDef<any>[] {
field: col.name,
sortable: col.sortable,
filter: col.filterable,
editable: !col.disable_edit,
cellClass: col.disable_edit ? "cell-disable-edit" : "",
valueParser: (params: ValueParserParams) => {
const { context, newValue, colDef } = params;
const { context, newValue, colDef, oldValue } = params;
if (
context.field_parsers &&
context.field_parsers[colDef.field ?? ""]
) {
return parseString(
newValue,
context.field_parsers[colDef.field ?? ""],
);
try {
return parseString(
newValue,
context.field_parsers[colDef.field ?? ""],
);
} catch (error: any) {
useAlertStore.getState().setErrorData({
title: "Error parsing string",
list: [String(error.message ?? error)],
});
return oldValue;
}
}
return newValue;
},
Expand All @@ -551,15 +560,17 @@ export function FormatColumns(columns: ColumnField[]): ColDef<any>[] {
formatter: col.formatter,
};
if (col.formatter !== FormatterType.text || col.edit_mode !== "inline") {
newCol.cellRenderer = TableAutoCellRender;
} else {
newCol.wrapText = true;
newCol.autoHeight = true;
newCol.cellEditor = "agLargeTextCellEditor";
newCol.cellEditorPopup = true;
newCol.cellEditorParams = {
maxLength: 100000000,
};
if (col.edit_mode === "popover") {
newCol.wrapText = true;
newCol.autoHeight = true;
newCol.cellEditor = "agLargeTextCellEditor";
newCol.cellEditorPopup = true;
newCol.cellEditorParams = {
maxLength: 100000000,
};
} else {
newCol.cellRenderer = TableAutoCellRender;
}
}
}
return newCol;
Expand Down
Loading