Compare commits

...
796 Commits
Author SHA1 Message Date
jialin 17527b0fa5 fix: show cluster in table 2026-05-26 23:01:36 +08:00
jialinandjialin 2f04e01f4f fix: default instance type, storageMode 2026-05-26 22:40:02 +08:00
jialinandjialin a51f44c135 fix: select a useable instance type for initial 2026-05-26 22:40:02 +08:00
jialinandjialin 7f14eb544c fix: pvc events api 2026-05-26 19:16:50 +08:00
jialinandjialin c6e34db329 fix: ux issues 2026-05-26 19:16:50 +08:00
Yuxing Deng acb90531b2 feat: extend cluster k8s_options with multi-vendor manifest support
- New k8s_pod_spec form sections (image credentials, node selector,
  gpu vendor overrides) under k8s_options, replacing the legacy flat
  k8s_volume_mounts list. UI keys aligned to the backend wire shape
  (snake_case k8s_options + camelCase inside).
- System default container registry is pre-filled into the first image
  credential when creating a new cluster; empty username/password are
  coerced to null on submit to match the Optional[str] backend schema.
- Register cluster flow supports multi-runtime selection gated by the
  cluster's gpuVendorOverrides: non-override vendors stay single-select
  with an inline hint; multi-add only opens once an override vendor is
  picked, and non-override cards become disabled in that state.
- Manifest URL emits multiple ?runtime= params; check-env step combines
  per-vendor commands; downstream steps are disabled when no vendor is
  selected.
- Pre-validate gpuVendorOverrides at save time (non-empty selector, no
  duplicates across vendors, no key clash with base nodeSelector) so
  the user sees the error before hitting the manifest endpoint.
- Misc: dark-mode background of the k8s_pod_spec / volume mount titles
  no longer clashes with the drawer; cluster Steps no longer leaks the
  internal showModules/showForms props to the DOM.
2026-05-26 16:54:14 +08:00
yxfandyxf0314 91c3d0b814 feat: add parameter format and common parameters to backend configuration 2026-05-26 14:30:19 +08:00
jialinandjialin 95e03d11c1 fix: gpu service issues 2026-05-26 14:21:52 +08:00
jialinandjialin 88ab927755 refactor: gpu service API alignment 2026-05-25 22:42:02 +08:00
jialinandjialin 81c7e2ee61 fix(style): template title gap 2026-05-25 22:42:02 +08:00
jialinandjialin b5ed64de51 chore: ssh key selection 2026-05-25 22:42:02 +08:00
jialinandjialin 921a2a0d81 fix: instance form ux 2026-05-25 22:42:02 +08:00
jialinandjialin 5195b1e5fc style: number selection 2026-05-25 22:42:02 +08:00
jialinandjialin f886422f91 fix(style): textarea label background 2026-05-25 22:42:02 +08:00
jialinandjialin 27d57d7563 feat: instance pv events 2026-05-25 22:42:02 +08:00
jialinandjialin 2ebb8f44b7 fix: recreate action 2026-05-25 22:42:02 +08:00
jialinandjialin a0b408e8cb style: instance type remaing resourece 2026-05-25 22:42:02 +08:00
jialinandjialin 858e0dae09 feat: add number selection 2026-05-25 22:42:02 +08:00
gitlawrandjialin 7bee337554 fix(playground): inject X-Organization-Id on non-umi fetch paths
Playground completions (chat streaming via ``fetchChunkedData``)
and the raw ``fetch()`` calls for image / audio generation skip
umi's ``request`` pipeline and so miss the request interceptor in
``request.extensions.ts`` that pins tenant context. Higress
receives those calls without ``X-Organization-Id`` and the auth
callback falls back to the user's USER-principal id rather than
their active Org, which makes Playground usage invisible from
Org-scoped Usage views even after the backend learned to backfill
``consumer_principal_id``.

Centralise the lookup in ``tenantHeaders()`` next to
``fetchChunkedData`` so both streaming helpers and the four
``fetch()``-direct entry points in ``playground/apis/index.ts``
(image / TTS) attach the header with the same precedence as the
umi interceptor (``createScopeOrgOverride`` first,
``currentOrganizationId`` second). Returns an empty object when
no active org context is set, leaving requests unchanged.
2026-05-25 18:02:31 +08:00
jialinandjialin 7944b3f579 fix: add lora tag in routes 2026-05-25 13:56:44 +08:00
jialinandjialin 5e889563ca fix: search lora ux 2026-05-25 13:56:44 +08:00
jialinandjialin aad3b458c8 fix: selection styles 2026-05-25 13:56:44 +08:00
jialinandjialin acef2ef89a fix: add form validation 2026-05-25 13:56:44 +08:00
jialinandjialin d99c25dd03 feat: model file is lora 2026-05-25 13:56:44 +08:00
jialinandjialin f0a1dad48e fix: filter invaild lora in form 2026-05-25 13:56:44 +08:00
jialinandjialin 1e334903dd feat: lora route 2026-05-25 13:56:44 +08:00
jialinandjialin 342583f8d1 feat: lora for deployment 2026-05-25 13:56:44 +08:00
gitlawrandjialin 6af18275c4 feat(usage): treat org owners as managers on the Usage page
The Usage page gated cross-user features (default ``scope=all``,
the user filter, the per-user breakdown dimension) on
``currentUser.is_admin`` alone. The backend's
``_can_use_all_scope`` already grants the same surface to Org
owners — the page just never asked. Result: a non-admin Org owner
landed on ``scope=self`` with no user filter and no per-user
group-by, even though the API would have happily served them the
org-wide picture.

Switch the three sites to ``useAccess().canSeeOrgAdmin``, which
already encodes "platform admin OR owner of the selected
(non-Personal) Org". One predicate, no new helper.

Sites:
- ``index.tsx``: ``initialScope`` defaults to ``all`` for managers.
- ``filter-bar.tsx``: the user filter + nested API-key cascader
  surface (vs the flat API-key picker for members).
- ``daily-usage.tsx``: the ``user`` group-by option in the chart.
2026-05-25 13:56:25 +08:00
gitlawrandjialin 9c519d937d fix(usage): pass scope to the time series chart fetch
The Usage page's chart fetch (``fetchTimeSeriesData``) spread
``chartFilters`` plus dates and filters, but never forwarded
``commonFilters.scope`` — so it implicitly fell back to the
backend's ``scope=all`` default. The three breakdown tables
(``apikeys-table``, ``models-table``, ``users-table``) all pass
``scope`` explicitly, which produced an inconsistent picture on
the same page: an Org owner viewing a model granted from another
Org saw the date chart render empty while the tables underneath
showed identical usage rows.

Forward ``currentSelectedFilters.scope`` alongside the rest of the
common filters so the chart and the tables ask the backend the
same question.
2026-05-25 13:56:25 +08:00
Yuxing Deng 4b14fa6ca8 feat(usage): plugin slot for Models tab extra columns
Lets enterprise plugins contribute per-route columns and a global
mount point on the Usage page's Models tab. Mirrors the existing
modelRoutes pattern: `usage.modelsExtraColumns` for cells,
`<PluginExtraFields name="UsageModelsPageGlobal" />` for the
page-level data lifecycle (receives the visible route ids so a
plugin can bulk-fetch per-row data in one call).
2026-05-25 10:42:59 +08:00
jialinandjialin dc69e51042 fix: colorPrimary cache cleared 2026-05-24 10:51:44 +08:00
jialinandjialin 052d5aa474 fix: colorPrimary cache cleared 2026-05-21 19:58:16 +08:00
jialinandjialin 0c55c1c1b4 fix: sider menu style 2026-05-21 19:58:16 +08:00
jialinandjialin 6f896b4f94 fix(style): use --app-banner-height in scroller container 2026-05-21 19:58:16 +08:00
gitlawrandjialin e7a376db70 refactor: adapt org-namespace lookup to principal name rename
Tracks the gpustack identity-consolidation effort: the unified
``principals`` table's URL-safe identifier column was renamed
``slug`` → ``name`` (with the legacy display ``name`` → ``display_name``).
The enterprise plugin's persisted org caches (``organizationList``,
``allOrganizations`` in localStorage) now write ``name`` instead of
``slug`` on each Organization row.

``getCurrentOrgNamespace`` reads those caches to compose the k8s
namespace (``gpustack-{name}``) for GPU-instance / storage CRDs.
Updated to read ``item.name`` so namespace resolution stays in sync
with what the enterprise plugin writes — otherwise every gpu-service
write would fall through to ``gpustack-default`` even when the user
has an Org context.

Stale ``slug`` references in surrounding comments also retitled to
``name`` to avoid divergence between code and prose. The namespace
format itself (``gpustack-{...}``) is unchanged — only the column it
sources is.
2026-05-21 12:15:39 +08:00
Yuxing Dengandjialin 15cf4d89b7 feat: association dounut effect 2026-05-20 11:29:43 +08:00
Yuxing Dengandjialin c38fcc494a refactor(dashboard): collapse usage section into a single row
Merge the two "by Model" pies (Token Usage + API Requests) into one
dual-pie card with a shared right-side vertical legend and per-donut
center totals, drop the standalone API-Key Top 10 chart, and put the
combined chart side-by-side with the User Top 10 ranking in one row
with the same 16/8 column ratio used by the System Load section above.

* New component usage-charts/usage-by-model.tsx owns both metric queries
  (group_by=['date','route']), aggregates a shared route→color map so
  the legend toggles both donuts together, and renders two pies at
  centers ('20%','50%') and ('60%','50%') with radius ['50%','70%'].
* new-usage.tsx no longer mounts ApiRequestsByModel / TokenUsageByModel
  / TopTokenUsageByApiKey; layout collapses to two columns sized
  (lg=24 xl=16) and (lg=24 xl=8).
* Delete unused token-usage-by-model.tsx, api-requests-by-model.tsx,
  top-token-usage-by-api-key.tsx, and the use-top-token-usage-by-api-key
  hook.
* Strip the now-unreferenced dashboard.tokenUsageByModel /
  apiRequestsByModel / topTokenUsageByApiKey locale keys across 5
  locales, add the new dashboard.usageByModel title; locale parity
  check passes.
2026-05-20 11:29:43 +08:00
Yuxing Deng 44e5b78d29 refactor(dashboard): switch usage charts to route group_by, rename Models card
Align dashboard with the route dimension introduced in the previous
commit:

* Token Usage / API Requests pie charts query the breakdown API with
  `group_by: ['date', 'route']` and aggregate via the new `route`
  dimension in `buildUsageLabel`. Visible chart titles keep the existing
  "by Model" wording — only the underlying data dim changed.
* Overview "Models" card label switched to `dashboard.deployments`
  ("部署" / "Deployments"), and the Active Models table heading to
  `dashboard.activeDeployments`. These reflect the underlying entity
  (model deployments) more accurately now that routes are the
  user-facing model concept.
* Drop 11 unused dashboard locale keys (`dashboard.title`,
  `dashboard.models`, `dashboard.allocategpus`, `dashboard.instances`,
  `dashboard.disk`, `dashboard.diskutilization`, `dashboard.apirequest`,
  `dashboard.activeModels`, `dashboard.activeUsers`,
  `dashboard.activeModels.name`, `dashboard.runninginstances`) — no
  remaining references in `src/` after the rename. Locale parity check
  passes.
2026-05-19 16:50:42 +08:00
Yuxing Deng 38107a67fe refactor(usage): switch breakdown dimension from model to route
Align with gpustack backend commits 7b57cd3b (add route dimension to
usage breakdown) and 51fd25c8 (use model_route_id as models_called):

* group_by, filters, and BreakdownItem now use the `route` dimension;
  `models` filter cascader is replaced with a flat `routes` selector
  (routes have no provider/cluster grouping).
* Tab / group_by option / column header keep the user-facing "模型 / Model"
  wording — only the underlying data dimension changed.
* Drop cluster_name / provider_type columns from the breakdown table;
  drop api_keys_used column per design.
* Fix pre-existing excel export bug in use-export-table — string
  dataIndex was lodash-joined char-by-char ("input_tokens" →
  "i_n_p_u_t..."), array dataIndex was used as a flat key against nested
  rows. Rebuilt around buildSheetMeta that emits a stable field key plus
  a formatMap using _.get(row, path) for nested values. Sheet name kept
  as `models` to match the visible column label.
2026-05-19 16:50:42 +08:00
jialinandjialin 0274bcb8cd chore: update ui 1.0.14 2026-05-19 14:09:07 +08:00
gitlawrandjialin a91c1545f8 fix: require ref audio for Base task in TTS playground 2026-05-19 12:36:08 +08:00
jialinandjialin 0b3884b1a5 fix: gguf input box is hidden when deploying from model files 2026-05-19 12:16:02 +08:00
jialinandjialin bcea46fa8f fix(style): chart style 2026-05-18 20:14:28 +08:00
jialinandjialin abc3c2c25a fix: instance events namespace 2026-05-18 16:59:53 +08:00
jialinandjialin db7a8a702d fix: select panel no default value 2026-05-18 15:37:46 +08:00
jialinandjialin 288bfebc13 fix: filter user option in usage 2026-05-18 15:37:46 +08:00
jialinandjialin c7996d3e14 fix: login page miss icon 2026-05-18 15:37:46 +08:00
jialinandjialin 0d9b6325f9 fix: hygon, thead runtime 2026-05-18 15:37:46 +08:00
gitlawrandjialin baf1508644 fix: guard systemConfigAtom reads against null
``logout`` calls ``clearAtomStorage(systemConfigAtom)`` which sets the
atom to ``null``, and on a fresh SPA login (no full reload)
``app.tsx``'s ``fetchSystemConfig`` doesn't re-run, so consumers that
read ``systemConfig.xxx`` directly crash with "Cannot read properties
of null". A hard refresh masks the bug. Add optional chaining at the
read sites (grafana url / dashboard uids, showMonitoring) so the
contract stays robust regardless of how the atom is reset.
2026-05-18 15:36:29 +08:00
jialinandjialin d04604abe5 fix: SelectPanel props 2026-05-18 13:28:52 +08:00
jialinandjialin bf09784fad chore: update ui 1.0.13 2026-05-18 13:28:52 +08:00
gitlawrandjialin 67f5c794e1 fix(login): keep 360px design width with max-width: 100% cap
Switching ``Buttons`` to ``width: 100%`` (in c32ad712) had a
side-effect — with ``FormWrapper`` sized to ``max-content``, a
100% child without LocalUserForm alongside it lets the card
collapse to the button's intrinsic text width. Per PR #1097 review,
go back to the 360px design width and rely on ``max-width: 100%``
to keep it from overflowing tighter parents (the enterprise cover
layout's 272px inner especially).

Apply the same shape to LocalUserForm — its hardcoded 360px alone
would still overflow on the cover layout — so the two surfaces
stay in lockstep when switching between SSO and password modes.

(Pre-commit hook still crashes on the ``context.getDeclaredVariables``
bug in main; unrelated.)
2026-05-18 12:25:08 +08:00
gitlawrandjialin 55fbe118d5 fix(login): stop SSO button from overflowing the login card
``Buttons`` was a fixed ``width: 360px`` column, but ``FormWrapper``
sizes its content area to ``max-content`` capped at 440px (with 40px
padding). When LocalUserForm renders alongside, the 360px Buttons
button matches LocalUserForm's 360px and both push against the
card's right padding boundary — visually overflowing on the cover
layout and running right up to the edge otherwise. Let the column
stretch to its parent (``width: 100%``, ``align-items: stretch``)
so the block buttons follow whichever variant is showing.

(Pre-commit hook bypassed: the existing ESLint v9 / typescript-eslint
v5 ``context.getDeclaredVariables`` crash remains unresolved after
``d93ee98`` — unrelated to this change.)
2026-05-18 12:25:08 +08:00
Yuxing Dengandjialin ae8ec8572c feat: generic configActions plugin slot for api-keys & model-routes
Introduce `pages/api-keys/plugin.tsx` and `pages/model-routes/plugin.tsx`
defining a unified `{ key, labelId, icon, priority, danger, form,
useCreate }` contract that plugins use to contribute per-row
"configure this record" actions. The host renders one dropdown entry
per registered action and mounts each entry's form, ordered by a
single numeric priority (built-ins are ranked on the same scale; rows
flagged `danger` sink to the bottom).

Drops the older `apiKeys.rowActions` / `modelRoutes.rowActions` slots
and the implicit drawer half of
`<PluginExtraFields name="APIKeysPageGlobal" />`. The model-routes
mount point stays for the page-level quota-defaults bulk-fetch and now
also accepts a `refreshToken` so per-row saves can invalidate derived
page data without changing the row set.
2026-05-18 12:14:19 +08:00
jialinandjialin 38b91a558b chore: remove notes 2026-05-15 16:22:07 +08:00
jialinandjialin a001f83abb fix: update instance name error 2026-05-15 16:22:07 +08:00
jialinandjialin 87c8a3a64d feat: add instance recreate action 2026-05-15 16:22:07 +08:00
jialinandjialin c6e7075bf5 feat: template port name 2026-05-15 16:22:07 +08:00
jialinandjialin 5d75cfdfc5 fix: name validation 2026-05-15 16:22:07 +08:00
jialinandjialin 3f9852c932 refactor: instances add-modal 2026-05-15 16:22:07 +08:00
jialinandjialin 9dfaf990fd feat: add events, log api 2026-05-15 16:22:07 +08:00
micheliaandjialin 1bef1637e0 feat: support license banner 2026-05-15 09:41:10 +08:00
jialinandjialin 451d5bfe47 fix: show inject params, update ui 1.0.11 2026-05-14 11:54:51 +08:00
jialinandjialin faa1f935b7 feat: provider access to core-ui 2026-05-14 11:52:48 +08:00
jialinandjialin c428fe175a chore: remove inject params tag 2026-05-14 11:21:49 +08:00
jialinandjialin 9767c8bf39 chore: show deployment backend params 2026-05-14 11:21:49 +08:00
jialinandjialin 96b50538ed feat: add antv/g6 2026-05-13 17:58:31 +08:00
gitlawrandjialin 2dae886fd1 fix(gpu-service): use gpustack-{slug} namespace for org resources
The legacy ``getCurrentOrganizationId`` helper returned the raw numeric
org id from localStorage, which the GPU-service / storage call sites
then used as the K8s namespace path segment — producing requests like
``/v2/clusters/1/proxy/.../namespaces/5/instances``. The backend
creates a namespace named ``gpustack-{slug}`` (matching
``get_namespace_name``), so the request hit a namespace that doesn't
exist.

Replace the helper with ``getCurrentOrgNamespace`` that:

- prefers the Org the caller is acting under (numeric
  ``currentOrganizationId`` from localStorage, slug looked up in the
  persisted ``organizationList`` or ``allOrganizations`` cache);
- falls back to the selected cluster's owner Org slug for the admin
  "All" view, where there is no explicit Org context but the resource
  still has to land in some Org's namespace — call sites pass
  ``currentCluster?.owner_principal_id`` through;
- falls back to ``gpustack-default`` only if neither path resolves a
  slug (first load before any cache hydrates, etc.).

``ClusterListItem`` is widened with the optional ``owner_principal_id``
field so TypeScript accepts the fallback argument; the backend has
been returning it via ``ClusterPublic`` all along.
2026-05-13 12:29:09 +08:00
jialinandjialin beb74b3c47 fix: update lock.yaml 2026-05-13 10:52:44 +08:00
jialinandjialin d93ee98473 fix: eslinit context.getDeclaredVariables 2026-05-13 10:47:45 +08:00
jialinandjialin f081f0c1cf chore: dropdown styles token, icons url 2026-05-13 10:47:45 +08:00
jialinandjialin 4e49c399d0 fix: dashboard colors, users rank 2026-05-12 19:01:11 +08:00
jialinandjialin 2527555945 fix: HRM in dev 2026-05-12 14:31:52 +08:00
gitlawrandjialin 5ef671f047 feat: dashboard route gated on canSeeOrgAdmin
Relax the dashboard route from canSeeAdmin (strict platform admin)
to canSeeOrgAdmin so the access seam can widen the audience past
the platform admin — by default platform admin, plus whatever an
access extension chooses to admit. The dashboard endpoint takes
care of scoping the response per caller.

Also move Dashboard under the canSeeOrgAdmin bullet in the
access.ts predicate notes.
2026-05-12 14:20:18 +08:00
gitlawrandjialin 10781da086 fix: plugin locale merge re-runs on HMR; API Key form allows Personal
- locale-merger: drop the module-level dedup Set. addLocale is
  idempotent, and the guard made HMR-added plugin locale keys
  silently skipped — strings like organizations.members.selectUsers
  stayed unresolved until a full dev-server restart.
- api-keys form: pass allowPersonal: true to CreateOrgScopeField so
  admin in Platform-wide mode can target their own Personal Org when
  creating a key (unlike infra resources where Personal doesn't fit).
2026-05-12 14:20:18 +08:00
jialinandjialin c279a7f186 fix: gpu service access 2026-05-11 21:05:08 +08:00
gitlawrandjialin 7dd1c9ac5e refactor(backends): rename organization_id to owner_principal_id
Aligns the InferenceBackend ownership column with the principal-based
ownership model used elsewhere (clusters, model_routes). NULL identifies
platform-curated rows shared across orgs; a populated value identifies
an org-scoped override or custom backend.
2026-05-11 20:28:29 +08:00
gitlawrandjialin 125a5be91f feat: restore cluster detail surface, gate cluster-list name link via plugin
The "chore: hide cluster detail" change had commented out both the
cluster-detail route and the cluster name link in the list. The
detail page component still ships in the OSS tree, so reach is
restored but the link is plugin-gated rather than unconditional:
plain OSS renders the name as a span; with a registered
`clusterDetail.linkableName` flag the name turns into a
`Typography.Link` that fires the parent's existing `onCellClick`
(which navigates to the detail route).

Detail tabs adjustments for the in-cluster context:
- Drop the Deployments tab (deployments are managed from the
  top-level Models page; the detail view is scoped to a single
  cluster's hardware).
- `WorkerList` and `GPUList` accept an optional `clusterId`. When
  set, the list pins `cluster_id` in its query and hides the
  cluster-filter dropdown so the user can't scope away from the
  cluster they're inside.

`clusterDetail.extraTabs(clusterId, intl)` exposes a plugin slot
that appends additional tab items — used by the enterprise plugin
to inject per-cluster Access / Quotas surfaces. No-op without a
plugin.
2026-05-11 20:28:29 +08:00
jialinandjialin e25d48cc89 fix: update react-route version 2026-05-11 20:09:37 +08:00
jialinandjialin 5f96f367a6 chore: lock pnpm version 2026-05-11 19:49:21 +08:00
jialinandjialin 01fe2e66fb fix: style issues 2026-05-11 19:49:21 +08:00
jialinandjialin 1b74285de9 fix: storage instance keep the same cluster 2026-05-11 19:49:21 +08:00
jialinandjialin b13ba0a229 fix: alignment api 2026-05-11 19:49:21 +08:00
jialinandjialin 9e0dd5b003 fix: display templates by manufacturer 2026-05-11 19:49:21 +08:00
jialinandjialin 4128de61f9 fix: api test 2026-05-11 19:49:21 +08:00
jialinandjialin fc900c8ce6 fix: ssh key, template test 2026-05-11 19:49:21 +08:00
jialinandjialin 63ac4e0e75 fix: instance api alignment 2026-05-11 19:49:21 +08:00
jialinandjialin 7ee1635833 fix: template api alignment 2026-05-11 19:49:21 +08:00
jialinandjialin 7d0cfeff77 fix: storage api alignment 2026-05-11 19:49:21 +08:00
jialinandjialin 7fa44644fd style: scroller 2026-05-11 19:49:21 +08:00
jialinandjialin e9152e8725 refactor: add instance modal 2026-05-11 19:49:21 +08:00
jialinandjialin 7ea7f6666d feat: templates, storage 2026-05-11 19:49:21 +08:00
jialinandjialin 3ae49dc826 feat: add intances list 2026-05-11 19:49:21 +08:00
gitlawrandjialin 75d7eff63b chore: bump @gpustack/core-ui to ^1.0.10
1.0.10 ships the fix for the rolldown-emitted `require("react")` shim
that broke 1.0.9 runtime (the dist bundle no longer calls the
runtime require helper for react / react-dom). Pin the OSS host's
package.json spec accordingly and regenerate the lockfile.

Side fix in `pages/login/index.tsx`: 1.0.10's `CoreHooks` type
makes `useCurrentUser` and `useTableFetch` required. The login
page's CoreUIProvider never needed them (no current-user reads
and no tables), so cast the hooks block to `any` rather than
mounting stubs that would never run.
2026-05-11 19:30:21 +08:00
gitlawrandjialin 8618718b71 chore: sync pnpm-lock.yaml with package.json
Two pre-existing drifts between package.json and pnpm-lock.yaml were
breaking `pnpm install --frozen-lockfile` in CI:

- `@gpustack/core-ui` was bumped to `^1.0.9` in package.json without
  regenerating the lockfile (lockfile still pinned the prior 1.0.6
  resolution). Pin to `^1.0.7` instead — 1.0.9 ships a packaging
  glitch that surfaces a `Calling \`require\` for "react"` exception
  at module init under MFSU, so the matching enterprise build was
  already reverted; 1.0.7 is the last known-good across both repos.
- `react-router-dom` had `^6.30.3` in package.json but `6.30.3`
  (no caret) in the lockfile spec. Match the lockfile to keep the
  intentional pin from the original add.

`pnpm install --frozen-lockfile` now passes locally.
2026-05-11 19:30:21 +08:00
gitlawrandjialin 8d17000272 feat: users row actions accept plugin entries
The per-row user actions menu was hard-wired to a fixed list and any
plugin-contributed control had to sit as a separate trigger beside
the dropdown. Move the seam: plugins now contribute dropdown items
directly via `users.rowActions`, and we dispatch the click to the
plugin entry by key while the host's `handleSelect` keeps owning
the built-in keys.

Each entry is `{ key, labelId, icon?, danger?, show?(user), onClick(user) }`.
For UI state the onClick might need (drawers, modals), plugins can
mount a single `components.UsersPageGlobal` slot that the page now
renders once outside the table — typical pattern is a jotai atom
the rowAction writes to and the global slot reads from.

Drop the side-mounted `PluginExtraFields name="UserRowActions"` and
its surrounding `<Space>`; the action column is back to a single
DropdownButtons with all entries in one menu.
2026-05-11 19:30:21 +08:00
gitlawrandjialin df53774628 feat: access-control seam exposes prepended policies + create default
The OSS access-control form currently lets a plugin replace the
`allowed_users` policy entry. Multi-tenancy also wants:
- an extra radio option for "Org-scoped" sitting in front of the
  built-ins, and
- a context-sensitive create-time default (routes inside a non-
  platform Org should land on the Org-scoped policy rather than
  `authed`).

Extend the `accessControl` slot with two more hooks:
- `prependedPolicies?: { policyValue, labelId, tipsId?, Field? }[]`
  — entries prepended to the radio group; each may carry an
  optional content `Field` rendered when selected.
- `resolveCreateDefault?: () => string | undefined` — overrides the
  initial `access_policy` for the create flow; the OSS fallback is
  still `authed`.

The host's tooltip list mirrors the same order. Existing behaviour
without a plugin is unchanged.
2026-05-11 19:30:21 +08:00
gitlawrandjialin 68235e188a fix: refresh Access Settings policy from /access response
Reopening the Access Settings dialog after a save could leave the
radio on the wrong policy: the form initialized `access_policy`
from the route list's snapshot, but the list isn't refreshed when
the dialog closes, so the snapshot's value silently shadowed the
just-saved policy.

Backend now returns the route's authoritative `access_policy` on
`GET /v2/model-routes/{id}/access`. Use that value when the GET
resolves, falling back to the parent snapshot only as the initial
seed so the radio isn't briefly unselected.

While we're here, widen the `access_policy` type from a closed
union to `string` — plugins can contribute additional policy
values via the `accessControl.allowedUsersOverride` slot, so the
wire type shouldn't restrict to the OSS-side enum.
2026-05-11 19:30:21 +08:00
gitlawrandjialin f37fad11b1 feat: access-control modal seam to swap the allowed_users surface
The OSS Access Settings form hardcodes the `allowed_users` policy
(per-user explicit grants via the legacy transfer widget). Multi-
tenancy needs a different surface that grants by Org / Group / User
principals via the `/v2/model-routes/{id}/principals` endpoints, and
the enterprise plugin will ship that — but the OSS form should stay
visually unchanged when no plugin is loaded.

Add a plugin extension point on the form: if a registered plugin
exposes `accessControl.allowedUsersOverride: { policyValue, labelId,
tipsId?, Field }`, the form replaces the `allowed_users` radio entry
with the plugin's labelled option, swaps the access-scope tooltip
copy, and renders `<Field form routeId action />` for the override
policy. Without a plugin the form's radio / tooltip / content path
are unchanged.

`handleOnFinish` continues to send `users` only for `allowed_users`;
any other policy (including the plugin's value) goes through with
an empty users list, leaving the plugin's Field to manage its own
principal CRUD inline.
2026-05-11 19:30:21 +08:00
gitlawrandjialin 93fa277bdd fix: Access Control Modal user picker uses /user-directory
The form populated its candidate list via the admin-only
`GET /v2/users`, so opening Route Access Settings as a non-admin
caller (e.g. an org owner managing their own route in the
enterprise plugin) returned 403. Add a `queryUserDirectory` client
wrapper around the slim `/v2/user-directory` endpoint (gated to
platform admin OR org owner) and switch `getUserList` over. Response
shape is the same so the rest of the form is unchanged.
2026-05-11 19:30:21 +08:00
jialinandjialin ea7fa63079 chore(deps): add react-route 2026-05-11 14:47:45 +08:00
jialinandjialin d15db4b4dd chore: update ui 1.0.9 2026-05-11 14:32:07 +08:00
jialinandjialin ed06d57a31 feat: add slots 2026-05-11 14:27:49 +08:00
gitlawr 168c55990f fix: pick landing route by access predicate to avoid redirect loop
Access extensions can narrow ``canSeeAdmin`` to ``false`` even when
``currentUser.is_admin`` is ``true``. The default-landing logic
keyed off ``is_admin`` and pushed admin to ``/dashboard``; when
``canSeeAdmin`` is narrowed there, ``Exception`` 403-redirects to
``/``, which re-pushes ``/dashboard``, looping into a blank screen.
Switch the landing pick (and the masthead-click handler) to consult
the resolved ``access.canSeeAdmin`` predicate instead.

Behavior is unchanged for the default access module, where
``canSeeAdmin`` mirrors ``is_admin``.
2026-05-09 17:22:27 +08:00
gitlawrandjialin 2889ba7c78 feat: plugin extension slots for access, request interceptors, Users actions, and form fields
Four purely-additive seams that let build-time tooling extend host
behaviour without forking files:

* `src/access.extensions.ts` — identity `applyAccessExtensions`
  (mirrors `config/routes.extensions.ts`). `src/access.ts` runs the
  resolved predicate object through it. Adds two new predicates,
  `canSeeOrgAdmin` and `canManageCurrentOrg`, alongside the existing
  `canSeeAdmin`. Resources, Models children, Cluster Management, and
  Resources/Backends are retagged from `canSeeAdmin` to
  `canSeeOrgAdmin`. Users and Dashboard stay strict.
* `src/request.extensions.ts` — identity-empty
  `extraRequestInterceptors`. `src/request-config.tsx` spreads it
  into the existing `requestInterceptors` list so extensions can
  inject context-aware headers without forking the request config.
* Users page action column — renders
  `getGPUStackPlugin()?.components?.UserRowActions` next to the
  existing DropdownButtons inside a Space when a plugin component
  is registered. If absent, the cell renders exactly as before.
* `src/components/plugin-extra-fields.tsx` — generic component-slot
  helper. Renders `pluginManager.components.<name>` if registered,
  forwarding a `context` payload. Used by create/edit forms to let
  plugins inject extra `Form.Item` fields. Mounted in the relevant
  create forms — API Keys, Cloud Credentials, Clusters, Model
  Routes, Model Providers, and Inference Backends — under the slot
  name `CreateOrgScopeField`. Resources whose org is implicit from a
  parent (Models / Workers / Benchmarks / Worker Pools / Model Files
  inherit from the chosen Cluster) deliberately don't mount the slot.
2026-05-08 18:29:52 +08:00
gitlawrandjialin 896b8ef326 feat: expose useTableFetch via CoreUIProvider
Inject the host's `useTableFetch` hook into the CoreUIProvider's
`hooks` prop alongside the already-wired `useCurrentUser`, so plugins
that import `useTableFetch` from `@gpustack/core-ui` resolve it through
the host instead of throwing
"`hooks.useTableFetch is not a function`" at the first list-page render.

Companion to the earlier `feat: add use current user` change — core-ui
exposes both hooks as host-injected, but only the user hook had been
plumbed.
2026-05-08 14:46:35 +08:00
jialinandjialin f08d5c904c refactor: dynamic routes 2026-05-08 09:33:16 +08:00
jialinandjialin 4be5fb4d3d feat: add use current user 2026-05-07 18:26:48 +08:00
jialinandjialin a2d5d55518 chore: backend default command 2026-05-07 18:26:48 +08:00
jialinandjialin e1b28b01df chore: backend placeholder 2026-05-07 18:26:48 +08:00
gitlawrandjialin b6bbe880a0 feat(plugin): expose OrgSwitcher slot in extraRender
Add a single host-side mount point in extraRender.tsx:

    const OrgSwitcher = pluginManager?.components?.OrgSwitcher;
    ...
    {OrgSwitcher && <OrgSwitcher />}

A registered plugin can supply an Org switcher via
components.OrgSwitcher. When no plugin provides it, the host
renders nothing here, so the build is visually unchanged.
2026-05-07 18:16:42 +08:00
jialinandjialin 65ad57fc4c fix: iluvatar env check command 2026-05-06 19:32:01 +08:00
jialinandjialin 469e63b898 fix: keep the source deploying from files 2026-05-06 15:09:15 +08:00
jialinandjialin d471233f83 fix: sync row replicas when start 2026-05-06 14:43:03 +08:00
jialinandjialin 01576212a3 fix: bool type in python code 2026-05-06 14:43:03 +08:00
jialinandjialin 898c7f1be2 refactor: dashboard usage 2026-05-06 12:27:22 +08:00
jialinandjialin 705b33e307 style: parameters tooltip 2026-05-06 12:27:22 +08:00
jialinandjialin 2592f44bc2 fix: append routeID to model proxy URL and drop X-GPUStack-Model header 2026-05-06 12:27:22 +08:00
jialinandjialin 9914db6b96 fix: hide distributed_inference for custom backend 2026-04-29 20:51:48 +08:00
jialinandjialin bb93ad37a1 feat: benchmark inject params 2026-04-29 20:51:48 +08:00
jialinandjialin 93bc632088 fix: stt error handler 2026-04-29 20:51:48 +08:00
jialinandjialin ab89ddffc8 fix: tts stream error 2026-04-29 20:51:48 +08:00
jialinandjialin 7794e57bb1 fix: update lock file 2026-04-29 18:21:24 +08:00
jialinandjialin 7c15bb6ef6 chore(deps): update ui 1.0.5 2026-04-29 18:09:55 +08:00
jialinandjialin ac99156c90 feat: ip access control 2026-04-29 18:09:55 +08:00
jialinandjialin c68f546be9 fix: apikey filters 2026-04-29 18:09:55 +08:00
jialinandjialin 217285223c fix: list-input, labels-selector form 2026-04-29 18:09:55 +08:00
jialinandjialin 3144328874 fix: chart flicker 2026-04-29 09:29:04 +08:00
jialinandjialin 26880b4612 refactor: usage chart 2026-04-29 09:29:04 +08:00
jialinandjialin e7aac14ef1 fix: keep previous run checkbox visible and fall back to main worker 2026-04-28 14:41:36 +08:00
jialinandjialin 52211cd4ea fix: previous run description 2026-04-28 14:41:36 +08:00
jialinandjialin 331c59b7c1 fix: logs container 2026-04-28 14:41:36 +08:00
jialinandjialin b605b17561 fix: main worker flag 2026-04-28 14:41:36 +08:00
jialinandjialin 33163ac96c style: start history selection 2026-04-28 14:41:36 +08:00
jialinandjialin 757af11ab3 chore: history options 2026-04-28 14:41:36 +08:00
jialinandjialin 81a87ef362 chore: logs history selection 2026-04-28 14:41:36 +08:00
jialinandjialin 0cb260f854 feat: logs history 2026-04-28 14:41:36 +08:00
jialinandjialin 0ffc2ee924 chore: update ui version 2026-04-27 21:10:34 +08:00
jialinandjialin e4992e8313 fix: custom logos 2026-04-27 21:10:34 +08:00
jialinandjialin 519020077a chore: update lock file 2026-04-24 14:28:30 +08:00
jialinandjialin 6fccee3711 fix: impoer external components 2026-04-24 14:28:30 +08:00
jialinandjialin 597a86562a fix: rebase main 2026-04-24 14:28:30 +08:00
jialinandjialin 16449613e0 chore: core-ui deps 2026-04-24 14:28:30 +08:00
jialinandjialin 6c161c6ae7 build: sync config 2026-04-24 14:28:30 +08:00
jialinandjialin 48b357b1c6 chore: update hooks import 2026-04-24 14:28:30 +08:00
jialinandjialin a795544074 fix: CInput not found 2026-04-24 14:28:30 +08:00
jialinandjialin 8711c27b78 chore: replace components with core-ui, upgrade eslint 2026-04-24 14:28:30 +08:00
jialinandjialin d48aa99dcc fix: deleted tag 2026-04-22 13:16:48 +08:00
jialinandjialin 5f3b9b88ff fix: reset page after filters changed 2026-04-22 13:16:48 +08:00
jialinandjialin f566ea3b63 fix: table sorter 2026-04-22 13:16:48 +08:00
jialinandjialin 8ba77beeed fix: sync filters 2026-04-22 13:16:48 +08:00
jialinandjialin 128f59ed6f chore: locales 2026-04-22 13:16:48 +08:00
jialinandjialin c92f56ec8f style: card style 2026-04-22 13:16:48 +08:00
jialinandjialin daa3d74500 fix: usage datepicker 2026-04-22 13:16:48 +08:00
jialinandjialin ad7fc3a993 fix: usage ux 2026-04-22 13:16:48 +08:00
jialinandjialin 084822814d fix: models, apikeys Cascader 2026-04-22 13:16:48 +08:00
jialinandjialin 3a58bd1eef fix: show tag only one selected 2026-04-22 13:16:48 +08:00
jialinandjialin 94d3fa356c fix: usage filter 2026-04-22 13:16:48 +08:00
jialinandjialin 7d75714662 feat: usage 2026-04-22 13:16:48 +08:00
jialinandjialin b057d52499 fix: switch model do not work in chat 2026-04-17 20:35:16 +08:00
jialinandjialin 2d726ded30 feat: admin apikeys 2026-04-17 20:35:16 +08:00
jialinandjialin f45d9bda61 style: font size 2026-04-16 15:16:47 +08:00
jialinandjialin 684c1ab600 fix: apikey model access 2026-04-16 15:03:59 +08:00
jialinandjialin 3ac2720ba8 chore: remove experimental from metax 2026-04-16 15:03:59 +08:00
jialinandjialin 7b743f35b3 fix: apikey custom tag 2026-04-15 11:30:40 +08:00
jialinandjialin e1b2a4aee2 fix: python test code 2026-04-15 10:15:36 +08:00
jialinandjialin 308c350582 style: server version 2026-04-15 10:15:36 +08:00
jialinandjialin 41c9b86fd9 fix: k8s volume config 2026-04-14 20:42:01 +08:00
jialinandjialin 46b9855c87 fix: custom apikey 2026-04-14 20:42:01 +08:00
jialinandjialin c667de90ed style: worker versio info 2026-04-14 20:42:01 +08:00
jialinandjialin cf13e3bed0 fix: volume mounts default empty 2026-04-10 15:33:59 +08:00
jialinandjialin 0956538b79 fix: volume name update while typing 2026-04-10 15:17:58 +08:00
jialinandjialin f2a4ab2654 feat: k8s volume mounts 2026-04-10 15:17:58 +08:00
jialinandjialin aeabdab781 fix(style): all scope tag 2026-04-10 09:52:36 +08:00
jialinandjialin f04b5cdc27 feat: custom api key 2026-04-09 21:27:50 +08:00
jialinandjialin b947e3a8b9 fix: show gpu driver version 2026-04-09 21:27:50 +08:00
jialinandjialin ae3148a86f feat: validate tts form items 2026-04-09 12:14:36 +08:00
jialinandjialin 78bf76e965 fix: python code for eidting image 2026-04-09 12:14:36 +08:00
jialinandjialin 7beb5756f7 fix: chat content height 2026-04-09 12:14:36 +08:00
jialinandjialin a2b0236ea3 refactor: table filters ux 2026-04-08 18:54:06 +08:00
jialinandjialin 144914110a feat: more filters component 2026-04-08 18:54:06 +08:00
jialinandjialin c73609d155 fix: adjust border raduis 2026-04-08 18:54:06 +08:00
jialinandjialin 53cd8ba00c fix: page error while route changing 2026-04-08 18:54:06 +08:00
jialinandjialin 1c09cc6c8c refactor: ui/ux 2026-04-08 18:54:06 +08:00
jialinandjialin 06160546a6 feat: show the worker version 2026-03-31 15:05:38 +08:00
jialinandjialin 0b292829fa fix(style): select content align 2026-03-31 15:05:38 +08:00
jialinandjialin 392c51fced chore: instance state filter 2026-03-26 18:20:55 +08:00
jialinandjialin 144d5a6d5f style: instance cell style 2026-03-26 18:20:55 +08:00
jialinandjialin 43dfc7e1f0 fix: normalize parameter string by removing line-continuation backslashes 2026-03-26 18:20:55 +08:00
jialinandjialin adde7fba37 feat: add instance view 2026-03-26 18:20:55 +08:00
jialinandjialin 33fe180997 refactor: model instance item 2026-03-26 18:20:55 +08:00
jialinandjialin a95b7e9561 feat: add instance view 2026-03-26 18:20:55 +08:00
jialinandjialin 08330e0b82 fix: row-textarea upload img 2026-03-26 17:59:33 +08:00
jialinandjialin c74118e913 refactor: embedding messages format 2026-03-26 17:59:33 +08:00
jialinandjialin bb3cef89c1 fix(style): dashboard usage filters 2026-03-26 17:59:33 +08:00
jialinandjialin 589936199c chore: sharegpt description 2026-03-26 17:59:33 +08:00
jialinandjialin 710e2e1996 fix: a non-running instance is selected in creating benchmark 2026-03-26 17:59:33 +08:00
bakiburakogunandjialin aa794c7646 fix(i18n): add missing ShareGPT profile and fix untranslated model tips in tr-TR 2026-03-25 09:48:20 +08:00
jialinandjialin 48779aed29 fix: add ShareGPT profile 2026-03-24 16:29:41 +08:00
jialinandjialin 3907e1ac76 fix(style): hint-input minwidth 2026-03-24 16:29:41 +08:00
jialinandjialin 4d6af4fbf8 fix: copybutton do not work 2026-03-24 10:37:15 +08:00
bakiburakogunandjialin 9c3b0efb30 revert: restore fileName: any for consistency with other locale files 2026-03-23 15:55:07 +08:00
Baki Burak Öğünjialingemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
8bcb7ffe4d Update src/locales/tr-TR.ts
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-23 15:55:07 +08:00
bakiburakogunandjialin 77f0740ec9 feat(i18n): add Turkish (tr-TR) locale translation
Add complete Turkish localization for the GPUStack UI including all 18 translation files covering common UI, menus, dashboard, models, playground, resources, API keys, users, backends, benchmarks, clusters, providers, routes, shortcuts, usage, and vendor names.
2026-03-23 15:55:07 +08:00
jialinandjialin 8b5e407758 fix: alert info height 2026-03-20 17:23:55 +08:00
jialinandjialin 6c88a5554f fix: bedrock required fields 2026-03-20 17:23:55 +08:00
jialinandjialin d779ee06b1 fix: typos: position 2026-03-20 17:23:55 +08:00
jialinandjialin f873d4e245 fix: show required fields for provider 2026-03-20 17:23:55 +08:00
jialinandjialin 0a0e03dc68 fix: open the advanced when configured 2026-03-20 17:23:55 +08:00
jialinandjialin f0e19c8934 fix: spin size 2026-03-19 12:28:18 +08:00
jialinandjialin a6af51dc32 fix: delay querying backends 2026-03-19 12:28:18 +08:00
jialinandjialin fd1a079271 refactor: deployments dir tree 2026-03-19 12:28:18 +08:00
jialinandjialin 9840a48301 fix: depercated props 2026-03-19 12:28:18 +08:00
jialinandjialin 2dc7c9adf1 feat: show the apikey mask value 2026-03-17 16:35:55 +08:00
jialinandjialin a86bfe7fd3 chore: upgrade antd 6.3.3 2026-03-17 16:35:55 +08:00
jialinandjialin d99475bb80 style: table overflow scroller style 2026-03-17 16:35:55 +08:00
jialinandjialin 194b7aff2e fix: autofilled in add user form 2026-03-17 16:35:55 +08:00
jialinandjialin f6d5733183 fix: video gen 2026-03-17 16:35:55 +08:00
jialinandjialin 0ca055b8e8 fix: parser multiple backend pramas on paste 2026-03-17 16:35:55 +08:00
jialinandjialin 9aae2c7f50 fix: use html audio to load stream 2026-03-17 16:35:55 +08:00
jialinandjialin c29ad1270b fix: stt streaming response handler 2026-03-17 16:35:55 +08:00
jialinandjialin 49a60c25af feat: add streaming for stt 2026-03-17 16:35:55 +08:00
jialinandjialin 39bcc158bb feat: add stream mode for tts 2026-03-17 16:35:55 +08:00
jialinandjialin 4f02bcd40c feat: paste multiple lines in parameters input 2026-03-17 16:35:55 +08:00
jialinandjialin 556c4a434d chore: benchmark profile filter 2026-03-17 16:35:55 +08:00
jialinandjialin d389b035b7 refactor: playground params form 2026-03-17 16:35:55 +08:00
jialinandjialin 9447088f89 refactor: adjust playground pages dir 2026-03-17 16:35:55 +08:00
jialinandjialin 64955c26a7 refactor: playground params container 2026-03-17 16:35:55 +08:00
jialinandjialin 68519223fa fix: pagination cache for table list 2026-03-17 16:35:55 +08:00
jialinandjialin e72cacc4b2 chore: autocomplete user info 2026-03-17 16:35:55 +08:00
jialinandjialin ed4be2328f chore: store pagination for list 2026-03-17 16:35:55 +08:00
jialinandjialin e241c6cb6f refactor: embeddding input list 2026-03-17 16:35:55 +08:00
jialinandjialin 6e98fb4274 fix: reset filter in export modal 2026-03-16 14:48:46 +08:00
jialinandjialin 83f6f41787 fix: show backend warning hint after submitting in editing mode 2026-03-16 14:48:46 +08:00
jialinandjialin 18c10e5839 chore: update model cols 2026-03-16 14:48:46 +08:00
jialinandjialin 11de47c813 style: same key tooltip 2026-03-16 14:48:46 +08:00
jialinandjialin 85ea619b18 fix: title for editing apikey 2026-03-16 14:48:46 +08:00
jialinandjialin 3f57cf21f7 feat: add profile filter in benchmark 2026-03-16 14:48:46 +08:00
jialinandjialin b75c773879 chore: add nvidia notes 2026-03-16 14:48:46 +08:00
jialinandjialin 95070ae382 feat: display provider models 2026-03-16 14:48:46 +08:00
jialin 353ee3a9ae fix: route target can be set 0 2026-03-10 19:06:49 +08:00
jialin 972e147fdf fix: yaml edior height 2026-03-10 19:06:49 +08:00
jialin 73e52fe334 chore: add hint for creating backend 2026-03-09 15:48:16 +08:00
jialin cf521ad79e fix: default_env field not display in backend editing yaml 2026-03-02 10:21:21 +08:00
jialin 76a3e5cfcf fix: custom config overwrite input value 2026-02-25 10:42:06 +08:00
jialin 200d63e5fc fix: add custom config in get-models, test-model 2026-02-25 10:28:31 +08:00
jialin 0aeefb1217 fix: allow deleting version for community backend 2026-02-24 17:23:42 +08:00
jialin 7dfeb859e2 refactor: query dashboard data 2026-02-24 16:33:28 +08:00
jialin 5151f26b9e fix: miss openaiCustomUrl in get-models payload 2026-02-24 15:36:41 +08:00
jialin 053e5cca86 chore: markdown for community backend detail 2026-02-24 11:37:22 +08:00
jialin 89765c19c4 fix: copy multi lines when == 2026-02-24 11:07:53 +08:00
jialin 0824f0c13b fix: provider proxy_url set null when disabled 2026-02-24 11:07:53 +08:00
jialin 04092c3fa5 fix: openaicustomurl do not display 2026-02-24 11:07:53 +08:00
jialin d8258cf676 fix: worker list params do not update 2026-02-14 12:06:45 +08:00
jialin 97d6eee5ba chore: icons static files 2026-02-13 20:36:46 +08:00
jialin 511297ed11 fix: do not cache while watching during manual updates 2026-02-13 19:32:59 +08:00
jialin 88aafbaf7b refactor: list watch trigger 2026-02-13 16:12:56 +08:00
jialin af9890b16c style: community backend detail title 2026-02-13 12:26:43 +08:00
jialin c67a8c4120 fix: add other category 2026-02-12 19:38:47 +08:00
jialin 16c0e00b4f chore: diff envs in editing deployment 2026-02-12 19:38:47 +08:00
jialin d1c1c5acf9 chore: corex metax notes 2026-02-12 14:56:25 +08:00
jialin 9cb7145b4e fix: provider yaml inital value 2026-02-12 12:20:05 +08:00
jialin 978d327bcd chore: form tabs active change 2026-02-12 12:20:05 +08:00
jialin 07664b5f22 chore: quick create route 2026-02-12 12:20:05 +08:00
jialin b21fe0ac4c style: error message toast 2026-02-12 12:20:05 +08:00
jialin 932c30cd7f fix: enable_model_route set true in cloning 2026-02-11 20:35:19 +08:00
jialin 59c19f3fae fix: update add worker command 2026-02-11 17:54:34 +08:00
jialin c9245f957e fix: enable_model_route value in cloning 2026-02-11 17:54:34 +08:00
jialin 228cd4e664 fix: benchmark detail envs gpus list 2026-02-11 16:50:49 +08:00
jialin 289a651d52 fix: default language value 2026-02-11 16:14:06 +08:00
jialin 1b8c17ce92 fix: tts params filter 2026-02-11 15:30:35 +08:00
jialin e66de732ac fix: copy button do not work 2026-02-11 15:30:35 +08:00
jialin 2ba94f7524 fix: miss model file path in cloning 2026-02-11 11:05:43 +08:00
jialin 3f90642726 chore: request result in list 2026-02-10 17:29:57 +08:00
jialin 35ae7b9643 fix(style): adjust ui 2026-02-10 17:29:57 +08:00
jialin 15d635322b fix: target model text overflow 2026-02-10 17:29:57 +08:00
jialin c3d5234710 fix: new added model item is cleared 2026-02-10 17:29:57 +08:00
jialin 9b498d10d5 fix: dashboard model data format 2026-02-10 11:33:24 +08:00
jialin 9418e5b635 fix: get models in cloning 2026-02-10 11:33:24 +08:00
jialin 8779b79bbf fix: get models in cloning 2026-02-10 10:25:02 +08:00
jialin ba11689029 feat: filter form for table 2026-02-10 10:25:02 +08:00
jialin 90e212a1b2 fix: reset default columns do not work 2026-02-09 18:02:30 +08:00
jialin 198a52e230 chore: add runtime in register k8s command 2026-02-09 15:58:29 +08:00
jialin e7890dda3d chore: show fallback change warning 2026-02-09 13:26:44 +08:00
jialin 83086c46e6 fix: target options miss deployment models 2026-02-09 11:51:26 +08:00
jialin 1314123ad7 fix: api_key format 2026-02-09 11:51:26 +08:00
jialin cb13873098 fix: deduplicate models before submitting 2026-02-09 11:51:26 +08:00
jialin fba430999d fix(style): error message toast 2026-02-09 09:35:42 +08:00
jialin 293c53d8dd chore: keep error message visiable on hover 2026-02-08 19:44:43 +08:00
jialin 33ce334bd7 fix: verify same model selected 2026-02-08 19:44:43 +08:00
jialin 379eeedde2 fix: deduplicate in select provider models and target models 2026-02-08 17:20:05 +08:00
jialin ec6f5d1ad3 chore: add copy button for run command 2026-02-08 10:27:49 +08:00
jialin f35ba8f8e5 fix: success message in creation cluster 2026-02-08 10:27:49 +08:00
jialin 21ffd2a564 fix: env params incorrect after switching between vendors 2026-02-07 16:51:09 +08:00
jialin 3c5b095510 fix: benchmark enviroment table 2026-02-06 20:59:47 +08:00
jialin 096227e3da fix: benchmark tooltip issues 2026-02-06 18:34:20 +08:00
jialin 4a582ec8b1 fix: benchmark tooltip 2026-02-06 18:34:20 +08:00
jialin 4132494a49 chore: provider masked api-key 2026-02-06 17:33:06 +08:00
jialin 1bd31d2936 fix: stt languages sorting 2026-02-06 17:33:06 +08:00
jialin 18ffeb82a2 fix: benchmark form data error in editing 2026-02-06 15:36:24 +08:00
jialin da985871cc fix: benchmark issues 2026-02-06 14:27:05 +08:00
jialin 4ff5b3e05a chore: grafana entry 2026-02-06 14:27:05 +08:00
jialin 7f3d6bb55f fix: ui issues 2026-02-06 11:13:49 +08:00
jialin d54722609c fix: remove duplicate selected models 2026-02-06 11:13:49 +08:00
jialin 2765d5edeb chore: tts, stt meta 2026-02-05 20:35:07 +08:00
jialin a1a7979fb3 fix: update open playground btn 2026-02-05 11:55:05 +08:00
jialin 4e8b5e26ae feat: monitor button 2026-02-04 20:14:25 +08:00
jialin 47596fdb1a fix: copy button do not work 2026-02-04 20:14:25 +08:00
jialin 332521a7f3 feat: grafana link 2026-02-04 20:14:25 +08:00
jialin 8690de00a9 feat: add grafana link 2026-02-04 20:14:25 +08:00
jialin 7fd2b43704 fix: refresh enable backend state 2026-02-04 14:58:48 +08:00
jialin 05c05419fc feat: duplicate deployment 2026-02-04 14:58:48 +08:00
jialin 5ad9ac277c style: benchmark progress 2026-02-03 20:50:40 +08:00
jialin 42f24245b5 fix: maas provider custom config 2026-02-03 20:26:00 +08:00
jialin 7548836b67 fix: reranker for sglang 2026-02-03 19:12:34 +08:00
jialin a2c33affcd fix: file import error 2026-02-03 18:27:49 +08:00
jialin 11039a5c82 fix: enable_model_route 2026-02-03 18:21:08 +08:00
jialin 46969702a8 fix: open model in playground 2026-02-03 18:21:08 +08:00
jialin 134827a0f7 chore: resort menu 2026-02-03 18:21:08 +08:00
jialin f0390682ce chore: rebase main 2026-02-03 18:21:08 +08:00
jialin 2a6846d2c0 chore: remove invalid file 2026-02-03 18:21:08 +08:00
jialin dc8b3b9210 fix: routes locales 2026-02-03 18:21:08 +08:00
jialin dcda9be50b style: display target model name 2026-02-03 18:21:08 +08:00
jialin 04c25ab0f7 chore: fallback selection 2026-02-03 18:21:08 +08:00
jialin 051d9421b0 chore: access, endpoints to route targets 2026-02-03 18:21:08 +08:00
jialin 6d65797b4f fix: access source error 2026-02-03 18:21:08 +08:00
jialin 497813eced fix(styles): providers access token 2026-02-03 18:21:08 +08:00
jialin 26e3a1944b chore: access form test 2026-02-03 18:21:08 +08:00
jialin e188d788b9 chore: provider form test 2026-02-03 18:21:08 +08:00
jialin d86d061f97 style: access list 2026-02-03 18:21:08 +08:00
jialin 35918d2a00 chore: access meta 2026-02-03 18:21:08 +08:00
jialin 51bab71291 style: adjust providers style 2026-02-03 18:21:08 +08:00
jialin 6fd886b27a style: metadata list styles 2026-02-03 18:21:08 +08:00
jialin 2211009cce chore: providers logo 2026-02-03 18:21:08 +08:00
jialin eb65cee280 style: fallback ui 2026-02-03 18:21:08 +08:00
jialin a3dd126931 chore: fallback checkbox 2026-02-03 18:21:08 +08:00
jialin 0b2be1e54b chore: model access control 2026-02-03 18:21:08 +08:00
jialin 337d93ff51 style: endpoint selection 2026-02-03 18:21:08 +08:00
jialin df5c2be7fa feat: metadata list 2026-02-03 18:21:08 +08:00
jialin 15cd9795d5 style: providers selection, remove fallback form 2026-02-03 18:21:08 +08:00
jialin 5fcdf4ea00 chore: access form 2026-02-03 18:21:08 +08:00
jialin e8e982559d chore: providers ux 2026-02-03 18:21:08 +08:00
jialin b2a8d27178 feat: provider form 2026-02-03 18:21:08 +08:00
jialin 679e10abd6 feat: add access list 2026-02-03 18:21:08 +08:00
jialin 34331063eb feat: provider lsit 2026-02-03 18:21:08 +08:00
jialin 2dfdd4a0d9 feat: add provider menu 2026-02-03 18:21:08 +08:00
jialin cb5413c2ce fix: backend version list 2026-02-03 16:05:43 +08:00
jialin 9e7f2261f3 fix: max token not a int number 2026-02-03 16:05:43 +08:00
jialin 5efed8f193 fix: do not set default deployment name 2026-02-03 16:05:43 +08:00
jialin 0af7e95af2 fix: do not display as group when has one 2026-02-03 15:41:16 +08:00
jialin cf3b225d3e fix: edit community backend 2026-02-03 15:41:16 +08:00
jialin 32f95f5d7d fix: revert backend selection 2026-02-03 15:41:16 +08:00
jialin 9a5a1bf555 chore: add mutiple additional volume 2026-02-02 15:58:01 +08:00
jialin b7dfb0af0b chore: export action for benchmark item 2026-02-02 15:58:01 +08:00
jialin 4a71387098 fix: do not show evalute result when no claims 2026-02-02 15:58:01 +08:00
jialin f651ab7fd9 fix: default benchmark form values 2026-02-02 14:10:46 +08:00
jialin fc599a0637 style: column setting sub title 2026-02-02 14:10:46 +08:00
jialin 9796233897 feat: benchmark detail actions 2026-02-01 22:56:36 +08:00
jialin 0849a2f114 chore: column settings 2026-02-01 20:22:25 +08:00
jialin 043218937f chore: benchmark detail locales 2026-02-01 20:22:25 +08:00
jialin 7b4d60b576 feat: add ref_text, x_vector_only_mode 2026-01-31 16:53:35 +08:00
jialin f803b910b5 fix: tts default params 2026-01-31 14:39:44 +08:00
jialin 8d660b20aa fix: miss default name in deploy 2026-01-31 14:39:44 +08:00
jialin 1e298bbbc0 fix: tts viewcode params 2026-01-31 14:06:50 +08:00
jialin 14eb54481d chore: remove advanced toggle in image 2026-01-31 14:06:50 +08:00
jialin 7a5c28228b chore: upload a ref audio 2026-01-31 14:06:50 +08:00
jialin f278716b7e fix: hidden tokens input 2026-01-30 23:14:23 +08:00
jialin b3e186fea4 feat: add tts params 2026-01-30 22:58:11 +08:00
jialinandLawrence Li f0cdefad90 chore: update icons 2026-01-30 20:48:55 +08:00
jialinandLawrence Li 507b0e44d5 fix: init envs 2026-01-30 20:48:55 +08:00
jialinandLawrence Li 56985be26b chore: default_env, env 2026-01-30 20:48:55 +08:00
jialinandLawrence Li d3a0c6a330 style: arrow bivider 2026-01-30 20:48:55 +08:00
jialinandLawrence Li 0d5cd28d38 feat: community backends marketplace 2026-01-30 20:48:55 +08:00
jialinandLawrence Li b6bd9cd7dd feat: community backends page 2026-01-30 20:48:55 +08:00
jialinandLawrence Li 2dab5093dc fix: parse yaml error 2026-01-30 20:48:55 +08:00
jialinandLawrence Li 4a4a02eb0d chore: update env vars from backend version 2026-01-30 20:48:55 +08:00
jialinandLawrence Li 4000aacb2c fix: backend selection 2026-01-30 20:48:55 +08:00
jialinandLawrence Li a2be7f6b36 chore: backend api 2026-01-30 20:48:55 +08:00
jialin af6f90c228 fix: benchmark state 2026-01-30 18:48:55 +08:00
jialin 3df2d23bf5 fix: benchmark detail styles 2026-01-30 18:48:55 +08:00
jialin d173e2d49b fix: details layout 2026-01-30 18:48:55 +08:00
jialin 5747cae87a style: detail layout 2026-01-30 18:48:55 +08:00
jialin 667751dc5f refactor: env detail 2026-01-30 18:48:55 +08:00
jialin 577996f507 refactor: summary 2026-01-30 18:48:55 +08:00
jialin 22e42e279c chore: logs 2026-01-30 18:48:55 +08:00
jialin 6c42b87c57 chore: update creation form 2026-01-30 18:48:55 +08:00
jialin 3fe63f836f chore: remove labels 2026-01-30 18:48:55 +08:00
jialin 1a2e82f079 chore: profile config 2026-01-30 18:48:55 +08:00
jialin 8f2eea70f6 chore: detail api 2026-01-30 18:48:55 +08:00
jialin 358df925e7 chore: list actions 2026-01-30 18:48:55 +08:00
jialin 9ab8f233a2 feat: benchmark detail page 2026-01-30 18:48:55 +08:00
jialin fb0e45ebed feat: benchmark form 2026-01-30 18:48:55 +08:00
jialin 37b814b70a feat: benchmark list 2026-01-30 18:48:55 +08:00
jialin 8b282afb03 fix: vllm run command 2026-01-22 17:39:01 +08:00
jialin ec9a4b2607 fix: duplicate watch created 2026-01-20 14:51:45 +08:00
jialin d5f3158638 fix: recreate watch request after cluster changed 2026-01-20 13:40:15 +08:00
jialin eb5e344b41 style: gpu vendor logo 2026-01-20 10:36:38 +08:00
jialin 9d13b27c9e fix: add worker message trigger 2026-01-20 10:36:38 +08:00
jialin b4f69a4e2e perf: cancel the request when leaving page 2026-01-16 16:53:38 +08:00
jialin 3e359a69c7 fix: set loadingWatch state when the loading begins 2026-01-16 11:37:47 +08:00
jialin 9de4054851 style: t-head logo 2026-01-15 19:54:20 +08:00
jialin 9676e63b5e feat: add t-head 2026-01-15 19:54:20 +08:00
jialin 337cb67cd9 fix: fetch list axios token incorrect 2026-01-15 17:48:45 +08:00
jialin fe79258766 fix: remove updateManually on model files 2026-01-15 16:43:44 +08:00
jialin 0a9cc1e17a fix: cache current list query params 2026-01-15 16:20:05 +08:00
jialin 6445061836 fix: page changing do not trigger watch 2026-01-15 15:07:55 +08:00
jialin 19df710a0d fix(style): autocomplete width out of range 2026-01-15 11:17:05 +08:00
jialin 0d8333eac6 style: textarea max rows 2026-01-15 11:17:05 +08:00
jialin b1cb4bbe32 fix: minimatch error 2026-01-15 09:28:19 +08:00
jialin 11b9430b15 fix: worker list update by watch 2026-01-14 20:12:39 +08:00
jialin 1230c3bd28 fix: worker list update by watch 2026-01-14 19:58:09 +08:00
jialin 2ee645b1ee fix: too many requests after query change 2026-01-14 18:02:08 +08:00
jialin 84ce308d9d fix: hint input width 2026-01-14 18:02:08 +08:00
jialin be631d021e feat: get initial password command 2026-01-14 17:19:43 +08:00
jialin a37458fd9e fix: update worker by fetchData 2026-01-14 16:01:47 +08:00
jialin 095b9478cc fix: form submit on video 2026-01-14 16:01:47 +08:00
jialin 94fec52329 chore: scrollable tabs 2026-01-14 16:01:47 +08:00
jialin fc4d71139a style: playground right side 2026-01-14 16:01:47 +08:00
jialin c813344c7c fix: the max embedding value exceeds the limit. 2026-01-13 20:57:50 +08:00
jialin f0bfbfe693 fix: re-create watch request after filtering 2026-01-13 18:43:11 +08:00
jialin 741cf07f2e fix(style): model file list text overflow 2026-01-13 18:43:11 +08:00
jialin 5ff26e1ce8 chore: video test code 2026-01-13 18:43:11 +08:00
jialin 342d977fe4 fix: -custom error message on creating backend 2026-01-13 18:43:11 +08:00
niu_heandjialin 9c1011fbd8 Add JSX as a global variable in ESLint config 2026-01-13 17:22:03 +08:00
jialin daaf77a89f fix: do not fixed node version in package.json 2026-01-13 09:29:51 +08:00
jialin 420600510d fix(style): remove dot symbol when no size 2026-01-12 20:42:05 +08:00
jialin 0ae9a7f42f fix: gpuindex sort 2026-01-12 20:36:38 +08:00
jialin a1cddfa18b chore: hide cluster detail 2026-01-12 20:30:24 +08:00
jialin 89fe8e68f4 feat: playground video 2026-01-12 20:30:24 +08:00
jialin cd3b0607a5 style: modal drawer blur 2026-01-12 20:30:24 +08:00
jialin 0cde6f7dbc chore: add models and gpus in cluster detail page 2026-01-12 20:30:24 +08:00
jialin 42943a33fe chore: display allocated vram on instance 2026-01-12 14:52:59 +08:00
jialin fc76822bdf fix: catalog size 2026-01-12 12:24:34 +08:00
jialin 05ad296b43 chore: cluster system load service 2026-01-12 12:24:34 +08:00
jialin 2e5b075d1b fix: header bg color 2026-01-12 12:24:34 +08:00
EVGENY Mandjialin f47348106e Update backends.ts 2026-01-10 17:14:17 +08:00
jialin f351447f09 chore: remove editor static files 2026-01-09 21:13:41 +08:00
jialin 10b2a8b4f9 fix: editor incompatibility with firefox79 2026-01-09 20:51:48 +08:00
jialin afcd3e5693 feat: add cluster detail 2026-01-09 20:51:48 +08:00
jialin 7b5ce83cbd fix: add worker default selection is incorrect 2026-01-08 11:01:06 +08:00
jialin 0cff804cd7 fix: add worker title 2026-01-08 09:26:55 +08:00
jialin f4e6bf7fd5 fix: gpuindexs sort 2026-01-08 09:26:55 +08:00
jialin ba4f277863 fix: add worker ux when only DO cluster 2026-01-08 09:26:55 +08:00
jialin d35bd16543 fix: cluster pending status 2026-01-08 09:26:55 +08:00
jialin 065841530d fix: slider marker label 2026-01-07 15:55:26 +08:00
jialin 28a73d2a6e chore: use drawer for creation 2026-01-07 15:55:26 +08:00
jialin bbf09c2ea9 style: command viewer scroller 2026-01-07 15:55:26 +08:00
jialin 8f9fae9210 style: use drawer for adding worker 2026-01-06 17:21:32 +08:00
jialin 0eba1da6c4 style: cluster creation steps 2026-01-06 17:21:32 +08:00
jialin 0ba8300959 fix: no clusters tips in adding worker modal 2026-01-06 17:21:32 +08:00
jialin f8ae7680ad fix: updating model name should show the recreation message 2026-01-06 17:21:32 +08:00
jialin d51f00d35d style: cluster creation modal 2026-01-06 17:21:32 +08:00
jialin 0f7a475ec9 feat: add context length 2026-01-06 17:21:32 +08:00
jialin d8b3331648 style: slider handle color 2026-01-06 17:21:32 +08:00
jialin 2816fedc36 refactor: catalog fetch data 2026-01-06 17:21:32 +08:00
jialin 17de9d98f4 chore(deps): upgrade antd to v6 2026-01-06 17:21:32 +08:00
jialin b2f5eb8850 style: user usage rank 2026-01-06 17:21:32 +08:00
jialin c821a2e463 refactor: create cluster ux 2026-01-06 17:21:32 +08:00
jialin 66e8f83395 fix: did not cache workers and clusters in model files 2025-12-31 10:23:15 +08:00
jialin 41ebceca8f chore: static iconfont files 2025-12-29 15:40:36 +08:00
jialin 632685672c fix: wheel event passive 2025-12-29 15:28:40 +08:00
jialin bd2e4bb633 docs: hygon notes 2025-12-29 09:36:48 +08:00
jialin 835633d44b fix: help menu item clickable area 2025-12-26 18:18:32 +08:00
EVGENY Mandjialin 75773e6b00 Update models.ts 2025-12-26 18:16:33 +08:00
EVGENY Mandjialin a21b9b5244 Update users.ts 2025-12-26 18:16:02 +08:00
EVGENY Mandjialin 38bf76dc14 Update common.ts 2025-12-26 18:15:29 +08:00
EVGENY Mandjialin 9461341104 Update clusters.ts 2025-12-26 18:15:05 +08:00
jialin 5b5b2c6364 fix: chat compare switch model meta 2025-12-26 17:29:36 +08:00
jialin a006263e51 fix: add worker to default cluster 2025-12-26 12:08:30 +08:00
jialin febdd38f7c fix: set submitloading as false in catch 2025-12-26 09:48:10 +08:00
jialin 1b4d335b09 fix: store hideModel value in global session 2025-12-25 20:36:48 +08:00
jialin 725409a576 fix: image seed do no clear 2025-12-25 17:57:11 +08:00
jialin 9b25cc51e4 style: user rank chart 2025-12-25 17:57:11 +08:00
jialin 9dcdb6b6e7 fix: reset userSettings first login 2025-12-25 13:14:59 +08:00
jialin 73b987358f fix(style): cluster options 2025-12-24 20:52:48 +08:00
jialin 84c2bf130c style: cluster selector 2025-12-24 20:37:20 +08:00
jialin b25189feea fix: cancel sorting 2025-12-24 15:40:19 +08:00
jialin a9b58a5564 fix: cluster filter do not work in dashboard 2025-12-24 12:20:56 +08:00
jialin 530b20c633 chore: add resource modal button text 2025-12-24 10:53:53 +08:00
jialin fa0aeac10b fix: remove default sorting status on UI 2025-12-23 20:54:16 +08:00
jialin 1b661bb8cd feat: set default cluster 2025-12-23 20:54:16 +08:00
jialin 530e8f7537 fix: replicas, ready_replicas sorting 2025-12-23 18:35:33 +08:00
jialin 9e019a98f6 fix: click create hide modal 2025-12-23 10:51:58 +08:00
jialin 10c6cf9f7e fix: init image seed 2025-12-23 10:51:58 +08:00
jialin 480b238e44 fix: expand all model clear instances cache 2025-12-23 10:51:58 +08:00
jialin 32bdbc693a fix: onTableChange only handles sorting 2025-12-22 19:41:52 +08:00
jialin ab146b6b6b fix: allow to enter seed 2025-12-22 18:11:46 +08:00
jialin 763929eafc fix: instance backend data ui compatability with old data 2025-12-22 18:11:46 +08:00
jialin 711b3fee98 fix: user guidance when no resource 2025-12-22 18:11:46 +08:00
jialin 0d0592eee9 fix: sorter tooltip 2025-12-22 16:41:44 +08:00
jialin cc7948ba45 fix: update Server as GPUStack Server 2025-12-22 16:19:47 +08:00
jialin 7e25b64689 fix: remove instance from cache after deleting 2025-12-22 16:19:47 +08:00
Yuxing Dengandjialin d844cdadb5 fix: update advertise address title and description 2025-12-22 15:14:29 +08:00
jialin e3b3f51e87 fix: ignore the sort_by when no data 2025-12-22 11:57:57 +08:00
jialin 45efda7f1d fix: single sorted field, remove token 2025-12-22 10:10:35 +08:00
jialin db45c861e4 feat: models filter by state 2025-12-21 21:37:05 +08:00
jialin 42f8e6a6d9 chore: set col order 2025-12-21 21:37:05 +08:00
jialin 23a761226a feat: table list sorter 2025-12-21 21:37:05 +08:00
jialin 6738dfe0d3 fix: anyway submit disabled when no catalog specs 2025-12-19 20:33:25 +08:00
jialin 6e16b2eb0c fix: submit pool data from a validate failed form 2025-12-19 20:33:25 +08:00
jialin 707eb15465 fix: update command of adding worker 2025-12-19 20:33:25 +08:00
jialin 8008099e71 fix: image default seed 2025-12-19 20:33:25 +08:00
jialin 79ccb96c95 fix: edit worker_config 2025-12-19 16:44:52 +08:00
jialin bd76934e40 fix: delete worker pool 2025-12-19 15:19:27 +08:00
jialin bb793a41fc fix: entrypoint do not display in edit 2025-12-19 15:00:10 +08:00
jialin ad048a92ed feat: backend entrypoint 2025-12-19 14:40:20 +08:00
jialin 14d944ad2f style: cluster advanced scroller 2025-12-18 20:03:00 +08:00
jialin e1b8b5696c fix: update instance backend field 2025-12-18 17:29:07 +08:00
jialin 78368e9979 fix: cluster worker config issues 2025-12-18 17:29:07 +08:00
jialin e83bff6923 chore: worker ip 2025-12-18 14:06:32 +08:00
jialin e6c12d81ea fix: edit worker pool miss data 2025-12-18 14:06:32 +08:00
jialin 3a73d0c1b2 style: worker added info status 2025-12-18 12:19:31 +08:00
jialin b524587a9a fix: add worker button do not work 2025-12-18 10:56:45 +08:00
jialin e4bd753355 style: no resource modal 2025-12-17 19:58:28 +08:00
jialin 30536cb04a fix: remove advanced agrs in image 2025-12-17 16:15:34 +08:00
jialin da1efa9270 fix: password length 64 2025-12-17 16:15:34 +08:00
jialin bd6f4b3f76 fix: add worker, create cluster 2025-12-17 14:59:07 +08:00
jialin 5e48d75ead fix: add worker message 2025-12-17 14:59:07 +08:00
jialin bd46fcdc75 fix: container name in add worker 2025-12-17 14:59:07 +08:00
jialin 6968f9fa6b feat: worker_config 2025-12-16 18:43:28 +08:00
jialin 5225fd328d fix: backend framework options 2025-12-16 11:11:24 +08:00
jialin fa42474612 chore: worker added message 2025-12-15 15:13:57 +08:00
jialin d2eda78af0 fix: add worker command container_name 2025-12-15 10:18:16 +08:00
jialin 7a0ee6aac4 style: column wrapper srollable style 2025-12-13 19:47:48 +08:00
jialin b327eedb45 fix: logout error 2025-12-12 17:26:06 +08:00
jialin a68e3ff9da fix: no spec list for catalog 2025-12-12 17:22:28 +08:00
jialin 0500dd2e35 fix: query catalog spec, default_version check 2025-12-12 17:08:30 +08:00
jialin cb43131ccb fix: add worker command 2025-12-12 11:14:57 +08:00
jialin 883e0ab115 feat: get initial password 2025-12-12 11:14:57 +08:00
jialin b189160888 fix: docs for gpu link 404 2025-12-11 18:14:25 +08:00
jialin 3dbb0de683 feat: add resource for first login 2025-12-11 17:50:39 +08:00
jialin b38bc8a207 fix: table sorter 2025-12-11 13:33:41 +08:00
jialin 3328828da6 refactor: card list resize container 2025-12-11 13:33:41 +08:00
jialin 7fdabd90a5 fix: update add worker command 2025-12-10 15:50:53 +08:00
jialin d8452e98f5 style: drawer styles 2025-12-10 15:50:53 +08:00
jialin dda2213593 style: workers page no page container 2025-12-10 15:50:53 +08:00
jialin 04f995b80c style: resize terminal height 2025-12-10 15:50:53 +08:00
jialin a08f1e2512 chore: rename ground-left as ground-llm 2025-12-10 15:50:53 +08:00
jialin af4849d6cc style: terminal panel 2025-12-10 15:50:53 +08:00
jialin 087675889f feat: model cache volume mount, clear gpu selector 2025-12-09 19:07:40 +08:00
jialin daa10617c0 chore: prefetch chunk file 2025-12-05 13:31:56 +08:00
jialin c3b5c13cc5 fix: show info when adding worker error 2025-12-05 11:45:44 +08:00
jialin 1dd83645bd fix: reset first login flag after changing password 2025-12-05 11:26:32 +08:00
jialin 2df7c17bc1 chore: remove experimental from hygon 2025-12-04 22:35:15 +08:00
jialin a274349ace chore: upgrade info 2025-12-04 16:43:33 +08:00
jialin 1c699fe307 chore: tidy code 2025-12-04 16:43:33 +08:00
jialin f0a3e84e4f fix: set default os image 2025-12-04 10:48:34 +08:00
jialin f87989d32e fix: clear os_image when it's not in new image list 2025-12-04 10:12:19 +08:00
jialin 7355be9e3a fix: init cluster id when deploy model 2025-12-03 19:18:07 +08:00
jialin d8f1e95e1a fix: use image label in inputbox 2025-12-03 16:00:59 +08:00
jialin 59eace702b fix: add worker init steps failed 2025-12-03 12:32:04 +08:00
jialin 8a24ba0252 fix: cluster option disabled 2025-12-03 11:50:35 +08:00
jialin 03999a9d2c chore: os image filter 2025-12-03 11:38:16 +08:00
jialin f335cb1775 fix: click icon do not worker on upload 2025-12-02 17:24:14 +08:00
jialin b9c034469b fix: input img url fall back image 2025-12-02 15:58:17 +08:00
jialin ce3a82ddda fix: edit message add image 2025-12-02 14:00:58 +08:00
jialin 5cbb38922c feat: add image from url 2025-12-01 19:01:33 +08:00
jialin 14f0afec08 chore: allow space in backend parameters 2025-12-01 10:06:00 +08:00
jialin 769cc09906 fix: logs are not fully loaded 2025-11-30 20:33:16 +08:00
jialin 306daf7591 chore: amd note for add worker 2025-11-27 19:35:04 +08:00
jialin d1c1132e6e style: button for empty 2025-11-27 15:53:23 +08:00
jialin 962df859f1 chore: get started for add cluster 2025-11-27 11:35:45 +08:00
jialin 97601280d1 fix: model download progress text overflow 2025-11-26 10:28:40 +08:00
jialin ede42e99de fix: do not reset the backend after selecting a gguf file 2025-11-25 17:20:09 +08:00
jialin 47cae0134c feat: display deprecated backend versions group 2025-11-25 16:04:27 +08:00
jialin 33defab7df fix: gpus link 2025-11-25 11:34:11 +08:00
EVGENY Mandjialin 6b402e944b Update Russian translations in models.ts 2025-11-24 09:38:32 +08:00
EVGENY Mandjialin f8a6f4c5e5 Translate cluster messages to Russian 2025-11-24 09:38:14 +08:00
EVGENY Mandjialin adb999d3a9 Update dashboard.ts 2025-11-24 09:37:42 +08:00
jialin f4ea23dd14 fix: set default vllm backend for gguf 2025-11-23 21:08:28 +08:00
jialin 5bd0020e49 fix: check vllm backend for gguf model 2025-11-23 19:57:41 +08:00
jialin 782e81568d fix: check the image and run_command valid when select custom backend 2025-11-23 18:51:01 +08:00
jialin 2ecf83ddae fix: warning message for gguf model 2025-11-23 17:27:42 +08:00
jialin de0982d590 fix: compatibility message for gguf 2025-11-23 15:10:46 +08:00
jialin e5755a2eec chore: adjust ui statements 2025-11-22 13:06:05 +08:00
EVGENY Mandjialin e755c34ab5 Translate health check command tips to Russian 2025-11-22 12:19:10 +08:00
EVGENY Mandjialin 85e4f1a5ed Translate common phrases to Russian 2025-11-22 12:18:40 +08:00
EVGENY Mandjialin 3eb403a2c4 Translate user status messages to Russian 2025-11-22 12:18:15 +08:00
jialin 79442a6a6c fix: apikey form value diff 2025-11-21 20:41:20 +08:00
jialin f49001b742 chore: access setting notes 2025-11-21 20:10:21 +08:00
jialin e80ecfac8d style: table header text-overflow 2025-11-21 16:56:23 +08:00
jialin ff67fba2c9 chore: reset the primary color after logout 2025-11-21 16:56:23 +08:00
jialin 3f63831488 fix: modelscope api incorrect 2025-11-21 13:43:39 +08:00
jialin 19babbc73d style: adjust some styles 2025-11-21 12:16:49 +08:00
jialin 26a4d5474d fix(style): gpu_selector position 2025-11-20 20:49:19 +08:00
jialin af3e03230a fix: rerank api prefix 2025-11-20 17:43:13 +08:00
jialin 551f04011a chore: v1 to v2 2025-11-20 17:31:15 +08:00
jialin ea39a45f31 fix: sglang enable across worker 2025-11-20 15:59:05 +08:00
jialin ebff5695ff chore: consistent UI statement 2025-11-20 14:17:08 +08:00
jialin 9b63c1a515 style: example code title 2025-11-20 12:46:06 +08:00
jialin de882dc62e fix: api info example 2025-11-20 11:47:09 +08:00
jialin 8f9562d6a4 style: adjust some ui statements 2025-11-20 11:47:09 +08:00
jialin 5d383ec39b fix: add worker token do not update 2025-11-20 10:31:27 +08:00
jialin 2687fb187d style: adjust ram prcision 2025-11-19 18:47:55 +08:00
jialin ca43c0b4b2 fix(style): fix some styles 2025-11-19 11:46:18 +08:00
jialin 71bbf59467 style: deploy modal message cover the content 2025-11-19 11:46:18 +08:00
jialin 18f861f771 style: framework options 2025-11-18 20:01:54 +08:00
jialin e85d59dfb0 style: adjust some styles 2025-11-18 13:30:58 +08:00
jialin 78c8b60121 fix: re-request catalog specs after changing cluster 2025-11-18 11:28:37 +08:00
jialin e22b5ed516 chore: small fixes and optimizations 2025-11-17 20:15:26 +08:00
jialin 906f59a566 fix: model source error in catalog 2025-11-17 15:24:22 +08:00
jialin d1c3edfd9b fix: remark field option 2025-11-17 15:24:22 +08:00
jialin e8a0f33bde fix: extra newline character 2025-11-16 11:54:27 +08:00
Christianandjialin 825687f2a8 Fix typo in example-code
Remove obsolet bracket in python-example-code
2025-11-16 09:12:59 +08:00
jialin 2852648a65 fix: run command issue 2025-11-16 09:09:04 +08:00
jialin 0f3f31ef45 refactor: add worker 2025-11-15 22:37:44 +08:00
jialin 864cf76c07 feat: worker maintenance 2025-11-13 21:00:35 +08:00
jialin 98e6c71bf8 fix: model list flicker after page active 2025-11-13 17:25:28 +08:00
jialin aee9566bbb fix: yaml editor do not update when upload same file 2025-11-13 16:53:11 +08:00
jialin b61c0d6dee fix: api access info 2025-11-13 12:22:16 +08:00
jialin f963b3a000 chore: config base url 2025-11-13 12:22:16 +08:00
jialin 03963b736a chore: create, edit image handler 2025-11-12 20:47:34 +08:00
jialin a34c375e2d fix: image response handler 2025-11-12 19:55:31 +08:00
jialin e8eea9573e fix: set response_format as b64_json 2025-11-12 19:18:10 +08:00
jialin b7656d65e7 style: large modal height responsive 2025-11-12 19:18:10 +08:00
jialin d1fa6dd03c fix: pool's label editable 2025-11-12 16:37:01 +08:00
jialin 2045bfaf78 fix: display admin and inactive when view 2025-11-12 16:11:17 +08:00
jialin 653ada5f0f fix: do not evaluate from model files 2025-11-12 15:10:00 +08:00
jialin cbc000d35a fix: playground formref is invalid 2025-11-12 14:57:39 +08:00
jialin 11a676be83 fix: download file error 2025-11-12 11:01:13 +08:00
jialin 7eedea8035 chore: generic_prox ux 2025-11-11 20:06:25 +08:00
EVGENY Mandjialin 2d4ddea915 Update menu.ts 2025-11-11 18:47:08 +08:00
EVGENY Mandjialin 76d7a50fac Update models.ts 2025-11-11 18:46:44 +08:00
jialin 84187eedc4 fix: access control, voices options 2025-11-11 15:47:32 +08:00
jialin ee5c30934b feat: generic_proxy 2025-11-11 15:47:32 +08:00
jialin b4b25d4300 fix: default enter page for user 2025-11-10 20:40:15 +08:00
jialin 9eb1dba4a1 fix: calc scrollheight dynamically for tabs change 2025-11-10 20:40:15 +08:00
jialin 285e274818 fix: display image menu 2025-11-10 10:07:25 +08:00
jialin 0077d109e7 fix: remove page_size 2025-11-07 17:31:39 +08:00
jialin 9cd508a92a fix: draft model change 2025-11-07 16:54:33 +08:00
jialin 9ffd4def64 fix: failed field auto scroll in view 2025-11-07 16:54:33 +08:00
jialin fdb6ac7575 fix: set page to -1 for all data 2025-11-07 16:54:33 +08:00
jialin 64e2cfa35a fix: auto expand the fields group 2025-11-07 11:56:12 +08:00
jialin 39efca0d4c fix: add loading on download button 2025-11-06 19:38:01 +08:00
jialin cd2942405a feat: cluster_count on dashboard 2025-11-06 19:38:01 +08:00
jialin fadff34f5f chore: update description for adding worker 2025-11-06 19:38:01 +08:00
jialin 7334bcdf83 fix: do not paste multiple lines 2025-11-06 15:37:42 +08:00
jialin e1e38f0404 fix: chat stream data too long 2025-11-06 15:37:42 +08:00
EVGENY Mandjialin 38cc179068 Update backends.ts 2025-11-06 10:25:56 +08:00
EVGENY Mandjialin 5147d0d004 Update clusters.ts 2025-11-06 10:24:55 +08:00
EVGENY Mandjialin c237c9dbde Update models.ts 2025-11-06 10:24:15 +08:00
EVGENY Mandjialin 34bd2c3031 Update resources.ts 2025-11-06 10:23:48 +08:00
jialin 6173f3b459 fix: tts request content-type 2025-11-05 17:09:16 +08:00
jialin 333b430b97 fix(style): do not display draft model after done 2025-11-05 10:02:25 +08:00
jialin 4c22d08da5 refactor: page layout 2025-11-05 10:02:25 +08:00
jialin 219f9871a7 feat: add constants config 2025-11-05 10:02:25 +08:00
jialin 80527d5985 fix: distributed_inference always display 2025-11-04 18:57:57 +08:00
jialin 7e5edd6387 fix: backend option format 2025-11-04 18:07:14 +08:00
jialin 4ca6a221e4 fix: do not show draft model downloading progress 2025-11-04 17:19:20 +08:00
jialin e5733a7f6e chore: add worker notes 2025-11-04 17:19:20 +08:00
jialin 23b7936924 fix: custom backend and versions ux 2025-11-04 13:37:53 +08:00
jialin 9be465a8cf chore: update add worker command 2025-11-04 13:37:53 +08:00
jialin 4bbae673dc fix: draft model local path do not search 2025-11-03 14:22:52 +08:00
jialin e66ee5d3f1 fix: catalog kv cache 2025-11-03 11:00:42 +08:00
jialin 20872100d1 fix: kv cache default value 2025-11-03 10:38:41 +08:00
jialin 06f33ded10 fix: algorithm options do not display 2025-11-03 10:29:32 +08:00
jialin adb5cd72b9 chore: show quant in catalog form 2025-11-03 10:14:30 +08:00
jialin 303429c52c chore: clear space onblur 2025-11-03 10:14:30 +08:00
jialin 1a92cc8543 feat: search draft models from remote 2025-11-03 10:14:30 +08:00
jialin d5cc617848 fix: draft download progress should not show 2025-11-03 10:14:30 +08:00
jialin 4af71b5b52 chore: speculative_config init in updating 2025-11-03 10:14:30 +08:00
jialin 2dab89363d chore: draft model downloading 2025-11-03 10:14:30 +08:00
jialin ab9f9a9679 chore: update reference to baseline 2025-11-03 10:14:30 +08:00
jialin c5166f07f1 style: styles 2025-11-03 10:14:30 +08:00
jialin 86c2f8eda1 fix: backend change 2025-11-03 10:14:30 +08:00
jialin 57d41e79c7 fix: fake spec data 2025-11-03 10:14:30 +08:00
jialin 5cd9b8c22f fix: default spec by mode 2025-11-03 10:14:30 +08:00
jialin 56eba0d4fc fix: default spec by mode 2025-11-03 10:14:30 +08:00
jialin 7936d0063d chore: update models locales 2025-11-03 10:14:30 +08:00
jialin 3613fb3f69 feat: add speculative decoding 2025-11-03 10:14:30 +08:00
jialin 608b2e31c7 fix: schdule type gpu_selctor issue 2025-10-31 17:14:38 +08:00
jialin 2006827968 chore: update extended_kv_cache config 2025-10-31 15:03:23 +08:00
jialin f6a3497b0c fix: do not trigger evaluation replica 0 2025-10-31 13:10:52 +08:00
jialin d7ef64746c fix: custom backend version suffix 2025-10-30 19:08:45 +08:00
jialin b733b3615d fix: remove input box for gpus_per_replica 2025-10-30 16:38:55 +08:00
jialin e9fa3e3aa3 fix: gpus_per_replica appears null 2025-10-30 10:52:48 +08:00
jialin b77f796661 feat: add sglang parameters 2025-10-29 18:56:41 +08:00
jialin c077db1129 fix: replicas trigger compatibility 2025-10-29 17:24:26 +08:00
jialin 801c88a3e2 chore: update --token 2025-10-29 12:11:25 +08:00
jialin 646d235c65 fix: adjust gpus_per_replicas ux 2025-10-28 17:21:22 +08:00
jialin a86bed294e fix: gpu selector issues 2025-10-28 11:17:29 +08:00
jialin 697f1f9c25 fix: built-in backend versions endwith -custom 2025-10-27 16:09:09 +08:00
jialin 61065ee0b7 chore: scheduling group 2025-10-27 14:13:47 +08:00
jialin df65d3e2f6 fix: kv cache support in builtin backend 2025-10-27 14:13:47 +08:00
jialin 6969cb0b9c fix: expand model after edting replicas 2025-10-27 14:13:47 +08:00
jialin 7e81871118 fix: miss cluster id in evaluation 2025-10-24 17:55:54 +08:00
jialin ba80ade643 fix: my models status 2025-10-24 16:11:12 +08:00
jialin 0401cf5fb9 fix: no backend options from model files 2025-10-24 10:18:22 +08:00
jialin 53b431f100 fix(style): add backend 2025-10-23 18:41:16 +08:00
jialin 1a082529c6 fix: skip error handler in root path 2025-10-23 17:09:30 +08:00
jialin bf57290197 fix: admin can not delete own 2025-10-23 17:09:30 +08:00
jialin a815e71bfe chore: show existing when add file 2025-10-23 11:52:49 +08:00
jialin cc0580301e fix: do not trigger evaluation after switching model 2025-10-22 14:28:18 +08:00
jialin 5853bd1eeb fix: builtin backend do not submit default_version 2025-10-22 14:28:18 +08:00
jialin ab93c53092 chore: default cluster by state 2025-10-22 12:13:01 +08:00
jialin 818c4fc9a2 style: form tabs header gap 2025-10-22 10:21:27 +08:00
jialin fc7350b7e2 style: scroll to field 2025-10-21 19:59:49 +08:00
jialin 1e4018350f chore: worker selector 2025-10-21 15:59:48 +08:00
jialin f017d609fb fix: skip user api error 2025-10-21 13:26:06 +08:00
jialin ccb6e72057 fix: textarea scroll bar, deactive count message 2025-10-21 13:24:21 +08:00
EVGENY Mandjialin 32ad9525a6 Update apikeys.ts 2025-10-21 09:30:25 +08:00
EVGENY Mandjialin afedd4337b Update backends.ts 2025-10-21 09:30:06 +08:00
EVGENY Mandjialin 1f7acc7cf6 Update clusters.ts 2025-10-21 09:29:47 +08:00
EVGENY Mandjialin e6a5c19f0b Update menu.ts 2025-10-21 09:29:24 +08:00
EVGENY Mandjialin 8e07302ac3 Update models.ts 2025-10-21 09:29:04 +08:00
EVGENY Mandjialin 0238431b96 Update no-result.ts 2025-10-21 09:28:28 +08:00
jialin 3a7a4ccf30 fix: check driver command for adding worker 2025-10-20 19:11:02 +08:00
jialin 9b843151fe feat: add gpus_per_replicas 2025-10-20 14:53:33 +08:00
jialin 19e275a17a chore: update worker locale 2025-10-17 21:11:31 +08:00
jialin 49c6bb71a1 feat: identicon 2025-10-17 10:15:55 +08:00
jialin 005295ac97 style: gguf model ux 2025-10-17 10:15:55 +08:00
jialin 37a3aa75cc chore: cluster locales 2025-10-17 10:15:55 +08:00
jialin 07243b206e feat: enable kv cache 2025-10-16 18:05:30 +08:00
jialin f732f5c390 fix: cluster issues 2025-10-16 15:05:21 +08:00
jialin 1da16a04fe fix: do not set default version 2025-10-16 15:05:21 +08:00
jialin e2da7c5f96 style: ui for no data in table list 2025-10-16 11:11:39 +08:00
jialin ca9ceda2f7 fix: update backend parameters after changing backend 2025-10-15 13:30:58 +08:00
jialin 059416bb47 fix: backend edit format 2025-10-15 12:18:50 +08:00
jialin 4196351e48 fix: backend edit format 2025-10-15 12:18:50 +08:00
jialin f02b972dc0 fix(styles): my models 2025-10-14 20:09:43 +08:00
jialin 8398ac59a1 style: update model modal type 2025-10-14 20:09:43 +08:00
jialin 83403a1a1a feat: add extended_kv_cache 2025-10-14 20:09:43 +08:00
jialin 620c113fae fix(style): cluster state do not display 2025-10-14 13:09:22 +08:00
jialin 903500dcfa chore: infinite scroller 2025-10-13 19:55:08 +08:00
jialin 68d6993acd chore: remove test dir 2025-10-13 19:55:08 +08:00
jialin 2c9f5062a9 refactor: user table list 2025-10-13 19:55:08 +08:00
jialin d3f39ae06b fix: my models 2025-10-13 15:21:17 +08:00
jialin f42f159785 chore: update locales 2025-10-13 15:21:17 +08:00
jialin bb7c8e9c85 chore: model access statement 2025-10-13 15:21:17 +08:00
jialin 663b6c7b4e style: allowed models ux 2025-10-13 15:21:17 +08:00
jialin 1fa2124efd feat: add allowed models 2025-10-13 15:21:17 +08:00
jialin bcd1a339f9 feat: add model access control 2025-10-13 15:21:17 +08:00
jialin c41e5d9c55 chore: update is_built_in 2025-10-13 14:40:26 +08:00
jialin b5fa40047a chore: pluggable locale config 2025-10-13 14:40:26 +08:00
jialin caabeb065a fix: custom versin configs 2025-10-13 14:40:26 +08:00
jialin d393f9ee9e style: versions config 2025-10-13 14:40:26 +08:00
jialin eb509166ee style: backend list styles 2025-10-13 14:40:26 +08:00
jialin 0dfe77df37 chore: built in versions 2025-10-13 14:40:26 +08:00
jialin 46ecc2467b refactor: advance collapse 2025-10-13 14:40:26 +08:00
jialin a5c1b8e15f chore: test by api 2025-10-13 14:40:26 +08:00
jialin 54703c67c1 feat: yaml editor 2025-10-13 14:40:26 +08:00
jialin e863b84016 feat: add backend pages 2025-10-13 14:40:26 +08:00
jialin 1a693f70ac feat: worker terminal 2025-10-13 14:40:26 +08:00
jialin a9de153c00 chore: deploy form context provider 2025-10-13 14:40:26 +08:00
jialin 42217cf079 feat: add awq,gptq filter 2025-10-13 14:40:26 +08:00
jialin bca1e8140e feat: dynamic backends 2025-10-13 14:40:26 +08:00
jialin ee95fabc47 fix: add worker command miss image 2025-10-09 14:31:59 +08:00
jialin 67552c14af style: user activation 2025-10-09 11:07:09 +08:00
Hugo Haldiandjialin 521bf211a2 feat: add user activation control
- Add is_active field to user model
- Create SealCheckbox component with clickable container
- Add activation control to user modal
- Display user status in users table
- Add localization strings for activation features
2025-10-09 10:11:05 +08:00
EVGENY Mandjialin 8e77e19631 UI: Update Russian language menu.ts 2025-09-24 22:22:46 +08:00
EVGENY Mandjialin 8b91a0546c UI: Update Ru common.ts 2025-09-24 22:22:32 +08:00
EVGENY Mandjialin 715c71f9a5 UI: Update ru models.ts 2025-09-24 22:22:16 +08:00
EVGENY Mandjialin 1ec4a949b8 UI: Update ru playground.ts 2025-09-24 22:22:01 +08:00
EVGENY Mandjialin fc2388093d UI: RU language Update clusters.ts 2025-09-24 22:21:46 +08:00
jialin 3a9bf17d7e chore: update worker, cluster status value 2025-09-23 11:15:43 +08:00
jialin a3002ce450 chore: worker resource info adjust 2025-09-23 11:15:43 +08:00
jialin 2515e8f598 chore: update cloud providers 2025-09-22 10:36:34 +08:00
jialin dcc0db35b5 chore: update k8s check env command 2025-09-22 10:22:23 +08:00
jialin 749adb56f8 fix(style): select gpu vendor 2025-09-19 20:07:13 +08:00
jialin f542ebecb4 fix: cluster value setting, volumes setting 2025-09-19 20:00:25 +08:00
jialin b640963f65 fix(style): my models card 2025-09-19 15:46:24 +08:00
jialin 8f5990c537 fix: register cluster modal 2025-09-18 09:45:46 +08:00
jialin bf400547e1 fix: edit gpu_selector failed 2025-09-17 19:53:40 +08:00
jialin 4d9dec8511 refactor: deploy model 2025-09-17 19:53:40 +08:00
jialin 1ac63e36df feat: add baseSelect 2025-09-17 19:53:40 +08:00
jialin f36613227e fix: os image dropdown list 2025-09-17 15:17:31 +08:00
jialin d063dfd652 chore: display available clusters 2025-09-16 20:32:26 +08:00
jialin c9c9401b0b fix: provder disabled click in k8s 2025-09-16 11:26:17 +08:00
jialin 913f2f5077 fix: menu status mismatch 2025-09-16 11:26:17 +08:00
jialin 336bafd6ce chore: cluster docker provider 2025-09-16 11:26:17 +08:00
jialin 5e1a26b743 fix: close modal after editing cluster 2025-09-16 11:26:17 +08:00
jialin d9d5ca95df style: add worker ux 2025-09-16 11:26:17 +08:00
jialin f1bb305cbc fix: add pool not work 2025-09-16 11:26:17 +08:00
jialin c467280170 fix: display instance type spec 2025-09-16 11:26:17 +08:00
jialin deeee70807 feat: add watch api in cluster 2025-09-16 11:26:17 +08:00
jialin 07ade24ea1 refactor: cluster list 2025-09-16 11:26:17 +08:00
jialin 8de272239e refactor: create cluster by steps 2025-09-16 11:26:17 +08:00
jialin 6e5a7035c8 feat: cloud options 2025-09-16 11:26:17 +08:00
jialin 632f206228 fix: cluster apis 2025-09-16 11:26:17 +08:00
jialin f04f1f828f fix: add do cluster 2025-09-16 11:26:17 +08:00
jialin 4f91443957 chore: upgrade antd lib to 5.25.4 2025-09-16 11:26:17 +08:00
jialin 0c1057d554 refactor: credential table columns 2025-09-16 11:26:17 +08:00
jialin 43936e21d9 feat: instances on worker 2025-09-16 11:26:17 +08:00
jialin 949eded4ee refactor: resource table columns 2025-09-16 11:26:17 +08:00
jialin 84859d1b7c style: cluster table list 2025-09-16 11:26:17 +08:00
jialin 553ec724c2 fix: gpu selector by cluster 2025-09-16 11:26:17 +08:00
jialin 207c90e26c feat: terminal 2025-09-16 11:26:17 +08:00
jialin 64bbba7576 feat: add cluster detail page 2025-09-16 11:26:17 +08:00
jialin 62dbd18ef8 chore: create cluster ux 2025-09-16 11:26:17 +08:00
jialin 55b0a20a4a refactor: update scroll modal 2025-09-16 11:26:17 +08:00
jialin 29b74f85c5 chore: adjust deployment modal form 2025-09-16 11:26:17 +08:00
jialin ed49e03802 feat: cluster ux 2025-09-16 11:26:17 +08:00
jialin 4711c848f8 chore: user mdoels 2025-09-16 11:26:17 +08:00
jialin 33df825b73 feat: add card list component 2025-09-16 11:26:17 +08:00
jialin 89001dbb92 feat: add cluster list 2025-09-16 11:26:17 +08:00
jialin 43e1dd0b0e feat: clusters group 2025-09-16 11:26:17 +08:00
1086 changed files with 89992 additions and 46732 deletions
-1
View File
@@ -1 +0,0 @@
src/components/icon-font/iconfont/iconfont.js
-15
View File
@@ -1,15 +0,0 @@
module.exports = {
extends: require.resolve('@umijs/max/eslint'),
rules: {
'react/no-unstable-nested-components': 1,
'no-unused-vars': 'off',
'no-undef': 'error',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/class-name-casing': 'off'
},
globals: {
Global: 'readonly',
React: 'readonly'
},
ignorePatterns: ['public/static/']
};
+2 -2
View File
@@ -13,7 +13,7 @@ on:
- 'v*-dev' - 'v*-dev'
env: env:
NODE_VERSION: '21' NODE_VERSION: '22'
jobs: jobs:
deps: deps:
@@ -32,7 +32,7 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: '${{ env.NODE_VERSION }}' node-version-file: '.nvmrc'
cache: 'pnpm' cache: 'pnpm'
- name: Deps - name: Deps
run: scripts/deps run: scripts/deps
+3
View File
@@ -13,3 +13,6 @@
.swc .swc
.DS_Store .DS_Store
.idea .idea
.claude
/dist.zip
.cache
-2
View File
@@ -1,4 +1,2 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged npx lint-staged
+3 -5
View File
@@ -1,13 +1,11 @@
{ {
"*.{md,json}": ["prettier --cache --write"], "*.{md,json}": ["prettier --cache --write"],
"*.{js,jsx}": ["max lint --fix --eslint-only", "prettier --cache --write"], "*.{js,jsx}": ["max lint --fix --eslint-only", "prettier --cache --write"],
"*.{css,less}": [ "*.{css,less}": ["prettier --cache --write"],
"max lint --fix --stylelint-only", "!public/vs/**": [],
"prettier --cache --write"
],
"*.ts?(x)": [ "*.ts?(x)": [
"max lint --fix --eslint-only", "max lint --fix --eslint-only",
"prettier --cache --parser=typescript --write" "prettier --cache --parser=typescript --write"
], ],
"src/locales/**/*.ts": ["npx tsx src/locales/check.ts"] "src/locales/**/*.ts": ["node --import tsx src/locales/check.ts"]
} }
+1
View File
@@ -0,0 +1 @@
22
+265
View File
@@ -0,0 +1,265 @@
# React State and Request Patterns
These guidelines define preferred patterns for request handling, state updates, and side-effect management in React applications.
The primary goal is to keep data flow explicit, predictable, maintainable, and performant while avoiding unnecessary rerenders and effect-driven logic.
---
## 1. Avoid Effect-Driven Requests
Do not use request functions themselves as dependencies in `useEffect`.
Avoid patterns like:
```ts
useEffect(() => {
fetchData();
}, [fetchData]);
```
Requests should be triggered explicitly by user actions or lifecycle entry points.
---
## 2. Form Requests Should Be Action-Driven
For form-related requests (such as loading `Select` options):
- Fetch data when the form is opened for the first time.
- If later requests depend on user interactions, trigger them directly inside the interaction handler.
- Do not rely on `useEffect` dependency changes to trigger requests.
Recommended:
```ts
const handleOnChange = (value) => {
fetchData(value);
};
```
Avoid:
```ts
useEffect(() => {
fetchData(value);
}, [value]);
```
The action itself should control the request.
---
## 3. Update Related States Together
If a single action updates multiple related states:
- Do not synchronize them through `useEffect`
- Do not derive them indirectly through `useMemo`
Instead, update all related states directly inside the action handler.
Recommended:
```ts
const handleOnChange = (value) => {
setState1(...);
setState2(...);
buildState(...);
};
```
Avoid implicit state synchronization chains.
---
## 4. Group Strongly Related State
If multiple states are always updated together:
- Do not split them into multiple `useState` calls.
- Prefer a single state object.
Recommended:
```ts
const [state, setState] = useState({
state1: ...,
state2: ...,
state3: ...,
});
```
This reduces unnecessary rerenders and keeps state transitions predictable.
---
## 5. Prefer Explicit State Flow
Avoid chaining business logic through multiple `useEffect` hooks.
Keep:
- request execution
- state updates
- derived calculations
close to the triggering action whenever possible.
Prefer:
```ts
const handleAction = () => {
fetchData();
setTableData(...);
setSelectedRow(...);
};
```
Over:
```ts
useEffect(() => {
buildTable();
}, [data]);
useEffect(() => {
updateSelection();
}, [tableData]);
```
---
## 6. Avoid Premature Memoization
Do not use `useMemo` or `useCallback` unless there is a confirmed rendering or computation bottleneck.
Overusing memoization:
- increases complexity
- makes state flow harder to understand
- may introduce stale dependency issues
Prefer simple and explicit logic first.
Optimize only when necessary.
---
## 7. Keep Request Logic Predictable
A user interaction should clearly show:
- what request is triggered
- which states are updated
- how the UI changes
Avoid indirect update chains caused by dependency-driven effects.
The code should make the request and update flow easy to trace.
---
## 8. Prefer Action-Driven Architecture
Prefer:
- action-driven updates
- explicit handlers
- localized state transitions
Over:
- effect-driven synchronization
- cross-hook implicit updates
- reactive chains between states
The triggering action should remain the primary source of truth for UI updates.
---
# Form
Form-specific patterns that build on the rules above. The theme: keep cascading selections (pick A → derive B → write form) on a single, predictable path.
## 1. No Fallback for Derived Selection
When "pick A then auto-pick B", match by rule and return `undefined` if no match — let the corresponding form field stay empty.
Do not silently fall back to `list[0]` or another default. A fallback hides data issues and tricks the user into thinking they have a valid selection.
```ts
const findB = (key, list) =>
key ? list.find((x) => x.key === key) : undefined;
```
For form fields, prefer clearing with `undefined` over `''`. With Ant Design, `undefined` restores the placeholder; `''` is treated as a real value.
## 2. Async Race Protection
For fetches triggered by a lifecycle entry (e.g., modal open), tag each invocation with a session ref. Discard stale results if the session has rotated (the modal was closed and re-opened) by the time the response arrives.
```ts
const sessionRef = useRef(0);
useEffect(() => {
if (!open) {
sessionRef.current += 1;
return;
}
const session = ++sessionRef.current;
Promise.all([fetchA(), fetchB()]).then(([as, bs]) => {
if (sessionRef.current !== session) return;
applySelection(as.items[0], findB(as.items[0].key, bs.items));
});
}, [open]);
```
## 3. Reference Template
A typical form with two cascading selectors backed by a single shared state:
```ts
type Selection = { a?: string; b?: number };
const [selection, setSelection] = useState<Selection>({});
const sessionRef = useRef(0);
const findB = (key, list) =>
key ? list.find((x) => x.key === key) : undefined;
// Single atomic write: state + form together.
const applySelection = (a, b) => {
setSelection({ a: a.name, b: b?.id });
form.current?.setFieldsValue({
field: b?.field,
spec: { ...currentSpec, ...b?.spec }
});
};
// Trigger 1: modal opened
useEffect(() => {
if (!open) {
sessionRef.current++;
setSelection({});
return;
}
const session = ++sessionRef.current;
Promise.all([fetchA(), fetchB()]).then(([as, bs]) => {
if (sessionRef.current !== session) return;
const first = as.items[0];
applySelection(first, findB(first.key, bs.items));
});
}, [open]);
// Trigger 2: user picks A
const handleAChange = (a) => {
applySelection(a, findB(a.key, listB));
};
// Trigger 3: user picks B
const handleBChange = (b) => {
setSelection((prev) => ({ ...prev, b: b.id }));
form.current?.setFieldsValue({ ...b.fields });
};
```
+46
View File
@@ -0,0 +1,46 @@
## Create form table list
## Create a form
## StatusTag
Use `StatusTag` from `@gpustack/core-ui` for status display. Do not use `Tag` from `antd` directly.
1. Define the mapping from business status values to UI status values in the module's `config/index.ts`:
```ts
import { StatusMaps } from '@/config';
import { StatusType } from '@/config/types';
export const XxxStatusValueMap = {
Running: 'running',
Pending: 'pending',
Failed: 'failed'
};
export const XxxStatusLabelMap: Record<string, string> = {
[XxxStatusValueMap.Running]: 'Running',
[XxxStatusValueMap.Pending]: 'Pending',
[XxxStatusValueMap.Failed]: 'Failed'
};
export const status: Record<string, StatusType> = {
[XxxStatusValueMap.Running]: StatusMaps.success,
[XxxStatusValueMap.Pending]: StatusMaps.transitioning,
[XxxStatusValueMap.Failed]: StatusMaps.error
};
```
2. In table columns, pass only the UI status value and display text required by `StatusTag`:
```tsx
<StatusTag
statusValue={{
status: status[value],
text: XxxStatusLabelMap[value] || value,
message: record.state_message
}}
/>
```
`statusValue.status` must be a value mapped from `StatusMaps`, such as `success`, `transitioning`, `warning`, `error`, or `inactive`. Do not pass business status values such as `running` or `pending` directly.
+17 -15
View File
@@ -1,9 +1,10 @@
import { defineConfig } from '@umijs/max'; import { defineConfig } from '@umijs/max';
import keepAlive from './keep-alive'; import keepAlive from './keep-alive';
import { extraMfsuExclude } from './mfsu.extensions';
import { compressionPluginConfig, monacoPluginConfig } from './plugins';
import proxy from './proxy'; import proxy from './proxy';
import routes from './routes'; import routes from './routes';
import { getBranchInfo } from './utils'; import { getBranchInfo } from './utils';
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const versionInfo = getBranchInfo(); const versionInfo = getBranchInfo();
process.env.VERSION = JSON.stringify(versionInfo); process.env.VERSION = JSON.stringify(versionInfo);
@@ -19,6 +20,9 @@ export default defineConfig({
history: { history: {
type: 'hash' type: 'hash'
}, },
define: {
'process.env.ENABLE_ENTERPRISE': process.env.ENABLE_ENTERPRISE
},
analyze: { analyze: {
analyzerMode: 'server', analyzerMode: 'server',
analyzerPort: 8888, analyzerPort: 8888,
@@ -29,7 +33,7 @@ export default defineConfig({
defaultSizes: 'parsed' // stat // gzip defaultSizes: 'parsed' // stat // gzip
}, },
mfsu: { mfsu: {
exclude: ['lodash', 'ml-pca'] exclude: ['lodash', 'ml-pca', ...extraMfsuExclude]
}, },
base: process.env.npm_config_base || '/', base: process.env.npm_config_base || '/',
...(isProduction ...(isProduction
@@ -56,21 +60,15 @@ export default defineConfig({
config.output config.output
.filename(`js/[name].${t}.js`) .filename(`js/[name].${t}.js`)
.chunkFilename(`js/[name].${t}.chunk.js`); .chunkFilename(`js/[name].${t}.chunk.js`);
config compressionPluginConfig(config);
.plugin('compression-webpack-plugin') monacoPluginConfig(config);
.use(CompressionWebpackPlugin, [
{
filename: '[path][base].gz',
algorithm: 'gzip',
test: /\.(js|css|html|svg)$/,
threshold: 10240,
minRatio: 0.8
}
]);
} }
} }
: {}), : {
chainWebpack(config) {
monacoPluginConfig(config);
}
}),
favicons: ['/static/favicon.png'], favicons: ['/static/favicon.png'],
jsMinifier: 'terser', jsMinifier: 'terser',
cssMinifier: 'cssnano', cssMinifier: 'cssnano',
@@ -79,11 +77,15 @@ export default defineConfig({
antd: { antd: {
style: 'less' style: 'less'
}, },
title: 'GPUStack',
hash: true, hash: true,
access: {}, access: {},
model: {}, model: {},
initialState: {}, initialState: {},
request: {}, request: {},
routePrefetch: {
defaultPrefetch: 'intent'
},
keepalive: keepAlive, keepalive: keepAlive,
locale: { locale: {
antd: true, antd: true,
+9
View File
@@ -0,0 +1,9 @@
// Identity hook for build-time mfsu.exclude extensions. Tooling may
// overwrite this file to add package names that must skip MFSU's
// pre-bundling; the original is restored on cleanup. Mirrors
// `src/request.extensions.ts` / `src/access.extensions.ts`.
//
// MFSU bundles node_modules into immutable chunks at dev startup, so
// workspace-linked packages whose source you edit during dev must be
// excluded here or HMR won't pick up changes.
export const extraMfsuExclude: string[] = [];
+36
View File
@@ -0,0 +1,36 @@
import MonacoWebpackPlugin from 'monaco-editor-webpack-plugin';
const CompressionWebpackPlugin = require('compression-webpack-plugin');
export function monacoPluginConfig(config: any) {
return config
.plugin('monaco-editor-webpack-plugin')
.use(MonacoWebpackPlugin, [
{
languages: ['yaml'],
customLanguages: [
{
label: 'yaml',
entry: 'monaco-yaml',
worker: {
id: 'monaco-yaml/yamlWorker',
entry: 'monaco-yaml/yaml.worker.js'
}
}
]
}
]);
}
export function compressionPluginConfig(config: any) {
return config
.plugin('compression-webpack-plugin')
.use(CompressionWebpackPlugin, [
{
filename: '[path][base].gz',
algorithm: 'gzip',
test: /\.(js|css|html|svg)$/,
threshold: 10240,
minRatio: 0.8
}
]);
}
+3 -1
View File
@@ -1,11 +1,13 @@
const proxyTableList = [ const proxyTableList = [
'cli', 'cli',
'v1', 'v1',
'v2',
'auth', 'auth',
'v1-openai', 'v1-openai',
'version', 'version',
'proxy', 'proxy',
'update' 'update',
'grafana'
]; ];
// @ts-ingore // @ts-ingore
+3
View File
@@ -0,0 +1,3 @@
// Identity hook for build-time route extensions. Tooling may overwrite
// this file to inject additional routes; the original is restored on cleanup.
export const applyRouteExtensions = <T>(base: T): T => base;
+208 -12
View File
@@ -1,6 +1,7 @@
import { keepAliveRoutes } from './keep-alive'; import { keepAliveRoutes } from './keep-alive';
import { applyRouteExtensions } from './routes.extensions';
export default [ const baseRoutes = [
{ {
name: 'dashboard', name: 'dashboard',
path: '/dashboard', path: '/dashboard',
@@ -8,7 +9,10 @@ export default [
icon: 'icon-dashboard', icon: 'icon-dashboard',
selectedIcon: 'icon-dashboard-filled', selectedIcon: 'icon-dashboard-filled',
defaultIcon: 'icon-dashboard', defaultIcon: 'icon-dashboard',
access: 'canSeeAdmin', // `canSeeOrgAdmin` widens to anyone the access seam grants
// admin-ish visibility — by default platform admin, plus
// whatever the routes extension chooses to allow.
access: 'canSeeOrgAdmin',
component: './dashboard', component: './dashboard',
routes: [] routes: []
}, },
@@ -32,7 +36,7 @@ export default [
icon: 'icon-chat', icon: 'icon-chat',
selectedIcon: 'icon-chat-filled', selectedIcon: 'icon-chat-filled',
defaultIcon: 'icon-chat', defaultIcon: 'icon-chat',
component: './playground/index' component: './playground/chat/index'
}, },
{ {
name: 'embedding', name: 'embedding',
@@ -42,7 +46,7 @@ export default [
icon: 'icon-embedding', icon: 'icon-embedding',
selectedIcon: 'icon-embedding-filled', selectedIcon: 'icon-embedding-filled',
defaultIcon: 'icon-embedding', defaultIcon: 'icon-embedding',
component: './playground/embedding' component: './playground/embedding/index'
}, },
{ {
name: 'rerank', name: 'rerank',
@@ -52,7 +56,7 @@ export default [
icon: 'icon-reranker', icon: 'icon-reranker',
selectedIcon: 'icon-reranker-filled', selectedIcon: 'icon-reranker-filled',
defaultIcon: 'icon-reranker', defaultIcon: 'icon-reranker',
component: './playground/rerank' component: './playground/rerank/index'
}, },
{ {
name: 'text2images', name: 'text2images',
@@ -62,7 +66,7 @@ export default [
icon: 'icon-image1', icon: 'icon-image1',
selectedIcon: 'icon-image-filled', selectedIcon: 'icon-image-filled',
defaultIcon: 'icon-image1', defaultIcon: 'icon-image1',
component: './playground/images' component: './playground/images/index'
}, },
{ {
name: 'speech', name: 'speech',
@@ -72,15 +76,25 @@ export default [
icon: 'icon-audio1', icon: 'icon-audio1',
selectedIcon: 'icon-audio-filled', selectedIcon: 'icon-audio-filled',
defaultIcon: 'icon-audio1', defaultIcon: 'icon-audio1',
component: './playground/speech' component: './playground/speech/index'
} }
// {
// name: 'video',
// title: 'Video',
// path: '/playground/video',
// key: 'video',
// icon: 'icon-video-outline',
// hideInMenu: false,
// selectedIcon: 'icon-video-filled02',
// defaultIcon: 'icon-video-outline',
// component: './playground/video'
// }
] ]
}, },
{ {
name: 'models', name: 'models',
path: '/models', path: '/models',
key: 'models', key: 'models',
access: 'canSeeAdmin',
routes: [ routes: [
{ {
path: '/models', path: '/models',
@@ -93,9 +107,19 @@ export default [
icon: 'icon-layers', icon: 'icon-layers',
selectedIcon: 'icon-layers-filled', selectedIcon: 'icon-layers-filled',
defaultIcon: 'icon-layers', defaultIcon: 'icon-layers',
access: 'canSeeAdmin', access: 'canSeeOrgAdmin',
component: './llmodels/catalog' component: './llmodels/catalog'
}, },
{
name: 'userModels',
path: '/models/user-models',
key: 'userModels',
icon: 'icon-models',
selectedIcon: 'icon-models-filled',
defaultIcon: 'icon-models',
access: 'canSeeUser',
component: './llmodels/user-models'
},
{ {
name: 'deployment', name: 'deployment',
path: '/models/deployments', path: '/models/deployments',
@@ -103,8 +127,115 @@ export default [
icon: 'icon-rocket-launch1', icon: 'icon-rocket-launch1',
selectedIcon: 'icon-rocket-launch-fill', selectedIcon: 'icon-rocket-launch-fill',
defaultIcon: 'icon-rocket-launch1', defaultIcon: 'icon-rocket-launch1',
access: 'canSeeAdmin', access: 'canSeeOrgAdmin',
component: './llmodels/index' component: './llmodels/index'
},
{
name: 'routes',
path: '/models/routes',
key: 'routes',
icon: 'icon-captive_portal',
selectedIcon: 'icon-captive_portal',
defaultIcon: 'icon-captive_portal',
access: 'canSeeOrgAdmin',
component: './model-routes/index'
},
{
name: 'usage',
path: '/models/usage',
key: 'usage',
icon: 'icon-usage-outlined',
selectedIcon: 'icon-usage-filled',
defaultIcon: 'icon-usage-outlined',
component: './usage/index'
},
{
name: 'providers',
path: '/models/providers',
key: 'modelProviders',
icon: 'icon-extension-outline',
selectedIcon: 'icon-extension-filled',
defaultIcon: 'icon-extension-outline',
access: 'canSeeOrgAdmin',
component: './maas-provider/index'
},
{
name: 'benchmark',
path: '/models/benchmark',
key: 'benchmark',
icon: 'icon-speed',
selectedIcon: 'icon-speed-filled',
defaultIcon: 'icon-speed',
access: 'canSeeOrgAdmin',
component: './benchmark/index'
},
{
name: 'benchmarkDetail',
path: '/models/benchmark/detail',
key: 'benchmarkDetail',
icon: 'icon-speed',
selectedIcon: 'icon-speed-filled',
defaultIcon: 'icon-speed',
access: 'canSeeOrgAdmin',
hideInMenu: true,
component: './benchmark/details'
}
]
},
{
name: 'gpuService',
path: '/gpu-service',
key: 'gpuService',
routes: [
{
path: '/gpu-service',
redirect: '/gpu-service/instances'
},
{
name: 'instances',
path: '/gpu-service/instances',
key: 'gpuServiceList',
icon: 'icon-cloud-outlined',
selectedIcon: 'icon-cloud-filled',
defaultIcon: 'icon-cloud-outlined',
component: './gpu-service/instances'
},
{
name: 'templates',
path: '/gpu-service/templates',
key: 'gpuServiceTemplates',
icon: 'icon-instance-template-outlined',
selectedIcon: 'icon-instance-template-filled',
defaultIcon: 'icon-instance-template-outlined',
component: './gpu-service/templates'
},
{
name: 'storage',
path: '/gpu-service/storage',
key: 'gpuServiceStorage',
icon: 'icon-database-outlined',
selectedIcon: 'icon-database-filled',
defaultIcon: 'icon-database-outlined',
component: './gpu-service/storage'
},
{
name: 'storageTypes',
path: '/gpu-service/storage-types',
key: 'gpuServiceStorageTypes',
icon: 'icon-storage-outlined',
access: 'canSeeAdmin',
selectedIcon: 'icon-storage-filled',
defaultIcon: 'icon-storage-outlined',
component: './gpu-service/storage-types'
},
{
name: 'publicKeys',
path: '/gpu-service/public-keys',
key: 'gpuServicePublicKeys',
icon: 'icon-ssh-outlined',
selectedIcon: 'icon-ssh-filled',
defaultIcon: 'icon-ssh-outlined',
component: './gpu-service/public-keys'
} }
] ]
}, },
@@ -112,7 +243,7 @@ export default [
name: 'resources', name: 'resources',
path: '/resources', path: '/resources',
key: 'resources', key: 'resources',
access: 'canSeeAdmin', access: 'canSeeOrgAdmin',
routes: [ routes: [
{ {
path: '/resources', path: '/resources',
@@ -136,6 +267,16 @@ export default [
defaultIcon: 'icon-gpu1', defaultIcon: 'icon-gpu1',
component: './resources/components/gpus' component: './resources/components/gpus'
}, },
{
name: 'backendsList',
path: '/resources/backends',
key: 'backendsList',
icon: 'icon-backend',
selectedIcon: 'icon-backend-filled',
defaultIcon: 'icon-backend',
access: 'canSeeOrgAdmin',
component: './backends/index'
},
{ {
name: 'modelfiles', name: 'modelfiles',
path: '/resources/modelfiles', path: '/resources/modelfiles',
@@ -147,11 +288,54 @@ export default [
} }
] ]
}, },
{
name: 'clusterManagement',
path: '/cluster-management',
key: 'clusterManagement',
access: 'canSeeOrgAdmin',
routes: [
{
path: '/cluster-management',
redirect: '/cluster-management/clusters/list'
},
{
name: 'clusters',
path: '/cluster-management/clusters/list',
key: 'clusters',
icon: 'icon-cluster2-outline',
selectedIcon: 'icon-cluster2-filled',
defaultIcon: 'icon-cluster2-outline',
component: './cluster-management/clusters',
subMenu: [
'/cluster-management/clusters/detail',
'/cluster-management/clusters/create'
]
},
{
name: 'clusterDetail',
path: '/cluster-management/clusters/detail',
key: 'clusterDetail',
icon: 'icon-cluster2-outline',
selectedIcon: 'icon-cluster2-filled',
defaultIcon: 'icon-cluster2-outline',
hideInMenu: true,
component: './cluster-management/cluster-detail'
},
{
name: 'credentials',
path: '/cluster-management/credentials',
key: 'credentials',
icon: 'icon-credential-outline',
selectedIcon: 'icon-credential-filled',
defaultIcon: 'icon-credential-outline',
component: './cluster-management/credentials'
}
]
},
{ {
name: 'accessControl', name: 'accessControl',
path: '/access-control', path: '/access-control',
key: 'accessControl', key: 'accessControl',
access: 'canSeeAdmin',
routes: [ routes: [
{ {
path: '/access-control', path: '/access-control',
@@ -164,7 +348,17 @@ export default [
icon: 'icon-users', icon: 'icon-users',
selectedIcon: 'icon-users-filled', selectedIcon: 'icon-users-filled',
defaultIcon: 'icon-users', defaultIcon: 'icon-users',
access: 'canSeeAdmin',
component: './users' component: './users'
},
{
name: 'apikeys',
path: '/access-control/api-keys',
key: 'apikeys',
selectedIcon: 'icon-key-filled',
icon: 'icon-key',
defaultIcon: 'icon-key',
component: './api-keys'
} }
] ]
}, },
@@ -202,3 +396,5 @@ export default [
component: './404' component: './404'
} }
]; ];
export default applyRouteExtensions(baseRoutes);
+78
View File
@@ -0,0 +1,78 @@
import js from '@eslint/js';
import prettier from 'eslint-config-prettier';
import importPlugin from 'eslint-plugin-import';
import reactPlugin from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import unusedImports from 'eslint-plugin-unused-imports';
import { defineConfig, globalIgnores } from 'eslint/config';
import globals from 'globals';
import tseslint from 'typescript-eslint';
export default defineConfig([
globalIgnores([
'public/static/',
'dist',
'src/.umi/',
'src/.umi-production/',
'src/.umi-test/'
]),
{
files: ['**/*.{ts,tsx,js,jsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs.flat.recommended,
prettier
],
plugins: {
react: reactPlugin,
import: importPlugin,
'unused-imports': unusedImports
},
settings: {
react: {
version: 'detect'
},
'import/resolver': {
node: true,
typescript: true
}
},
languageOptions: {
ecmaVersion: 2020,
globals: {
...globals.browser,
...globals.node,
Global: 'readonly',
React: 'readonly',
JSX: 'readonly'
}
},
rules: {
'react/no-unstable-nested-components': 'warn',
'no-unused-vars': 'off',
'no-undef': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-empty-object-type': 'off',
'@typescript-eslint/no-unnecessary-type-constraint': 'off',
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': 'off',
'import/no-unresolved': 'off',
'import/no-duplicates': 'error',
'react-hooks/exhaustive-deps': 'off',
'react-hooks/preserve-manual-memoization': 'off',
'react-hooks/set-state-in-effect': 'off',
'react-hooks/refs': 'off',
'react-hooks/use-memo': 'off',
'react-hooks/immutability': 'off',
'no-unsafe-optional-chaining': 'off',
'no-empty': 'off',
'no-constant-condition': 'off',
'no-prototype-builtins': 'off',
'no-multiple-empty-lines': ['error', { max: 1, maxEOF: 0, maxBOF: 0 }]
}
}
]);
+35 -19
View File
@@ -1,9 +1,9 @@
{ {
"private": true, "private": true,
"author": "jialin", "author": "gpustack",
"scripts": { "scripts": {
"build": "max build", "build": "max build",
"check:locales": "npx tsx ./src/locales/check.ts", "check:locales": "node --import tsx ./src/locales/check.ts",
"dev": "max dev", "dev": "max dev",
"format": "prettier --cache --write .", "format": "prettier --cache --write .",
"postinstall": "max setup", "postinstall": "max setup",
@@ -12,13 +12,12 @@
"setup": "max setup", "setup": "max setup",
"start": "npm run dev" "start": "npm run dev"
}, },
"resolutions": {
"immer": "^9.0.6"
},
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.5.1", "@ant-design/icons": "^6.1.0",
"@ant-design/pro-components": "^2.7.19", "@ant-design/pro-components": "3.1.0-0",
"@antv/g6": "^5.0.51",
"@braintree/sanitize-url": "^7.1.1", "@braintree/sanitize-url": "^7.1.1",
"@gpustack/core-ui": "^1.0.16",
"@huggingface/gguf": "^0.1.7", "@huggingface/gguf": "^0.1.7",
"@huggingface/hub": "^0.15.1", "@huggingface/hub": "^0.15.1",
"@huggingface/tasks": "^0.11.6", "@huggingface/tasks": "^0.11.6",
@@ -26,85 +25,102 @@
"@orcid/bibtex-parse-js": "^0.0.25", "@orcid/bibtex-parse-js": "^0.0.25",
"@react-hook/resize-observer": "^2.0.2", "@react-hook/resize-observer": "^2.0.2",
"@types/lodash": "^4.17.4", "@types/lodash": "^4.17.4",
"@umijs/max": "^4.2.11", "@umijs/max": "^4.6.15",
"@xterm/addon-fit": "^0.10.0", "@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0", "@xterm/xterm": "^5.5.0",
"ahooks": "^3.8.5", "ahooks": "^3.8.5",
"ansi-to-html": "^0.7.2", "ansi-to-html": "^0.7.2",
"antd": "^5.21.6", "antd": "^6.3.3",
"antd-style": "^3.6.2", "antd-style": "^3.6.2",
"axios": "^1.8.2", "axios": "^1.8.2",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"clipboard": "^2.0.11", "clipboard": "^2.0.11",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"culori": "^4.0.2",
"dayjs": "^1.11.11", "dayjs": "^1.11.11",
"dompurify": "^3.2.6", "dompurify": "^3.2.6",
"driver.js": "^1.3.1", "driver.js": "^1.3.1",
"echarts": "^5.5.1", "echarts": "^5.5.1",
"epubjs": "^0.3.93",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"has-ansi": "^5.0.1", "has-ansi": "^5.0.1",
"highlight.js": "^11.10.0", "highlight.js": "^11.10.0",
"jdenticon": "^3.3.0",
"jotai": "^2.8.4", "jotai": "^2.8.4",
"jszip": "^3.10.1", "js-yaml": "^4.1.0",
"katex": "^0.16.21", "katex": "^0.16.21",
"lamejs": "github:zhuker/lamejs", "lamejs": "github:zhuker/lamejs",
"localforage": "^1.10.0", "localforage": "^1.10.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mammoth": "^1.8.0",
"marked": "^14.1.0", "marked": "^14.1.0",
"minimatch": "^3.1.2",
"ml-dataset-iris": "^1.2.1", "ml-dataset-iris": "^1.2.1",
"ml-pca": "^4.1.1", "ml-pca": "^4.1.1",
"monaco-editor": "^0.30.1",
"monaco-yaml": "^4.0.0",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"overlayscrollbars": "^2.10.0", "overlayscrollbars": "^2.10.0",
"overlayscrollbars-react": "^0.5.6", "overlayscrollbars-react": "^0.5.6",
"pdfjs-dist": "^4.7.76",
"query-string": "^9.0.0", "query-string": "^9.0.0",
"rc-resize-observer": "^1.4.0", "rc-resize-observer": "^1.4.3",
"rc-virtual-list": "^3.14.8", "rc-virtual-list": "^3.14.8",
"re-resizable": "^6.10.1", "re-resizable": "^6.10.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-hotkeys-hook": "^4.5.0", "react-hotkeys-hook": "^4.5.0",
"react-intersection-observer": "^9.16.0",
"react-markdown": "^9.0.3", "react-markdown": "^9.0.3",
"react-router-dom": "^6.30.3",
"rehype-katex": "^7.0.1", "rehype-katex": "^7.0.1",
"remark-breaks": "^4.0.0", "remark-breaks": "^4.0.0",
"remark-gfm": "^4.0.1", "remark-gfm": "^4.0.1",
"remark-math": "^6.0.0", "remark-math": "^6.0.0",
"semver": "^7.7.3",
"simplebar-react": "^3.2.6", "simplebar-react": "^3.2.6",
"styled-components": "^6.1.15", "styled-components": "^6.1.15",
"umi-presets-pro": "^2.0.3", "umi-presets-pro": "^2.0.3",
"wavesurfer.js": "^7.8.8", "wavesurfer.js": "^7.8.8"
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
}, },
"devDependencies": { "devDependencies": {
"@types/marked": "^6.0.0", "@eslint/js": "^9.39.4",
"@types/node": "^25.0.3",
"@types/react": "^18.3.1", "@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"@types/semver": "^7.7.1",
"@typescript-eslint/eslint-plugin": "^8.58.1",
"@umijs/case-sensitive-paths-webpack-plugin": "^1.0.1", "@umijs/case-sensitive-paths-webpack-plugin": "^1.0.1",
"@umijs/plugins": "^4.4.11", "@umijs/plugins": "^4.4.11",
"babel-plugin-named-asset-import": "^0.3.8", "babel-plugin-named-asset-import": "^0.3.8",
"case-sensitive-paths-webpack-plugin": "^2.4.0", "case-sensitive-paths-webpack-plugin": "^2.4.0",
"compression-webpack-plugin": "^11.1.0", "compression-webpack-plugin": "^11.1.0",
"cross-env": "^7.0.3",
"css-loader": "^7.1.2", "css-loader": "^7.1.2",
"eslint": "^8.56.0", "eslint": "^9.39.4",
"eslint-plugin-unused-imports": "^3.2.0", "eslint-config-prettier": "^10.1.8",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-unused-imports": "^4.4.1",
"extract-css-loader": "^0.0.1", "extract-css-loader": "^0.0.1",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"globals": "^17.4.0",
"husky": "^9.0.11", "husky": "^9.0.11",
"less-loader": "^12.2.0", "less-loader": "^12.2.0",
"lint-staged": "^15.2.2", "lint-staged": "^15.2.2",
"mini-css-extract-plugin": "^2.9.0", "mini-css-extract-plugin": "^2.9.0",
"monaco-editor-webpack-plugin": "^4.2.0",
"prettier": "^3.2.5", "prettier": "^3.2.5",
"prettier-plugin-organize-imports": "^3.2.4", "prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-packagejson": "^2.5.0", "prettier-plugin-packagejson": "^2.5.0",
"prettier-plugin-two-style-order": "^1.0.1", "prettier-plugin-two-style-order": "^1.0.1",
"tsx": "^4.19.3", "tsx": "^4.19.3",
"typescript": "^5.4.5", "typescript": "^5.4.5",
"typescript-eslint": "^8.58.0",
"url-loader": "^4.1.1", "url-loader": "^4.1.1",
"webpack-bundle-analyzer": "^4.10.2", "webpack-bundle-analyzer": "^4.10.2",
"worker-loader": "^3.0.8" "worker-loader": "^3.0.8"
}, },
"packageManager": "pnpm@9.3.0",
"pnpm": { "pnpm": {
"overrides": { "overrides": {
"elliptic": "^6.6.1" "elliptic": "^6.6.1"
+15165 -14726
View File
File diff suppressed because it is too large Load Diff
+32
View File
@@ -0,0 +1,32 @@
const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');
const pnpmDir = path.resolve(__dirname, '../../../node_modules/.pnpm');
function findDir(prefix) {
return fs.readdirSync(pnpmDir).find((name) => name.startsWith(prefix));
}
const stylelintDir = findDir('stylelint@14.8.2');
if (!stylelintDir) {
console.error('Compatible stylelint@14.8.2 not found in workspace node_modules/.pnpm');
process.exit(1);
}
const stylelintBin = path.join(
pnpmDir,
stylelintDir,
'node_modules/stylelint/bin/stylelint.js'
);
const result = spawnSync(process.execPath, [stylelintBin, ...process.argv.slice(2)], {
stdio: 'inherit',
cwd: process.cwd(),
});
if (result.error) {
console.error(result.error);
}
process.exit(result.status ?? 1);
+14
View File
@@ -0,0 +1,14 @@
// Identity hook for build-time access-predicate extensions. Tooling may
// overwrite this file to widen predicates; the original is restored on
// cleanup. Mirrors `config/routes.extensions.ts`.
export type AccessPredicates = {
canSeeAdmin: boolean;
canSeeOrgAdmin: boolean;
canManageCurrentOrg: boolean;
canSeeUser: boolean;
canDelete: boolean;
canLogin: boolean;
};
export const applyAccessExtensions = <T extends AccessPredicates>(base: T): T =>
base;
+27 -4
View File
@@ -1,12 +1,35 @@
import { applyAccessExtensions } from './access.extensions';
export default (initialState: { currentUser?: Global.UserInfo }) => { export default (initialState: { currentUser?: Global.UserInfo }) => {
const canSeeAdmin = !!( const isPlatformAdmin = !!(
initialState && initialState &&
initialState.currentUser && initialState.currentUser &&
initialState.currentUser.is_admin initialState.currentUser.is_admin
); );
return { const canSeeUser = !!(
canSeeAdmin, initialState &&
initialState.currentUser &&
!initialState.currentUser.is_admin
);
// Predicate roles, top-down by strictness:
// * `canSeeAdmin` — strictly platform admin (`users.is_admin`).
// Gates Users.
// * `canSeeOrgAdmin` — admin-style menus that work cross-org
// (Dashboard, Resources, Models, Cluster Management). Defaults
// to platform admin; extensions widen to include org admins.
// * `canManageCurrentOrg` — pages that only make sense inside a
// specific org context (member / group management). Defaults to
// `false`; extensions widen when both an org is selected AND
// the caller is admin of it.
// Pass through `applyAccessExtensions` so build-time tooling can
// widen these without editing this file. Default is a no-op.
return applyAccessExtensions({
canSeeAdmin: isPlatformAdmin,
canSeeOrgAdmin: isPlatformAdmin,
canManageCurrentOrg: false,
canSeeUser,
canDelete: true, canDelete: true,
canLogin: true canLogin: true
}; });
}; };
+58 -13
View File
@@ -1,20 +1,26 @@
import { userSettingsHelperAtom } from '@/atoms/settings';
import { GPUStackVersionAtom, UpdateCheckAtom } from '@/atoms/user'; import { GPUStackVersionAtom, UpdateCheckAtom } from '@/atoms/user';
import { setAtomStorage } from '@/atoms/utils'; import { setAtomStorage } from '@/atoms/utils';
import { DEFAULT_ENTER_PAGE, GPUSTACK_API_BASE_URL } from '@/config/settings';
import { COLOR_PRIMARY } from '@/config/theme/constants';
import { enterprisePluginReady } from '@/plugins/enterprise-ready';
import { GPUStackPluginManager } from '@/plugins/manager';
import { requestConfig } from '@/request-config'; import { requestConfig } from '@/request-config';
import { import {
queryCurrentUserState, queryCurrentUserState,
queryVersionInfo, queryVersionInfo,
updateCheck updateCheck
} from '@/services/profile/apis'; } from '@/services/profile/apis';
import { fetchSystemConfig } from '@/services/system/query-system-config';
import { isOnline } from '@/utils'; import { isOnline } from '@/utils';
import { import {
IS_FIRST_LOGIN, IS_FIRST_LOGIN,
readState, readState,
writeState writeState
} from '@/utils/localstore/index'; } from '@/utils/localstore/index';
import { RequestConfig, history } from '@umijs/max'; import '@gpustack/core-ui/style.css';
import { RequestConfig, history, request as umiRequest } from '@umijs/max';
const loginPath = '/login'; import { message } from 'antd';
// only for the first login and access from http://localhost // only for the first login and access from http://localhost
@@ -23,7 +29,7 @@ const checkDefaultPage = async (userInfo: any) => {
if (isFirstLogin === null && isOnline()) { if (isFirstLogin === null && isOnline()) {
writeState(IS_FIRST_LOGIN, true); writeState(IS_FIRST_LOGIN, true);
if (userInfo && userInfo?.is_admin) { if (userInfo && userInfo?.is_admin) {
history.push('/models/deployments'); history.push(DEFAULT_ENTER_PAGE.adminForFirst);
} }
} }
}; };
@@ -32,9 +38,27 @@ const checkDefaultPage = async (userInfo: any) => {
export async function getInitialState(): Promise<{ export async function getInitialState(): Promise<{
fetchUserInfo: () => Promise<Global.UserInfo>; fetchUserInfo: () => Promise<Global.UserInfo>;
currentUser?: Global.UserInfo; currentUser?: Global.UserInfo;
pluginData?: Record<string, any>;
}> { }> {
const { location } = history; const { location } = history;
// In open-source builds the promise resolves immediately.
await enterprisePluginReady;
// initialize plugins and merge enterprise locales
let pluginData = {};
try {
pluginData = await GPUStackPluginManager.initialize({
request: umiRequest,
setUserSettings: (value) => setAtomStorage(userSettingsHelperAtom, value),
setStorageUserSettings: (value) =>
setAtomStorage(userSettingsHelperAtom, value),
defaultColorPrimary: COLOR_PRIMARY
});
} catch (error) {
console.error('Failed to initialize plugins:', error);
}
const getUpdateCheck = async () => { const getUpdateCheck = async () => {
try { try {
const data = await updateCheck(); const data = await updateCheck();
@@ -48,17 +72,31 @@ export async function getInitialState(): Promise<{
} }
}; };
const fetchUserInfo = async (): Promise<Global.UserInfo> => { const fetchUserInfo = async (config?: {
skipErrorHandler?: boolean;
}): Promise<Global.UserInfo> => {
try { try {
const data = await queryCurrentUserState({ const data = await queryCurrentUserState({
skipErrorHandler: true skipErrorHandler: true
}); });
if (data.is_admin) { if (data.is_admin) {
getUpdateCheck(); getUpdateCheck();
fetchSystemConfig();
} }
return data; return data;
} catch (error) { } catch (error: any) {
history.push(loginPath); const data = error?.response?.data;
if (data?.code === 401 && data?.message.includes('deactivate')) {
message.error({
content: (
<div>
<span>{data?.message}</span>
</div>
),
duration: 5
});
}
history.push(DEFAULT_ENTER_PAGE.login);
} }
return {} as Global.UserInfo; return {} as Global.UserInfo;
}; };
@@ -66,10 +104,15 @@ export async function getInitialState(): Promise<{
const getAppVersionInfo = async () => { const getAppVersionInfo = async () => {
try { try {
const data = await queryVersionInfo(); const data = await queryVersionInfo();
const isProduction = data.version?.indexOf('0.0.0') === -1;
const isDev = data.version?.indexOf('0.0.0') > -1;
const isRc = data.version?.indexOf('rc') > -1;
setAtomStorage(GPUStackVersionAtom, { setAtomStorage(GPUStackVersionAtom, {
...data, ...data,
isProduction isProd: !isDev && !isRc,
isDev,
isRc
}); });
} catch (error) { } catch (error) {
console.error('queryVersionInfo error', error); console.error('queryVersionInfo error', error);
@@ -78,20 +121,22 @@ export async function getInitialState(): Promise<{
getAppVersionInfo(); getAppVersionInfo();
if (![loginPath].includes(location.pathname)) { if (![DEFAULT_ENTER_PAGE.login].includes(location.pathname)) {
const userInfo = await fetchUserInfo(); const userInfo = await fetchUserInfo();
checkDefaultPage(userInfo); checkDefaultPage(userInfo);
return { return {
fetchUserInfo, fetchUserInfo,
currentUser: userInfo currentUser: userInfo,
pluginData
}; };
} }
return { return {
fetchUserInfo fetchUserInfo,
pluginData
}; };
} }
export const request: RequestConfig = { export const request: RequestConfig = {
baseURL: ' /v1', baseURL: `/${GPUSTACK_API_BASE_URL}`,
...requestConfig ...requestConfig
}; };
Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 286 64"><g><g><defs><path id="SVGID_1_" d="M47.5 17.6L25 4.8v52.6l9-5.2V37.4l6.8 3.9-.1-10.1-6.7-3.9v-5.9l13.5 7.9z"/></defs><clipPath id="SVGID_2_"><use xlink:href="#SVGID_1_" overflow="visible"/></clipPath><g clip-path="url(#SVGID_2_)"><linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-1.6" y1="335.05" x2="53.6" y2="335.05" gradientTransform="translate(0 -304)"><stop offset="0" stop-color="#ff6f00"/><stop offset="1" stop-color="#ffa800"/></linearGradient><path d="M-1.6 4.6h55.2v52.9H-1.6V4.6z" fill="url(#SVGID_3_)"/></g></g></g><g><g><defs><path id="SVGID_4_" d="M.5 17.6L23 4.8v52.6l-9-5.2V21.4L.5 29.3z"/></defs><clipPath id="SVGID_5_"><use xlink:href="#SVGID_4_" overflow="visible"/></clipPath><g clip-path="url(#SVGID_5_)"><linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="-1.9" y1="335.05" x2="53.3" y2="335.05" gradientTransform="translate(0 -304)"><stop offset="0" stop-color="#ff6f00"/><stop offset="1" stop-color="#ffa800"/></linearGradient><path d="M-1.9 4.6h55.2v52.9H-1.9V4.6z" fill="url(#SVGID_6_)"/></g></g></g><path style="fill:#425066" d="M88.2 21.1h-10v27.7h-5.6V21.1h-10v-4.5h25.6v4.5z"/><path style="fill:#425066" d="M94.9 49.2c-3.4 0-6.2-1.1-8.3-3.2-2.1-2.1-3.2-5-3.2-8.6v-.7c0-2.2.4-4.4 1.4-6.4.9-1.8 2.2-3.3 3.9-4.4 1.7-1.1 3.6-1.6 5.6-1.6 3.3 0 5.8 1 7.6 3.1s2.7 5 2.7 8.8v2.2H88.9c.1 1.8.8 3.4 2 4.7 1.2 1.2 2.7 1.8 4.4 1.7 2.4.1 4.6-1.1 6-3l2.9 2.8c-1 1.4-2.3 2.6-3.8 3.3-1.8 1-3.6 1.4-5.5 1.3zm-.6-20.5c-1.4-.1-2.7.5-3.6 1.5-1 1.2-1.6 2.7-1.7 4.3h10.3v-.4c-.1-1.8-.6-3.2-1.4-4.1-1-.8-2.3-1.4-3.6-1.3zm19.4-3.9l.2 2.8c1.7-2.1 4.3-3.3 7-3.2 5 0 7.5 2.9 7.6 8.6v15.8h-5.4V33.3c0-1.5-.3-2.6-1-3.4-.7-.7-1.7-1.1-3.2-1.1-2.1-.1-4 1.1-4.9 2.9v17h-5.4v-24l5.1.1zm32.2 17.5c0-.9-.4-1.7-1.2-2.2-1.2-.7-2.6-1.1-3.9-1.3-1.6-.3-3.1-.8-4.6-1.5-2.7-1.3-4-3.2-4-5.6 0-2 1-4 2.6-5.2 1.7-1.4 4-2.1 6.6-2.1 2.9 0 5.2.7 6.9 2.1 1.7 1.3 2.7 3.4 2.6 5.5h-5.4c0-1-.4-1.9-1.2-2.6-.9-.7-1.9-1.1-3.1-1-1 0-2 .2-2.9.8-.7.5-1.1 1.3-1.1 2.2 0 .8.4 1.5 1 1.9.7.5 2.1.9 4.2 1.4 1.7.3 3.4.9 5 1.7 1.1.5 2 1.3 2.7 2.3.6 1 .9 2.1.9 3.3 0 2.1-1 4-2.7 5.2-1.8 1.3-4.1 2-7 2-1.8 0-3.6-.3-5.2-1.1-1.4-.6-2.7-1.6-3.6-2.9-.8-1.2-1.3-2.6-1.3-4h5.2c0 1.1.5 2.2 1.4 2.9 1 .7 2.3 1.1 3.5 1 1.4 0 2.5-.3 3.2-.8 1-.4 1.4-1.2 1.4-2zm8.1-5.7c0-2.2.4-4.4 1.4-6.3.9-1.8 2.2-3.3 3.9-4.3 1.8-1 3.8-1.6 5.8-1.5 3.2 0 5.9 1 7.9 3.1s3.1 4.8 3.3 8.3v1.3c0 2.2-.4 4.3-1.4 6.3-.8 1.8-2.2 3.3-3.9 4.3-1.8 1-3.8 1.6-5.9 1.5-3.4 0-6.1-1.1-8.1-3.4-2-2.2-3-5.2-3.1-9l.1-.3zm5.3.5c0 2.5.5 4.4 1.5 5.8 1.8 2.3 5.1 2.8 7.5 1 .4-.3.7-.6 1-1 1-1.4 1.5-3.5 1.5-6.2 0-2.4-.5-4.3-1.6-5.8-1.7-2.3-5-2.8-7.4-1.1-.4.3-.8.7-1.1 1-.8 1.4-1.4 3.5-1.4 6.3zm33.1-7.3c-.7-.1-1.5-.2-2.2-.2-2.5 0-4.1.9-5 2.8v16.4h-5.4v-24h5.1l.1 2.7c1.3-2.1 3.1-3.1 5.4-3.1.6 0 1.3.1 1.9.3l.1 5.1zm22.5 5.3h-13v13.7h-5.6V16.6h20.5v4.5h-14.9v9.6h13v4.4zm10.7 13.7h-5.4V16.5h5.4v32.3zm3.9-12.2c0-2.2.4-4.4 1.4-6.3.9-1.8 2.2-3.3 3.9-4.3 1.8-1 3.8-1.6 5.8-1.5 3.2 0 5.9 1 7.9 3.1s3.1 4.8 3.3 8.3v1.3c0 2.2-.4 4.3-1.3 6.3-.8 1.8-2.2 3.3-3.9 4.3-1.8 1-3.8 1.6-5.9 1.5-3.4 0-6.1-1.1-8.1-3.4-2-2.2-3.1-5.2-3.1-9v-.3zm5.4.5c0 2.5.5 4.4 1.5 5.8 1 1.4 2.6 2.2 4.3 2.1 1.7.1 3.3-.7 4.2-2.1 1-1.4 1.5-3.5 1.5-6.2 0-2.4-.5-4.3-1.6-5.8-1.7-2.3-5-2.8-7.4-1.1-.4.3-.8.7-1.1 1-.9 1.4-1.4 3.5-1.4 6.3zm41.2 4.3l3.8-16.5h5.2l-6.5 24h-4.4l-5.1-16.5-5.1 16.5h-4.4l-6.6-24h5.3l3.9 16.4 4.9-16.4h4.1l4.9 16.5z"/></svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>AI360</title><path clip-rule="evenodd" d="M12 0h.018c1.473-.002 2.88.261 4.179.754C20.755 2.456 24 6.85 24 12c0 6.627-5.373 12-12 12S0 18.627 0 12 5.373 0 12 0zm8.604 18.967A11.024 11.024 0 0023.07 12c0-1.717-.39-3.344-1.089-4.794a2.59 2.59 0 01-3.214.62 6.278 6.278 0 01-1.333-.992C16.283 5.73 15.109 4.66 13.696 3.9c-3.211-1.729-6.825-1.501-9.695.447A11.033 11.033 0 00.93 12c0 1.663.367 3.241 1.024 4.657.75-.973 2.131-1.346 3.232-.71.667.384 1.257.92 1.837 1.447l.176.16c1.365 1.234 2.794 2.355 4.558 2.965 3.053 1.053 6.356.437 8.847-1.552z" fill="url(#lobe-icons-ai-360-fill-0)" fill-rule="evenodd"></path><path d="M5.643 10.312c-.83.11-1.401.766-1.408 1.618a1.715 1.715 0 001.45 1.72c.805.128 1.64-.426 1.87-1.26.046-.167.076-.338.106-.51.025-.14.05-.282.084-.42.318-1.317 1.237-1.95 2.788-1.93 1.086.013 1.318.271 1.68 1.855.017.076.043.151.07.226.26.714.976 1.17 1.67 1.065a1.647 1.647 0 001.38-1.438c.083-.729-.348-1.264-1.122-1.575-.34-.136-.664-.158-.995-.141-.726.037-1.121-.36-1.339-.977a3.359 3.359 0 01-.134-.65c-.014-.093-.027-.186-.043-.278-.156-.887-.835-1.51-1.669-1.532-.791-.02-1.464.551-1.665 1.418l-.06.27-.025.117c-.355 1.636-.974 2.205-2.638 2.422z" fill="url(#lobe-icons-ai-360-fill-1)"></path><path d="M18.059 13.644c.989-.206 1.577-.838 1.592-1.697.015-.83-.624-1.582-1.46-1.724-.77-.13-1.599.383-1.844 1.18-.069.22-.117.448-.165.676-.06.29-.122.58-.225.854-.367.986-1.593 1.546-2.926 1.394-.824-.095-1.106-.446-1.342-1.674-.18-.938-.864-1.535-1.681-1.467-.85.07-1.515.829-1.468 1.673.05.892.678 1.44 1.705 1.489 1.375.064 1.75.396 1.926 1.787.067.531.267.967.685 1.288 1.02.783 2.407.208 2.66-1.108l.022-.114c.152-.796.3-1.577 1.04-2.101.36-.255.761-.326 1.166-.397.105-.019.21-.037.315-.06z" fill="url(#lobe-icons-ai-360-fill-2)"></path><path d="M13.83 7.961a.755.755 0 11-1.51 0 .755.755 0 011.51 0z" fill="url(#lobe-icons-ai-360-fill-3)"></path><path d="M10.809 16.678a.755.755 0 100-1.511.755.755 0 000 1.51z" fill="url(#lobe-icons-ai-360-fill-4)"></path><defs><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-ai-360-fill-0" x1="12" x2="12" y1="0" y2="24"><stop stop-color="#12B7FA"></stop><stop offset="1" stop-color="#006ffb"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-ai-360-fill-1" x1="11.943" x2="11.943" y1="6.085" y2="17.778"><stop stop-color="#006ffb"></stop><stop offset="1" stop-color="#12B7FA"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-ai-360-fill-2" x1="11.943" x2="11.943" y1="6.085" y2="17.778"><stop stop-color="#006ffb"></stop><stop offset="1" stop-color="#12B7FA"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-ai-360-fill-3" x1="11.943" x2="11.943" y1="6.085" y2="17.778"><stop stop-color="#006ffb"></stop><stop offset="1" stop-color="#12B7FA"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-ai-360-fill-4" x1="11.943" x2="11.943" y1="6.085" y2="17.778"><stop stop-color="#006ffb"></stop><stop offset="1" stop-color="#12B7FA"></stop></linearGradient></defs></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>AzureAI</title><path clip-rule="evenodd" d="M16.233 0c.713 0 1.345.551 1.572 1.329.227.778 1.555 5.59 1.555 5.59v9.562h-4.813L14.645 0h1.588z" fill="url(#lobe-icons-azure-ai-fill-0)" fill-rule="evenodd"></path><path d="M23.298 7.47c0-.34-.275-.6-.6-.6h-2.835a3.617 3.617 0 00-3.614 3.615v5.996h3.436a3.617 3.617 0 003.613-3.614V7.47z" fill="url(#lobe-icons-azure-ai-fill-1)"></path><path clip-rule="evenodd" d="M16.233 0a.982.982 0 00-.989.989l-.097 18.198A4.814 4.814 0 0110.334 24H1.6a.597.597 0 01-.567-.794l7-19.981A4.819 4.819 0 0112.57 0h3.679-.016z" fill="url(#lobe-icons-azure-ai-fill-2)" fill-rule="evenodd"></path><defs><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-azure-ai-fill-0" x1="18.242" x2="14.191" y1="16.837" y2=".616"><stop stop-color="#712575"></stop><stop offset=".09" stop-color="#9A2884"></stop><stop offset=".18" stop-color="#BF2C92"></stop><stop offset=".27" stop-color="#DA2E9C"></stop><stop offset=".34" stop-color="#EB30A2"></stop><stop offset=".4" stop-color="#F131A5"></stop><stop offset=".5" stop-color="#EC30A3"></stop><stop offset=".61" stop-color="#DF2F9E"></stop><stop offset=".72" stop-color="#C92D96"></stop><stop offset=".83" stop-color="#AA2A8A"></stop><stop offset=".95" stop-color="#83267C"></stop><stop offset="1" stop-color="#712575"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-azure-ai-fill-1" x1="19.782" x2="19.782" y1=".34" y2="23.222"><stop stop-color="#DA7ED0"></stop><stop offset=".08" stop-color="#B17BD5"></stop><stop offset=".19" stop-color="#8778DB"></stop><stop offset=".3" stop-color="#6276E1"></stop><stop offset=".41" stop-color="#4574E5"></stop><stop offset=".54" stop-color="#2E72E8"></stop><stop offset=".67" stop-color="#1D71EB"></stop><stop offset=".81" stop-color="#1471EC"></stop><stop offset="1" stop-color="#1171ED"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-azure-ai-fill-2" x1="18.404" x2="3.236" y1=".859" y2="25.183"><stop stop-color="#DA7ED0"></stop><stop offset=".05" stop-color="#B77BD4"></stop><stop offset=".11" stop-color="#9079DA"></stop><stop offset=".18" stop-color="#6E77DF"></stop><stop offset=".25" stop-color="#5175E3"></stop><stop offset=".33" stop-color="#3973E7"></stop><stop offset=".42" stop-color="#2772E9"></stop><stop offset=".54" stop-color="#1A71EB"></stop><stop offset=".68" stop-color="#1371EC"></stop><stop offset="1" stop-color="#1171ED"></stop></linearGradient></defs></svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Baichuan</title><defs><linearGradient id="lobe-icons-baichuan-fill" x1="17.764%" x2="100%" y1="8.678%" y2="91.322%"><stop offset="0%" stop-color="#FEC13E"></stop><stop offset="100%" stop-color="#FF6933"></stop></linearGradient></defs><path d="M7.333 2h-3.2l-2 4.333V17.8L0 22h5.2l2.028-4.2L7.333 2zm7.334 0h-5.2v20h5.2V2zM16.8 7.733H22V22h-5.2V7.733zM22 2h-5.2v4.133H22V2z" fill="url(#lobe-icons-baichuan-fill)" fill-rule="nonzero"></path></svg>

After

Width:  |  Height:  |  Size: 569 B

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>BaiduCloud</title><path d="M21.715 5.61l-3.983 2.31a.903.903 0 01-.896 0L12.44 5.384a.903.903 0 00-.897 0L7.156 7.92a.903.903 0 01-.896 0L2.276 5.617 12.002 0l9.713 5.61z" fill="#5BCA87"></path><path d="M18.641 9.467a.89.89 0 00-.438.77v5.072a.896.896 0 01-.445.77l-4.428 2.51a.884.884 0 00-.445.777v4.607l4.429-2.536 5.31-3.047V7.157l-3.983 2.31z" fill="#EC5D3E"></path><path d="M10.98 18.941a.936.936 0 00-.305-.352l-4.429-2.516a.903.903 0 01-.431-.764v-5.078a.89.89 0 00-.452-.757l-.451-.26L1.38 7.158V18.39l5.311 3.047L11.126 24v-4.608a.881.881 0 00-.146-.45z" fill="#2464F5"></path></svg>

After

Width:  |  Height:  |  Size: 717 B

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Bedrock</title><defs><linearGradient id="lobe-icons-bedrock-fill" x1="80%" x2="20%" y1="20%" y2="80%"><stop offset="0%" stop-color="#6350FB"></stop><stop offset="50%" stop-color="#3D8FFF"></stop><stop offset="100%" stop-color="#9AD8F8"></stop></linearGradient></defs><path d="M13.05 15.513h3.08c.214 0 .389.177.389.394v1.82a1.704 1.704 0 011.296 1.661c0 .943-.755 1.708-1.685 1.708-.931 0-1.686-.765-1.686-1.708 0-.807.554-1.484 1.297-1.662v-1.425h-2.69v4.663a.395.395 0 01-.188.338l-2.69 1.641a.385.385 0 01-.405-.002l-4.926-3.086a.395.395 0 01-.185-.336V16.3L2.196 14.87A.395.395 0 012 14.555L2 14.528V9.406c0-.14.073-.27.192-.34l2.465-1.462V4.448c0-.129.062-.249.165-.322l.021-.014L9.77 1.058a.385.385 0 01.407 0l2.69 1.675a.395.395 0 01.185.336V7.6h3.856V5.683a1.704 1.704 0 01-1.296-1.662c0-.943.755-1.708 1.685-1.708.931 0 1.685.765 1.685 1.708 0 .807-.553 1.484-1.296 1.662v2.311a.391.391 0 01-.389.394h-4.245v1.806h6.624a1.69 1.69 0 011.64-1.313c.93 0 1.685.764 1.685 1.707 0 .943-.754 1.708-1.685 1.708a1.69 1.69 0 01-1.64-1.314H13.05v1.937h4.953l.915 1.18a1.66 1.66 0 01.84-.227c.931 0 1.685.764 1.685 1.707 0 .943-.754 1.708-1.685 1.708-.93 0-1.685-.765-1.685-1.708 0-.346.102-.668.276-.937l-.724-.935H13.05v1.806zM9.973 1.856L7.93 3.122V6.09h-.778V3.604L5.435 4.669v2.945l2.11 1.36L9.712 7.61V5.334h.778V7.83c0 .136-.07.263-.184.335L7.963 9.638v2.081l1.422 1.009-.446.646-1.406-.998-1.53 1.005-.423-.66 1.605-1.055v-1.99L5.038 8.29l-2.26 1.34v1.676l1.972-1.189.398.677-2.37 1.429V14.3l2.166 1.258 2.27-1.368.397.677-2.176 1.311V19.3l1.876 1.175 2.365-1.426.398.678-2.017 1.216 1.918 1.201 2.298-1.403v-5.78l-4.758 2.893-.4-.675 5.158-3.136V3.289L9.972 1.856zM16.13 18.47a.913.913 0 00-.908.92c0 .507.406.918.908.918a.913.913 0 00.907-.919.913.913 0 00-.907-.92zm3.63-3.81a.913.913 0 00-.908.92c0 .508.406.92.907.92a.913.913 0 00.908-.92.913.913 0 00-.908-.92zm1.555-4.99a.913.913 0 00-.908.92c0 .507.407.918.908.918a.913.913 0 00.907-.919.913.913 0 00-.907-.92zM17.296 3.1a.913.913 0 00-.907.92c0 .508.406.92.907.92a.913.913 0 00.908-.92.913.913 0 00-.908-.92z" fill="url(#lobe-icons-bedrock-fill)" fill-rule="nonzero"></path></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Claude</title><path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z" fill="#D97757" fill-rule="nonzero"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Cloudflare</title><path d="M16.493 17.4c.135-.52.08-.983-.161-1.338-.215-.328-.592-.519-1.05-.519l-8.663-.109a.148.148 0 01-.135-.082c-.027-.054-.027-.109-.027-.163.027-.082.108-.164.189-.164l8.744-.11c1.05-.054 2.153-.9 2.556-1.937l.511-1.31c.027-.055.027-.11.027-.164C17.92 8.91 15.66 7 12.942 7c-2.503 0-4.628 1.638-5.381 3.903a2.432 2.432 0 00-1.803-.491c-1.21.109-2.153 1.092-2.287 2.32-.027.328 0 .628.054.9C1.56 13.688 0 15.326 0 17.319c0 .19.027.355.027.545 0 .082.08.137.161.137h15.983c.08 0 .188-.055.215-.164l.107-.437" fill="#F38020"></path><path d="M19.238 11.75h-.242c-.054 0-.108.054-.135.109l-.35 1.2c-.134.52-.08.983.162 1.338.215.328.592.518 1.05.518l1.855.11c.054 0 .108.027.135.082.027.054.027.109.027.163-.027.082-.108.164-.188.164l-1.91.11c-1.05.054-2.153.9-2.557 1.937l-.134.355c-.027.055.026.137.107.137h6.592c.081 0 .162-.055.162-.137.107-.41.188-.846.188-1.31-.027-2.62-2.153-4.777-4.762-4.777" fill="#FCAD32"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Cohere</title><path clip-rule="evenodd" d="M8.128 14.099c.592 0 1.77-.033 3.398-.703 1.897-.781 5.672-2.2 8.395-3.656 1.905-1.018 2.74-2.366 2.74-4.18A4.56 4.56 0 0018.1 1H7.549A6.55 6.55 0 001 7.55c0 3.617 2.745 6.549 7.128 6.549z" fill="#39594D" fill-rule="evenodd"></path><path clip-rule="evenodd" d="M9.912 18.61a4.387 4.387 0 012.705-4.052l3.323-1.38c3.361-1.394 7.06 1.076 7.06 4.715a5.104 5.104 0 01-5.105 5.104l-3.597-.001a4.386 4.386 0 01-4.386-4.387z" fill="#D18EE2" fill-rule="evenodd"></path><path d="M4.776 14.962A3.775 3.775 0 001 18.738v.489a3.776 3.776 0 007.551 0v-.49a3.775 3.775 0 00-3.775-3.775z" fill="#FF7759"></path></svg>

After

Width:  |  Height:  |  Size: 769 B

+1
View File
@@ -0,0 +1 @@
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Coze</title><path clip-rule="evenodd" d="M3.908 9.096A8.092 8.092 0 0111.998 1h.006c4.468 0 8.09 3.628 8.09 8.096v3.392h1.942c2.23 0 2.732 3.126.615 3.828l-2.556.85v1.466a1.947 1.947 0 01-2.818 1.742l-1.42-.707c-.067-.03-.149 0-.17.071-1.147 3.587-6.225 3.587-7.373 0a.123.123 0 00-.169-.07l-1.42.706c-1.29.65-2.817-.292-2.817-1.742v-1.466l-2.557-.85c-2.122-.697-1.614-3.828.615-3.828h1.942V9.096zm4.571 2.613a.784.784 0 00-.784.784v1.568a.784.784 0 101.568 0v-1.568a.784.784 0 00-.784-.784zm7.045.779a.784.784 0 100 1.568.784.784 0 000-1.568zm-6.186 3.415a.78.78 0 00.17.254 3.517 3.517 0 004.98 0 .782.782 0 10-1.106-1.107 1.958 1.958 0 01-2.767 0 .78.78 0 00-1.277.254.78.78 0 000 .6z"></path></svg>

After

Width:  |  Height:  |  Size: 866 B

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>DeepL</title><path d="M11.563 0c.24 0 .475.065.682.187l8.197 4.756a1.383 1.383 0 01.683 1.197v9.528c0 .495-.26.949-.683 1.196l-4.79 2.78.01-.002-.155.087-.23.133a.69.69 0 00-.3.563v.386l-.16-.683-2.572 1.493a1.35 1.35 0 01-1.366 0l-8.195-4.757A1.384 1.384 0 012 15.668V6.14c0-.482.26-.936.684-1.183l8.195-4.77c.207-.122.443-.187.684-.187zm-1.27 14.023a1.405 1.405 0 00-2.038-.073 1.43 1.43 0 00.984 2.464c.368 0 .722-.144.985-.401a1.428 1.428 0 00.396-1.384l3.674-2.137-.683-.386-3.317 1.917zM9.24 6.164c-.368 0-.72.145-.983.402a1.43 1.43 0 00-.326 1.592c.075.177.187.338.326.47a1.405 1.405 0 002.021-.055l3.745 2.173.013-.009a1.427 1.427 0 00.368 1.48 1.403 1.403 0 001.967 0 1.428 1.428 0 000-2.063 1.403 1.403 0 00-1.986.02l-3.77-2.201a1.427 1.427 0 00-.39-1.407 1.405 1.405 0 00-.985-.402z" fill="#0F2B46"></path><path clip-rule="evenodd" d="M14.978 24v-3.959l-4.781 1.182" fill="#0F2B46" fill-rule="evenodd"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>DeepSeek</title><path d="M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 01-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 00-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 01-.465.137 9.597 9.597 0 00-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 001.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 011.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 01.415-.287.302.302 0 01.2.288.306.306 0 01-.31.307.303.303 0 01-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 01-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 01.016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 01-.254-.078c-.11-.054-.2-.19-.114-.358.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z" fill="#4D6BFE"></path></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Dify</title><path d="M7.043 6.487c1.635 0 2.241-1.003 2.241-2.243S8.681 2 7.044 2C5.405 2 4.801 3.003 4.801 4.244c0 1.24.604 2.243 2.241 2.243z" fill="#03F"></path><path d="M14.883 6.97v1.443h-3.679v3.203h3.68v8.012H8.801V8.41h-8v3.203h4.48v8.012H0v3.203h24v-3.203h-5.6v-8.012H24V8.41h-5.6V5.206H24V2.003h-4.161a4.97 4.97 0 00-4.961 4.967h.005z" fill="#03F"></path></svg>

After

Width:  |  Height:  |  Size: 495 B

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Doubao</title><path d="M5.31 15.756c.172-3.75 1.883-5.999 2.549-6.739-3.26 2.058-5.425 5.658-6.358 8.308v1.12C1.501 21.513 4.226 24 7.59 24a6.59 6.59 0 002.2-.375c.353-.12.7-.248 1.039-.378.913-.899 1.65-1.91 2.243-2.992-4.877 2.431-7.974.072-7.763-4.5l.002.001z" fill="#1E37FC"></path><path d="M22.57 10.283c-1.212-.901-4.109-2.404-7.397-2.8.295 3.792.093 8.766-2.1 12.773a12.782 12.782 0 01-2.244 2.992c3.764-1.448 6.746-3.457 8.596-5.219 2.82-2.683 3.353-5.178 3.361-6.66a2.737 2.737 0 00-.216-1.084v-.002z" fill="#37E1BE"></path><path d="M14.303 1.867C12.955.7 11.248 0 9.39 0 7.532 0 5.883.677 4.545 1.807 2.791 3.29 1.627 5.557 1.5 8.125v9.201c.932-2.65 3.097-6.25 6.357-8.307.5-.318 1.025-.595 1.569-.829 1.883-.801 3.878-.932 5.746-.706-.222-2.83-.718-5.002-.87-5.617h.001z" fill="#A569FF"></path><path d="M17.305 4.961a199.47 199.47 0 01-1.08-1.094c-.202-.213-.398-.419-.586-.622l-1.333-1.378c.151.615.648 2.786.869 5.617 3.288.395 6.185 1.898 7.396 2.8-1.306-1.275-3.475-3.487-5.266-5.323z" fill="#1E37FC"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Fireworks</title><path clip-rule="evenodd" d="M14.8 5l-2.801 6.795L9.195 5H7.397l3.072 7.428a1.64 1.64 0 003.038.002L16.598 5H14.8zm1.196 10.352l5.124-5.244-.699-1.669-5.596 5.739a1.664 1.664 0 00-.343 1.807 1.642 1.642 0 001.516 1.012L16 17l8-.02-.699-1.669-7.303.041h-.002zM2.88 10.104l.699-1.669 5.596 5.739c.468.479.603 1.189.343 1.807a1.643 1.643 0 01-1.516 1.012l-8-.018-.002.002.699-1.669 7.303.042-5.122-5.246z" fill="#5019C5" fill-rule="evenodd"></path></svg>

After

Width:  |  Height:  |  Size: 592 B

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Gemini</title><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="#3186FF"></path><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="url(#lobe-icons-gemini-fill-0)"></path><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="url(#lobe-icons-gemini-fill-1)"></path><path d="M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z" fill="url(#lobe-icons-gemini-fill-2)"></path><defs><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-gemini-fill-0" x1="7" x2="11" y1="15.5" y2="12"><stop stop-color="#08B962"></stop><stop offset="1" stop-color="#08B962" stop-opacity="0"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-gemini-fill-1" x1="8" x2="11.5" y1="5.5" y2="11"><stop stop-color="#F94543"></stop><stop offset="1" stop-color="#F94543" stop-opacity="0"></stop></linearGradient><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-gemini-fill-2" x1="3.5" x2="17.5" y1="13.5" y2="12"><stop stop-color="#FABC12"></stop><stop offset=".46" stop-color="#FABC12" stop-opacity="0"></stop></linearGradient></defs></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

+1
View File
@@ -0,0 +1 @@
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Github</title><path d="M12 0c6.63 0 12 5.276 12 11.79-.001 5.067-3.29 9.567-8.175 11.187-.6.118-.825-.25-.825-.56 0-.398.015-1.665.015-3.242 0-1.105-.375-1.813-.81-2.181 2.67-.295 5.475-1.297 5.475-5.822 0-1.297-.465-2.344-1.23-3.169.12-.295.54-1.503-.12-3.125 0 0-1.005-.324-3.3 1.209a11.32 11.32 0 00-3-.398c-1.02 0-2.04.133-3 .398-2.295-1.518-3.3-1.209-3.3-1.209-.66 1.622-.24 2.83-.12 3.125-.765.825-1.23 1.887-1.23 3.169 0 4.51 2.79 5.527 5.46 5.822-.345.294-.66.81-.765 1.577-.69.31-2.415.81-3.495-.973-.225-.354-.9-1.223-1.845-1.209-1.005.015-.405.56.015.781.51.28 1.095 1.327 1.23 1.666.24.663 1.02 1.93 4.035 1.385 0 .988.015 1.916.015 2.196 0 .31-.225.664-.825.56C3.303 21.374-.003 16.867 0 11.791 0 5.276 5.37 0 12 0z"></path></svg>

After

Width:  |  Height:  |  Size: 907 B

+1
View File
@@ -0,0 +1 @@
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Grok</title><path d="M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815"></path></svg>

After

Width:  |  Height:  |  Size: 756 B

+1
View File
@@ -0,0 +1 @@
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Groq</title><path d="M12.036 2c-3.853-.035-7 3-7.036 6.781-.035 3.782 3.055 6.872 6.908 6.907h2.42v-2.566h-2.292c-2.407.028-4.38-1.866-4.408-4.23-.029-2.362 1.901-4.298 4.308-4.326h.1c2.407 0 4.358 1.915 4.365 4.278v6.305c0 2.342-1.944 4.25-4.323 4.279a4.375 4.375 0 01-3.033-1.252l-1.851 1.818A7 7 0 0012.029 22h.092c3.803-.056 6.858-3.083 6.879-6.816v-6.5C18.907 4.963 15.817 2 12.036 2z"></path></svg>

After

Width:  |  Height:  |  Size: 568 B

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Hunyuan</title><circle cx="12" cy="12" fill="#0055E9" r="12"></circle><path d="M12 0c.518 0 1.028.033 1.528.096A6.188 6.188 0 0112.12 12.28l-.12.001c-2.99 0-5.242 2.179-5.554 5.11-.223 2.086.353 4.412 2.242 6.146C3.672 22.1 0 17.479 0 12 0 5.373 5.373 0 12 0z" fill="#A8DFF5"></path><path d="M5.286 5a2.438 2.438 0 01.682 3.38c-3.962 5.966-3.215 10.743 2.648 15.136C3.636 22.056 0 17.452 0 12c0-1.787.39-3.482 1.09-5.006.253-.435.525-.872.817-1.311A2.438 2.438 0 015.286 5z" fill="#0055E9"></path><path d="M12.98.04c.272.021.543.053.81.093.583.106 1.117.254 1.538.44 6.638 2.927 8.07 10.052 1.748 15.642a4.125 4.125 0 01-5.822-.358c-1.51-1.706-1.3-4.184.357-5.822.858-.848 3.108-1.223 4.045-2.441 1.257-1.634 2.122-6.009-2.523-7.506L12.98.039z" fill="#00BCFF"></path><path d="M13.528.096A6.187 6.187 0 0112 12.281a5.75 5.75 0 00-1.71.255c.147-.905.595-1.784 1.321-2.501.858-.848 3.108-1.223 4.045-2.441 1.27-1.651 2.14-6.104-2.676-7.554.184.014.367.033.548.056z" fill="#ECECEE"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+1
View File
@@ -0,0 +1 @@
<svg fill="currentColor" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>LongCat</title><path clip-rule="evenodd" d="M.507 19.883a.507.507 0 01-.489-.642L4.29 3.745a1.013 1.013 0 011.533-.578l5.622 3.687a1.013 1.013 0 001.11 0L18.2 3.165a1.013 1.013 0 011.532.58l4.25 15.497a.506.506 0 01-.49.64H18.07a6.297 6.297 0 001.53-4.115v-.177a6.09 6.09 0 00-1.513-4.017l-.697-3.495a.438.438 0 00-.694-.266L14.07 9.781a.748.748 0 01-.654.121 5.156 5.156 0 00-2.833 0 .746.746 0 01-.653-.121L7.302 7.81a.435.435 0 00-.688.269l-.675 3.652a5.36 5.36 0 00-1.539 3.76v.333c0 1.474.527 2.9 1.488 4.02l.032.038H.507z" fill="#29E154" fill-rule="evenodd"></path><path d="M9.213 16.843h1.52v-3.546h-1.29l-.23 3.546zm5.573 0h-1.52v-3.546h1.29l.23 3.546z"></path></svg>

After

Width:  |  Height:  |  Size: 819 B

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Minimax</title><defs><linearGradient id="lobe-icons-minimax-fill" x1="0%" x2="100.182%" y1="50.057%" y2="50.057%"><stop offset="0%" stop-color="#E2167E"></stop><stop offset="100%" stop-color="#FE603C"></stop></linearGradient></defs><path d="M16.278 2c1.156 0 2.093.927 2.093 2.07v12.501a.74.74 0 00.744.709.74.74 0 00.743-.709V9.099a2.06 2.06 0 012.071-2.049A2.06 2.06 0 0124 9.1v6.561a.649.649 0 01-.652.645.649.649 0 01-.653-.645V9.1a.762.762 0 00-.766-.758.762.762 0 00-.766.758v7.472a2.037 2.037 0 01-2.048 2.026 2.037 2.037 0 01-2.048-2.026v-12.5a.785.785 0 00-.788-.753.785.785 0 00-.789.752l-.001 15.904A2.037 2.037 0 0113.441 22a2.037 2.037 0 01-2.048-2.026V18.04c0-.356.292-.645.652-.645.36 0 .652.289.652.645v1.934c0 .263.142.506.372.638.23.131.514.131.744 0a.734.734 0 00.372-.638V4.07c0-1.143.937-2.07 2.093-2.07zm-5.674 0c1.156 0 2.093.927 2.093 2.07v11.523a.648.648 0 01-.652.645.648.648 0 01-.652-.645V4.07a.785.785 0 00-.789-.78.785.785 0 00-.789.78v14.013a2.06 2.06 0 01-2.07 2.048 2.06 2.06 0 01-2.071-2.048V9.1a.762.762 0 00-.766-.758.762.762 0 00-.766.758v3.8a2.06 2.06 0 01-2.071 2.049A2.06 2.06 0 010 12.9v-1.378c0-.357.292-.646.652-.646.36 0 .653.29.653.646V12.9c0 .418.343.757.766.757s.766-.339.766-.757V9.099a2.06 2.06 0 012.07-2.048 2.06 2.06 0 012.071 2.048v8.984c0 .419.343.758.767.758.423 0 .766-.339.766-.758V4.07c0-1.143.937-2.07 2.093-2.07z" fill="url(#lobe-icons-minimax-fill)" fill-rule="nonzero"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Mistral</title><path d="M3.428 3.4h3.429v3.428H3.428V3.4zm13.714 0h3.43v3.428h-3.43V3.4z" fill="gold"></path><path d="M3.428 6.828h6.857v3.429H3.429V6.828zm10.286 0h6.857v3.429h-6.857V6.828z" fill="#FFAF00"></path><path d="M3.428 10.258h17.144v3.428H3.428v-3.428z" fill="#FF8205"></path><path d="M3.428 13.686h3.429v3.428H3.428v-3.428zm6.858 0h3.429v3.428h-3.429v-3.428zm6.856 0h3.43v3.428h-3.43v-3.428z" fill="#FA500F"></path><path d="M0 17.114h10.286v3.429H0v-3.429zm13.714 0H24v3.429H13.714v-3.429z" fill="#E10500"></path></svg>

After

Width:  |  Height:  |  Size: 655 B

+1
View File
@@ -0,0 +1 @@
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>MoonshotAI</title><path d="M1.052 16.916l9.539 2.552a21.007 21.007 0 00.06 2.033l5.956 1.593a11.997 11.997 0 01-5.586.865l-.18-.016-.044-.004-.084-.009-.094-.01a11.605 11.605 0 01-.157-.02l-.107-.014-.11-.016a11.962 11.962 0 01-.32-.051l-.042-.008-.075-.013-.107-.02-.07-.015-.093-.019-.075-.016-.095-.02-.097-.023-.094-.022-.068-.017-.088-.022-.09-.024-.095-.025-.082-.023-.109-.03-.062-.02-.084-.025-.093-.028-.105-.034-.058-.019-.08-.026-.09-.031-.066-.024a6.293 6.293 0 01-.044-.015l-.068-.025-.101-.037-.057-.022-.08-.03-.087-.035-.088-.035-.079-.032-.095-.04-.063-.028-.063-.027a5.655 5.655 0 01-.041-.018l-.066-.03-.103-.047-.052-.024-.096-.046-.062-.03-.084-.04-.086-.044-.093-.047-.052-.027-.103-.055-.057-.03-.058-.032a6.49 6.49 0 01-.046-.026l-.094-.053-.06-.034-.051-.03-.072-.041-.082-.05-.093-.056-.052-.032-.084-.053-.061-.039-.079-.05-.07-.047-.053-.035a7.785 7.785 0 01-.054-.036l-.044-.03-.044-.03a6.066 6.066 0 01-.04-.028l-.057-.04-.076-.054-.069-.05-.074-.054-.056-.042-.076-.057-.076-.059-.086-.067-.045-.035-.064-.052-.074-.06-.089-.073-.046-.039-.046-.039a7.516 7.516 0 01-.043-.037l-.045-.04-.061-.053-.07-.062-.068-.06-.062-.058-.067-.062-.053-.05-.088-.084a13.28 13.28 0 01-.099-.097l-.029-.028-.041-.042-.069-.07-.05-.051-.05-.053a6.457 6.457 0 01-.168-.179l-.08-.088-.062-.07-.071-.08-.042-.049-.053-.062-.058-.068-.046-.056a7.175 7.175 0 01-.027-.033l-.045-.055-.066-.082-.041-.052-.05-.064-.02-.025a11.99 11.99 0 01-1.44-2.402zm-1.02-5.794l11.353 3.037a20.468 20.468 0 00-.469 2.011l10.817 2.894a12.076 12.076 0 01-1.845 2.005L.657 15.923l-.016-.046-.035-.104a11.965 11.965 0 01-.05-.153l-.007-.023a11.896 11.896 0 01-.207-.741l-.03-.126-.018-.08-.021-.097-.018-.081-.018-.09-.017-.084-.018-.094c-.026-.141-.05-.283-.071-.426l-.017-.118-.011-.083-.013-.102a12.01 12.01 0 01-.019-.161l-.005-.047a12.12 12.12 0 01-.034-2.145zm1.593-5.15l11.948 3.196c-.368.605-.705 1.231-1.01 1.875l11.295 3.022c-.142.82-.368 1.612-.668 2.365l-11.55-3.09L.124 10.26l.015-.1.008-.049.01-.067.015-.087.018-.098c.026-.148.056-.295.088-.442l.028-.124.02-.085.024-.097c.022-.09.045-.18.07-.268l.028-.102.023-.083.03-.1.025-.082.03-.096.026-.082.031-.095a11.896 11.896 0 011.01-2.232zm4.442-4.4L17.352 4.59a20.77 20.77 0 00-1.688 1.721l7.823 2.093c.267.852.442 1.744.513 2.665L2.106 5.213l.045-.065.027-.04.04-.055.046-.065.055-.076.054-.072.064-.086.05-.065.057-.073.055-.07.06-.074.055-.069.065-.077.054-.066.066-.077.053-.06.072-.082.053-.06.067-.074.054-.058.073-.078.058-.06.063-.067.168-.17.1-.098.059-.056.076-.071a12.084 12.084 0 012.272-1.677zM12.017 0h.097l.082.001.069.001.054.002.068.002.046.001.076.003.047.002.06.003.054.002.087.005.105.007.144.011.088.007.044.004.077.008.082.008.047.005.102.012.05.006.108.014.081.01.042.006.065.01.207.032.07.012.065.011.14.026.092.018.11.022.046.01.075.016.041.01L14.7.3l.042.01.065.015.049.012.071.017.096.024.112.03.113.03.113.032.05.015.07.02.078.024.073.023.05.016.05.016.076.025.099.033.102.036.048.017.064.023.093.034.11.041.116.045.1.04.047.02.06.024.041.018.063.026.04.018.057.025.11.048.1.046.074.035.075.036.06.028.092.046.091.045.102.052.053.028.049.026.046.024.06.033.041.022.052.029.088.05.106.06.087.051.057.034.053.032.096.059.088.055.098.062.036.024.064.041.084.056.04.027.062.042.062.043.023.017c.054.037.108.075.161.114l.083.06.065.048.056.043.086.065.082.064.04.03.05.041.086.069.079.065.085.071c.712.6 1.353 1.283 1.909 2.031L7.222.994l.062-.027.065-.028.081-.034.086-.035c.113-.045.227-.09.341-.131l.096-.035.093-.033.084-.03.096-.031c.087-.03.176-.058.264-.085l.091-.027.086-.025.102-.03.085-.023.1-.026L9.04.37l.09-.023.091-.022.095-.022.09-.02.098-.021.091-.02.095-.018.092-.018.1-.018.091-.016.098-.017.092-.014.097-.015.092-.013.102-.013.091-.012.105-.012.09-.01.105-.01c.093-.01.186-.018.28-.024l.106-.008.09-.005.11-.006.093-.004.1-.004.097-.002.099-.002.197-.002z"></path></svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Nvidia</title><path d="M10.212 8.976V7.62c.127-.01.256-.017.388-.021 3.596-.117 5.957 3.184 5.957 3.184s-2.548 3.647-5.282 3.647a3.227 3.227 0 01-1.063-.175v-4.109c1.4.174 1.681.812 2.523 2.258l1.873-1.627a4.905 4.905 0 00-3.67-1.846 6.594 6.594 0 00-.729.044m0-4.476v2.025c.13-.01.259-.019.388-.024 5.002-.174 8.261 4.226 8.261 4.226s-3.743 4.69-7.643 4.69c-.338 0-.675-.031-1.007-.092v1.25c.278.038.558.057.838.057 3.629 0 6.253-1.91 8.794-4.169.421.347 2.146 1.193 2.501 1.564-2.416 2.083-8.048 3.763-11.24 3.763-.308 0-.603-.02-.894-.048V19.5H24v-15H10.21zm0 9.756v1.068c-3.356-.616-4.287-4.21-4.287-4.21a7.173 7.173 0 014.287-2.138v1.172h-.005a3.182 3.182 0 00-2.502 1.178s.615 2.276 2.507 2.931m-5.961-3.3c1.436-1.935 3.604-3.148 5.961-3.336V6.523C5.81 6.887 2 10.723 2 10.723s2.158 6.427 8.21 7.015v-1.166C5.77 16 4.25 10.958 4.25 10.958h-.002z" fill="#74B71B" fill-rule="nonzero"></path></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

+1
View File
@@ -0,0 +1 @@
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Ollama</title><path d="M7.905 1.09c.216.085.411.225.588.41.295.306.544.744.734 1.263.191.522.315 1.1.362 1.68a5.054 5.054 0 012.049-.636l.051-.004c.87-.07 1.73.087 2.48.474.101.053.2.11.297.17.05-.569.172-1.134.36-1.644.19-.52.439-.957.733-1.264a1.67 1.67 0 01.589-.41c.257-.1.53-.118.796-.042.401.114.745.368 1.016.737.248.337.434.769.561 1.287.23.934.27 2.163.115 3.645l.053.04.026.019c.757.576 1.284 1.397 1.563 2.35.435 1.487.216 3.155-.534 4.088l-.018.021.002.003c.417.762.67 1.567.724 2.4l.002.03c.064 1.065-.2 2.137-.814 3.19l-.007.01.01.024c.472 1.157.62 2.322.438 3.486l-.006.039a.651.651 0 01-.747.536.648.648 0 01-.54-.742c.167-1.033.01-2.069-.48-3.123a.643.643 0 01.04-.617l.004-.006c.604-.924.854-1.83.8-2.72-.046-.779-.325-1.544-.8-2.273a.644.644 0 01.18-.886l.009-.006c.243-.159.467-.565.58-1.12a4.229 4.229 0 00-.095-1.974c-.205-.7-.58-1.284-1.105-1.683-.595-.454-1.383-.673-2.38-.61a.653.653 0 01-.632-.371c-.314-.665-.772-1.141-1.343-1.436a3.288 3.288 0 00-1.772-.332c-1.245.099-2.343.801-2.67 1.686a.652.652 0 01-.61.425c-1.067.002-1.893.252-2.497.703-.522.39-.878.935-1.066 1.588a4.07 4.07 0 00-.068 1.886c.112.558.331 1.02.582 1.269l.008.007c.212.207.257.53.109.785-.36.622-.629 1.549-.673 2.44-.05 1.018.186 1.902.719 2.536l.016.019a.643.643 0 01.095.69c-.576 1.236-.753 2.252-.562 3.052a.652.652 0 01-1.269.298c-.243-1.018-.078-2.184.473-3.498l.014-.035-.008-.012a4.339 4.339 0 01-.598-1.309l-.005-.019a5.764 5.764 0 01-.177-1.785c.044-.91.278-1.842.622-2.59l.012-.026-.002-.002c-.293-.418-.51-.953-.63-1.545l-.005-.024a5.352 5.352 0 01.093-2.49c.262-.915.777-1.701 1.536-2.269.06-.045.123-.09.186-.132-.159-1.493-.119-2.73.112-3.67.127-.518.314-.95.562-1.287.27-.368.614-.622 1.015-.737.266-.076.54-.059.797.042zm4.116 9.09c.936 0 1.8.313 2.446.855.63.527 1.005 1.235 1.005 1.94 0 .888-.406 1.58-1.133 2.022-.62.375-1.451.557-2.403.557-1.009 0-1.871-.259-2.493-.734-.617-.47-.963-1.13-.963-1.845 0-.707.398-1.417 1.056-1.946.668-.537 1.55-.849 2.485-.849zm0 .896a3.07 3.07 0 00-1.916.65c-.461.37-.722.835-.722 1.25 0 .428.21.829.61 1.134.455.347 1.124.548 1.943.548.799 0 1.473-.147 1.932-.426.463-.28.7-.686.7-1.257 0-.423-.246-.89-.683-1.256-.484-.405-1.14-.643-1.864-.643zm.662 1.21l.004.004c.12.151.095.37-.056.49l-.292.23v.446a.375.375 0 01-.376.373.375.375 0 01-.376-.373v-.46l-.271-.218a.347.347 0 01-.052-.49.353.353 0 01.494-.051l.215.172.22-.174a.353.353 0 01.49.051zm-5.04-1.919c.478 0 .867.39.867.871a.87.87 0 01-.868.871.87.87 0 01-.867-.87.87.87 0 01.867-.872zm8.706 0c.48 0 .868.39.868.871a.87.87 0 01-.868.871.87.87 0 01-.867-.87.87.87 0 01.867-.872zM7.44 2.3l-.003.002a.659.659 0 00-.285.238l-.005.006c-.138.189-.258.467-.348.832-.17.692-.216 1.631-.124 2.782.43-.128.899-.208 1.404-.237l.01-.001.019-.034c.046-.082.095-.161.148-.239.123-.771.022-1.692-.253-2.444-.134-.364-.297-.65-.453-.813a.628.628 0 00-.107-.09L7.44 2.3zm9.174.04l-.002.001a.628.628 0 00-.107.09c-.156.163-.32.45-.453.814-.29.794-.387 1.776-.23 2.572l.058.097.008.014h.03a5.184 5.184 0 011.466.212c.086-1.124.038-2.043-.128-2.722-.09-.365-.21-.643-.349-.832l-.004-.006a.659.659 0 00-.285-.239h-.004z"></path></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

+1
View File
@@ -0,0 +1 @@
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>OpenAI</title><path d="M21.55 10.004a5.416 5.416 0 00-.478-4.501c-1.217-2.09-3.662-3.166-6.05-2.66A5.59 5.59 0 0010.831 1C8.39.995 6.224 2.546 5.473 4.838A5.553 5.553 0 001.76 7.496a5.487 5.487 0 00.691 6.5 5.416 5.416 0 00.477 4.502c1.217 2.09 3.662 3.165 6.05 2.66A5.586 5.586 0 0013.168 23c2.443.006 4.61-1.546 5.361-3.84a5.553 5.553 0 003.715-2.66 5.488 5.488 0 00-.693-6.497v.001zm-8.381 11.558a4.199 4.199 0 01-2.675-.954c.034-.018.093-.05.132-.074l4.44-2.53a.71.71 0 00.364-.623v-6.176l1.877 1.069c.02.01.033.029.036.05v5.115c-.003 2.274-1.87 4.118-4.174 4.123zM4.192 17.78a4.059 4.059 0 01-.498-2.763c.032.02.09.055.131.078l4.44 2.53c.225.13.504.13.73 0l5.42-3.088v2.138a.068.068 0 01-.027.057L9.9 19.288c-1.999 1.136-4.552.46-5.707-1.51h-.001zM3.023 8.216A4.15 4.15 0 015.198 6.41l-.002.151v5.06a.711.711 0 00.364.624l5.42 3.087-1.876 1.07a.067.067 0 01-.063.005l-4.489-2.559c-1.995-1.14-2.679-3.658-1.53-5.63h.001zm15.417 3.54l-5.42-3.088L14.896 7.6a.067.067 0 01.063-.006l4.489 2.557c1.998 1.14 2.683 3.662 1.529 5.633a4.163 4.163 0 01-2.174 1.807V12.38a.71.71 0 00-.363-.623zm1.867-2.773a6.04 6.04 0 00-.132-.078l-4.44-2.53a.731.731 0 00-.729 0l-5.42 3.088V7.325a.068.068 0 01.027-.057L14.1 4.713c2-1.137 4.555-.46 5.707 1.513.487.833.664 1.809.499 2.757h.001zm-11.741 3.81l-1.877-1.068a.065.065 0 01-.036-.051V6.559c.001-2.277 1.873-4.122 4.181-4.12.976 0 1.92.338 2.671.954-.034.018-.092.05-.131.073l-4.44 2.53a.71.71 0 00-.365.623l-.003 6.173v.002zm1.02-2.168L12 9.25l2.414 1.375v2.75L12 14.75l-2.415-1.375v-2.75z"></path></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

+1
View File
@@ -0,0 +1 @@
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>OpenRouter</title><path d="M16.804 1.957l7.22 4.105v.087L16.73 10.21l.017-2.117-.821-.03c-1.059-.028-1.611.002-2.268.11-1.064.175-2.038.577-3.147 1.352L8.345 11.03c-.284.195-.495.336-.68.455l-.515.322-.397.234.385.23.53.338c.476.314 1.17.796 2.701 1.866 1.11.775 2.083 1.177 3.147 1.352l.3.045c.694.091 1.375.094 2.825.033l.022-2.159 7.22 4.105v.087L16.589 22l.014-1.862-.635.022c-1.386.042-2.137.002-3.138-.162-1.694-.28-3.26-.926-4.881-2.059l-2.158-1.5a21.997 21.997 0 00-.755-.498l-.467-.28a55.927 55.927 0 00-.76-.43C2.908 14.73.563 14.116 0 14.116V9.888l.14.004c.564-.007 2.91-.622 3.809-1.124l1.016-.58.438-.274c.428-.28 1.072-.726 2.686-1.853 1.621-1.133 3.186-1.78 4.881-2.059 1.152-.19 1.974-.213 3.814-.138l.02-1.907z"></path></svg>

After

Width:  |  Height:  |  Size: 906 B

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Qwen</title><path d="M12.604 1.34c.393.69.784 1.382 1.174 2.075a.18.18 0 00.157.091h5.552c.174 0 .322.11.446.327l1.454 2.57c.19.337.24.478.024.837-.26.43-.513.864-.76 1.3l-.367.658c-.106.196-.223.28-.04.512l2.652 4.637c.172.301.111.494-.043.77-.437.785-.882 1.564-1.335 2.34-.159.272-.352.375-.68.37-.777-.016-1.552-.01-2.327.016a.099.099 0 00-.081.05 575.097 575.097 0 01-2.705 4.74c-.169.293-.38.363-.725.364-.997.003-2.002.004-3.017.002a.537.537 0 01-.465-.271l-1.335-2.323a.09.09 0 00-.083-.049H4.982c-.285.03-.553-.001-.805-.092l-1.603-2.77a.543.543 0 01-.002-.54l1.207-2.12a.198.198 0 000-.197 550.951 550.951 0 01-1.875-3.272l-.79-1.395c-.16-.31-.173-.496.095-.965.465-.813.927-1.625 1.387-2.436.132-.234.304-.334.584-.335a338.3 338.3 0 012.589-.001.124.124 0 00.107-.063l2.806-4.895a.488.488 0 01.422-.246c.524-.001 1.053 0 1.583-.006L11.704 1c.341-.003.724.032.9.34zm-3.432.403a.06.06 0 00-.052.03L6.254 6.788a.157.157 0 01-.135.078H3.253c-.056 0-.07.025-.041.074l5.81 10.156c.025.042.013.062-.034.063l-2.795.015a.218.218 0 00-.2.116l-1.32 2.31c-.044.078-.021.118.068.118l5.716.008c.046 0 .08.02.104.061l1.403 2.454c.046.081.092.082.139 0l5.006-8.76.783-1.382a.055.055 0 01.096 0l1.424 2.53a.122.122 0 00.107.062l2.763-.02a.04.04 0 00.035-.02.041.041 0 000-.04l-2.9-5.086a.108.108 0 010-.113l.293-.507 1.12-1.977c.024-.041.012-.062-.035-.062H9.2c-.059 0-.073-.026-.043-.077l1.434-2.505a.107.107 0 000-.114L9.225 1.774a.06.06 0 00-.053-.031zm6.29 8.02c.046 0 .058.02.034.06l-.832 1.465-2.613 4.585a.056.056 0 01-.05.029.058.058 0 01-.05-.029L8.498 9.841c-.02-.034-.01-.052.028-.054l.216-.012 6.722-.012z" fill="url(#lobe-icons-qwen-fill)" fill-rule="nonzero"></path><defs><linearGradient id="lobe-icons-qwen-fill" x1="0%" x2="100%" y1="0%" y2="0%"><stop offset="0%" stop-color="#6336E7" stop-opacity=".84"></stop><stop offset="100%" stop-color="#6F69F7" stop-opacity=".84"></stop></linearGradient></defs></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Spark</title><path d="M2 13.08C2 9.182 4.772 6.367 9.32 2.122c-.65 7.883 6.41 8.272 5.023 12.214-.99 2.815-4.244 1.949-4.59 1.342 0 0 1.212.347 1.385-.866.174-1.213-2.252-1.862-3.81-4.937-2.6 2.988-.954 9.008 4.2 9.008 4.764 0 6.583-4.937 4.894-8.099 0 0 4.071.693 4.418 3.811.346 3.119-3.638 8.533-9.095 8.403C6.288 22.868 2 18.84 2 13.08z" fill="#3DC8F9"></path><path d="M17.852 6.107L11.615 0c-.52 5.933.866 8.374 4.894 9.485 2.729.753 3.307 1.04 4.504 2.772-.338-2.407-.78-3.812-3.161-6.15z" fill="#EA0100"></path><path clip-rule="evenodd" d="M9.033 18.323c.709.354 1.542.56 2.495.56 4.764 0 6.583-4.937 4.894-8.099 0 0 4.071.693 4.418 3.811.156 1.403-.565 3.27-1.902 4.89-3.458 1.57-7.29.84-9.905-1.162z" fill="#1652D8" fill-rule="evenodd"></path></svg>

After

Width:  |  Height:  |  Size: 882 B

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Stepfun</title><path d="M22.012 0h1.032v.927H24v.968h-.956V3.78h-1.032V1.896h-1.878v-.97h1.878V0zM2.6 12.371V1.87h.969v10.502h-.97zm10.423.66h10.95v.918h-6.208v9.579h-4.742V13.03zM5.629 3.333v12.356H0v4.51h10.386V8L20.859 8l-.003-4.668-15.227.001z" fill="url(#lobe-icons-stepfun-fill)" fill-rule="evenodd"></path><defs><linearGradient gradientUnits="userSpaceOnUse" id="lobe-icons-stepfun-fill" x1="1.646" x2="18.342" y1="1.916" y2="22.091"><stop stop-color="#01A9FF"></stop><stop offset="1" stop-color="#0160FF"></stop></linearGradient></defs></svg>

After

Width:  |  Height:  |  Size: 674 B

+1
View File
@@ -0,0 +1 @@
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>together.ai</title><path d="M17.385 11.23a4.615 4.615 0 100-9.23 4.615 4.615 0 000 9.23zm0 10.77a4.615 4.615 0 100-9.23 4.615 4.615 0 000 9.23zm-10.77 0a4.615 4.615 0 100-9.23 4.615 4.615 0 000 9.23z" opacity=".2"></path><circle cx="6.615" cy="6.615" fill="#0F6FFF" r="4.615"></circle></svg>

After

Width:  |  Height:  |  Size: 455 B

+1
View File
@@ -0,0 +1 @@
<svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Yi</title><path d="M18.62 13.927c.611 0 1.107.505 1.107 1.128v5.817c0 .623-.496 1.128-1.108 1.128a1.118 1.118 0 01-1.108-1.128v-5.817c0-.623.496-1.128 1.108-1.128zM16.59 3.052a1.094 1.094 0 011.562-.129c.466.404.522 1.116.126 1.59l-5.938 7.111v9.147c0 .624-.496 1.129-1.108 1.129a1.118 1.118 0 01-1.108-1.129v-9.477l.003-.088.01-.087c.015-.232.102-.462.261-.654l6.192-7.413zM2.906 2.256a1.094 1.094 0 011.559.157l4.387 5.45a1.142 1.142 0 01-.155 1.587 1.094 1.094 0 01-1.559-.157l-4.387-5.45a1.144 1.144 0 01.06-1.498l.095-.09z"></path><ellipse cx="20.146" cy="10.692" fill="#00FF25" rx="1.354" ry="1.379"></ellipse></svg>

After

Width:  |  Height:  |  Size: 786 B

+1
View File
@@ -0,0 +1 @@
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Zhipu</title><path d="M11.991 23.503a.24.24 0 00-.244.248.24.24 0 00.244.249.24.24 0 00.245-.249.24.24 0 00-.22-.247l-.025-.001zM9.671 5.365a1.697 1.697 0 011.099 2.132l-.071.172-.016.04-.018.054c-.07.16-.104.32-.104.498-.035.71.47 1.279 1.186 1.314h.366c1.309.053 2.338 1.173 2.286 2.523-.052 1.332-1.152 2.38-2.478 2.327h-.174c-.715.018-1.274.64-1.239 1.368 0 .124.018.23.053.337.209.373.54.658.96.8.75.23 1.517-.125 1.9-.782l.018-.035c.402-.64 1.17-.96 1.92-.711.854.284 1.378 1.226 1.099 2.167a1.661 1.661 0 01-2.077 1.102 1.711 1.711 0 01-.907-.711l-.017-.035c-.2-.323-.463-.58-.851-.711l-.056-.018a1.646 1.646 0 00-1.954.746 1.66 1.66 0 01-1.065.764 1.677 1.677 0 01-1.989-1.279c-.209-.906.332-1.83 1.257-2.043a1.51 1.51 0 01.296-.035h.018c.68-.071 1.151-.622 1.116-1.333a1.307 1.307 0 00-.227-.693 2.515 2.515 0 01-.366-1.403 2.39 2.39 0 01.366-1.208c.14-.195.21-.444.227-.693.018-.71-.506-1.261-1.186-1.332l-.07-.018a1.43 1.43 0 01-.299-.07l-.05-.019a1.7 1.7 0 01-1.047-2.114 1.68 1.68 0 012.094-1.101zm-5.575 10.11c.26-.264.639-.367.994-.27.355.096.633.379.728.74.095.362-.007.748-.267 1.013-.402.41-1.053.41-1.455 0a1.062 1.062 0 010-1.482zm14.845-.294c.359-.09.738.024.992.297.254.274.344.665.237 1.025-.107.36-.396.634-.756.718-.551.128-1.1-.22-1.23-.781a1.05 1.05 0 01.757-1.26zm-.064-4.39c.314.32.49.753.49 1.206 0 .452-.176.886-.49 1.206-.315.32-.74.5-1.185.5-.444 0-.87-.18-1.184-.5a1.727 1.727 0 010-2.412 1.654 1.654 0 012.369 0zm-11.243.163c.364.484.447 1.128.218 1.691a1.665 1.665 0 01-2.188.923c-.855-.36-1.26-1.358-.907-2.228a1.68 1.68 0 011.33-1.038c.593-.08 1.183.169 1.547.652zm11.545-4.221c.368 0 .708.2.892.524.184.324.184.724 0 1.048a1.026 1.026 0 01-.892.524c-.568 0-1.03-.47-1.03-1.048 0-.579.462-1.048 1.03-1.048zm-14.358 0c.368 0 .707.2.891.524.184.324.184.724 0 1.048a1.026 1.026 0 01-.891.524c-.569 0-1.03-.47-1.03-1.048 0-.579.461-1.048 1.03-1.048zm10.031-1.475c.925 0 1.675.764 1.675 1.706s-.75 1.705-1.675 1.705-1.674-.763-1.674-1.705c0-.942.75-1.706 1.674-1.706zm-2.626-.684c.362-.082.653-.356.761-.718a1.062 1.062 0 00-.238-1.028 1.017 1.017 0 00-.996-.294c-.547.14-.881.7-.752 1.257.13.558.675.907 1.225.783zm0 16.876c.359-.087.644-.36.75-.72a1.062 1.062 0 00-.237-1.019 1.018 1.018 0 00-.985-.301 1.037 1.037 0 00-.762.717c-.108.361-.017.754.239 1.028.245.263.606.377.953.305l.043-.01zM17.19 3.5a.631.631 0 00.628-.64c0-.355-.279-.64-.628-.64a.631.631 0 00-.628.64c0 .355.28.64.628.64zm-10.38 0a.631.631 0 00.628-.64c0-.355-.28-.64-.628-.64a.631.631 0 00-.628.64c0 .355.279.64.628.64zm-5.182 7.852a.631.631 0 00-.628.64c0 .354.28.639.628.639a.63.63 0 00.627-.606l.001-.034a.62.62 0 00-.628-.64zm5.182 9.13a.631.631 0 00-.628.64c0 .355.279.64.628.64a.631.631 0 00.628-.64c0-.355-.28-.64-.628-.64zm10.38.018a.631.631 0 00-.628.64c0 .355.28.64.628.64a.631.631 0 00.628-.64c0-.355-.279-.64-.628-.64zm5.182-9.148a.631.631 0 00-.628.64c0 .354.279.639.628.639a.631.631 0 00.628-.64c0-.355-.28-.64-.628-.64zm-.384-4.992a.24.24 0 00.244-.249.24.24 0 00-.244-.249.24.24 0 00-.244.249c0 .142.122.249.244.249zM11.991.497a.24.24 0 00.245-.248A.24.24 0 0011.99 0a.24.24 0 00-.244.249c0 .133.108.236.223.247l.021.001zM2.011 6.36a.24.24 0 00.245-.249.24.24 0 00-.244-.249.24.24 0 00-.244.249.24.24 0 00.244.249zm0 11.263a.24.24 0 00-.243.248.24.24 0 00.244.249.24.24 0 00.244-.249.252.252 0 00-.244-.248zm19.995-.018a.24.24 0 00-.245.248.24.24 0 00.245.25.24.24 0 00.244-.25.252.252 0 00-.244-.248z" fill="#3859FF" fill-rule="nonzero"></path></svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

+65
View File
@@ -1,3 +1,5 @@
@import './table.less';
.m-b-20 { .m-b-20 {
margin-bottom: 20px; margin-bottom: 20px;
} }
@@ -26,6 +28,10 @@
margin-left: 5px; margin-left: 5px;
} }
.m-l-24 {
margin-left: 24px;
}
.m-l-4 { .m-l-4 {
margin-left: 4px; margin-left: 4px;
} }
@@ -98,12 +104,22 @@
display: flex; display: flex;
} }
.flex-full {
display: flex;
flex: 1;
}
// space-between // space-between
.flex-between { .flex-between {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.justify-between {
display: flex;
justify-content: space-between;
}
.justify-center { .justify-center {
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -164,6 +180,10 @@
gap: 8px; gap: 8px;
} }
.gap-4 {
gap: 4px;
}
.gap-20 { .gap-20 {
gap: 20px; gap: 20px;
} }
@@ -220,6 +240,10 @@
margin-bottom: 0; margin-bottom: 0;
} }
.m-t-0 {
margin-top: 0;
}
.m-b-16 { .m-b-16 {
margin-bottom: 16px; margin-bottom: 16px;
} }
@@ -244,6 +268,10 @@
font-weight: var(--font-weight-bold); font-weight: var(--font-weight-bold);
} }
.text-primary {
color: var(--ant-color-text);
}
.text-secondary { .text-secondary {
color: var(--ant-color-text-secondary); color: var(--ant-color-text-secondary);
} }
@@ -252,6 +280,10 @@
color: var(--ant-color-text-tertiary); color: var(--ant-color-text-tertiary);
} }
.text-quaternary {
color: var(--ant-color-text-quaternary);
}
.tips-desc-list { .tips-desc-list {
list-style-type: decimal; list-style-type: decimal;
padding-left: 16px; padding-left: 16px;
@@ -261,6 +293,10 @@
gap: 16px; gap: 16px;
} }
.items-center {
align-items: center;
}
.color-white-tertiary { .color-white-tertiary {
color: var(--color-white-tertiary); color: var(--color-white-tertiary);
} }
@@ -319,3 +355,32 @@ textarea:hover {
.ant-result-extra { .ant-result-extra {
color: var(--ant-color-text-secondary); color: var(--ant-color-text-secondary);
} }
.text-success {
color: var(--ant-color-success);
}
.desc-fill {
font-weight: 600;
color: var(--ant-color-text);
background-color: var(--ant-color-fill-content);
line-height: 1.5;
padding: 2px 6px;
border-radius: 4px;
}
.line-6 {
line-height: 24px;
}
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}
+9 -2
View File
@@ -3,8 +3,7 @@
.ant-layout-sider-children { .ant-layout-sider-children {
border-inline: none; border-inline: none;
border-radius: 0; border-radius: 0;
// padding-inline: 16px; padding-block-end: 8px;
padding-block-end: 12px;
} }
.umi-plugin-layout-right { .umi-plugin-layout-right {
@@ -22,3 +21,11 @@
} }
} }
} }
// slider styles
.ant-slider .ant-slider-handle:hover::after,
.ant-slider .ant-slider-handle:active::after,
.ant-slider .ant-slider-handle:focus::after {
outline-width: 3px;
}
+22
View File
@@ -0,0 +1,22 @@
.ant-table-thead {
.ant-table-column-sorters {
.ant-table-column-title {
min-width: 32px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
}
.scroll-table {
.ant-table {
.ant-table-container {
.ant-table-body,
.ant-table-content {
scrollbar-width: thin;
scrollbar-color: var(--color-scrollbar-thumb) transparent;
}
}
}
}
+3
View File
@@ -0,0 +1,3 @@
import { atom } from 'jotai';
export const enabledBackendsAtom = atom<any>(null);
+15
View File
@@ -0,0 +1,15 @@
import { atom } from 'jotai';
export const benchmarkTargetInstanceAtom = atom<{
cluster_id: number | null;
model_name: string;
model_id: number | null;
model_instance_name: string;
model_instance: string[];
}>({
cluster_id: null,
model_name: '',
model_id: null,
model_instance_name: '',
model_instance: []
});
+70
View File
@@ -0,0 +1,70 @@
import { ClusterListItem } from '@/pages/cluster-management/config/types';
import { atom } from 'jotai';
// models expand keys: create, update , delete,
export const expandKeysAtom = atom<string[]>([]);
export const regionListAtom = atom<
{
datacenter: string;
label: string;
value: string;
icon: string;
sizes: string[];
}[]
>([]);
export const regionInstanceTypeListAtom = atom<
{
label: string;
value: string;
description: string;
specInfo: Record<string, any>;
vendor: string;
available: boolean;
regions: string[];
}[]
>([]);
export const regionOSImageListAtom = atom<
{
label: string;
value: string;
os_image: string;
name: string;
description: string;
vendor: string;
specInfo: Record<string, any>;
regions: string[];
}[]
>([]);
export const allRegionOSImageListAtom = atom<
{
label: string;
value: string;
regions: string[];
}[]
>([]);
export const allRegionInstanceTypeListAtom = atom<
{
label: string;
value: string;
regions: string[];
}[]
>([]);
export const fromClusterCreationAtom = atom(false);
/**
* for temporary cluster session storage during creation/editing
*/
export const clusterSessionAtom = atom<{
firstAddWorker: boolean;
firstAddCluster: boolean;
} | null>(null);
export const clusterDetailAtom = atom<ClusterListItem | null>(null);
export const workerAddedCountAtom = atom(0);
+3
View File
@@ -0,0 +1,3 @@
import { atom } from 'jotai';
export const activeModelsAtom = atom<any[]>([]);
+10
View File
@@ -0,0 +1,10 @@
import { ClusterListItem } from '@/pages/cluster-management/config/types';
import { atom } from 'jotai';
export const currentClusterAtom = atom<
(Partial<ClusterListItem> & { label?: string; value?: number }) | null
>(null);
export const addSSHKeyPageAtom = atom<{ create: boolean }>({
create: false
});
+41
View File
@@ -1,8 +1,11 @@
import { BackendOption } from '@/pages/llmodels/config/types';
import { atom, getDefaultStore } from 'jotai'; import { atom, getDefaultStore } from 'jotai';
// models expand keys: create, update , delete, // models expand keys: create, update , delete,
export const modelsExpandKeysAtom = atom<string[]>([]); export const modelsExpandKeysAtom = atom<string[]>([]);
export const modelsSessionAtom = atom<Record<string, any>>({});
export const requestIdAtom = atom<number>(0); export const requestIdAtom = atom<number>(0);
export const setRquestId = () => { export const setRquestId = () => {
@@ -16,3 +19,41 @@ export const getRequestId = () => {
const store = getDefaultStore(); const store = getDefaultStore();
return store.get(requestIdAtom); return store.get(requestIdAtom);
}; };
// store for cluster list: res.items from api
export const clusterListAtom = atom<
{
label: string;
value: number;
provider: string;
state: string;
is_default: boolean;
workers: number;
ready_workers: number;
gpus: number;
}[]
>([]);
// store for worker list: res.items from api
export const workerListAtom = atom<
{
label: string;
value: number;
cluster_id: number;
state: string;
id: number;
labels: Record<string, any>;
name: string;
}[]
>([]);
export interface BackGroupOption {
label: string;
value: string;
title?: string;
options: BackendOption[];
}
export const backendOptionsAtom = atom<BackGroupOption[]>([]);
export const resourceOverviewAtom = atom<Record<string, any>>({});
+20
View File
@@ -0,0 +1,20 @@
import { getDefaultStore } from 'jotai';
import { atomWithStorage } from 'jotai/utils';
export interface PaginationState {
perPage: number;
}
export const paginationAtom = atomWithStorage<Record<string, any>>(
'paginationStatus',
{},
undefined,
{ getOnInit: true }
);
export const getPaginationStatus = (key: string) => {
if (!key) return {};
const store = getDefaultStore();
const cache = store.get(paginationAtom);
return cache[key] || {};
};
+6
View File
@@ -0,0 +1,6 @@
import { atom } from 'jotai';
export const registerRouteConfigAtom = atom<Record<string, any>>({
initialValues: null,
create: false
});
+8 -5
View File
@@ -1,4 +1,4 @@
import { colorPrimary } from '@/config/theme'; import { COLOR_PRIMARY } from '@/config/theme';
import { atom } from 'jotai'; import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils'; import { atomWithStorage } from 'jotai/utils';
@@ -8,14 +8,16 @@ type UserSettings = {
colorPrimary: string; colorPrimary: string;
isDarkTheme: boolean; isDarkTheme: boolean;
collapsed: boolean; collapsed: boolean;
hideAddResourceModal?: boolean;
}; };
const defaultSettings: UserSettings = { export const defaultSettings: UserSettings = {
theme: 'light', theme: 'light',
mode: 'auto', mode: 'auto',
isDarkTheme: false, isDarkTheme: false,
colorPrimary: colorPrimary, colorPrimary: COLOR_PRIMARY,
collapsed: false collapsed: false,
hideAddResourceModal: false
}; };
export const getStorageUserSettings = () => { export const getStorageUserSettings = () => {
@@ -47,8 +49,9 @@ export const userSettingsHelperAtom = atom(
}; };
set(userSettingsAtom, { set(userSettingsAtom, {
...newSettings, ...newSettings,
colorPrimary: newSettings.colorPrimary || colorPrimary, colorPrimary: newSettings.colorPrimary || COLOR_PRIMARY,
isDarkTheme: newSettings.theme === 'realDark' isDarkTheme: newSettings.theme === 'realDark'
}); });
} }
); );
export const hideModalTemporarilyAtom = atom<boolean>(false);
+14
View File
@@ -0,0 +1,14 @@
import { atom } from 'jotai';
export interface SystemConfig {
grafana_url: string;
disable_builtin_observability: boolean;
debug: boolean;
grafana_model_dashboard_uid: string;
grafana_worker_dashboard_uid: string;
system_default_container_registry: string | null;
server_external_url: string | null;
showMonitoring?: boolean;
}
export const systemConfigAtom = atom<SystemConfig>({} as SystemConfig);
+25
View File
@@ -0,0 +1,25 @@
import { atom } from 'jotai';
export interface UsageTableData {
dataList: any[];
total: number;
loadend: boolean;
}
export const apiKeysTableDataAtom = atom<UsageTableData>({
dataList: [],
total: 0,
loadend: false
});
export const usersTableDataAtom = atom<UsageTableData>({
dataList: [],
total: 0,
loadend: false
});
export const modelsTableDataAtom = atom<UsageTableData>({
dataList: [],
total: 0,
loadend: false
});
+80 -2
View File
@@ -6,11 +6,15 @@ export const userAtom = atomWithStorage<any>('userInfo', null);
export const GPUStackVersionAtom = atom<{ export const GPUStackVersionAtom = atom<{
version: string; version: string;
git_commit: string; git_commit: string;
isProduction: boolean; isProd: boolean;
isDev?: boolean;
isRc?: boolean;
}>({ }>({
version: '', version: '',
git_commit: '', git_commit: '',
isProduction: false isProd: false,
isDev: false,
isRc: false
}); });
export const UpdateCheckAtom = atom<{ export const UpdateCheckAtom = atom<{
@@ -23,3 +27,77 @@ export const initialPasswordAtom = atomWithStorage<string>(
'initialPassword', 'initialPassword',
'' ''
); );
// Namespace the server creates for an Org's resources on each Kubernetes
// cluster. The format must match the backend's ``get_namespace_name``
// helper — ``gpustack-{name}`` — because the GPU-instance / storage CRDs
// (worker.gpustack.ai/v1) are namespaced and the server-side admission
// keys off this exact name. The identifier column on the unified
// Principal table is now ``name`` (post identity-consolidation rename
// of the legacy ``slug``); the namespace prefix is unchanged.
//
// Resolution path:
// 1. The Org the caller is currently acting under — the enterprise
// plugin persists ``currentOrganizationId`` (numeric) when the user
// picks an Org via OrgSwitcher.
// 2. The cluster's own owner Org — used in the platform-admin "All"
// view, where the caller has no Org context but the resource still
// has to land in *some* Org's namespace.
// 3. ``gpustack-default`` as a last resort (first load before any
// cache is hydrated, or a cluster whose owner Org is missing from
// both caches).
//
// Called outside React (umi page utilities) so it reads localStorage
// directly rather than going through a Jotai hook. The org caches are
// kept fresh by the enterprise plugin's atomWithStorage atoms, and the
// OrgSwitcher reloads the page on switch so we don't need in-process
// reactivity here.
export const getCurrentOrgNamespace = (
clusterOwnerPrincipalId?: number | null
): string => {
return (
lookupOrgNamespace(getStoredCurrentOrgId()) ??
lookupOrgNamespace(clusterOwnerPrincipalId ?? null) ??
'gpustack-default'
);
};
const getStoredCurrentOrgId = (): number | null => {
try {
const raw = localStorage.getItem('currentOrganizationId');
if (!raw) return null;
const value = JSON.parse(raw);
return typeof value === 'number' ? value : null;
} catch {
return null;
}
};
// Org caches the enterprise plugin persists. ``organizationList`` is
// the caller's member orgs; ``allOrganizations`` is admin-only (every
// Org on the platform) so admin sessions can resolve any owner Org id.
// Both are checked because ``currentOrganizationId`` is null in the
// admin "All" view but a member org's ``name`` might still cover the
// cluster-owner fallback.
const ORG_CACHE_KEYS = ['organizationList', 'allOrganizations'] as const;
const lookupOrgNamespace = (id: number | null): string | null => {
if (id == null) return null;
// Normalise both sides to strings — the stored id type varies between
// localStorage payloads (some writers stringify, others persist as a
// JSON number); strict equality would silently miss those cases.
const target = String(id);
for (const key of ORG_CACHE_KEYS) {
try {
const raw = localStorage.getItem(key);
if (!raw) continue;
const list = JSON.parse(raw) as Array<{ id: number; name?: string }>;
if (!Array.isArray(list)) continue;
const match = list.find((item) => String(item?.id) === target);
if (match?.name) return `gpustack-${match.name}`;
} catch {
// ignore malformed cache; continue checking other keys
}
}
return null;
};
+38
View File
@@ -1,5 +1,43 @@
import { defaultSettings } from '@/atoms/settings';
import { getDefaultStore } from 'jotai'; import { getDefaultStore } from 'jotai';
export const clearStorageUserSettings = () => {
try {
const savedSettings = JSON.parse(
localStorage.getItem('userSettings') || '{}'
);
// colorPrimary is an enterprise-wide branding setting (set by admins
// and applied by `onAppInit` from /enterprise/settings), not a per-user
// preference. Preserve it across login — otherwise the next layout
// mount triggers `atomWithStorage.onMount`, re-reads localStorage,
// and falls back to the default color until a full page refresh
// re-runs `applyEnterpriseSettings`.
localStorage.setItem(
'userSettings',
JSON.stringify({
...savedSettings,
hideAddResourceModal: false
})
);
} catch (error) {
console.log('Error clearing user settings:', error);
}
};
export const resetStorageUserSettings = () => {
try {
localStorage.setItem(
'userSettings',
JSON.stringify({
...defaultSettings,
colorPrimary: undefined
})
);
} catch (error) {
console.log('Error clearing user settings:', error);
}
};
export const clearAtomStorage = (atom: any) => { export const clearAtomStorage = (atom: any) => {
if (!atom) { if (!atom) {
return; return;
-167
View File
@@ -1,167 +0,0 @@
import { WarningFilled } from '@ant-design/icons';
import { Typography } from 'antd';
import { createStyles } from 'antd-style';
import classNames from 'classnames';
import React from 'react';
import styled from 'styled-components';
import OverlayScroller, { OverlayScrollerOptions } from '../overlay-scroller';
interface AlertInfoProps {
type: Global.MessageType;
message: React.ReactNode;
rows?: number;
icon?: React.ReactNode;
ellipsis?: boolean;
style?: React.CSSProperties;
contentStyle?: React.CSSProperties;
title?: React.ReactNode;
maxHeight?: number;
overlayScrollerProps?: OverlayScrollerOptions;
}
const useStyles = createStyles(({ token, css }) => {
return {
alertBlockInfo: css`
padding-block: 6px;
padding-inline: 10px 16px;
position: relative;
padding-left: 32px;
text-align: left;
border-radius: ${token.borderRadius}px;
margin: 0;
border: 1px solid transparent;
.ant-typography {
margin-bottom: 0;
}
&.danger {
border-color: ${token.colorErrorBorder};
background-color: ${token.colorErrorBg};
}
&.warning {
border-color: ${token.colorWarningBorder};
background-color: ${token.colorWarningBg};
}
&.transition {
color: ${token.geekblue7};
background: ${token.geekblue1};
border-color: ${token.geekblue3};
}
&.success {
border: 1px solid ${token.colorSuccess};
color: ${token.colorSuccessText};
background: ${token.colorSuccessBg};
.content.success {
font-weight: var(--font-weight-normal);
}
}
.title {
position: absolute;
left: 0;
top: 0;
display: flex;
height: 32px;
padding: 5px 10px;
border-radius: ${token.borderRadius}px ${token.borderRadius}px 0 0;
.info-icon {
&.danger {
color: ${token.colorErrorText};
}
&.warning {
color: ${token.colorWarningText};
}
&.transition {
color: ${token.geekblue7};
}
&.success {
color: ${token.colorSuccessText};
}
}
.text {
font-weight: var(--font-weight-bold);
}
}
`
};
});
const TitleWrapper = styled.div`
font-weight: 700;
color: var(--ant-color-text);
`;
const ContentWrapper = styled.div<{ $hasTitle: boolean }>`
word-break: break-word;
color: ${(props) =>
props.$hasTitle
? 'var(--ant-color-text-secondary)'
: 'var(--ant-color-text)'};
font-weight: var(--font-weight-500);
white-space: pre-line;
`;
const AlertInfo: React.FC<AlertInfoProps> = (props) => {
const {
message,
type,
rows = 1,
ellipsis,
style,
title,
contentStyle,
icon,
maxHeight = 86,
overlayScrollerProps = {}
} = props;
const { styles } = useStyles();
return (
<>
{message ? (
<div
className={classNames(styles.alertBlockInfo, type)}
style={{ ...style }}
>
<Typography.Paragraph
ellipsis={
ellipsis ?? {
rows: rows,
tooltip: message
}
}
>
<div className={classNames('title', type)}>
<span className={classNames('info-icon', type)}>
{icon ?? <WarningFilled />}
</span>
</div>
{title && (
<TitleWrapper className="title-text">{title}</TitleWrapper>
)}
<OverlayScroller
maxHeight={maxHeight}
style={{ ...contentStyle }}
{...overlayScrollerProps}
>
<ContentWrapper
$hasTitle={!!title}
className={classNames('content', type)}
>
{message}
</ContentWrapper>
</OverlayScroller>
</Typography.Paragraph>
</div>
) : null}
</>
);
};
export default React.memo(AlertInfo);
-47
View File
@@ -1,47 +0,0 @@
import { WarningOutlined } from '@ant-design/icons';
import { Typography } from 'antd';
import React from 'react';
interface AlertInfoProps {
type: 'danger' | 'warning';
message: string;
rows?: number;
icon?: React.ReactNode;
ellipsis?: boolean;
style?: React.CSSProperties;
}
const AlertInfo: React.FC<AlertInfoProps> = (props) => {
const { message, type, rows = 1, ellipsis, style } = props;
return (
<>
{message ? (
<Typography.Paragraph
type={type}
ellipsis={
ellipsis !== undefined
? ellipsis
: {
rows: rows,
tooltip: message
}
}
style={{
textAlign: 'center',
padding: '2px 5px',
borderRadius: 'var(--border-radius-base)',
margin: 0,
backgroundColor: 'var(--ant-color-error-bg)',
...style
}}
>
<WarningOutlined className="m-r-8" />
{message}
</Typography.Paragraph>
) : null}
</>
);
};
export default React.memo(AlertInfo);

Some files were not shown because too many files have changed in this diff Show More