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

Feature: Docker Containers API #210

Merged
merged 34 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
bd870a3
wip: docker containers api handlers
alashchev17 Nov 26, 2024
514397f
wip: docker actions API & action buttons
alashchev17 Nov 27, 2024
201f29b
wip: better action handling
alashchev17 Nov 27, 2024
8eea732
wip: simplification of dockerApi & action buttons improvements
alashchev17 Nov 27, 2024
a2b8e42
chore: fixtures update
alashchev17 Nov 27, 2024
00874fd
chore: removal of unnecessary esling rule bypass
alashchev17 Nov 27, 2024
f09ef28
wip: docker container card & refactoring of integration form
alashchev17 Nov 28, 2024
edc071f
Merge branch 'feat/setup-integrations' into feat/docker-api
alashchev17 Nov 28, 2024
9a785c6
feat(configuration): adjusted size of inputs based on f_size & DataLi…
alashchev17 Nov 28, 2024
7f9e791
Merge branch 'feat/setup-integrations' into feat/docker-api
alashchev17 Nov 29, 2024
d46e9fd
wip: form appearance & responsive layout
alashchev17 Nov 29, 2024
2549fc1
wip: updated docker section
alashchev17 Nov 29, 2024
9104122
wip(refactoring): smartlink, availability, renderField, handleSmartli…
alashchev17 Nov 29, 2024
f941e8e
wip(form): bool f_type support
alashchev17 Nov 29, 2024
4d21638
wip(refactoring): making docker within integr_schema optional, condit…
alashchev17 Nov 29, 2024
2b1a314
wip(docker): error handling
alashchev17 Nov 29, 2024
ecaa68f
wip(refactoring): toolscontent usage summary refactoring
alashchev17 Dec 2, 2024
4fa35f9
wip(docker containers): collapsible container details & reveal if large
alashchev17 Dec 2, 2024
1b2fd88
wip(refactoring): project name handling for macOS & Windows
alashchev17 Dec 2, 2024
0dbb9f0
wip(refactoring): docker error card & debounced loaded state
alashchev17 Dec 2, 2024
c738f8b
wip(docker containers): better loading state management
alashchev17 Dec 2, 2024
f6951d0
wip: separation & refactoring of UI, making docker containers cards b…
alashchev17 Dec 2, 2024
5a11403
fix: error types for docker error cards
alashchev17 Dec 3, 2024
e45bff9
fix: unchecked switch values included to formData
alashchev17 Dec 3, 2024
94118f0
chore: removal no-console
alashchev17 Dec 3, 2024
de132ba
chore: removal of unexisting prop
alashchev17 Dec 3, 2024
eab73b0
fix: extra fields showup button conditional rendering
alashchev17 Dec 3, 2024
0ade262
chore: TODO insertion
alashchev17 Dec 3, 2024
6bbd026
fix: rule bypass removal
alashchev17 Dec 3, 2024
cd50907
feat: debug logging library usage for integrations logs
alashchev17 Dec 3, 2024
9d29882
feat: implementing root debug instance, managing debuggable instances…
alashchev17 Dec 3, 2024
67de24e
chore: better logging message
alashchev17 Dec 3, 2024
5e2797c
chore: TODO for tags invalidation docker
alashchev17 Dec 3, 2024
3232243
fix: replaced <label/> to <Text as='label' />
alashchev17 Dec 3, 2024
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
2 changes: 2 additions & 0 deletions src/__fixtures__/integrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export const INTEGRATIONS_RESPONSE: Integration = {
},
],
docker: {
filter_image: "postgres",
filter_label: "",
new_container_default: {
image: "postgres:13",
environment: {
Expand Down
47 changes: 47 additions & 0 deletions src/app/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from "../features/Chat/Thread";
import { statisticsApi } from "../services/refact/statistics";
import { integrationsApi } from "../services/refact/integrations";
import { dockerApi } from "../services/refact/docker";
import { capsApi, isCapsErrorResponse } from "../services/refact/caps";
import { promptsApi } from "../services/refact/prompts";
import { toolsApi } from "../services/refact/tools";
Expand Down Expand Up @@ -108,6 +109,52 @@ startListening({
listenerApi.dispatch(setError(errorMessage));
}

if (
dockerApi.endpoints.getAllDockerContainers.matchRejected(action) &&
!action.meta.condition
) {
// getting first 2 lines of error message to show to user
const errorMessage = isDetailMessage(action.payload?.data)
? action.payload.data.detail
: `fetching docker containers.`;
listenerApi.dispatch(setError(errorMessage));
}

if (
dockerApi.endpoints.getDockerContainersByImage.matchRejected(action) &&
!action.meta.condition
) {
// getting first 2 lines of error message to show to user
const errorMessage = isDetailMessage(action.payload?.data)
? action.payload.data.detail
: `fetching docker containers.`;
listenerApi.dispatch(setError(errorMessage));
}

if (
dockerApi.endpoints.getDockerContainersByLabel.matchRejected(action) &&
!action.meta.condition
) {
// getting first 2 lines of error message to show to user
const errorMessage = isDetailMessage(action.payload?.data)
? action.payload.data.detail
: `fetching docker containers.`;
listenerApi.dispatch(setError(errorMessage));
}

if (
dockerApi.endpoints.executeActionForDockerContainer.matchRejected(
action,
) &&
!action.meta.condition
) {
// getting first 2 lines of error message to show to user
const errorMessage = isDetailMessage(action.payload?.data)
? action.payload.data.detail
: `fetching docker containers.`;
listenerApi.dispatch(setError(errorMessage));
}

if (
pathApi.endpoints.getFullPath.matchRejected(action) &&
!action.meta.condition
Expand Down
3 changes: 3 additions & 0 deletions src/app/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
pathApi,
pingApi,
integrationsApi,
dockerApi,
} from "../services/refact";
import { smallCloudApi } from "../services/smallcloud";
import { reducer as fimReducer } from "../features/FIM/reducer";
Expand Down Expand Up @@ -82,6 +83,7 @@ const rootReducer = combineSlices(
informationSlice,
pagesSlice,
integrationsApi,
dockerApi,
confirmationSlice,
attachedImagesSlice,
userSurveySlice,
Expand Down Expand Up @@ -148,6 +150,7 @@ export function setUpStore(preloadedState?: Partial<RootState>) {
smallCloudApi.middleware,
pathApi.middleware,
integrationsApi.middleware,
dockerApi.middleware,
)
.prepend(historyMiddleware.middleware)
// .prepend(errorMiddleware.middleware)
Expand Down
133 changes: 73 additions & 60 deletions src/components/ChatContent/ToolsContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const Result: React.FC<ResultProps> = ({
}) => {
const lines = children.split("\n");
return (
<Reveal defaultOpen={lines.length < 9}>
<Reveal defaultOpen={lines.length < 9} isRevealingCode>
<ResultMarkdown
className={styles.tool_result}
isInsideScrollArea={isInsideScrollArea}
Expand Down Expand Up @@ -167,44 +167,14 @@ export const SingleModelToolContent: React.FC<{
<Container>
<Collapsible.Root open={open} onOpenChange={setOpen}>
<Collapsible.Trigger asChild>
{/**TODO: reuse this */}
<Flex gap="2" align="end">
<Flex gap="1" align="start" direction="column">
<Text weight="light" size="1">
🔨{" "}
{toolUsageAmount.map(
({ functionName, amountOfCalls }, index) => (
<span key={functionName}>
<ToolUsageDisplay
functionName={functionName}
amountOfCalls={amountOfCalls}
/>
{index === toolUsageAmount.length - 1 ? "" : ", "}
</span>
),
)}
</Text>
{hiddenFiles > 0 && (
<Text weight="light" size="1" ml="4">
{`🔎 <${hiddenFiles} files hidden>`}
</Text>
)}
{shownAttachedFiles.map((file, index) => (
<Text weight="light" size="1" key={index} ml="4">
🔎 {file}
</Text>
))}
{subchat && (
<Flex ml="4">
<Spinner />
<Text weight="light" size="1" ml="4px">
{subchat}
</Text>
</Flex>
)}
</Flex>
<Chevron open={open} />
</Flex>
<ToolUsageSummary
toolUsageAmount={toolUsageAmount}
hiddenFiles={hiddenFiles}
shownAttachedFiles={shownAttachedFiles}
subchat={subchat}
open={open}
onClick={() => setOpen((prev) => !prev)}
/>
</Collapsible.Trigger>
<Collapsible.Content>
{toolCalls.map((toolCall) => {
Expand Down Expand Up @@ -331,27 +301,12 @@ const MultiModalToolContent: React.FC<{
return (
<Container>
<Collapsible.Root open={open} onOpenChange={setOpen}>
<Collapsible.Trigger asChild>
{/**TODO: duplicated */}
<Flex gap="2" align="end">
<Flex gap="1" align="start" direction="column">
<Text weight="light" size="1">
🔨{" "}
{toolUsageAmount.map(
({ functionName, amountOfCalls }, index) => (
<span key={`${functionName}-${index}`}>
<ToolUsageDisplay
functionName={functionName}
amountOfCalls={amountOfCalls}
/>
{index === toolUsageAmount.length - 1 ? "" : ", "}
</span>
),
)}
</Text>
</Flex>
<Chevron open={open} />
</Flex>
<Collapsible.Trigger>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does the onClick handler work without the asChild prop being used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, because I'm specifying onClick directly on the element, not relying on Trigger click

<ToolUsageSummary
toolUsageAmount={toolUsageAmount}
open={open}
onClick={() => setOpen((prev) => !prev)}
/>
</Collapsible.Trigger>
<Collapsible.Content>
{/** TODO: tool call name and text result */}
Expand Down Expand Up @@ -430,3 +385,61 @@ const MultiModalToolContent: React.FC<{
</Container>
);
};

const ToolUsageSummary: React.FC<{
toolUsageAmount: ToolUsage[];
hiddenFiles?: number;
shownAttachedFiles?: (string | undefined)[];
subchat?: string;
open: boolean;
onClick?: () => void;
}> = ({
toolUsageAmount,
hiddenFiles,
shownAttachedFiles,
subchat,
open,
onClick,
}) => {
return (
<Flex gap="2" align="end" onClick={onClick}>
<Flex gap="1" align="start" direction="column">
<Text weight="light" size="1">
🔨{" "}
{toolUsageAmount.map(({ functionName, amountOfCalls }, index) => (
<span key={functionName}>
<ToolUsageDisplay
functionName={functionName}
amountOfCalls={amountOfCalls}
/>
{index === toolUsageAmount.length - 1 ? "" : ", "}
</span>
))}
</Text>
{hiddenFiles && hiddenFiles > 0 && (
<Text weight="light" size="1" ml="4">
{`🔎 <${hiddenFiles} files hidden>`}
</Text>
)}
{shownAttachedFiles?.map((file, index) => {
if (!file) return null;

return (
<Text weight="light" size="1" key={index} ml="4">
🔎 {file}
</Text>
);
})}
{subchat && (
<Flex ml="4">
<Spinner />
<Text weight="light" size="1" ml="4px">
{subchat}
</Text>
</Flex>
)}
</Flex>
<Chevron open={open} />
</Flex>
);
};
16 changes: 14 additions & 2 deletions src/components/Collapsible/Chevron.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,24 @@ import styles from "./Chevron.module.css";
export type ChevronProps = {
open: boolean;
className?: string;
isUpDownChevron?: boolean;
};

export const Chevron: React.FC<ChevronProps> = ({ open, className }) => {
export const Chevron: React.FC<ChevronProps> = ({
open,
className,
isUpDownChevron = false,
}) => {
return (
<ChevronDownIcon
className={classNames(open ? styles.down : styles.right, className)}
className={classNames(
{
[styles.down]: open,
[styles.right]: !open && !isUpDownChevron,
[styles.up]: !open && isUpDownChevron,
},
className,
)}
style={{ minWidth: 16, minHeight: 16 }}
/>
);
Expand Down
Loading
Loading