-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat: add page for ai-bridge interception logs #20331
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
Merged
Merged
Changes from all commits
Commits
Show all changes
70 commits
Select commit
Hold shift + click to select a range
cfc4aa9
feat!: impl `/aigovernance` to `Admin Settings` (hardcoded on)
jakehwll 134495a
feat: add `/aigovernance` routes and layout
jakehwll 6cd0819
feat: feed some dummy content
jakehwll 1f9fddf
feat: implement `<RequestLogsRow />`
jakehwll 0231d38
feat: query interceptions from backend
jakehwll bc71782
feat: render interceptions in frontend
jakehwll 6e05475
fix: omit `status` column (lacking data)
jakehwll afab507
fix: ensure that we're checking for `aibridge` for `ai governance` menu
jakehwll 828d381
feat: empty and loading states on `<RequestLogsPageView />` table
jakehwll ba289ec
feat: add `<Paywall />` to `/ai-governance/request-logs`
jakehwll b7280f5
chore: add missing todo
jakehwll 5abbac5
feat: link documentation to `/ai-coder/ai-bridge`
jakehwll 811d0c5
fix: menu checking for `aibridge` experiment on
jakehwll 6a74e80
fix: prefer to use `.toLocalString()` over string
jakehwll ebf2e91
feat: add storybook generation
jakehwll 37df869
chore: resolve build
jakehwll f282470
feat: use `usePaginatedQuery()` and `<PaginationContainer />`
jakehwll 4f09456
feat: implement pagination
jakehwll baad816
fix: improve opening button
jakehwll 32ae292
fix: show useravatar and username
jakehwll 0d4bd15
fix: improve rendered content from json blob
jakehwll 5dc3679
chore: remove redundant `onclick`
jakehwll 0346760
fix: improve the gaps in content
jakehwll 8ef4207
fix: remove redundant `cursor-pointer`
jakehwll c0113b9
feat: implement filtering, for users
jakehwll ecdc47b
feat: implement filter, provider
jakehwll ec5f26f
fix: move back to clickable row
jakehwll 0a556a0
fix: resolve padding on error not existing
jakehwll 126c72a
chore: remove export to pass CI (TODO still)
jakehwll e7d32a2
chore: refactor
jakehwll a47a885
chore: improve rendering logic on table
jakehwll cec12d3
feat: add a tooltip to describe the feature
jakehwll 256f66f
fix: ensure that experiment is enabled
jakehwll 6146518
chore: resolve formatting
jakehwll 40aef12
Merge branch 'main' into jakehwll/routing-ai-governance
jakehwll d3eb975
chore: resolve mismerged type
jakehwll 23719e6
fix: resolve todo type
jakehwll 125097e
fix: resolve `pageTitle()` ordering
jakehwll 18edcdb
feat: resolve storybook story
jakehwll 0b4bb34
feat: `Close` story on `<RequestLogsRow />`
jakehwll 12bdc9a
fix: refactor renames in `<RequestLogsPageView />` stories
jakehwll ec05db5
feat: add `Loading` story in `<RequestLogsPageView />` story
jakehwll 930e9af
Merge branch 'main' into jakehwll/routing-ai-governance
jakehwll ac869e1
fix: add `ended_at` to `testHelpers/entities`
jakehwll e18640d
feat: move to using `input` tokens and `output` tokens
jakehwll 7d6f8b3
feat: show end time if it exists
jakehwll a47f2bb
chore: resolve docs link to `/docs/ai-coder/ai-bridge`
jakehwll aeb7f29
feat: add tooltips and iconography to `input/output` on table rows
jakehwll 32e8777
fix: prefer tailwind over `<Stack />`
jakehwll 3415635
fix: reduce `<TooltipProvider />` delays
jakehwll 9d09f5a
chore: resolve lint
jakehwll b00b43f
chore: migrate to using `Boolean()` on `isRequestLogsVisible`
jakehwll 067a361
chore: inline `Language` constant
jakehwll e762a6c
chore: redact down storybook title
jakehwll 347aa14
chore: remove unnecessary `{}` around props
jakehwll 7a4bf51
chore: use `viewAnyAIBridgeInterception` permission
jakehwll 1b883f3
Merge branch 'main' into jakehwll/routing-ai-governance
jakehwll 13a0cc9
Merge branch 'main' into jakehwll/routing-ai-governance
jakehwll f5909e5
Merge branch 'main' into jakehwll/routing-ai-governance
jakehwll 4fb2c36
fix: prefer `FC<ProviderFilterProps>`
jakehwll e955388
fix: typo
jakehwll 45c1529
fix: resolve using `size={}` (prefer class)
jakehwll 2ae8d74
fix: remove `/docs` prepended
jakehwll a0239a3
fix: resolve missing `key`
jakehwll e1dbdb1
chore: remove `children` from `<AIGovernanceLayout />`
jakehwll 14654d3
fix: let type inference do its thing
jakehwll a115cc9
fix: resolve `interceptionQuery` on `Story`ies
jakehwll 99b0eb5
Merge branch 'main' into jakehwll/routing-ai-governance
jakehwll ea66dc1
chore: resolve lint
jakehwll 8bbfca3
chore: commit bump
jakehwll File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { API } from "api/api"; | ||
| import type { AIBridgeListInterceptionsResponse } from "api/typesGenerated"; | ||
| import { useFilterParamsKey } from "components/Filter/Filter"; | ||
| import type { UsePaginatedQueryOptions } from "hooks/usePaginatedQuery"; | ||
|
|
||
| export const paginatedInterceptions = ( | ||
| searchParams: URLSearchParams, | ||
| ): UsePaginatedQueryOptions<AIBridgeListInterceptionsResponse, string> => { | ||
| return { | ||
| queryPayload: () => searchParams.get(useFilterParamsKey) ?? "", | ||
| queryKey: ({ payload, pageNumber }) => { | ||
| return ["aiBridgeInterceptions", payload, pageNumber] as const; | ||
| }, | ||
| queryFn: ({ limit, offset, payload }) => | ||
| API.experimental.getAIBridgeInterceptions({ | ||
| offset, | ||
| limit, | ||
| q: payload, | ||
| }), | ||
| }; | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
site/src/pages/AIGovernancePage/AIGovernanceHelpTooltip.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import { | ||
| HelpTooltip, | ||
| HelpTooltipContent, | ||
| HelpTooltipIconTrigger, | ||
| HelpTooltipLink, | ||
| HelpTooltipLinksGroup, | ||
| HelpTooltipText, | ||
| HelpTooltipTitle, | ||
| } from "components/HelpTooltip/HelpTooltip"; | ||
| import type { FC } from "react"; | ||
| import { docs } from "utils/docs"; | ||
|
|
||
| export const AIGovernanceHelpTooltip: FC = () => { | ||
| return ( | ||
| <HelpTooltip> | ||
| <HelpTooltipIconTrigger /> | ||
|
|
||
| <HelpTooltipContent> | ||
| <HelpTooltipTitle>What is AI Governance?</HelpTooltipTitle> | ||
| <HelpTooltipText> | ||
| AI Governance is a proxy that unifies and audits LLM usage across your | ||
| organization. | ||
| </HelpTooltipText> | ||
| <HelpTooltipLinksGroup> | ||
| <HelpTooltipLink href={docs("/ai-coder/ai-bridge")}> | ||
| What we track | ||
| </HelpTooltipLink> | ||
| </HelpTooltipLinksGroup> | ||
| </HelpTooltipContent> | ||
| </HelpTooltip> | ||
| ); | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import { Margins } from "components/Margins/Margins"; | ||
| import { | ||
| PageHeader, | ||
| PageHeaderSubtitle, | ||
| PageHeaderTitle, | ||
| } from "components/PageHeader/PageHeader"; | ||
| import type { FC, PropsWithChildren } from "react"; | ||
| import { Outlet } from "react-router"; | ||
| import { AIGovernanceHelpTooltip } from "./AIGovernanceHelpTooltip"; | ||
|
|
||
| const AIGovernanceLayout: FC<PropsWithChildren> = () => { | ||
| return ( | ||
| <Margins className="pb-12"> | ||
| <PageHeader> | ||
| <PageHeaderTitle> | ||
| <div className="flex items-center gap-2"> | ||
| <span>AI Governance</span> | ||
| <AIGovernanceHelpTooltip /> | ||
| </div> | ||
| </PageHeaderTitle> | ||
| <PageHeaderSubtitle> | ||
| Manage usage for your organization. | ||
| </PageHeaderSubtitle> | ||
| </PageHeader> | ||
| <Outlet /> | ||
| </Margins> | ||
| ); | ||
| }; | ||
|
|
||
| export default AIGovernanceLayout; |
66 changes: 66 additions & 0 deletions
66
site/src/pages/AIGovernancePage/RequestLogsPage/RequestLogsPage.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| import { paginatedInterceptions } from "api/queries/aiBridge"; | ||
| import { useFilter } from "components/Filter/Filter"; | ||
| import { useUserFilterMenu } from "components/Filter/UserFilter"; | ||
| import { usePaginatedQuery } from "hooks/usePaginatedQuery"; | ||
| import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; | ||
| import type { FC } from "react"; | ||
| import { useSearchParams } from "react-router"; | ||
| import { pageTitle } from "utils/page"; | ||
| import { useProviderFilterMenu } from "./filter/filter"; | ||
| import { RequestLogsPageView } from "./RequestLogsPageView"; | ||
|
|
||
| const RequestLogsPage: FC = () => { | ||
| const feats = useFeatureVisibility(); | ||
| const isRequestLogsVisible = Boolean(feats.aibridge); | ||
|
|
||
| const [searchParams, setSearchParams] = useSearchParams(); | ||
| const interceptionsQuery = usePaginatedQuery( | ||
| paginatedInterceptions(searchParams), | ||
| ); | ||
| const filter = useFilter({ | ||
| searchParams, | ||
| onSearchParamsChange: setSearchParams, | ||
| onUpdate: interceptionsQuery.goToFirstPage, | ||
| }); | ||
|
|
||
| const userMenu = useUserFilterMenu({ | ||
| value: filter.values.initiator, | ||
| onChange: (option) => | ||
| filter.update({ | ||
| ...filter.values, | ||
| initiator: option?.value, | ||
| }), | ||
| }); | ||
|
|
||
| const providerMenu = useProviderFilterMenu({ | ||
| value: filter.values.provider, | ||
| onChange: (option) => | ||
| filter.update({ | ||
| ...filter.values, | ||
| provider: option?.value, | ||
| }), | ||
| }); | ||
|
|
||
| return ( | ||
| <> | ||
| <title>{pageTitle("Request Logs", "AI Governance")}</title> | ||
|
|
||
| <RequestLogsPageView | ||
| isLoading={interceptionsQuery.isLoading} | ||
| isRequestLogsVisible={isRequestLogsVisible} | ||
| interceptions={interceptionsQuery.data?.results} | ||
| interceptionsQuery={interceptionsQuery} | ||
| filterProps={{ | ||
| filter, | ||
| error: interceptionsQuery.error, | ||
| menus: { | ||
| user: userMenu, | ||
| provider: providerMenu, | ||
| }, | ||
| }} | ||
| /> | ||
| </> | ||
| ); | ||
| }; | ||
|
|
||
| export default RequestLogsPage; |
77 changes: 77 additions & 0 deletions
77
site/src/pages/AIGovernancePage/RequestLogsPage/RequestLogsPageView.stories.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| import { MockInterception } from "testHelpers/entities"; | ||
| import type { Meta, StoryObj } from "@storybook/react-vite"; | ||
| import { | ||
| getDefaultFilterProps, | ||
| MockMenu, | ||
| } from "components/Filter/storyHelpers"; | ||
| import { | ||
| mockInitialRenderResult, | ||
| mockSuccessResult, | ||
| } from "components/PaginationWidget/PaginationContainer.mocks"; | ||
| import type { ComponentProps } from "react"; | ||
| import { RequestLogsPageView } from "./RequestLogsPageView"; | ||
|
|
||
| type FilterProps = ComponentProps<typeof RequestLogsPageView>["filterProps"]; | ||
|
|
||
| const defaultFilterProps = getDefaultFilterProps<FilterProps>({ | ||
| query: "owner:me", | ||
| values: { | ||
| username: undefined, | ||
| provider: undefined, | ||
| }, | ||
| menus: { | ||
| user: MockMenu, | ||
| provider: MockMenu, | ||
| }, | ||
| }); | ||
|
|
||
| const interceptions = [MockInterception, MockInterception, MockInterception]; | ||
|
|
||
| const meta: Meta<typeof RequestLogsPageView> = { | ||
| title: "pages/AIGovernancePage/RequestLogsPageView", | ||
| component: RequestLogsPageView, | ||
| args: {}, | ||
| }; | ||
|
|
||
| export default meta; | ||
| type Story = StoryObj<typeof RequestLogsPageView>; | ||
|
|
||
| export const Paywall: Story = { | ||
| args: { | ||
| isRequestLogsVisible: false, | ||
| }, | ||
| }; | ||
|
|
||
| export const Loaded: Story = { | ||
| args: { | ||
| isRequestLogsVisible: true, | ||
| interceptions, | ||
| filterProps: { | ||
| ...defaultFilterProps, | ||
| }, | ||
| interceptionsQuery: mockSuccessResult, | ||
| }, | ||
| }; | ||
|
|
||
| export const Empty: Story = { | ||
| args: { | ||
| isRequestLogsVisible: true, | ||
| interceptions: [], | ||
| filterProps: { | ||
| ...defaultFilterProps, | ||
| }, | ||
| interceptionsQuery: mockSuccessResult, | ||
| }, | ||
| }; | ||
|
|
||
| export const Loading: Story = { | ||
| args: { | ||
| isLoading: true, | ||
| isRequestLogsVisible: true, | ||
| interceptions: [], | ||
| filterProps: { | ||
| ...defaultFilterProps, | ||
| }, | ||
| interceptionsQuery: mockInitialRenderResult, | ||
| }, | ||
| }; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.