Commit Graph
1617 Commits
Author SHA1 Message Date
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