Skip to content

Commit

Permalink
feat(ui): add ability to use tools in chat ui (#238)
Browse files Browse the repository at this point in the history
  • Loading branch information
PetrBulanek authored Mar 4, 2025
1 parent ac8db32 commit ee8c81c
Show file tree
Hide file tree
Showing 35 changed files with 689 additions and 155 deletions.
2 changes: 1 addition & 1 deletion apps/beeai-ui/src/components/ErrorMessage/ErrorMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function ErrorMessage({ title, subtitle, onRetry, isRefetching, children
{subtitle && <p>{subtitle}</p>}

{onRetry && (
<Button size="md" onClick={() => onRetry()} disabled={isRefetching}>
<Button size="sm" onClick={() => onRetry()} disabled={isRefetching}>
{!isRefetching ? 'Retry' : <InlineLoading description="Retrying&hellip;" />}
</Button>
)}
Expand Down
2 changes: 1 addition & 1 deletion apps/beeai-ui/src/components/Modal/Modal.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
}

:global(.cds--modal-footer) {
border-radius: 0 0 $spacing-03 $spacing-03;
border-radius: 0 0 $border-radius $border-radius;
padding: $spacing-06 $spacing-05 $spacing-05;

&:global(.cds--btn-set) {
Expand Down
26 changes: 26 additions & 0 deletions apps/beeai-ui/src/components/SkeletonItems/SkeletonItems.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Copyright 2025 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { ReactNode } from 'react';

interface Props {
count: number;
render: (idx: number) => ReactNode;
}

export function SkeletonItems({ count, render }: Props) {
return Array.from({ length: count }, (_, idx) => render(idx));
}
5 changes: 2 additions & 3 deletions apps/beeai-ui/src/components/TagsList/TagsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

import { SkeletonItems } from '#components/SkeletonItems/SkeletonItems.tsx';
import { TagSkeleton } from '@carbon/react';
import clsx from 'clsx';
import { ReactElement } from 'react';
Expand Down Expand Up @@ -42,9 +43,7 @@ interface SkeletonProps {
TagsList.Skeleton = function TagsListSkeleton({ length = 1, className }: SkeletonProps) {
return (
<div className={clsx(classes.root, className)}>
{Array.from({ length }).map((_, idx) => (
<TagSkeleton key={idx} />
))}
<SkeletonItems count={length} render={(idx) => <TagSkeleton key={idx} />} />
</div>
);
};
30 changes: 13 additions & 17 deletions apps/beeai-ui/src/components/layouts/Container.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,22 @@

@use 'sass:map';

$sizes: (
xs: rem(504px),
sm: rem(608px),
md: rem(768px),
lg: rem(928px),
xlg: rem(1088px),
xxlg: rem(1248px),
);

.root {
margin-inline: auto;
padding-inline: $grid-margin;
inline-size: 100%;
&.xs {
max-inline-size: calc(rem(504px) + 2 * $grid-margin);
}
&.sm {
max-inline-size: calc(rem(608px) + 2 * $grid-margin);
}
&.md {
max-inline-size: calc(rem(768px) + 2 * $grid-margin);
}
&.lg {
max-inline-size: calc(rem(928px) + 2 * $grid-margin);
}
&.xlg {
max-inline-size: calc(rem(1088px) + 2 * $grid-margin);
}
&.xxlg {
max-inline-size: calc(rem(1248px) + 2 * $grid-margin);
@each $size, $width in $sizes {
&.#{$size} {
max-inline-size: calc($width + 2 * $grid-margin);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@
margin-block-start: $spacing-06;
}

.launchButton {
min-inline-size: rem(208px);
}

.copySnippet {
min-inline-size: rem(288px);
}
Expand Down
25 changes: 13 additions & 12 deletions apps/beeai-ui/src/modules/agents/components/AgentDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,26 @@

'use client';

import type { ReactNode } from 'react';
import { ButtonSkeleton, SkeletonText } from '@carbon/react';
import { CopySnippet } from '#components/CopySnippet/CopySnippet.tsx';
import { MarkdownContent } from '#components/MarkdownContent/MarkdownContent.tsx';
import { TagsList } from '#components/TagsList/TagsList.tsx';
import commands from '#utils/commands.ts';
import { fadeProps } from '#utils/fadeProps.ts';
import { spacing } from '@carbon/layout';
import { moderate01 } from '@carbon/motion';
import { motion } from 'framer-motion';
import { ButtonSkeleton, SkeletonText } from '@carbon/react';
import clsx from 'clsx';
import { motion } from 'framer-motion';
import type { ReactNode } from 'react';
import type { Agent } from '../api/types';
import { AgentLaunchButton } from '../detail/AgentLaunchButton';
import { getAgentTitle } from '../utils';
import { AgentMetadata } from './AgentMetadata';
import { TagsList } from '#components/TagsList/TagsList.tsx';
import { CopySnippet } from '#components/CopySnippet/CopySnippet.tsx';
import { MarkdownContent } from '#components/MarkdownContent/MarkdownContent.tsx';
import classes from './AgentDetail.module.scss';
import { AgentDetailSection } from './AgentDetailSection';
import { AgentExampleRequests } from './AgentExampleRequests';
import { AgentMetadata } from './AgentMetadata';
import { AgentTags } from './AgentTags';
import { BeeBadge } from './BeeBadge';
import { fadeProps } from '#utils/fadeProps.ts';
import commands from '#utils/commands.ts';
import classes from './AgentDetail.module.scss';

interface Props {
agent: Agent;
Expand Down Expand Up @@ -103,9 +104,9 @@ AgentDetail.Skeleton = function AgentDetailSkeleton() {
<TagsList.Skeleton length={2} className={classes.tags} />

<div className={classes.buttons}>
{/* .cds--layout--size-md fixes Carbon bug where button size prop is not respected */}
<ButtonSkeleton size="md" className={clsx('cds--layout--size-md', classes.launchButton)} />
<AgentLaunchButton.Skeleton />

{/* .cds--layout--size-md fixes Carbon bug where button size prop is not respected */}
<ButtonSkeleton size="md" className={clsx('cds--layout--size-md', classes.copySnippet)} />
</div>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import { useModal } from '#contexts/Modal/index.tsx';
import { AddRequiredEnvsModal } from '#modules/envs/components/AddRequiredEnvsModal.tsx';
import { routes } from '#utils/router.ts';
import { ArrowRight } from '@carbon/icons-react';
import { Button } from '@carbon/react';
import { Button, ButtonSkeleton } from '@carbon/react';
import clsx from 'clsx';
import isEmpty from 'lodash/isEmpty';
import type { Agent } from '../api/types';
import { useMissingEnvs } from '../hooks/useMissingEnvs';
Expand Down Expand Up @@ -55,3 +56,8 @@ export function AgentLaunchButton({ agent }: Props) {
</Button>
) : null;
}

AgentLaunchButton.Skeleton = function AgentLaunchButtonSkeleton() {
/* .cds--layout--size-md fixes Carbon bug where button size prop is not respected */
return <ButtonSkeleton size="md" className={clsx('cds--layout--size-md', classes.root)} />;
};
36 changes: 21 additions & 15 deletions apps/beeai-ui/src/modules/agents/list/AgentsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,19 @@
* limitations under the License.
*/

import { useFormContext } from 'react-hook-form';
import { AgentsFilters } from '../components/AgentsFilters';
import { ErrorMessage } from '#components/ErrorMessage/ErrorMessage.tsx';
import { AgentsList } from '../components/AgentsList';
import { AgentCard } from '../components/AgentCard';
import { Agent } from '../api/types';
import { SkeletonItems } from '#components/SkeletonItems/SkeletonItems.tsx';
import { TransitionLink } from '#components/TransitionLink/TransitionLink.tsx';
import { getAgentTitle } from '../utils';
import { routes } from '#utils/router.ts';
import { ImportAgents } from '../components/ImportAgents';
import { useFormContext } from 'react-hook-form';
import { useListAgents } from '../api/queries/useListAgents';
import { Agent } from '../api/types';
import { AgentCard } from '../components/AgentCard';
import { AgentsFilters } from '../components/AgentsFilters';
import { AgentsList } from '../components/AgentsList';
import { ImportAgents } from '../components/ImportAgents';
import { AgentsFiltersParams } from '../providers/AgentsFiltersProvider';
import { getAgentTitle } from '../utils';

export function AgentsView() {
const { data, isPending, error, refetch, isRefetching } = useListAgents();
Expand All @@ -46,17 +47,22 @@ export function AgentsView() {
return (
<AgentsList agents={data} filters={filters} action={<ImportAgents />}>
{(filteredAgents) =>
!isPending
? filteredAgents?.map((agent, idx) => (
<li key={idx}>
<AgentCard agent={agent} renderTitle={renderAgentTitle} />
</li>
))
: Array.from({ length: 3 }, (_, idx) => (
!isPending ? (
filteredAgents?.map((agent, idx) => (
<li key={idx}>
<AgentCard agent={agent} renderTitle={renderAgentTitle} />
</li>
))
) : (
<SkeletonItems
count={5}
render={(idx) => (
<li key={idx}>
<AgentCard.Skeleton />
</li>
))
)}
/>
)
}
</AgentsList>
);
Expand Down
2 changes: 1 addition & 1 deletion apps/beeai-ui/src/modules/envs/components/EnvsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export function EnvsView() {
</div>

{isPending ? (
<DataTableSkeleton headers={HEADERS} showToolbar={false} />
<DataTableSkeleton headers={HEADERS} showToolbar={false} showHeader={false} />
) : (
<Table {...getTableProps()}>
<TableHead>
Expand Down
3 changes: 3 additions & 0 deletions apps/beeai-ui/src/modules/home/api/queries/useGitHubRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export function useGitHubRepo(params: GitHubRepoParams) {
queryFn: () => fetchGitHubRepo(params),
staleTime: 1000 * 60 * 5,
retry: 1,
meta: {
errorToast: false,
},
});

return query;
Expand Down
10 changes: 2 additions & 8 deletions apps/beeai-ui/src/modules/home/components/GitHubStarsButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

import { Spinner } from '#components/Spinner/Spinner.tsx';
import { GITHUB_REPO } from '#utils/constants.ts';
import { GITHUB_REPO, GITHUB_REPO_LINK } from '#utils/constants.ts';
import { LogoGithub } from '@carbon/icons-react';
import { Button } from '@carbon/react';
import { millify } from 'millify';
Expand All @@ -27,13 +27,7 @@ export function GitHubStarsButton() {
const count = data?.stargazers_count && millify(data.stargazers_count);

return (
<Button
as="a"
href={`https://github.com/${GITHUB_REPO.owner}/${GITHUB_REPO.repo}`}
target="_blank"
size="md"
className={classes.root}
>
<Button as="a" href={GITHUB_REPO_LINK} target="_blank" size="md" className={classes.root}>
<LogoGithub />

{isLoading ? <Spinner size="sm" /> : <span>{count || 'Star'}</span>}
Expand Down
4 changes: 2 additions & 2 deletions apps/beeai-ui/src/modules/run/api/mutations/useRunAgent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
* limitations under the License.
*/

import { useMutation } from '@tanstack/react-query';
import { useCreateMCPClient } from '#api/mcp-client/useCreateMCPClient.ts';
import { Agent } from '@i-am-bee/acp-sdk/types.js';
import { useMutation } from '@tanstack/react-query';
import z, { ZodLiteral, ZodObject } from 'zod';
import { useCreateMCPClient } from '#api/mcp-client/useCreateMCPClient.ts';

interface Props<
NotificationsSchema extends ZodObject<{
Expand Down
33 changes: 33 additions & 0 deletions apps/beeai-ui/src/modules/run/chat/ChatSettings.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Copyright 2025 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

@use 'styles/common' as *;

.root {
position: relative;
inline-size: 100%;
z-index: z('modal') - 1;
}

.content {
background-color: $layer;
border-radius: $border-radius;
box-shadow: $box-shadow;
padding: $spacing-05;
display: flex;
flex-direction: column;
row-gap: $spacing-06;
}
Loading

0 comments on commit ee8c81c

Please sign in to comment.