Compare commits
128
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a90e02a04c | ||
|
|
9a223f9565 | ||
|
|
4150070829 | ||
|
|
62351a781f | ||
|
|
eb2561ff1e | ||
|
|
c6643f2bc9 | ||
|
|
8901118bd2 | ||
|
|
db17192e55 | ||
|
|
a1dd1ec861 | ||
|
|
a516e6ce72 | ||
|
|
2e375c6603 | ||
|
|
7d94c77c15 | ||
|
|
457d2f2f72 | ||
|
|
5e7d83e5dd | ||
|
|
b1cffe047c | ||
|
|
6509f2a4ff | ||
|
|
f719c11606 | ||
|
|
b8d7873b77 | ||
|
|
a9248a98a5 | ||
|
|
8f85e9a082 | ||
|
|
1a6d1654b2 | ||
|
|
abe705c034 | ||
|
|
8b34f68824 | ||
|
|
e37828a2cd | ||
|
|
4709661f93 | ||
|
|
1d7543f19c | ||
|
|
1cf146ca32 | ||
|
|
b05c510776 | ||
|
|
e79d5f8962 | ||
|
|
5503fdc21e | ||
|
|
36a1038d12 | ||
|
|
ee42a9d0ed | ||
|
|
28976dea4b | ||
|
|
22e5cc3aa5 | ||
|
|
3052c0b23e | ||
|
|
1c9cabf7e7 | ||
|
|
03842d1741 | ||
|
|
84304eadb7 | ||
|
|
ab3739219e | ||
|
|
7cf4932f3a | ||
|
|
032f1eefef | ||
|
|
e35be94f7c | ||
|
|
e76e2ad85a | ||
|
|
cb19cd2476 | ||
|
|
c532732ce9 | ||
|
|
2bc10dbb2e | ||
|
|
b634a03ef9 | ||
|
|
ac64bb98ad | ||
|
|
aa49539210 | ||
|
|
1f5678f781 | ||
|
|
7adc089e94 | ||
|
|
6e1e9c07ee | ||
|
|
1d55382f3b | ||
|
|
e68bb0bc4e | ||
|
|
c8e14dade5 | ||
|
|
e4c1a3f5c2 | ||
|
|
cdd6ef9cb3 | ||
|
|
737d43fd16 | ||
|
|
9f5163531c | ||
|
|
df5cf0f4e5 | ||
|
|
e160b64697 | ||
|
|
7d36c6ac4a | ||
|
|
0820edf55f | ||
|
|
12e324893f | ||
|
|
4017c4dd33 | ||
|
|
17b65d80e1 | ||
|
|
47cb3321ab | ||
|
|
547b9f617b | ||
|
|
9e7bd78693 | ||
|
|
c53d60b628 | ||
|
|
9566e0cdb2 | ||
|
|
ed3e779d22 | ||
|
|
3e2133753d | ||
|
|
736a853192 | ||
|
|
08ef2ffa9a | ||
|
|
6cf512cccd | ||
|
|
6f56e614f3 | ||
|
|
8c06862705 | ||
|
|
48159171c2 | ||
|
|
d5d0749b72 | ||
|
|
dc4dd81e11 | ||
|
|
c736e2186d | ||
|
|
7a76bda484 | ||
|
|
778ea36a9d | ||
|
|
04e1e1e566 | ||
|
|
01f66085ab | ||
|
|
ddf723525a | ||
|
|
7b18a92388 | ||
|
|
b985dcee63 | ||
|
|
77e92432ed | ||
|
|
a7b33a928b | ||
|
|
1218c6d096 | ||
|
|
6337431ed4 | ||
|
|
2ba5118bc2 | ||
|
|
12649c7ccf | ||
|
|
5d96932870 | ||
|
|
e6cfa6cf77 | ||
|
|
55d16c5681 | ||
|
|
ab75685955 | ||
|
|
bd0bf0bf63 | ||
|
|
fd050b33d9 | ||
|
|
698090b17a | ||
|
|
6f96260993 | ||
|
|
98a6b19298 | ||
|
|
ded270ff25 | ||
|
|
c8860207e8 | ||
|
|
8d045ffd8b | ||
|
|
fd7437e74a | ||
|
|
807ba866d3 | ||
|
|
5e2808d7c4 | ||
|
|
a26a3ff8f9 | ||
|
|
a2e9f69b96 | ||
|
|
ac800a303a | ||
|
|
dd542a9f29 | ||
|
|
26ce456bde | ||
|
|
7ce1faaf6c | ||
|
|
878bdaa5a7 | ||
|
|
68a7e3f66a | ||
|
|
feccc81c5f | ||
|
|
620045d7a3 | ||
|
|
6dc28d61b0 | ||
|
|
754cc29793 | ||
|
|
ed525509ea | ||
|
|
2b6f26e6c8 | ||
|
|
09821aab85 | ||
|
|
636190b8e6 | ||
|
|
e420c22a45 | ||
|
|
993f6edcc4 |
@@ -0,0 +1,143 @@
|
|||||||
|
---
|
||||||
|
name: create-crud-page
|
||||||
|
description: Scaffold a CRUD list/table page module in the gpustack-ui monorepo. Use when creating a new page module, building a list/table page, adding a create/edit drawer, or setting up the components/config/forms/hooks/services structure for a feature.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Create a CRUD Table Page
|
||||||
|
|
||||||
|
## Inputs (do this first)
|
||||||
|
|
||||||
|
- The argument passed to this skill is the **module name** (e.g. `/create-crud-page api-keys` → module `api-keys`). If no name was given, ask for it.
|
||||||
|
- **Always ask the user for the API documentation before generating any code**, even if a module name was provided:
|
||||||
|
|
||||||
|
> Where is the API documentation for this module? (OpenAPI/Swagger URL, schema file path, or an interface description)
|
||||||
|
|
||||||
|
- Wait for the answer, then read/fetch it. Derive `config/types.ts` (`FormData`, `ListItem`), the `services` request hooks, and form fields from that schema. Do not guess field names or endpoints — if the doc is missing details, ask.
|
||||||
|
|
||||||
|
- **Also ask which form layout to scaffold:**
|
||||||
|
|
||||||
|
> Should the form use tabs? (1) a plain form without tabs, or (2) a tabbed form
|
||||||
|
|
||||||
|
Choose the form structure in section 3 accordingly. Default to **no tabs** unless the user picks tabs or the schema clearly has many grouped sections.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Before anything: **reuse common `components`, `hooks`, and `utils` from `@gpustack/core-ui` whenever possible.**
|
||||||
|
|
||||||
|
Reference implementation for sections below: `src/pages/model-routes`.
|
||||||
|
|
||||||
|
## Module structure
|
||||||
|
|
||||||
|
Create the module under `src/pages/{module}`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
{module}
|
||||||
|
├── components
|
||||||
|
├── config
|
||||||
|
├── forms
|
||||||
|
├── hooks
|
||||||
|
├── index.tsx
|
||||||
|
└── services
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1. components
|
||||||
|
|
||||||
|
Module-specific components.
|
||||||
|
|
||||||
|
- The create/edit form component is named `add-xxx-modal.tsx` (repo convention — keep the `-modal` suffix even though it is built with `FormDrawer`).
|
||||||
|
- Use `FormDrawer` from `@gpustack/core-ui`.
|
||||||
|
- If a table cell's render logic/structure is complex, extract it into `xxx-cell.tsx`.
|
||||||
|
|
||||||
|
## 2. config
|
||||||
|
|
||||||
|
```text
|
||||||
|
config
|
||||||
|
├── index.ts # static configs & constants
|
||||||
|
└── types.ts # TypeScript types
|
||||||
|
```
|
||||||
|
|
||||||
|
Naming: form types → `FormData`; table list item types → `ListItem`.
|
||||||
|
|
||||||
|
## 3. forms
|
||||||
|
|
||||||
|
Main form component goes in `forms/index.tsx`.
|
||||||
|
|
||||||
|
- **Complex interactions** (Form.Item split across components): create a dedicated Form Context and wrap with `FormContext.Provider`.
|
||||||
|
- **Tab-based forms**: use `ScrollSpyTabs` from `@gpustack/core-ui`, wrapping the `Form` or `FormContext.Provider`. Do not use tabs unless necessary.
|
||||||
|
- **Required-field validation**: use `getRuleMessage` for standard `input`/`select`.
|
||||||
|
- For cascading selectors and async race protection, follow the **form-patterns** skill.
|
||||||
|
|
||||||
|
## 4. hooks
|
||||||
|
|
||||||
|
- Table columns → `use-xxx-columns.tsx`.
|
||||||
|
- Open/close hooks for `add-xxx-modal.tsx` → `use-create-xxx.ts`.
|
||||||
|
|
||||||
|
## 5. index.tsx (list page entry)
|
||||||
|
|
||||||
|
- **Data fetching**: `useTableFetch` from `@gpustack/core-ui`.
|
||||||
|
- **Data display**:
|
||||||
|
- Standard table → Ant Design `Table`. Ref: `src/pages/users/index.tsx`.
|
||||||
|
- Expandable/collapsible rows → `Table` from `@gpustack/core-ui`. Ref: `src/pages/model-routes/index.tsx`.
|
||||||
|
- Card-style lists → use `InfiniteScrollerProvider`. Ref: `src/pages/backends/index.tsx`.
|
||||||
|
|
||||||
|
## 6. services
|
||||||
|
|
||||||
|
`request` is injected via a provider — do **not** create a centralized `apis` directory like in `gpustack-ui`. Define request hooks directly in `services`.
|
||||||
|
|
||||||
|
- Use `useRequest` from `@gpustack/core-ui`, or `useQueryData` (same underlying method).
|
||||||
|
- Ref: `src/pages/gpu-service/storage-types/services/use-create-storage-type.ts`.
|
||||||
|
|
||||||
|
## 7. Empty data
|
||||||
|
|
||||||
|
- Page table lists → `NoResult`.
|
||||||
|
- Simple (non-page) tables → `Empty` with `image={Empty.PRESENTED_IMAGE_SIMPLE}`.
|
||||||
|
|
||||||
|
## Common UI conventions
|
||||||
|
|
||||||
|
- **Drawer/Modal open/close**: use `useBodyScroll` from `@gpustack/core-ui`. Ref: `src/pages/model-routes/hooks/use-create-route.ts`.
|
||||||
|
- **Status display** (success/failed/processing/warning): use `StatusTag`, never `Tag` from `antd` directly. See **Status display** below. Ref: `src/pages/llmodels/components/table-list.tsx`.
|
||||||
|
- **Permission-gated visibility**: use `Access` / `useAccess`. Ref: `src/pages/access/index.tsx`.
|
||||||
|
- **Styles**: avoid `styled-components` for complex/large styling. Prefer `createStyles` for component-scoped dynamic styles, CSS Modules (`xxx.module.less`) for static structured styles.
|
||||||
|
|
||||||
|
## Status display
|
||||||
|
|
||||||
|
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` (`success`, `transitioning`, `warning`, `error`, `inactive`). Do not pass business status values such as `running` or `pending` directly.
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
name: form-patterns
|
||||||
|
description: Patterns for forms with cascading/dependent selections in the gpustack-ui monorepo. Use when building a form where picking one field derives another (pick A → auto-pick B → write form), handling async option loading on modal open, or protecting against stale async results.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Form Patterns
|
||||||
|
|
||||||
|
Theme: keep cascading selections (pick A → derive B → write form) on a single, predictable path.
|
||||||
|
|
||||||
|
## Accessing the form: `form` vs `form.current`
|
||||||
|
|
||||||
|
This is **not** absolute — it depends on the call site:
|
||||||
|
|
||||||
|
- **Inside the form component** (`forms/index.tsx`), or anywhere holding a `Form.useForm()` instance → call it directly: `form.setFieldsValue(...)`.
|
||||||
|
- **In the outer Drawer/Modal wrapper** that opens the form and holds it via `ref={form}` (`const form = useRef(null)`), driven by an `open` prop → go through the ref: `form.current?.setFieldsValue(...)`.
|
||||||
|
|
||||||
|
The reference template below is written for the **Drawer-wrapper scenario** (it reacts to `open` and owns the shared `selection` state), so it uses `form.current?` throughout. If you lift this logic into the form body with a `useForm()` instance, drop the `.current`.
|
||||||
|
|
||||||
|
## 1. No fallback for derived selection
|
||||||
|
|
||||||
|
When "pick A then auto-pick B", match by rule and return `undefined` if no match — let the form field stay empty. Do **not** silently fall back to `list[0]`; a fallback hides data issues and fakes a valid selection.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const findB = (key, list) =>
|
||||||
|
key ? list.find((x) => x.key === key) : undefined;
|
||||||
|
```
|
||||||
|
|
||||||
|
For form fields, clear with `undefined`, not `''`. In 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 rotated (modal closed and re-opened) before 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
|
||||||
|
|
||||||
|
Two cascading selectors backed by a single shared state, with a single atomic write (state + form together):
|
||||||
|
|
||||||
|
```ts
|
||||||
|
type Selection = { a?: string; b?: number };
|
||||||
|
|
||||||
|
const [selection, setSelection] = useState<Selection>({});
|
||||||
|
const sessionRef = useRef(0);
|
||||||
|
const form = useRef<any>(null); // wrapper holds the form via <Form ref={form} /> — see "Accessing the form" above
|
||||||
|
|
||||||
|
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 });
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- Module/file structure for forms lives in the **create-crud-page** skill (section 3).
|
||||||
|
- Required-field validation: use `getRuleMessage`.
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
workflow_dispatch: {}
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'main'
|
- 'main'
|
||||||
@@ -117,3 +118,20 @@ jobs:
|
|||||||
remote_path: releases/${{ steps.version.outputs.version }}.tar.gz
|
remote_path: releases/${{ steps.version.outputs.version }}.tar.gz
|
||||||
accelerate: true
|
accelerate: true
|
||||||
clean: false
|
clean: false
|
||||||
|
|
||||||
|
trigger-backend:
|
||||||
|
needs: build-publish
|
||||||
|
if: (github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/')) || github.event_name == 'workflow_dispatch'
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- name: Dispatch backend build
|
||||||
|
uses: peter-evans/repository-dispatch@v3
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.DISPATCH_PAT }}
|
||||||
|
repository: gpustack/gpustack
|
||||||
|
event-type: ui-built
|
||||||
|
client-payload: |
|
||||||
|
{
|
||||||
|
"ref": "${{ github.ref }}",
|
||||||
|
"sha": "${{ github.sha }}"
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -13,6 +13,6 @@
|
|||||||
.swc
|
.swc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.idea
|
.idea
|
||||||
.claude
|
.claude/settings.local.json
|
||||||
/dist.zip
|
/dist.zip
|
||||||
.cache
|
.cache
|
||||||
@@ -1,265 +0,0 @@
|
|||||||
# 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 });
|
|
||||||
};
|
|
||||||
```
|
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
# Agent Instructions
|
||||||
|
|
||||||
|
This project keeps a single source of truth for agent/contributor conventions in [`CLAUDE.md`](./CLAUDE.md). **Read [`CLAUDE.md`](./CLAUDE.md) and follow it.**
|
||||||
|
|
||||||
|
@CLAUDE.md
|
||||||
|
|
||||||
|
## Downstream fork workflow
|
||||||
|
|
||||||
|
This repo is a **downstream fork** that customizes the product appearance on top of
|
||||||
|
upstream `gpustack/gpustack-ui`. The mirror chain is:
|
||||||
|
|
||||||
|
```
|
||||||
|
upstream https://github.com/gpustack/gpustack-ui.git
|
||||||
|
| (fetch)
|
||||||
|
origin ssh://git@192.168.0.23:11022/root/gpustack-ui.git (private registry, also https://git.digiman.live)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Goal
|
||||||
|
|
||||||
|
Track upstream releases. When upstream changes, we pull it in, then apply our own
|
||||||
|
appearance/customization changes on a dedicated branch so we keep our look-and-feel
|
||||||
|
on top of the latest upstream product.
|
||||||
|
|
||||||
|
### Branch naming
|
||||||
|
|
||||||
|
Customization work lives on `v<upstream-version>-lofyer` branches (e.g.
|
||||||
|
`v2.2.0-lofyer`). Each time upstream ships a new version we want to follow, create a
|
||||||
|
new `v<version>-lofyer` branch from the corresponding upstream tag/branch and re-apply
|
||||||
|
(or rebase) our customizations onto it.
|
||||||
|
|
||||||
|
### Syncing from upstream
|
||||||
|
|
||||||
|
`scripts/sync-github` mirrors upstream into the private `origin` (full mirror, force
|
||||||
|
push of all branches + tags). It auto-configures the `upstream` remote on first run.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# preview only, no push
|
||||||
|
DRY_RUN=1 ./scripts/sync-github
|
||||||
|
|
||||||
|
# real sync (force-pushes every upstream branch + tag to origin)
|
||||||
|
./scripts/sync-github
|
||||||
|
|
||||||
|
# also delete origin branches that no longer exist upstream (true mirror, destructive)
|
||||||
|
PRUNE_BRANCHES=1 ./scripts/sync-github
|
||||||
|
```
|
||||||
|
|
||||||
|
Env knobs: `UPSTREAM_URL`, `ORIGIN_REMOTE`, `UPSTREAM_REMOTE`, `PRUNE_BRANCHES`,
|
||||||
|
`DRY_RUN`. After syncing, branch a fresh `v<version>-lofyer` off the updated upstream
|
||||||
|
ref and apply the appearance changes there.
|
||||||
|
|
||||||
|
### Re-applying brand customizations
|
||||||
|
|
||||||
|
`scripts/rebrand` swaps the standalone brand word `GPUStack` for our brand
|
||||||
|
(`MesaStack`) across user-facing text. It is the first appearance change to re-apply
|
||||||
|
on every new `v<version>-lofyer` branch.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# preview hits, no writes
|
||||||
|
DRY_RUN=1 ./scripts/rebrand
|
||||||
|
|
||||||
|
# apply (default GPUStack -> MesaStack)
|
||||||
|
./scripts/rebrand
|
||||||
|
|
||||||
|
# custom brand words
|
||||||
|
FROM=GPUStack TO=AcmeStack ./scripts/rebrand
|
||||||
|
```
|
||||||
|
|
||||||
|
It deliberately **does not** touch functional references — lowercase `gpustack`
|
||||||
|
(npm pkg / URLs / paths / k8s namespace), ALL-CAPS `GPUSTACK_*` constants, JS
|
||||||
|
identifiers like `getGPUStackPlugin`, and `X-*` HTTP headers — and carries a
|
||||||
|
line-level skip list for backend-contract strings matched at runtime (see
|
||||||
|
`SKIP_LINE_PATTERNS` in the script). Always review `git diff` afterwards. Logo
|
||||||
|
images under `src/assets/images/` are NOT changed by the script — replace those PNGs
|
||||||
|
separately when new brand assets are available.
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
# Repo
|
||||||
|
|
||||||
|
This is the **open source UI** (`gpustack-ui`). Common `components`, `hooks`, and `utils` are published as `@gpustack/core-ui` and consumed throughout `src`.
|
||||||
|
|
||||||
|
**Always prioritize reusing common `components`, `hooks`, and `utils` from `@gpustack/core-ui`.**
|
||||||
|
|
||||||
|
Task-specific conventions live in skills: use **create-crud-page** when building a page module, **form-patterns** when building cascading/dependent forms.
|
||||||
|
|
||||||
|
# React State and Request Patterns
|
||||||
|
|
||||||
|
Keep data flow explicit, predictable, and performant. The triggering **action** is the source of truth for UI updates — not effect-driven synchronization.
|
||||||
|
|
||||||
|
## 1. Avoid effect-driven requests
|
||||||
|
|
||||||
|
Do not use request functions as `useEffect` dependencies. Trigger requests explicitly from user actions or lifecycle entry points.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// Avoid
|
||||||
|
useEffect(() => {
|
||||||
|
fetchData();
|
||||||
|
}, [fetchData]);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Form requests should be action-driven
|
||||||
|
|
||||||
|
- Fetch form data (e.g. `Select` options) when the form first opens.
|
||||||
|
- If later requests depend on interactions, trigger them inside the interaction handler.
|
||||||
|
- Do not rely on `useEffect` dependency changes.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// Recommended
|
||||||
|
const handleOnChange = (value) => {
|
||||||
|
fetchData(value);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Update related states together
|
||||||
|
|
||||||
|
When one action updates multiple related states, update them all directly in the handler. Do not sync via `useEffect` or derive indirectly via `useMemo`.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const handleOnChange = (value) => {
|
||||||
|
setState1(...);
|
||||||
|
setState2(...);
|
||||||
|
buildState(...);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Group strongly related state
|
||||||
|
|
||||||
|
If multiple states always update together, use a single state object instead of multiple `useState` calls — fewer rerenders, more predictable transitions.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const [state, setState] = useState({ state1: ..., state2: ..., state3: ... });
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. Prefer explicit state flow
|
||||||
|
|
||||||
|
Keep request execution, state updates, and derived calculations close to the triggering action. Avoid chaining business logic through multiple `useEffect` hooks.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// Prefer
|
||||||
|
const handleAction = () => {
|
||||||
|
fetchData();
|
||||||
|
setTableData(...);
|
||||||
|
setSelectedRow(...);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. Avoid premature memoization
|
||||||
|
|
||||||
|
Do not use `useMemo` / `useCallback` unless there is a confirmed bottleneck. Overuse adds complexity, obscures state flow, and risks stale dependencies. Optimize only when necessary.
|
||||||
|
|
||||||
|
## 7. Keep request logic predictable
|
||||||
|
|
||||||
|
A user interaction should clearly show: what request fires, which states update, how the UI changes. Avoid indirect update chains from dependency-driven effects.
|
||||||
|
|
||||||
|
## 8. Prefer action-driven architecture
|
||||||
|
|
||||||
|
Prefer action-driven updates, explicit handlers, and localized state transitions over effect-driven synchronization, cross-hook implicit updates, and reactive chains between states.
|
||||||
|
|
||||||
|
# Styles
|
||||||
|
|
||||||
|
**Future direction (apply to all new code):** avoid `styled-components`. Prefer:
|
||||||
|
|
||||||
|
1. `createStyles` for component-scoped dynamic styles
|
||||||
|
2. CSS Modules (`xxx.module.less`) for structured static styles
|
||||||
|
|
||||||
|
Existing `styled-components` usage is legacy tech debt — do not migrate it wholesale, but do not add new `styled-components` either. Theme tokens (`var(--ant-color-*)`) work in all three approaches.
|
||||||
|
|
||||||
|
# Naming conventions
|
||||||
|
|
||||||
|
A page module lives under `src/pages/{module}` with this sub-structure: `components/`, `config/`, `forms/`, `hooks/`, `services/`, `index.tsx`. File naming:
|
||||||
|
|
||||||
|
- **Create/edit modal**: `add-{feature}-modal.tsx` (keep the `-modal` suffix even when built with `FormDrawer`).
|
||||||
|
- **Table columns hook**: `use-{feature}-columns.tsx`.
|
||||||
|
- **Open/close & request hooks**: `use-{verb}-{noun}.ts` (e.g. `use-create-user.ts`, `use-query-user-list.ts`).
|
||||||
|
- **Complex table cell**: extract into `{feature}-cell.tsx`.
|
||||||
|
|
||||||
|
# Config & types
|
||||||
|
|
||||||
|
- `config/types.ts` — TypeScript types. Form shape → `FormData`; table/list row → `ListItem`.
|
||||||
|
- `config/index.ts` — static constants, enums, and value/label maps (e.g. `XxxStatusValueMap`, `XxxStatusLabelMap`). Keep constants out of `types.ts`.
|
||||||
|
|
||||||
|
# Common components
|
||||||
|
|
||||||
|
Always check `@gpustack/core-ui` first. Frequently reused:
|
||||||
|
|
||||||
|
- **Drawer/Modal open/close**: `useBodyScroll`.
|
||||||
|
- **Form drawer / footer**: `FormDrawer`, `ModalFooter`.
|
||||||
|
- **Delete confirmation**: `DeleteModal`.
|
||||||
|
- **Search + bulk actions bar**: `FilterBar`.
|
||||||
|
- **Form fields**: `BaseSelect`, `Input` (labeled).
|
||||||
|
- **Text overflow**: `AutoTooltip`.
|
||||||
|
- **Icons**: `IconFont`.
|
||||||
|
- **Status display** (success/failed/processing/warning): `StatusTag`.
|
||||||
|
- **Permission-gated visibility**: `Access` / `useAccess`.
|
||||||
|
- **Request hooks**: `useRequest` / `useQueryData` / `useQueryDataList`.
|
||||||
|
- **Table data fetching**: `useTableFetch`.
|
||||||
|
- **Submit guard** (prevent double-submit): `useSubmitLock`.
|
||||||
|
- **Tabbed forms**: `ScrollSpyTabs`.
|
||||||
|
|
||||||
|
# Dynamic add-item form fields
|
||||||
|
|
||||||
|
When building a form, select the add-item component from the **shape of the field's data** (its schema). Match the schema, don't hand-roll a list UI:
|
||||||
|
|
||||||
|
- **Plain object** (key→value map) → `LabelSelector`.
|
||||||
|
- **String array** → `ListInput`. Ref `src/pages/llmodels/forms/backend-parameters-list.tsx`.
|
||||||
|
- **Object array** → `MetadataList` with a custom item renderer per entry. Ref `src/pages/llmodels/forms/model-lora-list.tsx`.
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
## 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.
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# GPUStack UI
|
# MesaStack UI
|
||||||
|
|
||||||
UI for [GPUStack](https://github.com/gpustack/gpustack).
|
UI for [MesaStack](https://github.com/gpustack/gpustack).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -77,7 +77,7 @@ export default defineConfig({
|
|||||||
antd: {
|
antd: {
|
||||||
style: 'less'
|
style: 'less'
|
||||||
},
|
},
|
||||||
title: 'GPUStack',
|
title: 'MesaStack',
|
||||||
hash: true,
|
hash: true,
|
||||||
access: {},
|
access: {},
|
||||||
model: {},
|
model: {},
|
||||||
|
|||||||
@@ -31,5 +31,6 @@ export default function createProxyTable(target?: string) {
|
|||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|
||||||
return proxyTable;
|
return proxyTable;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,6 +338,20 @@ const baseRoutes = [
|
|||||||
selectedIcon: 'icon-usage-filled',
|
selectedIcon: 'icon-usage-filled',
|
||||||
defaultIcon: 'icon-usage-outlined',
|
defaultIcon: 'icon-usage-outlined',
|
||||||
component: './usage/index'
|
component: './usage/index'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'billing',
|
||||||
|
path: '/usage/billing',
|
||||||
|
key: 'billing',
|
||||||
|
icon: 'icon-billing-outlined',
|
||||||
|
selectedIcon: 'icon-billing-filled',
|
||||||
|
defaultIcon: 'icon-billing-outlined',
|
||||||
|
hideInMenu: process.env.ENABLE_ENTERPRISE === 'true',
|
||||||
|
// OSS exposes the menu as a teaser for the enterprise billing
|
||||||
|
// module. The page itself just renders an upsell notice — the real
|
||||||
|
// billing UI lives in the enterprise plugin and shadows this route
|
||||||
|
// via `routes.extensions.ts`.
|
||||||
|
component: './billing'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
"@ant-design/pro-components": "3.1.0-0",
|
"@ant-design/pro-components": "3.1.0-0",
|
||||||
"@antv/g6": "^5.0.51",
|
"@antv/g6": "^5.0.51",
|
||||||
"@braintree/sanitize-url": "^7.1.1",
|
"@braintree/sanitize-url": "^7.1.1",
|
||||||
"@gpustack/core-ui": "^1.0.22",
|
"@gpustack/core-ui": "^1.0.32",
|
||||||
"@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",
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ export default (api: IApi) => {
|
|||||||
const info = JSON.parse(process.env.VERSION || '{}');
|
const info = JSON.parse(process.env.VERSION || '{}');
|
||||||
const env = process.env.NODE_ENV;
|
const env = process.env.NODE_ENV;
|
||||||
|
|
||||||
|
$('html').attr('lang', 'en');
|
||||||
|
|
||||||
$('html').attr('data-env', env);
|
$('html').attr('data-env', env);
|
||||||
|
|
||||||
$('html').attr(
|
$('html').attr(
|
||||||
|
|||||||
Generated
+117
-117
@@ -24,8 +24,8 @@ importers:
|
|||||||
specifier: ^7.1.1
|
specifier: ^7.1.1
|
||||||
version: 7.1.2
|
version: 7.1.2
|
||||||
'@gpustack/core-ui':
|
'@gpustack/core-ui':
|
||||||
specifier: ^1.0.22
|
specifier: ^1.0.32
|
||||||
version: 1.0.22(czdvzceysqw7iv6pct2ucnb23e)
|
version: 1.0.32(czdvzceysqw7iv6pct2ucnb23e)
|
||||||
'@huggingface/gguf':
|
'@huggingface/gguf':
|
||||||
specifier: ^0.1.7
|
specifier: ^0.1.7
|
||||||
version: 0.1.18
|
version: 0.1.18
|
||||||
@@ -49,7 +49,7 @@ importers:
|
|||||||
version: 4.17.24
|
version: 4.17.24
|
||||||
'@umijs/max':
|
'@umijs/max':
|
||||||
specifier: ^4.6.15
|
specifier: ^4.6.15
|
||||||
version: 4.6.51(@babel/core@7.29.0)(@types/node@25.6.2)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(lightningcss@1.22.1)(prettier@3.8.3)(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
version: 4.6.51(@babel/core@7.23.6)(@types/node@25.6.2)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(lightningcss@1.22.1)(prettier@3.8.3)(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
||||||
'@xterm/addon-fit':
|
'@xterm/addon-fit':
|
||||||
specifier: ^0.10.0
|
specifier: ^0.10.0
|
||||||
version: 0.10.0(@xterm/xterm@5.5.0)
|
version: 0.10.0(@xterm/xterm@5.5.0)
|
||||||
@@ -109,7 +109,7 @@ importers:
|
|||||||
version: 3.3.0
|
version: 3.3.0
|
||||||
jotai:
|
jotai:
|
||||||
specifier: ^2.8.4
|
specifier: ^2.8.4
|
||||||
version: 2.20.0(@babel/core@7.29.0)(@babel/template@7.28.6)(@types/react@18.3.28)(react@18.3.1)
|
version: 2.20.0(@babel/core@7.23.6)(@babel/template@7.28.6)(@types/react@18.3.28)(react@18.3.1)
|
||||||
js-yaml:
|
js-yaml:
|
||||||
specifier: ^4.1.0
|
specifier: ^4.1.0
|
||||||
version: 4.1.1
|
version: 4.1.1
|
||||||
@@ -205,7 +205,7 @@ importers:
|
|||||||
version: 6.4.1(css-to-react-native@3.2.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 6.4.1(css-to-react-native@3.2.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
umi-presets-pro:
|
umi-presets-pro:
|
||||||
specifier: ^2.0.3
|
specifier: ^2.0.3
|
||||||
version: 2.0.3(@babel/core@7.29.0)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(chokidar@3.6.0)(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(encoding@0.1.13)(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)(umi@4.6.51(@babel/core@7.29.0)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@9.39.4(jiti@2.7.0))(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))
|
version: 2.0.3(@babel/core@7.23.6)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(chokidar@3.6.0)(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(encoding@0.1.13)(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)(umi@4.6.51(@babel/core@7.23.6)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@9.39.4(jiti@2.7.0))(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))
|
||||||
wavesurfer.js:
|
wavesurfer.js:
|
||||||
specifier: ^7.8.8
|
specifier: ^7.8.8
|
||||||
version: 7.12.6
|
version: 7.12.6
|
||||||
@@ -233,10 +233,10 @@ importers:
|
|||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
'@umijs/plugins':
|
'@umijs/plugins':
|
||||||
specifier: ^4.4.11
|
specifier: ^4.4.11
|
||||||
version: 4.6.51(@babel/core@7.29.0)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
version: 4.6.51(@babel/core@7.23.6)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
babel-plugin-named-asset-import:
|
babel-plugin-named-asset-import:
|
||||||
specifier: ^0.3.8
|
specifier: ^0.3.8
|
||||||
version: 0.3.8(@babel/core@7.29.0)
|
version: 0.3.8(@babel/core@7.23.6)
|
||||||
case-sensitive-paths-webpack-plugin:
|
case-sensitive-paths-webpack-plugin:
|
||||||
specifier: ^2.4.0
|
specifier: ^2.4.0
|
||||||
version: 2.4.0
|
version: 2.4.0
|
||||||
@@ -1484,24 +1484,24 @@ packages:
|
|||||||
resolution: {integrity: sha512-KWk80UPIzPmUg+P0rKh6TqspRw0G6eux1PuJr+zz47ftMaZ9QDwbGzHZbtzWkl5hgayM/qrKRutllRC7D/vVXQ==, tarball: https://registry.npmjs.org/@formatjs/intl-utils/-/intl-utils-2.3.0.tgz}
|
resolution: {integrity: sha512-KWk80UPIzPmUg+P0rKh6TqspRw0G6eux1PuJr+zz47ftMaZ9QDwbGzHZbtzWkl5hgayM/qrKRutllRC7D/vVXQ==, tarball: https://registry.npmjs.org/@formatjs/intl-utils/-/intl-utils-2.3.0.tgz}
|
||||||
deprecated: the package is rather renamed to @formatjs/ecma-abstract with some changes in functionality (primarily selectUnit is removed and we don't plan to make any further changes to this package
|
deprecated: the package is rather renamed to @formatjs/ecma-abstract with some changes in functionality (primarily selectUnit is removed and we don't plan to make any further changes to this package
|
||||||
|
|
||||||
'@gpustack/core-ui@1.0.22':
|
'@gpustack/core-ui@1.0.32':
|
||||||
resolution: {integrity: sha512-uFLGalziwuojjMIeXMlCZn3tLRGA6PCa0JxLxa/+kKP+xAsy7Fcxgh4PerbTyk+P+hKnYv8cD+DPpkObDGqJgg==, tarball: https://registry.npmjs.org/@gpustack/core-ui/-/core-ui-1.0.22.tgz}
|
resolution: {integrity: sha512-kGTazoqbK2KyZgOP6gmQaRxTiQVfF2IKLGDXjJq6w6BbmJgALXFJA2v2ROjAbjEVyfTdBzyYeXfPo/JgISpMNw==, tarball: https://registry.npmjs.org/@gpustack/core-ui/-/core-ui-1.0.32.tgz}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@ant-design/icons': '>=6.0.0'
|
'@ant-design/icons': ^6.1.0
|
||||||
'@ant-design/pro-components': 3.1.0-0
|
'@ant-design/pro-components': 3.1.0-0
|
||||||
'@monaco-editor/react': ^4.6.0
|
'@monaco-editor/react': ^4.6.0
|
||||||
ahooks: '>=3.0.0'
|
ahooks: ^3.8.5
|
||||||
antd: '>=6.0.0'
|
antd: ^6.3.3
|
||||||
antd-style: '>=3.0.0'
|
antd-style: ^3.6.2
|
||||||
axios: '>=1.8.0'
|
axios: ^1.8.2
|
||||||
echarts: '>=5.0.0'
|
echarts: ^5.5.1
|
||||||
file-saver: ^2.0.5
|
file-saver: ^2.0.5
|
||||||
monaco-editor: ^0.30.1
|
monaco-editor: ^0.30.1
|
||||||
monaco-yaml: ^4.0.0
|
monaco-yaml: ^4.0.0
|
||||||
overlayscrollbars-react: ^0.5.6
|
overlayscrollbars-react: ^0.5.6
|
||||||
react: '>=18.0.0'
|
react: ^18.2.0
|
||||||
react-dom: '>=18.0.0'
|
react-dom: ^18.2.0
|
||||||
styled-components: '>=6.0.0'
|
styled-components: ^6.1.15
|
||||||
|
|
||||||
'@hono/node-server@1.19.14':
|
'@hono/node-server@1.19.14':
|
||||||
resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==, tarball: https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz}
|
resolution: {integrity: sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==, tarball: https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz}
|
||||||
@@ -9257,14 +9257,14 @@ snapshots:
|
|||||||
'@radix-ui/popper': 0.0.10
|
'@radix-ui/popper': 0.0.10
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
|
|
||||||
'@alita/plugins@3.5.5(@babel/core@7.29.0)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@alita/plugins@3.5.5(@babel/core@7.23.6)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@alita/babel-transform-jsx-class': 0.0.2
|
'@alita/babel-transform-jsx-class': 0.0.2
|
||||||
'@alita/inspx': 0.0.2(react@18.3.1)
|
'@alita/inspx': 0.0.2(react@18.3.1)
|
||||||
'@alita/request': 3.1.2
|
'@alita/request': 3.1.2
|
||||||
'@alita/types': 3.1.2
|
'@alita/types': 3.1.2
|
||||||
'@umijs/bundler-utils': 4.4.11
|
'@umijs/bundler-utils': 4.4.11
|
||||||
'@umijs/plugins': 4.4.11(@babel/core@7.29.0)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@umijs/plugins': 4.4.11(@babel/core@7.23.6)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@umijs/utils': 4.4.11
|
'@umijs/utils': 4.4.11
|
||||||
ahooks: 3.9.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
ahooks: 3.9.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
antd-mobile-alita: 2.3.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
antd-mobile-alita: 2.3.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
@@ -10134,90 +10134,90 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.29.0
|
'@babel/types': 7.29.0
|
||||||
|
|
||||||
'@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.0)':
|
'@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
|
|
||||||
'@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.29.0)':
|
'@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0)
|
'@babel/helper-module-transforms': 7.28.6(@babel/core@7.23.6)
|
||||||
'@babel/helper-plugin-utils': 7.28.6
|
'@babel/helper-plugin-utils': 7.28.6
|
||||||
'@babel/helper-simple-access': 7.27.1
|
'@babel/helper-simple-access': 7.27.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -10808,7 +10808,7 @@ snapshots:
|
|||||||
|
|
||||||
'@formatjs/intl-utils@2.3.0': {}
|
'@formatjs/intl-utils@2.3.0': {}
|
||||||
|
|
||||||
'@gpustack/core-ui@1.0.22(czdvzceysqw7iv6pct2ucnb23e)':
|
'@gpustack/core-ui@1.0.32(czdvzceysqw7iv6pct2ucnb23e)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ant-design/icons': 6.2.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@ant-design/icons': 6.2.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@ant-design/pro-components': 3.1.0-0(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@ant-design/pro-components': 3.1.0-0(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
@@ -12281,11 +12281,11 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@umijs/bundler-utoopack@4.6.51(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))':
|
'@umijs/bundler-utoopack@4.6.51(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@umijs/bundler-utils': 4.6.51
|
'@umijs/bundler-utils': 4.6.51
|
||||||
'@umijs/bundler-webpack': 4.6.51(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
'@umijs/bundler-webpack': 4.6.51(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
||||||
'@utoo/pack': 1.4.3(less-loader@11.1.0(less@4.1.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))(less@4.1.3)(postcss@8.5.14)(resolve-url-loader@5.0.0)(sass-loader@13.2.0(sass@1.54.0)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))
|
'@utoo/pack': 1.4.3(less-loader@11.1.0(less@4.1.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))(less@4.1.3)(postcss@8.5.14)(resolve-url-loader@5.0.0)(sass-loader@13.2.0(sass@1.54.0)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))
|
||||||
compression: 1.8.1
|
compression: 1.8.1
|
||||||
connect-history-api-fallback: 2.0.0
|
connect-history-api-fallback: 2.0.0
|
||||||
cors: 2.8.6
|
cors: 2.8.6
|
||||||
@@ -12553,14 +12553,14 @@ snapshots:
|
|||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
|
|
||||||
'@umijs/max@4.6.51(@babel/core@7.29.0)(@types/node@25.6.2)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(lightningcss@1.22.1)(prettier@3.8.3)(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))':
|
'@umijs/max@4.6.51(@babel/core@7.23.6)(@types/node@25.6.2)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(lightningcss@1.22.1)(prettier@3.8.3)(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@umijs/lint': 4.6.51(eslint@8.35.0)(stylelint@14.8.2)(typescript@5.9.3)
|
'@umijs/lint': 4.6.51(eslint@8.35.0)(stylelint@14.8.2)(typescript@5.9.3)
|
||||||
'@umijs/plugins': 4.6.51(@babel/core@7.29.0)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@4.24.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@umijs/plugins': 4.6.51(@babel/core@7.23.6)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@4.24.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
antd: 4.24.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
antd: 4.24.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
eslint: 8.35.0
|
eslint: 8.35.0
|
||||||
stylelint: 14.8.2
|
stylelint: 14.8.2
|
||||||
umi: 4.6.51(@babel/core@7.29.0)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@8.35.0)(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
umi: 4.6.51(@babel/core@7.23.6)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@8.35.0)(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@babel/core'
|
- '@babel/core'
|
||||||
- '@rspack/core'
|
- '@rspack/core'
|
||||||
@@ -12642,7 +12642,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tsx: 3.12.2
|
tsx: 3.12.2
|
||||||
|
|
||||||
'@umijs/plugins@4.4.11(@babel/core@7.29.0)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@umijs/plugins@4.4.11(@babel/core@7.23.6)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ahooksjs/use-request': 2.8.15(react@18.3.1)
|
'@ahooksjs/use-request': 2.8.15(react@18.3.1)
|
||||||
'@ant-design/antd-theme-variable': 1.0.0
|
'@ant-design/antd-theme-variable': 1.0.0
|
||||||
@@ -12657,7 +12657,7 @@ snapshots:
|
|||||||
antd-dayjs-webpack-plugin: 1.0.6(dayjs@1.11.20)
|
antd-dayjs-webpack-plugin: 1.0.6(dayjs@1.11.20)
|
||||||
axios: 0.27.2
|
axios: 0.27.2
|
||||||
babel-plugin-import: 1.13.8
|
babel-plugin-import: 1.13.8
|
||||||
babel-plugin-styled-components: 2.1.4(@babel/core@7.29.0)(styled-components@6.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
babel-plugin-styled-components: 2.1.4(@babel/core@7.23.6)(styled-components@6.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||||
dayjs: 1.11.20
|
dayjs: 1.11.20
|
||||||
dva-core: 2.0.4(redux@4.2.1)
|
dva-core: 2.0.4(redux@4.2.1)
|
||||||
dva-immer: 1.0.2(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
dva-immer: 1.0.2(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||||
@@ -12687,7 +12687,7 @@ snapshots:
|
|||||||
- react-native
|
- react-native
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@umijs/plugins@4.6.51(@babel/core@7.29.0)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@4.24.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@umijs/plugins@4.6.51(@babel/core@7.23.6)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@4.24.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ahooksjs/use-request': 2.8.15(react@18.3.1)
|
'@ahooksjs/use-request': 2.8.15(react@18.3.1)
|
||||||
'@ant-design/antd-theme-variable': 1.0.0
|
'@ant-design/antd-theme-variable': 1.0.0
|
||||||
@@ -12702,7 +12702,7 @@ snapshots:
|
|||||||
antd-dayjs-webpack-plugin: 1.0.6(dayjs@1.11.20)
|
antd-dayjs-webpack-plugin: 1.0.6(dayjs@1.11.20)
|
||||||
axios: 0.27.2
|
axios: 0.27.2
|
||||||
babel-plugin-import: 1.13.8
|
babel-plugin-import: 1.13.8
|
||||||
babel-plugin-styled-components: 2.1.4(@babel/core@7.29.0)(styled-components@6.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
babel-plugin-styled-components: 2.1.4(@babel/core@7.23.6)(styled-components@6.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||||
dayjs: 1.11.20
|
dayjs: 1.11.20
|
||||||
dva-core: 2.0.4(redux@4.2.1)
|
dva-core: 2.0.4(redux@4.2.1)
|
||||||
dva-immer: 1.0.2(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
dva-immer: 1.0.2(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||||
@@ -12732,7 +12732,7 @@ snapshots:
|
|||||||
- react-native
|
- react-native
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@umijs/plugins@4.6.51(@babel/core@7.29.0)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
'@umijs/plugins@4.6.51(@babel/core@7.23.6)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ahooksjs/use-request': 2.8.15(react@18.3.1)
|
'@ahooksjs/use-request': 2.8.15(react@18.3.1)
|
||||||
'@ant-design/antd-theme-variable': 1.0.0
|
'@ant-design/antd-theme-variable': 1.0.0
|
||||||
@@ -12747,7 +12747,7 @@ snapshots:
|
|||||||
antd-dayjs-webpack-plugin: 1.0.6(dayjs@1.11.20)
|
antd-dayjs-webpack-plugin: 1.0.6(dayjs@1.11.20)
|
||||||
axios: 0.27.2
|
axios: 0.27.2
|
||||||
babel-plugin-import: 1.13.8
|
babel-plugin-import: 1.13.8
|
||||||
babel-plugin-styled-components: 2.1.4(@babel/core@7.29.0)(styled-components@6.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
babel-plugin-styled-components: 2.1.4(@babel/core@7.23.6)(styled-components@6.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||||
dayjs: 1.11.20
|
dayjs: 1.11.20
|
||||||
dva-core: 2.0.4(redux@4.2.1)
|
dva-core: 2.0.4(redux@4.2.1)
|
||||||
dva-immer: 1.0.2(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
dva-immer: 1.0.2(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))
|
||||||
@@ -12777,7 +12777,7 @@ snapshots:
|
|||||||
- react-native
|
- react-native
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@umijs/preset-umi@4.6.51(@types/node@25.6.2)(@types/react@18.3.28)(lightningcss@1.22.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))':
|
'@umijs/preset-umi@4.6.51(@types/node@25.6.2)(@types/react@18.3.28)(lightningcss@1.22.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@iconify/utils': 2.1.1
|
'@iconify/utils': 2.1.1
|
||||||
'@stagewise/toolbar': 0.6.2
|
'@stagewise/toolbar': 0.6.2
|
||||||
@@ -12787,7 +12787,7 @@ snapshots:
|
|||||||
'@umijs/bundler-esbuild': 4.6.51
|
'@umijs/bundler-esbuild': 4.6.51
|
||||||
'@umijs/bundler-mako': 0.11.10(postcss@8.5.14)(sass@1.54.0)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
'@umijs/bundler-mako': 0.11.10(postcss@8.5.14)(sass@1.54.0)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
||||||
'@umijs/bundler-utils': 4.6.51
|
'@umijs/bundler-utils': 4.6.51
|
||||||
'@umijs/bundler-utoopack': 4.6.51(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
'@umijs/bundler-utoopack': 4.6.51(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
||||||
'@umijs/bundler-vite': 4.6.51(@types/node@25.6.2)(lightningcss@1.22.1)(postcss@8.5.14)(rollup@3.30.0)(sass@1.54.0)(terser@5.48.0)
|
'@umijs/bundler-vite': 4.6.51(@types/node@25.6.2)(lightningcss@1.22.1)(postcss@8.5.14)(rollup@3.30.0)(sass@1.54.0)(terser@5.48.0)
|
||||||
'@umijs/bundler-webpack': 4.6.51(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
'@umijs/bundler-webpack': 4.6.51(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
||||||
'@umijs/core': 4.6.51
|
'@umijs/core': 4.6.51
|
||||||
@@ -12870,13 +12870,13 @@ snapshots:
|
|||||||
react-helmet-async: 1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
react-helmet-async: 1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
react-router-dom: 6.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
react-router-dom: 6.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
|
|
||||||
'@umijs/request-record@1.1.4(umi@4.6.51(@babel/core@7.29.0)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@9.39.4(jiti@2.7.0))(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))':
|
'@umijs/request-record@1.1.4(umi@4.6.51(@babel/core@7.23.6)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@9.39.4(jiti@2.7.0))(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))':
|
||||||
dependencies:
|
dependencies:
|
||||||
chokidar: 3.6.0
|
chokidar: 3.6.0
|
||||||
express: 4.22.1
|
express: 4.22.1
|
||||||
lodash: 4.18.1
|
lodash: 4.18.1
|
||||||
prettier: 2.8.8
|
prettier: 2.8.8
|
||||||
umi: 4.6.51(@babel/core@7.29.0)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@9.39.4(jiti@2.7.0))(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
umi: 4.6.51(@babel/core@7.23.6)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@9.39.4(jiti@2.7.0))(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -12892,13 +12892,13 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@umijs/test@4.6.51(@babel/core@7.29.0)':
|
'@umijs/test@4.6.51(@babel/core@7.23.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.29.0)
|
'@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.23.6)
|
||||||
'@jest/types': 27.5.1
|
'@jest/types': 27.5.1
|
||||||
'@umijs/bundler-utils': 4.6.51
|
'@umijs/bundler-utils': 4.6.51
|
||||||
'@umijs/utils': 4.6.51
|
'@umijs/utils': 4.6.51
|
||||||
babel-jest: 29.7.0(@babel/core@7.29.0)
|
babel-jest: 29.7.0(@babel/core@7.23.6)
|
||||||
esbuild: 0.21.4
|
esbuild: 0.21.4
|
||||||
identity-obj-proxy: 3.0.0
|
identity-obj-proxy: 3.0.0
|
||||||
isomorphic-unfetch: 4.0.2
|
isomorphic-unfetch: 4.0.2
|
||||||
@@ -13018,7 +13018,7 @@ snapshots:
|
|||||||
'@utoo/pack-win32-x64-msvc@1.4.3':
|
'@utoo/pack-win32-x64-msvc@1.4.3':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@utoo/pack@1.4.3(less-loader@11.1.0(less@4.1.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))(less@4.1.3)(postcss@8.5.14)(resolve-url-loader@5.0.0)(sass-loader@13.2.0(sass@1.54.0)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))':
|
'@utoo/pack@1.4.3(less-loader@11.1.0(less@4.1.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))(less@4.1.3)(postcss@8.5.14)(resolve-url-loader@5.0.0)(sass-loader@13.2.0(sass@1.54.0)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.22.5
|
'@babel/code-frame': 7.22.5
|
||||||
'@hono/node-server': 1.19.14(hono@4.12.18)
|
'@hono/node-server': 1.19.14(hono@4.12.18)
|
||||||
@@ -13039,7 +13039,7 @@ snapshots:
|
|||||||
sass-loader: 13.2.0(sass@1.54.0)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
sass-loader: 13.2.0(sass@1.54.0)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
||||||
semver: 7.8.0
|
semver: 7.8.0
|
||||||
send: 0.17.1
|
send: 0.17.1
|
||||||
styled-jsx: 5.1.7(@babel/core@7.29.0)(react@18.3.1)
|
styled-jsx: 5.1.7(@babel/core@7.23.6)(react@18.3.1)
|
||||||
ws: 8.20.0
|
ws: 8.20.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@utoo/pack-darwin-arm64': 1.4.3
|
'@utoo/pack-darwin-arm64': 1.4.3
|
||||||
@@ -13555,13 +13555,13 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- debug
|
- debug
|
||||||
|
|
||||||
babel-jest@29.7.0(@babel/core@7.29.0):
|
babel-jest@29.7.0(@babel/core@7.23.6):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@jest/transform': 29.7.0
|
'@jest/transform': 29.7.0
|
||||||
'@types/babel__core': 7.20.5
|
'@types/babel__core': 7.20.5
|
||||||
babel-plugin-istanbul: 6.1.1
|
babel-plugin-istanbul: 6.1.1
|
||||||
babel-preset-jest: 29.6.3(@babel/core@7.29.0)
|
babel-preset-jest: 29.6.3(@babel/core@7.23.6)
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
slash: 3.0.0
|
slash: 3.0.0
|
||||||
@@ -13601,9 +13601,9 @@ snapshots:
|
|||||||
cosmiconfig: 7.1.0
|
cosmiconfig: 7.1.0
|
||||||
resolve: 1.22.12
|
resolve: 1.22.12
|
||||||
|
|
||||||
babel-plugin-named-asset-import@0.3.8(@babel/core@7.29.0):
|
babel-plugin-named-asset-import@0.3.8(@babel/core@7.23.6):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
|
|
||||||
babel-plugin-react-compiler@0.0.0-experimental-c23de8d-20240515:
|
babel-plugin-react-compiler@0.0.0-experimental-c23de8d-20240515:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -13615,11 +13615,11 @@ snapshots:
|
|||||||
zod: 3.25.76
|
zod: 3.25.76
|
||||||
zod-validation-error: 2.1.0(zod@3.25.76)
|
zod-validation-error: 2.1.0(zod@3.25.76)
|
||||||
|
|
||||||
babel-plugin-styled-components@2.1.4(@babel/core@7.29.0)(styled-components@6.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)):
|
babel-plugin-styled-components@2.1.4(@babel/core@7.23.6)(styled-components@6.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/helper-annotate-as-pure': 7.27.3
|
'@babel/helper-annotate-as-pure': 7.27.3
|
||||||
'@babel/helper-module-imports': 7.28.6
|
'@babel/helper-module-imports': 7.28.6
|
||||||
'@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0)
|
'@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.23.6)
|
||||||
lodash: 4.18.1
|
lodash: 4.18.1
|
||||||
picomatch: 2.3.2
|
picomatch: 2.3.2
|
||||||
styled-components: 6.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
styled-components: 6.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
@@ -13627,30 +13627,30 @@ snapshots:
|
|||||||
- '@babel/core'
|
- '@babel/core'
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.0):
|
babel-preset-current-node-syntax@1.2.0(@babel/core@7.23.6):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.0)
|
'@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.0)
|
'@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.0)
|
'@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.0)
|
'@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0)
|
'@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.0)
|
'@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.0)
|
'@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.0)
|
'@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.0)
|
'@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.0)
|
'@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.0)
|
'@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.0)
|
'@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.0)
|
'@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.0)
|
'@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.23.6)
|
||||||
'@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.0)
|
'@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.23.6)
|
||||||
|
|
||||||
babel-preset-jest@29.6.3(@babel/core@7.29.0):
|
babel-preset-jest@29.6.3(@babel/core@7.23.6):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
babel-plugin-jest-hoist: 29.6.3
|
babel-plugin-jest-hoist: 29.6.3
|
||||||
babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0)
|
babel-preset-current-node-syntax: 1.2.0(@babel/core@7.23.6)
|
||||||
|
|
||||||
babel-runtime-jsx-plus@0.1.5: {}
|
babel-runtime-jsx-plus@0.1.5: {}
|
||||||
|
|
||||||
@@ -16410,9 +16410,9 @@ snapshots:
|
|||||||
|
|
||||||
jiti@2.7.0: {}
|
jiti@2.7.0: {}
|
||||||
|
|
||||||
jotai@2.20.0(@babel/core@7.29.0)(@babel/template@7.28.6)(@types/react@18.3.28)(react@18.3.1):
|
jotai@2.20.0(@babel/core@7.23.6)(@babel/template@7.28.6)(@types/react@18.3.28)(react@18.3.1):
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
'@babel/template': 7.28.6
|
'@babel/template': 7.28.6
|
||||||
'@types/react': 18.3.28
|
'@types/react': 18.3.28
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
@@ -19805,12 +19805,12 @@ snapshots:
|
|||||||
css-to-react-native: 3.2.0
|
css-to-react-native: 3.2.0
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
|
||||||
styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1):
|
styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
client-only: 0.0.1
|
client-only: 0.0.1
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@babel/core': 7.29.0
|
'@babel/core': 7.23.6
|
||||||
|
|
||||||
stylelint-config-recommended@7.0.0(stylelint@14.8.2):
|
stylelint-config-recommended@7.0.0(stylelint@14.8.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -20164,12 +20164,12 @@ snapshots:
|
|||||||
|
|
||||||
ua-parser-js@0.7.41: {}
|
ua-parser-js@0.7.41: {}
|
||||||
|
|
||||||
umi-presets-pro@2.0.3(@babel/core@7.29.0)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(chokidar@3.6.0)(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(encoding@0.1.13)(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)(umi@4.6.51(@babel/core@7.29.0)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@9.39.4(jiti@2.7.0))(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))):
|
umi-presets-pro@2.0.3(@babel/core@7.23.6)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(chokidar@3.6.0)(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(encoding@0.1.13)(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)(umi@4.6.51(@babel/core@7.23.6)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@9.39.4(jiti@2.7.0))(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@alita/plugins': 3.5.5(@babel/core@7.29.0)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@alita/plugins': 3.5.5(@babel/core@7.23.6)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@umijs/max-plugin-openapi': 2.0.3(chokidar@3.6.0)(encoding@0.1.13)(typescript@5.9.3)
|
'@umijs/max-plugin-openapi': 2.0.3(chokidar@3.6.0)(encoding@0.1.13)(typescript@5.9.3)
|
||||||
'@umijs/plugins': 4.6.51(@babel/core@7.29.0)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@umijs/plugins': 4.6.51(@babel/core@7.23.6)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(antd@6.3.7(date-fns@2.30.0)(moment@2.30.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(dva@2.5.0-beta.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(rc-field-form@2.7.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@umijs/request-record': 1.1.4(umi@4.6.51(@babel/core@7.29.0)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@9.39.4(jiti@2.7.0))(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))
|
'@umijs/request-record': 1.1.4(umi@4.6.51(@babel/core@7.23.6)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@9.39.4(jiti@2.7.0))(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)))
|
||||||
swagger-ui-dist: 4.19.1
|
swagger-ui-dist: 4.19.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@babel/core'
|
- '@babel/core'
|
||||||
@@ -20193,17 +20193,17 @@ snapshots:
|
|||||||
isomorphic-fetch: 2.2.1
|
isomorphic-fetch: 2.2.1
|
||||||
qs: 6.15.1
|
qs: 6.15.1
|
||||||
|
|
||||||
umi@4.6.51(@babel/core@7.29.0)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@8.35.0)(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)):
|
umi@4.6.51(@babel/core@7.23.6)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@8.35.0)(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.23.6
|
'@babel/runtime': 7.23.6
|
||||||
'@umijs/bundler-utils': 4.6.51
|
'@umijs/bundler-utils': 4.6.51
|
||||||
'@umijs/bundler-webpack': 4.6.51(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
'@umijs/bundler-webpack': 4.6.51(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
||||||
'@umijs/core': 4.6.51
|
'@umijs/core': 4.6.51
|
||||||
'@umijs/lint': 4.6.51(eslint@8.35.0)(stylelint@14.8.2)(typescript@5.9.3)
|
'@umijs/lint': 4.6.51(eslint@8.35.0)(stylelint@14.8.2)(typescript@5.9.3)
|
||||||
'@umijs/preset-umi': 4.6.51(@types/node@25.6.2)(@types/react@18.3.28)(lightningcss@1.22.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
'@umijs/preset-umi': 4.6.51(@types/node@25.6.2)(@types/react@18.3.28)(lightningcss@1.22.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
||||||
'@umijs/renderer-react': 4.6.51(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@umijs/renderer-react': 4.6.51(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@umijs/server': 4.6.51
|
'@umijs/server': 4.6.51
|
||||||
'@umijs/test': 4.6.51(@babel/core@7.29.0)
|
'@umijs/test': 4.6.51(@babel/core@7.23.6)
|
||||||
'@umijs/utils': 4.6.51
|
'@umijs/utils': 4.6.51
|
||||||
prettier-plugin-organize-imports: 3.2.4(prettier@3.8.3)(typescript@5.9.3)
|
prettier-plugin-organize-imports: 3.2.4(prettier@3.8.3)(typescript@5.9.3)
|
||||||
prettier-plugin-packagejson: 2.4.3(prettier@3.8.3)
|
prettier-plugin-packagejson: 2.4.3(prettier@3.8.3)
|
||||||
@@ -20247,17 +20247,17 @@ snapshots:
|
|||||||
- webpack-hot-middleware
|
- webpack-hot-middleware
|
||||||
- webpack-plugin-serve
|
- webpack-plugin-serve
|
||||||
|
|
||||||
umi@4.6.51(@babel/core@7.29.0)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@9.39.4(jiti@2.7.0))(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)):
|
umi@4.6.51(@babel/core@7.23.6)(@types/node@25.6.2)(@types/react@18.3.28)(eslint@9.39.4(jiti@2.7.0))(lightningcss@1.22.1)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(stylelint@14.8.2)(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.23.6
|
'@babel/runtime': 7.23.6
|
||||||
'@umijs/bundler-utils': 4.6.51
|
'@umijs/bundler-utils': 4.6.51
|
||||||
'@umijs/bundler-webpack': 4.6.51(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
'@umijs/bundler-webpack': 4.6.51(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
||||||
'@umijs/core': 4.6.51
|
'@umijs/core': 4.6.51
|
||||||
'@umijs/lint': 4.6.51(eslint@9.39.4(jiti@2.7.0))(stylelint@14.8.2)(typescript@5.9.3)
|
'@umijs/lint': 4.6.51(eslint@9.39.4(jiti@2.7.0))(stylelint@14.8.2)(typescript@5.9.3)
|
||||||
'@umijs/preset-umi': 4.6.51(@types/node@25.6.2)(@types/react@18.3.28)(lightningcss@1.22.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.29.0)(react@18.3.1))(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
'@umijs/preset-umi': 4.6.51(@types/node@25.6.2)(@types/react@18.3.28)(lightningcss@1.22.1)(rollup@3.30.0)(sass@1.54.0)(styled-jsx@5.1.7(@babel/core@7.23.6)(react@18.3.1))(terser@5.48.0)(type-fest@0.20.2)(typescript@5.9.3)(webpack@5.106.2(lightningcss@1.22.1)(postcss@8.5.14))
|
||||||
'@umijs/renderer-react': 4.6.51(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
'@umijs/renderer-react': 4.6.51(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
'@umijs/server': 4.6.51
|
'@umijs/server': 4.6.51
|
||||||
'@umijs/test': 4.6.51(@babel/core@7.29.0)
|
'@umijs/test': 4.6.51(@babel/core@7.23.6)
|
||||||
'@umijs/utils': 4.6.51
|
'@umijs/utils': 4.6.51
|
||||||
prettier-plugin-organize-imports: 3.2.4(prettier@3.8.3)(typescript@5.9.3)
|
prettier-plugin-organize-imports: 3.2.4(prettier@3.8.3)(typescript@5.9.3)
|
||||||
prettier-plugin-packagejson: 2.4.3(prettier@3.8.3)
|
prettier-plugin-packagejson: 2.4.3(prettier@3.8.3)
|
||||||
|
|||||||
Executable
+102
@@ -0,0 +1,102 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# rebrand: 把面向用户的品牌标识从 GPUStack 批量替换为 MesaStack(或自定义品牌)。
|
||||||
|
#
|
||||||
|
# 设计目标:上游每次更新后,在新的 v<version>-lofyer 分支上跑一次即可重新应用品牌定制。
|
||||||
|
#
|
||||||
|
# 只替换「独立的品牌词」FROM,并刻意跳过所有功能性引用:
|
||||||
|
# - 小写 `gpustack` —— npm 包名 (@gpustack/core-ui)、URL、路径、k8s 命名空间、author(大小写敏感,天然不匹配)
|
||||||
|
# - 全大写 `GPUSTACK` —— 常量/环境变量/全局 (GPUSTACK_API_BASE_URL, __GPUSTACK_*__, GPUSTACK_UI_*)(大小写敏感,不匹配)
|
||||||
|
# - 代码标识符 —— getGPUStackPlugin / GPUStackVersionAtom / GPUStackPluginManager / GPUStackLogo 等
|
||||||
|
# (FROM 紧邻字母时视为标识符的一部分,跳过)
|
||||||
|
# - HTTP 头 X-GPUStack-* —— 后端契约 (如 X-GPUStack-Model),跳过
|
||||||
|
#
|
||||||
|
# 匹配规则:FROM 前后都不是字母(独立单词),且不是 `X-` 前缀的头名。
|
||||||
|
#
|
||||||
|
# 环境变量:
|
||||||
|
# FROM 源品牌词(默认 GPUStack)
|
||||||
|
# TO 目标品牌词(默认 MesaStack)
|
||||||
|
# DRY_RUN 设为 1 时只预览将改动的行,不写文件
|
||||||
|
#
|
||||||
|
set -e
|
||||||
|
|
||||||
|
FROM="${FROM:-GPUStack}"
|
||||||
|
TO="${TO:-MesaStack}"
|
||||||
|
DRY_RUN="${DRY_RUN:-0}"
|
||||||
|
|
||||||
|
log() { echo -e "\033[1;34m[rebrand]\033[0m $*"; }
|
||||||
|
|
||||||
|
# 大小写敏感、单词边界、排除 X- 头前缀的 Perl 正则。
|
||||||
|
# (?<![A-Za-z]) 前面不是字母 (?<!X-) 不是 X- 头 (?![A-Za-z]) 后面不是字母
|
||||||
|
# FROM 为纯字母品牌词(无正则元字符),故直接拼接,不用 \Q\E
|
||||||
|
# —— \Q\E 在「经变量插值进正则」时不会被求值,反而会破坏匹配。
|
||||||
|
PATTERN="(?<![A-Za-z])(?<!X-)${FROM}(?![A-Za-z])"
|
||||||
|
|
||||||
|
# 行级排除:某些 FROM 出现在「与后端契约绑定的字符串」里,改了会破坏运行时逻辑,
|
||||||
|
# 即使是独立单词也必须整行跳过。命中下列任一正则的行不替换。
|
||||||
|
# 已知例外:
|
||||||
|
# - llmodels/hooks/index.ts 用 startsWith() 比对后端返回的英文兼容性消息
|
||||||
|
# ("... does not exist on the GPUStack server ..."),后端仍发 GPUStack,前端不能改。
|
||||||
|
SKIP_LINE_PATTERNS=(
|
||||||
|
'does not exist on the .*server. It'"'"'s recommended'
|
||||||
|
)
|
||||||
|
skip_line() {
|
||||||
|
local line="$1" pat
|
||||||
|
for pat in "${SKIP_LINE_PATTERNS[@]}"; do
|
||||||
|
if echo "$line" | grep -qP "$pat"; then return 0; fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 待处理的已跟踪文本文件(排除 lockfile 与本脚本自身)。
|
||||||
|
mapfile -t files < <(
|
||||||
|
git ls-files -- \
|
||||||
|
'*.ts' '*.tsx' '*.js' '*.jsx' '*.json' '*.less' '*.html' '*.md' \
|
||||||
|
| grep -v 'pnpm-lock.yaml'
|
||||||
|
)
|
||||||
|
|
||||||
|
log "品牌替换: '${FROM}' -> '${TO}'"
|
||||||
|
log "候选文件: ${#files[@]}"
|
||||||
|
|
||||||
|
# 把行级排除合并成一个 perl 正则,供预览与替换共用(经环境变量传入,免去转义)。
|
||||||
|
SKIP_RE=""
|
||||||
|
for pat in "${SKIP_LINE_PATTERNS[@]}"; do
|
||||||
|
SKIP_RE="${SKIP_RE:+${SKIP_RE}|}(?:${pat})"
|
||||||
|
done
|
||||||
|
export REBRAND_SKIP_RE="${SKIP_RE}"
|
||||||
|
export REBRAND_PATTERN="${PATTERN}"
|
||||||
|
export REBRAND_TO="${TO}"
|
||||||
|
|
||||||
|
# 统计命中行(预览/确认用),已扣除被行级排除的行。
|
||||||
|
log "命中行预览(最多 40 行):"
|
||||||
|
grep -rnP "${PATTERN}" "${files[@]}" 2>/dev/null \
|
||||||
|
| { [[ -n "${SKIP_RE}" ]] && grep -vP "${SKIP_RE}" || cat; } \
|
||||||
|
| head -40 || true
|
||||||
|
total=$(grep -rnP "${PATTERN}" "${files[@]}" 2>/dev/null \
|
||||||
|
| { [[ -n "${SKIP_RE}" ]] && grep -vP "${SKIP_RE}" || cat; } | wc -l)
|
||||||
|
log "命中总行数: ${total}"
|
||||||
|
if [[ -n "${SKIP_RE}" ]]; then
|
||||||
|
skipped=$(grep -rnP "${PATTERN}" "${files[@]}" 2>/dev/null | grep -cP "${SKIP_RE}" || true)
|
||||||
|
log "行级排除(后端契约,保留 ${FROM}): ${skipped} 行"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${DRY_RUN}" == "1" ]]; then
|
||||||
|
log "DRY_RUN=1:未写入任何文件。"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 实际替换(in-place)。命中行级排除的行整行跳过。
|
||||||
|
changed=0
|
||||||
|
for f in "${files[@]}"; do
|
||||||
|
if grep -qP "${PATTERN}" "$f" 2>/dev/null; then
|
||||||
|
perl -i -pe '
|
||||||
|
my $skip = $ENV{REBRAND_SKIP_RE};
|
||||||
|
next if length($skip) && /$skip/;
|
||||||
|
s/$ENV{REBRAND_PATTERN}/$ENV{REBRAND_TO}/g;
|
||||||
|
' "$f"
|
||||||
|
changed=$((changed + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
log "已修改文件数: ${changed}"
|
||||||
|
log "完成。请用 'git diff' 复核改动。"
|
||||||
Executable
+83
@@ -0,0 +1,83 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# sync-github: 从上游 GitHub 拉取最新源码,并全量镜像同步到 192.168.0.23 私有源。
|
||||||
|
#
|
||||||
|
# 默认行为(全量镜像 / 强制):
|
||||||
|
# 1. 确保存在 upstream remote 指向 GitHub(不存在则自动添加,URL 不一致则更新)。
|
||||||
|
# 2. 从 upstream 抓取所有分支与 tag(--prune 清理已删除的远端引用)。
|
||||||
|
# 3. 将上游每个分支强制推送到私有源同名分支(force push)。
|
||||||
|
# 4. 将上游所有 tag 强制推送到私有源。
|
||||||
|
#
|
||||||
|
# 可用环境变量:
|
||||||
|
# UPSTREAM_URL 上游 GitHub 仓库地址(默认 https://github.com/gpustack/gpustack-ui.git)
|
||||||
|
# ORIGIN_REMOTE 私有源 remote 名称(默认 origin)
|
||||||
|
# UPSTREAM_REMOTE 上游 remote 名称(默认 upstream)
|
||||||
|
# PRUNE_BRANCHES 设为 1 时,删除私有源上「上游已不存在」的分支(真·镜像,破坏性,默认关闭)
|
||||||
|
# DRY_RUN 设为 1 时,仅打印将要执行的推送动作,不实际推送
|
||||||
|
#
|
||||||
|
set -e
|
||||||
|
|
||||||
|
UPSTREAM_URL="${UPSTREAM_URL:-https://github.com/gpustack/gpustack-ui.git}"
|
||||||
|
ORIGIN_REMOTE="${ORIGIN_REMOTE:-origin}"
|
||||||
|
UPSTREAM_REMOTE="${UPSTREAM_REMOTE:-upstream}"
|
||||||
|
PRUNE_BRANCHES="${PRUNE_BRANCHES:-0}"
|
||||||
|
DRY_RUN="${DRY_RUN:-0}"
|
||||||
|
|
||||||
|
log() { echo -e "\033[1;34m[sync-github]\033[0m $*"; }
|
||||||
|
warn() { echo -e "\033[1;33m[sync-github]\033[0m $*" >&2; }
|
||||||
|
|
||||||
|
run() {
|
||||||
|
if [[ "${DRY_RUN}" == "1" ]]; then
|
||||||
|
echo " (dry-run) git $*"
|
||||||
|
else
|
||||||
|
git "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1. 确保 upstream remote 指向 GitHub。
|
||||||
|
if git remote get-url "${UPSTREAM_REMOTE}" >/dev/null 2>&1; then
|
||||||
|
current_url=$(git remote get-url "${UPSTREAM_REMOTE}")
|
||||||
|
if [[ "${current_url}" != "${UPSTREAM_URL}" ]]; then
|
||||||
|
log "更新 ${UPSTREAM_REMOTE} 地址: ${current_url} -> ${UPSTREAM_URL}"
|
||||||
|
git remote set-url "${UPSTREAM_REMOTE}" "${UPSTREAM_URL}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "添加 upstream remote: ${UPSTREAM_REMOTE} -> ${UPSTREAM_URL}"
|
||||||
|
git remote add "${UPSTREAM_REMOTE}" "${UPSTREAM_URL}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
origin_url=$(git remote get-url "${ORIGIN_REMOTE}")
|
||||||
|
log "上游 (拉取): ${UPSTREAM_URL}"
|
||||||
|
log "私有源 (推送): ${origin_url}"
|
||||||
|
|
||||||
|
# 2. 抓取上游所有分支与 tag。
|
||||||
|
log "抓取上游分支与 tag..."
|
||||||
|
git fetch --prune --tags "${UPSTREAM_REMOTE}"
|
||||||
|
|
||||||
|
# 3. 逐个分支强制推送到私有源。
|
||||||
|
log "强制同步分支到私有源..."
|
||||||
|
upstream_branches=$(git for-each-ref --format='%(refname:strip=3)' "refs/remotes/${UPSTREAM_REMOTE}/" | grep -v '^HEAD$')
|
||||||
|
|
||||||
|
for branch in ${upstream_branches}; do
|
||||||
|
log " -> ${branch}"
|
||||||
|
run push --force "${ORIGIN_REMOTE}" \
|
||||||
|
"refs/remotes/${UPSTREAM_REMOTE}/${branch}:refs/heads/${branch}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# 4. 强制同步所有 tag。
|
||||||
|
log "强制同步 tag 到私有源..."
|
||||||
|
run push --force --tags "${ORIGIN_REMOTE}"
|
||||||
|
|
||||||
|
# 5. 可选:删除私有源上、上游已不存在的分支(真·镜像)。
|
||||||
|
if [[ "${PRUNE_BRANCHES}" == "1" ]]; then
|
||||||
|
warn "PRUNE_BRANCHES=1:将删除私有源上上游已不存在的分支"
|
||||||
|
origin_branches=$(git ls-remote --heads "${ORIGIN_REMOTE}" | sed 's@.*refs/heads/@@')
|
||||||
|
for branch in ${origin_branches}; do
|
||||||
|
if ! echo "${upstream_branches}" | grep -qx "${branch}"; then
|
||||||
|
warn " 删除私有源分支: ${branch}"
|
||||||
|
run push "${ORIGIN_REMOTE}" --delete "${branch}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "同步完成。"
|
||||||
+17
-85
@@ -3,9 +3,6 @@ import { GPUStackVersionAtom, UpdateCheckAtom, userAtom } 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 { DEFAULT_ENTER_PAGE, GPUSTACK_API_BASE_URL } from '@/config/settings';
|
||||||
import { COLOR_PRIMARY } from '@/config/theme/constants';
|
import { COLOR_PRIMARY } from '@/config/theme/constants';
|
||||||
import { queryClusterList } from '@/pages/cluster-management/apis';
|
|
||||||
import { ProviderValueMap } from '@/pages/cluster-management/config';
|
|
||||||
import { queryResourceEvents } from '@/pages/usage/apis/resource';
|
|
||||||
import { getGPUStackPlugin } from '@/plugins';
|
import { getGPUStackPlugin } from '@/plugins';
|
||||||
import { enterprisePluginReady } from '@/plugins/enterprise-ready';
|
import { enterprisePluginReady } from '@/plugins/enterprise-ready';
|
||||||
import { GPUStackPluginManager } from '@/plugins/manager';
|
import { GPUStackPluginManager } from '@/plugins/manager';
|
||||||
@@ -17,6 +14,10 @@ import {
|
|||||||
} from '@/services/profile/apis';
|
} from '@/services/profile/apis';
|
||||||
import { fetchSystemConfig } from '@/services/system/query-system-config';
|
import { fetchSystemConfig } from '@/services/system/query-system-config';
|
||||||
import { isOnline } from '@/utils';
|
import { isOnline } from '@/utils';
|
||||||
|
import {
|
||||||
|
markInitialStateProbed,
|
||||||
|
probeAccessFlags
|
||||||
|
} from '@/utils/access-probes';
|
||||||
import { installTenantFetch } from '@/utils/install-fetch';
|
import { installTenantFetch } from '@/utils/install-fetch';
|
||||||
import {
|
import {
|
||||||
IS_FIRST_LOGIN,
|
IS_FIRST_LOGIN,
|
||||||
@@ -41,80 +42,6 @@ const checkDefaultPage = async (userInfo: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Probes the caller's cluster list once so access predicates can gate
|
|
||||||
// GPU Service (Kubernetes-only). Cheap (one list request) and never
|
|
||||||
// blocks login — any failure just falls back to `undefined`, which
|
|
||||||
// the predicate treats as "unknown / don't restrict beyond role".
|
|
||||||
// The result is also mirrored into sessionStorage so access extensions
|
|
||||||
// that run without the initialState argument can read it (e.g. to
|
|
||||||
// override the admin shortcut in scopes where the menu shouldn't
|
|
||||||
// show even for admins).
|
|
||||||
const HAS_K8S_CLUSTER_KEY = 'hasKubernetesCluster';
|
|
||||||
const probeHasKubernetesCluster = async (): Promise<boolean | undefined> => {
|
|
||||||
try {
|
|
||||||
const res = await queryClusterList(
|
|
||||||
{ page: -1 },
|
|
||||||
{
|
|
||||||
skipErrorHandler: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const value = (res?.items ?? []).some(
|
|
||||||
(c) => c?.provider === ProviderValueMap.Kubernetes
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
window.sessionStorage.setItem(HAS_K8S_CLUSTER_KEY, JSON.stringify(value));
|
|
||||||
} catch {
|
|
||||||
// sessionStorage may be unavailable (Safari private mode); the
|
|
||||||
// access predicate already handles a missing value as "unknown".
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('probeHasKubernetesCluster error', error);
|
|
||||||
try {
|
|
||||||
window.sessionStorage.removeItem(HAS_K8S_CLUSTER_KEY);
|
|
||||||
} catch {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Probes whether the caller has ANY resource-usage events (GPU/CPU instance or
|
|
||||||
// storage lifecycle). Used alongside the cluster probe so a user who has run
|
|
||||||
// GPU instances still sees GPU Service / the full Usage page even if they
|
|
||||||
// currently have no Kubernetes cluster. Mirrored into sessionStorage for the
|
|
||||||
// access extensions; any failure → undefined ("unknown — don't restrict").
|
|
||||||
const HAS_RESOURCE_EVENTS_KEY = 'hasResourceEvents';
|
|
||||||
const probeHasResourceEvents = async (): Promise<boolean | undefined> => {
|
|
||||||
try {
|
|
||||||
// No date range = "ever"; scope is clamped to the caller server-side.
|
|
||||||
const res = await queryResourceEvents(
|
|
||||||
{ perPage: 1 },
|
|
||||||
{
|
|
||||||
skipErrorHandler: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const value = (res?.pagination?.total ?? 0) > 0;
|
|
||||||
try {
|
|
||||||
window.sessionStorage.setItem(
|
|
||||||
HAS_RESOURCE_EVENTS_KEY,
|
|
||||||
JSON.stringify(value)
|
|
||||||
);
|
|
||||||
} catch {
|
|
||||||
// sessionStorage may be unavailable; predicate treats missing as unknown.
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('probeHasResourceEvents error', error);
|
|
||||||
try {
|
|
||||||
window.sessionStorage.removeItem(HAS_RESOURCE_EVENTS_KEY);
|
|
||||||
} catch {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// runtime configuration
|
// runtime configuration
|
||||||
export async function getInitialState(): Promise<{
|
export async function getInitialState(): Promise<{
|
||||||
fetchUserInfo: () => Promise<Global.UserInfo>;
|
fetchUserInfo: () => Promise<Global.UserInfo>;
|
||||||
@@ -235,19 +162,24 @@ export async function getInitialState(): Promise<{
|
|||||||
getAppVersionInfo();
|
getAppVersionInfo();
|
||||||
|
|
||||||
if (![DEFAULT_ENTER_PAGE.login].includes(location.pathname)) {
|
if (![DEFAULT_ENTER_PAGE.login].includes(location.pathname)) {
|
||||||
const [userInfo, hasKubernetesCluster, hasResourceEvents] =
|
const [userInfo, accessFlags] = await Promise.all([
|
||||||
await Promise.all([
|
fetchUserInfo(),
|
||||||
fetchUserInfo(),
|
probeAccessFlags()
|
||||||
probeHasKubernetesCluster(),
|
]);
|
||||||
probeHasResourceEvents()
|
// Record that the probes ran for an authenticated user this page load
|
||||||
]);
|
// (the refresh path) so the layout doesn't re-probe. A failed
|
||||||
|
// fetch (empty user — e.g. unauthenticated deep link that bounces to
|
||||||
|
// login) is NOT marked: the user will log in via SPA afterwards and
|
||||||
|
// the layout becomes responsible for probing.
|
||||||
|
if (userInfo?.username) {
|
||||||
|
markInitialStateProbed();
|
||||||
|
}
|
||||||
checkDefaultPage(userInfo);
|
checkDefaultPage(userInfo);
|
||||||
return {
|
return {
|
||||||
fetchUserInfo,
|
fetchUserInfo,
|
||||||
currentUser: userInfo,
|
currentUser: userInfo,
|
||||||
pluginData,
|
pluginData,
|
||||||
hasKubernetesCluster,
|
...accessFlags
|
||||||
hasResourceEvents
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -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>AlibabaCloud</title><path d="M14.752 4.64h5.274C22.242 4.64 24 6.475 24 8.691V15.8a3.947 3.947 0 01-3.974 3.975h-5.274l1.299-1.835 3.822-1.222c.688-.23 1.146-.918 1.146-1.605v-5.81c0-.687-.458-1.375-1.146-1.605L16.05 6.475l-1.3-1.835zM2.98 15.111c0 .688.46 1.376 1.147 1.606l3.822 1.146 1.3 1.835H3.974A3.947 3.947 0 010 15.723V8.69c0-2.216 1.758-4.05 3.975-4.05h5.273L7.95 6.474 4.127 7.697c-.688.23-1.146.918-1.146 1.606v5.808z" fill="#FF6A00"></path><path d="M16.051 11.213H8.025v1.835h8.026v-1.835z" fill="#FF6A00"></path></svg>
|
||||||
|
After Width: | Height: | Size: 656 B |
@@ -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>BaiLian</title><path d="M6.336 8.919v6.162l5.335-3.083L6.337 8.92z" fill="#1C54E3"></path><path d="M21.394 5.288s-.006-.006-.01-.006L17.01 2.754 6.336 8.92l5.335 3.082 9.701-5.6.016-.01a.635.635 0 00.006-1.1v-.003z" fill="#AA9AFF"></path><path d="M21.71 12.465a.62.62 0 00-.316.085s-.006 0-.009.003l-4.375 2.528 5.05 2.915h.006a2.06 2.06 0 00.28-1.04v-3.855a.637.637 0 00-.636-.636z" fill="#00EAD1"></path><path d="M22.06 17.996l-5.05-2.915L6.34 21.242l4.27 2.465s.016.006.022.012a2.102 2.102 0 002.093 0c.006-.003.016-.006.022-.012l8.538-4.93c.003 0 .006-.003.01-.006.321-.183.589-.45.775-.772h-.006l-.004-.003z" fill="#00CEC9"></path><path d="M11.672 11.998l-5.336 3.083-1.444.832-3.605 2.083H1.28c.173.303.416.555.709.738l.078.044.016.01.02.012 4.232 2.442 10.671-6.161-5.335-3.082z" fill="#00EAD1"></path><path d="M12.74.29c-.1-.06-.208-.107-.315-.148-.02-.006-.038-.016-.057-.022a2.121 2.121 0 00-.7-.12c-.233 0-.457.038-.668.11l-.031.01a2.196 2.196 0 00-.372.17L2.068 5.222s-.003 0-.006.003c-.324.183-.592.451-.781.773h.006l5.049 2.918L17.01 2.758 12.74.29z" fill="#7347FF"></path><path d="M1.287 6.001H1.28A2.06 2.06 0 001 7.041v9.915c0 .378.1.735.28 1.043h.007l5.049-2.918V8.919l-5.05-2.918z" fill="#0423DA"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -63,6 +63,7 @@ export const fromClusterCreationAtom = atom(false);
|
|||||||
export const clusterSessionAtom = atom<{
|
export const clusterSessionAtom = atom<{
|
||||||
firstAddWorker: boolean;
|
firstAddWorker: boolean;
|
||||||
firstAddCluster: boolean;
|
firstAddCluster: boolean;
|
||||||
|
presetClusterType?: 'model' | 'gpu';
|
||||||
// Provider to preselect when the create flow opens — set by the
|
// Provider to preselect when the create flow opens — set by the
|
||||||
// empty-state CTA on feature pages that need a specific provider
|
// empty-state CTA on feature pages that need a specific provider
|
||||||
// (e.g. GPU Service can only schedule on Kubernetes, so its
|
// (e.g. GPU Service can only schedule on Kubernetes, so its
|
||||||
|
|||||||
@@ -55,3 +55,10 @@ export const userSettingsHelperAtom = atom(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
export const hideModalTemporarilyAtom = atom<boolean>(false);
|
export const hideModalTemporarilyAtom = atom<boolean>(false);
|
||||||
|
|
||||||
|
export const collapsedMenuGroupsAtom = atomWithStorage<string[]>(
|
||||||
|
'collapsedMenuGroups',
|
||||||
|
[],
|
||||||
|
undefined,
|
||||||
|
{ getOnInit: true }
|
||||||
|
);
|
||||||
|
|||||||
+1
-4
@@ -32,10 +32,7 @@ export const UpdateCheckAtom = atom<{
|
|||||||
latest_version: ''
|
latest_version: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
export const initialPasswordAtom = atomWithStorage<string>(
|
export const initialPasswordAtom = atom<string>('');
|
||||||
'initialPassword',
|
|
||||||
''
|
|
||||||
);
|
|
||||||
|
|
||||||
// Namespace the server creates for an Org's resources on each Kubernetes
|
// Namespace the server creates for an Org's resources on each Kubernetes
|
||||||
// cluster. The format must match the backend's ``get_namespace_name``
|
// cluster. The format must match the backend's ``get_namespace_name``
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { GPUStackVersionAtom } from '@/atoms/user';
|
import { GPUStackVersionAtom } from '@/atoms/user';
|
||||||
import { getAtomStorage } from '@/atoms/utils';
|
import { getAtomStorage } from '@/atoms/utils';
|
||||||
import VersionInfo, { modalConfig } from '@/components/version-info';
|
|
||||||
import externalLinks from '@/constants/external-links';
|
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Button, Divider, Modal, Typography } from 'antd';
|
import { Divider, Typography } from 'antd';
|
||||||
import { createStyles } from 'antd-style';
|
import { createStyles } from 'antd-style';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
@@ -33,20 +31,10 @@ const useStyles = createStyles(({ token, css }) => ({
|
|||||||
|
|
||||||
const Footer: React.FC = () => {
|
const Footer: React.FC = () => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [modal, contextHolder] = Modal.useModal();
|
|
||||||
const { styles } = useStyles();
|
const { styles } = useStyles();
|
||||||
|
|
||||||
const showVersion = () => {
|
|
||||||
modal.info({
|
|
||||||
...modalConfig,
|
|
||||||
width: 460,
|
|
||||||
content: <VersionInfo intl={intl} />
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{contextHolder}
|
|
||||||
<div className={styles.footer}>
|
<div className={styles.footer}>
|
||||||
<div className="footer-content">
|
<div className="footer-content">
|
||||||
<div className="footer-content-left">
|
<div className="footer-content-left">
|
||||||
@@ -63,18 +51,7 @@ const Footer: React.FC = () => {
|
|||||||
</Typography.Link>
|
</Typography.Link>
|
||||||
</CompanyWrapper>
|
</CompanyWrapper>
|
||||||
<Divider orientation="vertical" />
|
<Divider orientation="vertical" />
|
||||||
<Button
|
<span>{getAtomStorage(GPUStackVersionAtom)?.version}</span>
|
||||||
type="link"
|
|
||||||
size="small"
|
|
||||||
href={externalLinks.documentation}
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
{intl.formatMessage({ id: 'common.button.help' })}
|
|
||||||
</Button>
|
|
||||||
<Divider orientation="vertical" />
|
|
||||||
<Button type="link" size="small" onClick={showVersion}>
|
|
||||||
{getAtomStorage(GPUStackVersionAtom)?.version}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 4613488 */
|
font-family: "iconfont"; /* Project id 4613488 */
|
||||||
src: url('iconfont.woff2?t=1780035199453') format('woff2'),
|
src: url('iconfont.woff2?t=1780907696624') format('woff2'),
|
||||||
url('iconfont.woff?t=1780035199453') format('woff'),
|
url('iconfont.woff?t=1780907696624') format('woff'),
|
||||||
url('iconfont.ttf?t=1780035199453') format('truetype');
|
url('iconfont.ttf?t=1780907696624') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
@@ -13,6 +13,18 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-billing-outlined:before {
|
||||||
|
content: "\e70d";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-billing-filled:before {
|
||||||
|
content: "\e70e";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-fingerprint:before {
|
||||||
|
content: "\e70c";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-database-outlined:before {
|
.icon-database-outlined:before {
|
||||||
content: "\e70a";
|
content: "\e70a";
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -5,6 +5,27 @@
|
|||||||
"css_prefix_text": "icon-",
|
"css_prefix_text": "icon-",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "47798379",
|
||||||
|
"name": "request_quote_24dp_1F1F1F_FILL0_wght300_GRAD0_opsz",
|
||||||
|
"font_class": "billing-outlined",
|
||||||
|
"unicode": "e70d",
|
||||||
|
"unicode_decimal": 59149
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "47798378",
|
||||||
|
"name": "request_quote_24dp_1F1F1F_FILL1_wght300_GRAD0_opsz",
|
||||||
|
"font_class": "billing-filled",
|
||||||
|
"unicode": "e70e",
|
||||||
|
"unicode_decimal": 59150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "47761129",
|
||||||
|
"name": "fingerprint",
|
||||||
|
"font_class": "fingerprint",
|
||||||
|
"unicode": "e70c",
|
||||||
|
"unicode_decimal": 59148
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"icon_id": "47654402",
|
"icon_id": "47654402",
|
||||||
"name": "database_24dp_1F1F1F_FILL0_wght300_GRAD0_opsz24 (1",
|
"name": "database_24dp_1F1F1F_FILL0_wght300_GRAD0_opsz24 (1",
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+10
-3
@@ -276,7 +276,6 @@ body {
|
|||||||
border-radius: var(--table-td-radius);
|
border-radius: var(--table-td-radius);
|
||||||
|
|
||||||
> td {
|
> td {
|
||||||
background-color: unset !important;
|
|
||||||
border-bottom: 1px solid var(--ant-color-split);
|
border-bottom: 1px solid var(--ant-color-split);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -639,10 +638,15 @@ body {
|
|||||||
inset: 53px auto auto 0 !important;
|
inset: 53px auto auto 0 !important;
|
||||||
border-radius: 0 0 var(--border-radius-base) var(--border-radius-base);
|
border-radius: 0 0 var(--border-radius-base) var(--border-radius-base);
|
||||||
border-top: none;
|
border-top: none;
|
||||||
max-height: 240px;
|
.ant-cascader-menus {
|
||||||
min-height: 100px;
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
&.gpu-selector {
|
&.gpu-selector {
|
||||||
|
.ant-cascader-menu {
|
||||||
|
max-height: 400px;
|
||||||
|
height: unset;
|
||||||
|
}
|
||||||
.ant-cascader-menu:last-child {
|
.ant-cascader-menu:last-child {
|
||||||
flex: auto;
|
flex: auto;
|
||||||
|
|
||||||
@@ -847,3 +851,6 @@ body {
|
|||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
padding-block: 8px;
|
padding-block: 8px;
|
||||||
}
|
}
|
||||||
|
.ant-select-multiple .ant-select-content {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|||||||
+113
-35
@@ -1,54 +1,132 @@
|
|||||||
import useMemoizedFn from 'ahooks/lib/useMemoizedFn';
|
import useMemoizedFn from 'ahooks/lib/useMemoizedFn';
|
||||||
import { converter, modeHsl, modeRgb, useMode } from 'culori/fn';
|
import { clampChroma, formatHex, modeOklch, modeRgb, useMode } from 'culori/fn';
|
||||||
|
import useUserSettings from './use-user-settings';
|
||||||
|
|
||||||
const toHsl = converter('hsl');
|
// Linear-style minimal/neutral palette: a TIGHT blue -> violet band in OKLCH
|
||||||
|
// (perceptually uniform), kept moderate-chroma so fills read as clean and gentle
|
||||||
const DEFAULT_BRAND_HUE = 211; // brand color
|
// rather than candy-colored. We deliberately stay narrow and DON'T fan out to
|
||||||
const COOL_HUE_START = 180;
|
// green/magenta — in this aesthetic series are separated by LIGHTNESS, not by
|
||||||
const COOL_HUE_END = 280;
|
// spreading across the hue wheel. Every series (including the first) is generated
|
||||||
|
// from this one ramp, so the whole palette stays in a single cohesive color
|
||||||
|
// family — no special high-saturation brand color that clashes with the rest.
|
||||||
|
const COOL_HUE_START = 250; // blue
|
||||||
|
const COOL_HUE_END = 315; // violet (stops short of magenta/pink, stays neutral-cool)
|
||||||
const COOL_HUE_RANGE = COOL_HUE_END - COOL_HUE_START;
|
const COOL_HUE_RANGE = COOL_HUE_END - COOL_HUE_START;
|
||||||
const GOLDEN_RATIO_CONJUGATE = 0.618033988749895;
|
|
||||||
|
|
||||||
function colorStringToHue(input?: string): number | undefined {
|
/**
|
||||||
if (!input) return undefined;
|
* Vivid, distinct cool accents — for places that need a handful of "primary"
|
||||||
const color = toHsl(input);
|
* colors, one per card/section (e.g. the summary trend cards), NOT a stacked
|
||||||
if (!color || typeof color.h !== 'number') return undefined;
|
* multi-series palette. Every color is anchor-quality (bright + saturated) and
|
||||||
return color.h;
|
* spread evenly across the blue→violet band, so the set reads as several equally
|
||||||
}
|
* strong primaries rather than one bold + several washed-out fills.
|
||||||
|
*/
|
||||||
export default function useCoolColors() {
|
export function useCoolAccents() {
|
||||||
// const brandHue = useMemo(
|
|
||||||
// () => colorStringToHue(userSettings.colorPrimary) ?? DEFAULT_BRAND_HUE,
|
|
||||||
// [userSettings.colorPrimary]
|
|
||||||
// );
|
|
||||||
useMode(modeRgb);
|
useMode(modeRgb);
|
||||||
useMode(modeHsl);
|
useMode(modeOklch);
|
||||||
|
|
||||||
const brandHue = DEFAULT_BRAND_HUE;
|
const { isDarkTheme } = useUserSettings();
|
||||||
|
|
||||||
return useMemoizedFn((count: number): string[] => {
|
return useMemoizedFn((count: number): string[] => {
|
||||||
if (count <= 0) return [];
|
if (count <= 0) return [];
|
||||||
|
|
||||||
const colors: string[] = [];
|
const l = isDarkTheme ? 0.62 : 0.64;
|
||||||
|
const c = isDarkTheme ? 0.16 : 0.2;
|
||||||
|
|
||||||
|
const out: string[] = [];
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
let hue: number;
|
const t = count <= 1 ? 0 : i / (count - 1);
|
||||||
|
const hue = COOL_HUE_START + t * COOL_HUE_RANGE;
|
||||||
|
out.push(
|
||||||
|
formatHex(clampChroma({ mode: 'oklch', l, c, h: hue }, 'oklch'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (i === 0) {
|
export default function useCoolColors() {
|
||||||
hue = brandHue - 5;
|
useMode(modeRgb);
|
||||||
} else {
|
useMode(modeOklch);
|
||||||
const offset = (i * GOLDEN_RATIO_CONJUGATE) % 1;
|
|
||||||
hue = COOL_HUE_START + offset * COOL_HUE_RANGE;
|
|
||||||
|
|
||||||
if (Math.abs(hue - brandHue) < 5) {
|
const { isDarkTheme } = useUserSettings();
|
||||||
hue = (hue + 10) % COOL_HUE_END;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const s = i === 0 ? 100 : 75 + (i % 3) * 5;
|
return useMemoizedFn((count: number): string[] => {
|
||||||
const l = i === 0 ? 50 : 55 + (i % 2) * 5;
|
if (count <= 0) return [];
|
||||||
|
|
||||||
colors.push(`hsl(${Math.round(hue)}, ${s}%, ${l}%)`);
|
// Moderate chroma: clean and crisp, but gentle (not neon). Too low reads as
|
||||||
|
// muddy/dirty; too high reads as harsh. Dark mode a touch lower so fills
|
||||||
|
// stay calm against the dark canvas.
|
||||||
|
const baseChroma = isDarkTheme ? 0.085 : 0.12;
|
||||||
|
|
||||||
|
// First series is the "primary" anchor: SAME blue family (the bluest end of
|
||||||
|
// the ramp, nearest the brand hue) but clearly brighter and more saturated —
|
||||||
|
// a vivid, clean brand-blue that reads as the base color. The rest of the
|
||||||
|
// palette stays low-chroma, so the anchor pops as the primary while the
|
||||||
|
// family still feels cohesive.
|
||||||
|
const colors: string[] = [
|
||||||
|
formatHex(
|
||||||
|
clampChroma(
|
||||||
|
{
|
||||||
|
mode: 'oklch',
|
||||||
|
l: isDarkTheme ? 0.62 : 0.66,
|
||||||
|
c: isDarkTheme ? 0.16 : 0.2,
|
||||||
|
h: COOL_HUE_START
|
||||||
|
},
|
||||||
|
'oklch'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
|
const rest = count - 1;
|
||||||
|
if (rest <= 0) return colors;
|
||||||
|
|
||||||
|
// Separation is driven by LIGHTNESS, not hue. The hue band is narrow, so as
|
||||||
|
// the count grows we add lightness TIERS — each tier reuses the same narrow
|
||||||
|
// hue ramp at a distinct lightness level, multiplying how many separable
|
||||||
|
// colors fit while keeping the whole palette in one cohesive family.
|
||||||
|
const tiers = rest <= 6 ? 1 : rest <= 12 ? 2 : 3;
|
||||||
|
const steps = Math.ceil(rest / tiers);
|
||||||
|
|
||||||
|
// Distinct lightness levels per tier count (index 0 → 2 tiers, 1 → 3 tiers).
|
||||||
|
// Lighter, airier levels for a fresh/crisp feel; kept in the upper-mid range
|
||||||
|
// so fills stay clean and legible.
|
||||||
|
const lightTiers = isDarkTheme
|
||||||
|
? [
|
||||||
|
[0.68, 0.5],
|
||||||
|
[0.72, 0.6, 0.48]
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
[0.82, 0.64],
|
||||||
|
[0.84, 0.72, 0.6]
|
||||||
|
];
|
||||||
|
// Single-tier light/dark zig-zag for the common small-count case.
|
||||||
|
const [lightLo, lightHi] = isDarkTheme ? [0.5, 0.68] : [0.64, 0.82];
|
||||||
|
|
||||||
|
for (let i = 0; i < rest; i++) {
|
||||||
|
// Cycle the tier on every step so consecutive series always differ in
|
||||||
|
// lightness — exactly where stacked bars are hardest to tell apart.
|
||||||
|
const tier = i % tiers;
|
||||||
|
const step = Math.floor(i / tiers);
|
||||||
|
|
||||||
|
// Even hue ramp across the narrow band. Each tier is offset by a fraction
|
||||||
|
// of a step so same-step colors in different tiers don't share a hue.
|
||||||
|
const t = steps <= 1 ? 0.5 : (step + tier / tiers) / steps;
|
||||||
|
const hue = COOL_HUE_START + t * COOL_HUE_RANGE;
|
||||||
|
|
||||||
|
// 1 tier (≤6 series): light/dark zig-zag. 2-3 tiers: the tier's level.
|
||||||
|
const lightness =
|
||||||
|
tiers === 1 ? (i % 2 ? lightLo : lightHi) : lightTiers[tiers - 2][tier];
|
||||||
|
|
||||||
|
// Clamp chroma into the sRGB gamut so values don't get distorted by a raw
|
||||||
|
// channel clip when serialized to hex.
|
||||||
|
colors.push(
|
||||||
|
formatHex(
|
||||||
|
clampChroma(
|
||||||
|
{ mode: 'oklch', l: lightness, c: baseChroma, h: hue },
|
||||||
|
'oklch'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return colors;
|
return colors;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export function useQueryDataList<
|
|||||||
Response = Array<ListItem>
|
Response = Array<ListItem>
|
||||||
>(option: {
|
>(option: {
|
||||||
key: string;
|
key: string;
|
||||||
|
manual?: boolean;
|
||||||
responseType?: 'array' | 'object';
|
responseType?: 'array' | 'object';
|
||||||
fetchList: (
|
fetchList: (
|
||||||
params: Params,
|
params: Params,
|
||||||
@@ -38,6 +39,7 @@ export function useQueryDataList<
|
|||||||
fetchList,
|
fetchList,
|
||||||
getLabel,
|
getLabel,
|
||||||
getValue,
|
getValue,
|
||||||
|
manual = true,
|
||||||
responseType = 'array',
|
responseType = 'array',
|
||||||
errorMsg
|
errorMsg
|
||||||
} = option;
|
} = option;
|
||||||
@@ -70,7 +72,7 @@ export function useQueryDataList<
|
|||||||
return responseType === 'array' ? res.items || [] : res;
|
return responseType === 'array' ? res.items || [] : res;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
manual: true,
|
manual: manual,
|
||||||
debounceWait: option.debounceWait || 300,
|
debounceWait: option.debounceWait || 300,
|
||||||
onSuccess: () => {},
|
onSuccess: () => {},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
@@ -105,16 +107,18 @@ export function useQueryDataList<
|
|||||||
export function useQueryData<Detail, Params = any>(option: {
|
export function useQueryData<Detail, Params = any>(option: {
|
||||||
key: string;
|
key: string;
|
||||||
delay?: number;
|
delay?: number;
|
||||||
|
manual?: boolean;
|
||||||
fetchDetail: (params: Params, options?: any) => Promise<Detail>;
|
fetchDetail: (params: Params, options?: any) => Promise<Detail>;
|
||||||
getData?: (response: Detail, params?: any) => any;
|
getData?: (response: Detail, params?: any) => any;
|
||||||
errorMsg?: string;
|
errorMsg?: string;
|
||||||
}): {
|
}): {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
detailData: Detail;
|
detailData: Detail;
|
||||||
|
manual?: boolean;
|
||||||
cancelRequest: () => void;
|
cancelRequest: () => void;
|
||||||
fetchData: (params: Params, extra?: any) => Promise<Detail>;
|
fetchData: (params: Params, extra?: any) => Promise<Detail>;
|
||||||
} {
|
} {
|
||||||
const { key, fetchDetail, getData, errorMsg, delay } = option;
|
const { key, fetchDetail, getData, errorMsg, delay, manual = true } = option;
|
||||||
const axiosTokenRef = useRef<CancelTokenSource | null>(null);
|
const axiosTokenRef = useRef<CancelTokenSource | null>(null);
|
||||||
const [detailData, setDetailData] = useState<Detail>({} as Detail);
|
const [detailData, setDetailData] = useState<Detail>({} as Detail);
|
||||||
|
|
||||||
@@ -142,7 +146,7 @@ export function useQueryData<Detail, Params = any>(option: {
|
|||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
manual: true,
|
manual: manual,
|
||||||
onSuccess: () => {},
|
onSuccess: () => {},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
message.error(
|
message.error(
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { useMemoizedFn } from 'ahooks';
|
||||||
|
import { useRef, useState } from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Centralizes the anti-double-submit + anti-deadlock logic shared by the
|
||||||
|
* "add/edit" modals.
|
||||||
|
*
|
||||||
|
* The lock has to straddle antd's async field validation, whose result comes
|
||||||
|
* back through two separate callbacks (`onFinish` / `onFinishFailed`). So the
|
||||||
|
* three wiring points below are intentional and map 1:1 to those anchors:
|
||||||
|
*
|
||||||
|
* - `guard` wrap the submit trigger (button / ModalFooter onOk). Blocks
|
||||||
|
* re-entry while a submit is already in flight, then fires submit.
|
||||||
|
* - `run` wrap the `onFinish` handler. Holds the lock + loading until the
|
||||||
|
* `onOk` request settles (success or error).
|
||||||
|
* - `release` pass as the form's `onFinishFailed`. Releases the lock when
|
||||||
|
* validation fails, otherwise the button would dead-lock.
|
||||||
|
*/
|
||||||
|
export default function useSubmitLock() {
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
const lockRef = useRef<boolean>(false);
|
||||||
|
|
||||||
|
const release = useMemoizedFn(() => {
|
||||||
|
setLoading(false);
|
||||||
|
lockRef.current = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
const guard = useMemoizedFn((submit: () => void) => {
|
||||||
|
if (lockRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lockRef.current = true;
|
||||||
|
submit();
|
||||||
|
});
|
||||||
|
|
||||||
|
const run = useMemoizedFn(async (task: () => void | Promise<void>) => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
await task();
|
||||||
|
} finally {
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return { loading, guard, run, release };
|
||||||
|
}
|
||||||
@@ -89,6 +89,10 @@ export function useUpdateChunkedList(options: {
|
|||||||
...cacheDataListRef.current
|
...cacheDataListRef.current
|
||||||
].slice(0, limit);
|
].slice(0, limit);
|
||||||
|
|
||||||
|
options.setDataList?.([...cacheDataListRef.current], {
|
||||||
|
createdIds: newDataList.map((item) => item.id)
|
||||||
|
});
|
||||||
|
|
||||||
options.onCreate?.(latestCreateList);
|
options.onCreate?.(latestCreateList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,8 +63,7 @@ export default function useWatchList<T = Record<string, any>>(API: string) {
|
|||||||
listRequestTokenRef.current?.cancel?.();
|
listRequestTokenRef.current?.cancel?.();
|
||||||
listRequestTokenRef.current = createAxiosToken();
|
listRequestTokenRef.current = createAxiosToken();
|
||||||
const params = {
|
const params = {
|
||||||
page: 1,
|
page: -1
|
||||||
perPage: 100
|
|
||||||
};
|
};
|
||||||
const res: any = await queryAllDataList(params, {
|
const res: any = await queryAllDataList(params, {
|
||||||
token: listRequestTokenRef.current.token
|
token: listRequestTokenRef.current.token
|
||||||
@@ -86,6 +85,7 @@ export default function useWatchList<T = Record<string, any>>(API: string) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
watchDataList,
|
watchDataList,
|
||||||
|
setWatchDataList,
|
||||||
deleteItemFromCache: handleDeleteItemFromCache
|
deleteItemFromCache: handleDeleteItemFromCache
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { GPUStackVersionAtom, UpdateCheckAtom } from '@/atoms/user';
|
import { GPUStackVersionAtom, UpdateCheckAtom } from '@/atoms/user';
|
||||||
import PluginExtraField from '@/components/plugin-extra-fields';
|
import PluginExtraField from '@/components/plugin-extra-fields';
|
||||||
import VersionInfo, { modalConfig } from '@/components/version-info';
|
|
||||||
import externalLinks from '@/constants/external-links';
|
import externalLinks from '@/constants/external-links';
|
||||||
import useBodyScroll from '@/hooks/use-body-scroll';
|
|
||||||
import { logout } from '@/pages/login/apis';
|
import { logout } from '@/pages/login/apis';
|
||||||
import { useModel } from '@@/plugin-model';
|
import { useModel } from '@@/plugin-model';
|
||||||
import {
|
import {
|
||||||
@@ -13,7 +11,7 @@ import {
|
|||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { DropdownActions, IconFont } from '@gpustack/core-ui';
|
import { DropdownActions, IconFont } from '@gpustack/core-ui';
|
||||||
import { history, useIntl, useNavigate } from '@umijs/max';
|
import { history, useIntl, useNavigate } from '@umijs/max';
|
||||||
import { Avatar, Button, Divider, Modal } from 'antd';
|
import { Avatar, Divider } from 'antd';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
@@ -97,11 +95,9 @@ const CustomItem = styled.div`
|
|||||||
|
|
||||||
export const ExtraContent = (props: { isDarkTheme?: boolean }) => {
|
export const ExtraContent = (props: { isDarkTheme?: boolean }) => {
|
||||||
const { isDarkTheme } = props;
|
const { isDarkTheme } = props;
|
||||||
const { saveScrollHeight, restoreScrollHeight } = useBodyScroll();
|
const intl = useIntl();
|
||||||
const [modal, contextHolder] = Modal.useModal();
|
|
||||||
const [version] = useAtom(GPUStackVersionAtom);
|
const [version] = useAtom(GPUStackVersionAtom);
|
||||||
const [updateCheck] = useAtom(UpdateCheckAtom);
|
const [updateCheck] = useAtom(UpdateCheckAtom);
|
||||||
const intl = useIntl();
|
|
||||||
const initialInfo = useModel('@@initialState') || {
|
const initialInfo = useModel('@@initialState') || {
|
||||||
initialState: undefined,
|
initialState: undefined,
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -139,16 +135,6 @@ export const ExtraContent = (props: { isDarkTheme?: boolean }) => {
|
|||||||
return {};
|
return {};
|
||||||
}, [isDarkTheme]);
|
}, [isDarkTheme]);
|
||||||
|
|
||||||
const showVersion = () => {
|
|
||||||
saveScrollHeight();
|
|
||||||
modal.info({
|
|
||||||
...modalConfig,
|
|
||||||
width: 460,
|
|
||||||
content: <VersionInfo intl={intl} />,
|
|
||||||
onCancel: restoreScrollHeight
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleLogout = async () => {
|
const handleLogout = async () => {
|
||||||
await logout();
|
await logout();
|
||||||
navigate(loginPath);
|
navigate(loginPath);
|
||||||
@@ -158,7 +144,7 @@ export const ExtraContent = (props: { isDarkTheme?: boolean }) => {
|
|||||||
{
|
{
|
||||||
key: 'site',
|
key: 'site',
|
||||||
icon: <HomeOutlined />,
|
icon: <HomeOutlined />,
|
||||||
label: 'GPUStack',
|
label: 'MesaStack',
|
||||||
url: externalLinks.site
|
url: externalLinks.site
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -258,7 +244,6 @@ export const ExtraContent = (props: { isDarkTheme?: boolean }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
{contextHolder}
|
|
||||||
<PluginExtraField name="OrgSwitcher" isDarkTheme={isDarkTheme} />
|
<PluginExtraField name="OrgSwitcher" isDarkTheme={isDarkTheme} />
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -266,16 +251,13 @@ export const ExtraContent = (props: { isDarkTheme?: boolean }) => {
|
|||||||
alignItems: 'center'
|
alignItems: 'center'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<span
|
||||||
type="text"
|
|
||||||
size="small"
|
|
||||||
onClick={showVersion}
|
|
||||||
style={{
|
style={{
|
||||||
color: 'var(--ant-color-text-tertiary)'
|
color: 'var(--ant-color-text-tertiary)'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{version.version}
|
{version.version}
|
||||||
</Button>
|
</span>
|
||||||
{showUpgrade && (
|
{showUpgrade && (
|
||||||
<NewLabel>
|
<NewLabel>
|
||||||
<span className="text">
|
<span className="text">
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
import { IconFont } from '@gpustack/core-ui';
|
||||||
|
import { Link, useLocation, useNavigate } from '@umijs/max';
|
||||||
|
import { Menu } from 'antd';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
|
|
||||||
|
interface MenuItem {
|
||||||
|
icon?: string;
|
||||||
|
selectedIcon?: string;
|
||||||
|
defaultIcon?: string;
|
||||||
|
children?: MenuItem[];
|
||||||
|
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HeaderMenuProps {
|
||||||
|
menuData: MenuItem[];
|
||||||
|
initialState?: Global.InitialStateType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = createStyles(({ css }) => {
|
||||||
|
return {
|
||||||
|
headerMenu: css`
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
background: transparent;
|
||||||
|
border-bottom: none;
|
||||||
|
line-height: inherit;
|
||||||
|
|
||||||
|
&.ant-menu-horizontal {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
&.ant-menu-horizontal > .ant-menu-item::after,
|
||||||
|
&.ant-menu-horizontal > .ant-menu-submenu::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.ant-menu-title-content {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.anticon {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const isItemSelected = (item: MenuItem, pathname: string) => {
|
||||||
|
return (
|
||||||
|
pathname === item.path ||
|
||||||
|
(Array.isArray(item.subMenu) && item.subMenu.includes(pathname))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const HeaderMenu: React.FC<HeaderMenuProps> = (props) => {
|
||||||
|
const { menuData } = props;
|
||||||
|
const { styles } = useStyles();
|
||||||
|
const location = useLocation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const buildLeaf = (item: MenuItem) => {
|
||||||
|
const selected = isItemSelected(item, location.pathname);
|
||||||
|
return {
|
||||||
|
key: item.path as string,
|
||||||
|
label: (
|
||||||
|
<Link
|
||||||
|
prefetch="intent"
|
||||||
|
to={(item.path as string).replace('/*', '')}
|
||||||
|
target={item.target}
|
||||||
|
>
|
||||||
|
<span className="flex-center gap-8">
|
||||||
|
<IconFont
|
||||||
|
type={selected ? item.selectedIcon || '' : item.defaultIcon || ''}
|
||||||
|
/>
|
||||||
|
<span>{item.name}</span>
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const items = useMemo(() => {
|
||||||
|
return menuData.map((item) => {
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
return {
|
||||||
|
key: item.key,
|
||||||
|
label: item.name,
|
||||||
|
children: item.children.map((child) => buildLeaf(child))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return buildLeaf(item);
|
||||||
|
});
|
||||||
|
}, [menuData, location.pathname]);
|
||||||
|
|
||||||
|
const selectedKeys = useMemo(() => {
|
||||||
|
const keys: string[] = [];
|
||||||
|
for (const item of menuData) {
|
||||||
|
const leaves =
|
||||||
|
item.children && item.children.length > 0 ? item.children : [item];
|
||||||
|
for (const leaf of leaves) {
|
||||||
|
if (isItemSelected(leaf, location.pathname)) {
|
||||||
|
keys.push(leaf.path as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
}, [menuData, location.pathname]);
|
||||||
|
|
||||||
|
const handleClick = ({ key }: { key: string }) => {
|
||||||
|
if (key.startsWith('/')) {
|
||||||
|
navigate(key.replace('/*', ''));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Menu
|
||||||
|
className={styles.headerMenu}
|
||||||
|
mode="horizontal"
|
||||||
|
selectedKeys={selectedKeys}
|
||||||
|
items={items}
|
||||||
|
onClick={handleClick}
|
||||||
|
triggerSubMenuAction="hover"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HeaderMenu;
|
||||||
+68
-59
@@ -12,6 +12,7 @@ import useUserSettings from '@/hooks/use-user-settings';
|
|||||||
import useUserSettingsStorage from '@/hooks/use-user-settings-storage';
|
import useUserSettingsStorage from '@/hooks/use-user-settings-storage';
|
||||||
import useAddResource from '@/pages/dashboard/hooks/use-add-resource';
|
import useAddResource from '@/pages/dashboard/hooks/use-add-resource';
|
||||||
import { logout } from '@/pages/login/apis';
|
import { logout } from '@/pages/login/apis';
|
||||||
|
import { didInitialStateProbe, probeAccessFlags } from '@/utils/access-probes';
|
||||||
import {
|
import {
|
||||||
readColumnSettings,
|
readColumnSettings,
|
||||||
readState,
|
readState,
|
||||||
@@ -21,7 +22,7 @@ import {
|
|||||||
import { useAccessMarkedRoutes } from '@@/plugin-access';
|
import { useAccessMarkedRoutes } from '@@/plugin-access';
|
||||||
import { useModel } from '@@/plugin-model';
|
import { useModel } from '@@/plugin-model';
|
||||||
import { ProLayout } from '@ant-design/pro-components';
|
import { ProLayout } from '@ant-design/pro-components';
|
||||||
import { CoreUIProvider, IconFont } from '@gpustack/core-ui';
|
import { CoreUIProvider } from '@gpustack/core-ui';
|
||||||
import {
|
import {
|
||||||
Access,
|
Access,
|
||||||
Outlet,
|
Outlet,
|
||||||
@@ -38,18 +39,18 @@ import {
|
|||||||
useNavigate,
|
useNavigate,
|
||||||
type IRoute
|
type IRoute
|
||||||
} from '@umijs/max';
|
} from '@umijs/max';
|
||||||
import { Button, ConfigProvider, Modal, theme } from 'antd';
|
import { ConfigProvider, Modal, theme } from 'antd';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import 'overlayscrollbars/overlayscrollbars.css';
|
import 'overlayscrollbars/overlayscrollbars.css';
|
||||||
import { useMemo, useRef } from 'react';
|
import { useEffect, useMemo, useRef } from 'react';
|
||||||
import { PageContainerInner } from '../pages/_components/page-box';
|
import { PageContainerInner } from '../pages/_components/page-box';
|
||||||
import Exception from './Exception';
|
import Exception from './Exception';
|
||||||
import './Layout.css';
|
import './Layout.css';
|
||||||
import { LogoIcon, SLogoIcon } from './Logo';
|
import { LogoIcon } from './Logo';
|
||||||
import ErrorBoundary from './error-boundary';
|
import ErrorBoundary from './error-boundary';
|
||||||
import { ExtraContent } from './extraRender';
|
import { ExtraContent } from './extraRender';
|
||||||
|
import HeaderMenu from './header-menu';
|
||||||
import { patchRoutes } from './runtime';
|
import { patchRoutes } from './runtime';
|
||||||
import SiderMenu from './sider-menu';
|
|
||||||
|
|
||||||
// Pages that use the page container in the page
|
// Pages that use the page container in the page
|
||||||
const NO_CONTAINER_PAGES = [
|
const NO_CONTAINER_PAGES = [
|
||||||
@@ -132,7 +133,7 @@ const mapRoutes = (routes: IRoute[], role: string) => {
|
|||||||
|
|
||||||
export default (props: any) => {
|
export default (props: any) => {
|
||||||
const [, contextHolder] = Modal.useModal();
|
const [, contextHolder] = Modal.useModal();
|
||||||
const { themeData, setUserSettings, userSettings } = useUserSettings();
|
const { themeData, userSettings } = useUserSettings();
|
||||||
const [userInfo] = useAtom(userAtom);
|
const [userInfo] = useAtom(userAtom);
|
||||||
const [routeCache] = useAtom(routeCacheAtom);
|
const [routeCache] = useAtom(routeCacheAtom);
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
@@ -155,6 +156,50 @@ export default (props: any) => {
|
|||||||
|
|
||||||
const { initialState, loading, setInitialState } = initialInfo;
|
const { initialState, loading, setInitialState } = initialInfo;
|
||||||
const access = useAccess();
|
const access = useAccess();
|
||||||
|
const probedForUserRef = useRef<string | null>(null);
|
||||||
|
|
||||||
|
// Backfill the access probes (cluster / resource-events) once we're in
|
||||||
|
// the authenticated shell. `getInitialState` runs only once at app
|
||||||
|
// boot and can't probe on the login page (no session => 401), so after
|
||||||
|
// a first login the flags arrive here as `undefined` — which the
|
||||||
|
// access predicate treats as "don't restrict", flashing GPU Service /
|
||||||
|
// the full Usage page on until a manual refresh. This layout mounts
|
||||||
|
// only post-auth (login is `layout:false`) and on every entry, so it's
|
||||||
|
// the reliable place to resolve them.
|
||||||
|
//
|
||||||
|
// The effect is keyed on the user IDENTITY, not on the flag values —
|
||||||
|
// gating on the flags is what made this fragile (on a refresh
|
||||||
|
// `getInitialState` commits `currentUser` and the flags in the same
|
||||||
|
// update, so a flag-gated effect sees them already-known and never
|
||||||
|
// fires). Whether to actually hit the network is decided by the
|
||||||
|
// module-scoped `didInitialStateProbe()` marker, which is true only
|
||||||
|
// when `getInitialState` already probed for an authenticated user this
|
||||||
|
// page load (the refresh path) — so we skip the duplicate request there
|
||||||
|
// but still probe on the SPA-login path. Keying on identity also
|
||||||
|
// re-probes correctly if the signed-in user changes.
|
||||||
|
const currentUser = initialState?.currentUser;
|
||||||
|
const username = currentUser?.username;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!username || !setInitialState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (probedForUserRef.current === username) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
probedForUserRef.current = username;
|
||||||
|
// The refresh path already resolved the flags inside `getInitialState`
|
||||||
|
// for this user — don't issue a duplicate probe.
|
||||||
|
if (didInitialStateProbe()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
probeAccessFlags().then((accessFlags) => {
|
||||||
|
setInitialState((prev: any) => ({
|
||||||
|
...prev,
|
||||||
|
...accessFlags
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}, [username, setInitialState]);
|
||||||
|
|
||||||
const userConfig = {
|
const userConfig = {
|
||||||
title: '',
|
title: '',
|
||||||
@@ -193,13 +238,6 @@ export default (props: any) => {
|
|||||||
|
|
||||||
const coreUISlots = useMemo(() => ({ ExtraContent }), []);
|
const coreUISlots = useMemo(() => ({ ExtraContent }), []);
|
||||||
|
|
||||||
const handleToggleCollapse = (e: any) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
setUserSettings({
|
|
||||||
...userSettings,
|
|
||||||
collapsed: !userSettings.collapsed
|
|
||||||
});
|
|
||||||
};
|
|
||||||
const newRoutes = filterRoutes(
|
const newRoutes = filterRoutes(
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
clientRoutes.filter((route) => route.id === 'max-tabs'),
|
clientRoutes.filter((route) => route.id === 'max-tabs'),
|
||||||
@@ -229,16 +267,19 @@ export default (props: any) => {
|
|||||||
return NO_CONTAINER_PAGES.includes(matchedRoute?.name as string);
|
return NO_CONTAINER_PAGES.includes(matchedRoute?.name as string);
|
||||||
}, [matchedRoute]);
|
}, [matchedRoute]);
|
||||||
|
|
||||||
const collapsed = useMemo(() => {
|
|
||||||
return userSettings.collapsed || false;
|
|
||||||
}, [userSettings.collapsed]);
|
|
||||||
|
|
||||||
const renderMenuHeader = (logo: React.ReactNode, title: React.ReactNode) => {
|
const renderMenuHeader = (logo: React.ReactNode, title: React.ReactNode) => {
|
||||||
return <>{logo}</>;
|
return <>{logo}</>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const menuContentRender = (menuProps: any, defaultDom: React.ReactNode) => {
|
const headerContentRender = (
|
||||||
return <SiderMenu {...menuProps}></SiderMenu>;
|
headerProps: any,
|
||||||
|
defaultDom: React.ReactNode
|
||||||
|
) => {
|
||||||
|
return <HeaderMenu {...headerProps}></HeaderMenu>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const actionsRender = () => {
|
||||||
|
return <ExtraContent isDarkTheme={userSettings.isDarkTheme} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPageChange = async (route: any) => {
|
const onPageChange = async (route: any) => {
|
||||||
@@ -292,17 +333,6 @@ export default (props: any) => {
|
|||||||
navigate(pagepath);
|
navigate(pagepath);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCollapse = (value: boolean) => {
|
|
||||||
// only trigger by window resize
|
|
||||||
if (!value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setUserSettings({
|
|
||||||
...userSettings,
|
|
||||||
collapsed: value
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConfigProvider
|
<ConfigProvider
|
||||||
componentSize="large"
|
componentSize="large"
|
||||||
@@ -327,7 +357,7 @@ export default (props: any) => {
|
|||||||
config={{
|
config={{
|
||||||
apiBaseUrl: GPUSTACK_API_BASE_URL,
|
apiBaseUrl: GPUSTACK_API_BASE_URL,
|
||||||
theme: userSettings.theme,
|
theme: userSettings.theme,
|
||||||
iconUrl: '//at.alicdn.com/t/c/font_4613488_rwchdketjg8.js',
|
iconUrl: '',
|
||||||
isDarkTheme: userSettings.isDarkTheme,
|
isDarkTheme: userSettings.isDarkTheme,
|
||||||
defaultColorPrimary: COLOR_PRIMARY
|
defaultColorPrimary: COLOR_PRIMARY
|
||||||
}}
|
}}
|
||||||
@@ -363,48 +393,27 @@ export default (props: any) => {
|
|||||||
<DarkMask></DarkMask>
|
<DarkMask></DarkMask>
|
||||||
<ProLayout
|
<ProLayout
|
||||||
fixSiderbar
|
fixSiderbar
|
||||||
fixedHeader={false}
|
fixedHeader
|
||||||
headerRender={false}
|
|
||||||
breadcrumbRender={false}
|
breadcrumbRender={false}
|
||||||
route={route}
|
route={route}
|
||||||
location={location}
|
location={location}
|
||||||
title={userConfig.title}
|
title={userConfig.title}
|
||||||
navTheme={userSettings.theme}
|
navTheme={userSettings.theme}
|
||||||
layout="side"
|
layout="top"
|
||||||
contentStyle={{
|
contentStyle={{
|
||||||
paddingBlock: 0,
|
paddingBlock: 0,
|
||||||
paddingInline: 0
|
paddingInline: 0
|
||||||
}}
|
}}
|
||||||
openKeys={false}
|
|
||||||
disableMobile={true}
|
disableMobile={true}
|
||||||
siderWidth={220}
|
|
||||||
menuFooterRender={() => (
|
|
||||||
<Button
|
|
||||||
style={{
|
|
||||||
border: 'none'
|
|
||||||
}}
|
|
||||||
size="small"
|
|
||||||
type={'text'}
|
|
||||||
onClick={handleToggleCollapse}
|
|
||||||
>
|
|
||||||
<IconFont
|
|
||||||
type={collapsed ? 'icon-expand-left' : 'icon-expand-right'}
|
|
||||||
className="font-size-18"
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
onCollapse={onCollapse}
|
|
||||||
onMenuHeaderClick={onMenuHeaderClick}
|
onMenuHeaderClick={onMenuHeaderClick}
|
||||||
collapsed={userSettings.collapsed}
|
|
||||||
onPageChange={onPageChange}
|
onPageChange={onPageChange}
|
||||||
formatMessage={formatMessage}
|
formatMessage={formatMessage}
|
||||||
menu={{
|
menu={{
|
||||||
locale: true,
|
locale: true
|
||||||
type: 'group'
|
|
||||||
}}
|
}}
|
||||||
splitMenus={true}
|
logo={<LogoIcon />}
|
||||||
logo={userSettings.collapsed ? <SLogoIcon /> : <LogoIcon />}
|
headerContentRender={headerContentRender}
|
||||||
menuContentRender={menuContentRender}
|
actionsRender={actionsRender}
|
||||||
{...runtimeConfig}
|
{...runtimeConfig}
|
||||||
ErrorBoundary={ErrorBoundary}
|
ErrorBoundary={ErrorBoundary}
|
||||||
>
|
>
|
||||||
@@ -412,7 +421,7 @@ export default (props: any) => {
|
|||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
height: '100vh',
|
height: '100%',
|
||||||
overflow: 'hidden'
|
overflow: 'hidden'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export const getRightRenderContent = (opts: {
|
|||||||
{
|
{
|
||||||
key: 'site',
|
key: 'site',
|
||||||
icon: <HomeOutlined />,
|
icon: <HomeOutlined />,
|
||||||
label: 'GPUStack',
|
label: 'MesaStack',
|
||||||
url: externalLinks.site
|
url: externalLinks.site
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+21
-11
@@ -1,9 +1,11 @@
|
|||||||
|
import { collapsedMenuGroupsAtom } from '@/atoms/settings';
|
||||||
import { CaretDownOutlined } from '@ant-design/icons';
|
import { CaretDownOutlined } from '@ant-design/icons';
|
||||||
import { IconFont, OverlayScroller } from '@gpustack/core-ui';
|
import { IconFont, OverlayScroller } from '@gpustack/core-ui';
|
||||||
import { Link, useLocation } from '@umijs/max';
|
import { Link, useLocation } from '@umijs/max';
|
||||||
import { Tooltip } from 'antd';
|
import { Tooltip } from 'antd';
|
||||||
import { createStyles, type FullToken } from 'antd-style';
|
import { createStyles, type FullToken } from 'antd-style';
|
||||||
import React, { useMemo, useState } from 'react';
|
import { useAtom } from 'jotai';
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
|
|
||||||
interface MenuItem {
|
interface MenuItem {
|
||||||
icon?: string;
|
icon?: string;
|
||||||
@@ -144,8 +146,19 @@ const SiderMenu: React.FC<SiderMenuProps> = (props) => {
|
|||||||
const { menuData, collapsed } = props;
|
const { menuData, collapsed } = props;
|
||||||
const { styles, cx } = useStyles();
|
const { styles, cx } = useStyles();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [collapseKeys, setCollapseKeys] = useState<Set<string>>(new Set());
|
const [storedCollapsedGroups, setCollapsedGroups] = useAtom(
|
||||||
console.log('SiderMenu', location.pathname);
|
collapsedMenuGroupsAtom
|
||||||
|
);
|
||||||
|
// atomWithStorage falls back to the initial value on JSON parse
|
||||||
|
// errors, but not when the stored value is valid JSON of another
|
||||||
|
// shape — normalize so array methods below can't throw.
|
||||||
|
const collapsedGroups = Array.isArray(storedCollapsedGroups)
|
||||||
|
? storedCollapsedGroups
|
||||||
|
: [];
|
||||||
|
const collapseKeys = useMemo(
|
||||||
|
() => new Set(collapsedGroups),
|
||||||
|
[collapsedGroups]
|
||||||
|
);
|
||||||
|
|
||||||
const dividerStyles = useMemo(() => {
|
const dividerStyles = useMemo(() => {
|
||||||
if (collapsed) {
|
if (collapsed) {
|
||||||
@@ -164,14 +177,11 @@ const SiderMenu: React.FC<SiderMenuProps> = (props) => {
|
|||||||
const handleToggleGroup = (e: any, menuGroup: any) => {
|
const handleToggleGroup = (e: any, menuGroup: any) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
console.log('handleToggleGroup', menuGroup.key);
|
setCollapsedGroups(
|
||||||
|
collapsedGroups.includes(menuGroup.key)
|
||||||
if (collapseKeys.has(menuGroup.key)) {
|
? collapsedGroups.filter((key) => key !== menuGroup.key)
|
||||||
collapseKeys.delete(menuGroup.key);
|
: [...collapsedGroups, menuGroup.key]
|
||||||
} else {
|
);
|
||||||
collapseKeys.add(menuGroup.key);
|
|
||||||
}
|
|
||||||
setCollapseKeys(new Set(collapseKeys));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const menuItemRender = (menuItem: MenuItem, key: string) => {
|
const menuItemRender = (menuItem: MenuItem, key: string) => {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default {
|
|||||||
'ai.provider.ollama': 'Ollama',
|
'ai.provider.ollama': 'Ollama',
|
||||||
'ai.provider.openai': 'OpenAI',
|
'ai.provider.openai': 'OpenAI',
|
||||||
'ai.provider.openrouter': 'OpenRouter',
|
'ai.provider.openrouter': 'OpenRouter',
|
||||||
'ai.provider.qwen': 'Qwen',
|
'ai.provider.qwen': 'Alibaba Cloud Model Studio',
|
||||||
'ai.provider.spark': 'Spark',
|
'ai.provider.spark': 'Spark',
|
||||||
'ai.provider.stepfun': 'StepFun',
|
'ai.provider.stepfun': 'StepFun',
|
||||||
'ai.provider.together-ai': 'TogetherAI',
|
'ai.provider.together-ai': 'TogetherAI',
|
||||||
|
|||||||
@@ -23,11 +23,12 @@ export default {
|
|||||||
'backend.form.defaultExecuteCommand': 'Default Execution Command',
|
'backend.form.defaultExecuteCommand': 'Default Execution Command',
|
||||||
'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}', '{{'port'}}', '{{'worker_ip'}}' and '{{'model_name'}}' are placeholders that will be substituted with the actual values during deployment.`,
|
'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}', '{{'port'}}', '{{'worker_ip'}}' and '{{'model_name'}}' are placeholders that will be substituted with the actual values during deployment.`,
|
||||||
'backend.form.defaultBackendParameters': 'Default Backend Parameters',
|
'backend.form.defaultBackendParameters': 'Default Backend Parameters',
|
||||||
'backend.form.parameterFormat': 'Parameter Format',
|
'backend.form.flagFormat': 'Flag Format',
|
||||||
'backend.form.parameterFormat.default': 'Backend Default',
|
'backend.form.flagFormat.tips':
|
||||||
'backend.form.parameterFormat.space': 'Space (--key value)',
|
'The format applied between an option and its value. Leave empty to keep each parameter as entered, without normalizing it.',
|
||||||
'backend.form.parameterFormat.equal': 'Equal (--key=value)',
|
'backend.form.flagFormat.space': 'Space Separated (--key value)',
|
||||||
'backend.form.commonParameters': 'Common Parameters',
|
'backend.form.flagFormat.equal': 'Equal Sign (--key=value)',
|
||||||
|
'backend.form.commonParameters': 'Common Backend Parameters',
|
||||||
'backend.form.commonParameters.tips':
|
'backend.form.commonParameters.tips':
|
||||||
'Shown as suggestions in the backend parameters input during deployment.',
|
'Shown as suggestions in the backend parameters input during deployment.',
|
||||||
'backend.form.versionConfig': 'Versions Config',
|
'backend.form.versionConfig': 'Versions Config',
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ export default {
|
|||||||
'Stress test for long-context handling. Evaluates KV cache behavior, memory usage, and backend stability.',
|
'Stress test for long-context handling. Evaluates KV cache behavior, memory usage, and backend stability.',
|
||||||
'benchmark.form.profile.heavy.tips':
|
'benchmark.form.profile.heavy.tips':
|
||||||
'Decode-heavy generation benchmark. Measures sustained decoding speed and output token throughput.',
|
'Decode-heavy generation benchmark. Measures sustained decoding speed and output token throughput.',
|
||||||
'benchmark.table.filter.bygpu': 'Filter by GPU',
|
'benchmark.table.filter.bygpu': 'Search by GPU',
|
||||||
'benchmark.table.filter.bymodel': 'Filter by Model',
|
'benchmark.table.filter.bymodel': 'Search by model',
|
||||||
'benchmark.table.filter.bydataset': 'Filter by Dataset',
|
'benchmark.table.filter.bydataset': 'Filter by Dataset',
|
||||||
'benchmark.table.filter.byProfile': 'Filter by Profile',
|
'benchmark.table.filter.byProfile': 'Filter by profile',
|
||||||
'benchmark.table.avg': 'Avg',
|
'benchmark.table.avg': 'Avg',
|
||||||
'benchmark.table.columnSettings': 'Column Settings',
|
'benchmark.table.columnSettings': 'Column Settings',
|
||||||
'benchmark.detail.summary.results': 'Test Results',
|
'benchmark.detail.summary.results': 'Test Results',
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
export default {
|
||||||
|
'billing.upsell.title': 'Billing is an Enterprise feature',
|
||||||
|
'billing.upsell.subtitle':
|
||||||
|
'Track spend, generate invoices, and enforce budgets across teams. Upgrade to MesaStack Enterprise to manage billing.',
|
||||||
|
'billing.upsell.featuresTitle': 'What you get in Enterprise',
|
||||||
|
'billing.upsell.feature.usage':
|
||||||
|
'See cost breakdowns by organization, user, and model',
|
||||||
|
'billing.upsell.feature.invoices':
|
||||||
|
'Generate invoices and export billing reports',
|
||||||
|
'billing.upsell.feature.budgets':
|
||||||
|
'Set budgets and spending limits with alerts',
|
||||||
|
'billing.upsell.feature.chargeback':
|
||||||
|
'Attribute and charge back usage to teams and projects',
|
||||||
|
'billing.upsell.cta': 'Learn about Enterprise'
|
||||||
|
};
|
||||||
@@ -70,8 +70,13 @@ export default {
|
|||||||
'For <span class="bold-text">non-Docker</span> clusters, please register clusters or manage worker pools from the Clusters page.',
|
'For <span class="bold-text">non-Docker</span> clusters, please register clusters or manage worker pools from the Clusters page.',
|
||||||
'clusters.addworker.selectGPU': 'Select GPU Vendor',
|
'clusters.addworker.selectGPU': 'Select GPU Vendor',
|
||||||
'clusters.addworker.selectGPU.multiTag': 'Multi-select',
|
'clusters.addworker.selectGPU.multiTag': 'Multi-select',
|
||||||
|
'clusters.addworker.selectGPU.subtitle':
|
||||||
|
'You can select multiple GPU Vendors or none for CPU-only clusters',
|
||||||
'clusters.addworker.checkEnv': 'Check Environment',
|
'clusters.addworker.checkEnv': 'Check Environment',
|
||||||
|
'clusters.addworker.checkEnv.cpuOnlyTips':
|
||||||
|
'Use the following command to verify that the Kubernetes cluster has at least one ready node. You are registering a CPU-only cluster.',
|
||||||
'clusters.addworker.specifyArgs': 'Specify Arguments',
|
'clusters.addworker.specifyArgs': 'Specify Arguments',
|
||||||
|
'clusters.addworker.dtkVersion': 'DTK Version',
|
||||||
'clusters.addworker.runCommand': 'Run Command',
|
'clusters.addworker.runCommand': 'Run Command',
|
||||||
'clusters.addworker.specifyWorkerIP': 'Worker IP',
|
'clusters.addworker.specifyWorkerIP': 'Worker IP',
|
||||||
'clusters.addworker.detectWorkerIP': 'Auto-detect Worker IP',
|
'clusters.addworker.detectWorkerIP': 'Auto-detect Worker IP',
|
||||||
@@ -80,7 +85,7 @@ export default {
|
|||||||
'clusters.addworker.detectWorkerAddress.tips':
|
'clusters.addworker.detectWorkerAddress.tips':
|
||||||
'Defaults to Worker IP if not specified.',
|
'Defaults to Worker IP if not specified.',
|
||||||
'clusters.addworker.externalIP.tips':
|
'clusters.addworker.externalIP.tips':
|
||||||
'If running in a VPC or private network, please specify the Worker external address reachable by the GPUStack Server.',
|
'If running in a VPC or private network, please specify the Worker external address reachable by the MesaStack Server.',
|
||||||
'clusters.addworker.enterWorkerIP': 'Enter worker IP',
|
'clusters.addworker.enterWorkerIP': 'Enter worker IP',
|
||||||
'clusters.addworker.enterWorkerIP.error': 'Please enter the worker IP.',
|
'clusters.addworker.enterWorkerIP.error': 'Please enter the worker IP.',
|
||||||
'clusters.addworker.enterWorkerAddress': 'Enter worker external address',
|
'clusters.addworker.enterWorkerAddress': 'Enter worker external address',
|
||||||
@@ -108,22 +113,20 @@ export default {
|
|||||||
'{count} new worker has been added to the cluster.',
|
'{count} new worker has been added to the cluster.',
|
||||||
'clusters.addworker.message.success_multiple':
|
'clusters.addworker.message.success_multiple':
|
||||||
'{count} new workers have been added to the cluster.',
|
'{count} new workers have been added to the cluster.',
|
||||||
'clusters.create.serverUrl': 'GPUStack Server URL',
|
'clusters.create.serverUrl': 'MesaStack Server URL',
|
||||||
'clusters.create.workerConfig': 'Worker Configuration',
|
'clusters.create.workerConfig': 'Worker Configuration',
|
||||||
'clusters.edit.k8sOptions.changed.tip':
|
'clusters.edit.k8sOptions.changed.tip':
|
||||||
'You have changed the Kubernetes options. Re-run the registration command on the target cluster for the changes to take effect.',
|
'You have changed the Kubernetes options. Re-run the registration command on the target cluster for the changes to take effect.',
|
||||||
'clusters.edit.workerConfig.tip':
|
|
||||||
'Changes to the worker configuration take effect only after restarting the affected workers.',
|
|
||||||
'clusters.addworker.containerName': 'Worker Container Name',
|
'clusters.addworker.containerName': 'Worker Container Name',
|
||||||
'clusters.addworker.containerName.tips':
|
'clusters.addworker.containerName.tips':
|
||||||
'Specify a name for the worker container.',
|
'Specify a name for the worker container.',
|
||||||
'clusters.addworker.dataVolume': 'GPUStack Data Volume',
|
'clusters.addworker.dataVolume': 'MesaStack Data Volume',
|
||||||
'clusters.addworker.dataVolume.tips':
|
'clusters.addworker.dataVolume.tips':
|
||||||
'Specify a data storage path for GPUStack.',
|
'Specify a data storage path for MesaStack.',
|
||||||
'clusters.table.ip.internal': 'Internal',
|
'clusters.table.ip.internal': 'Internal',
|
||||||
'clusters.table.ip.external': 'External',
|
'clusters.table.ip.external': 'External',
|
||||||
'clusters.form.serverUrl.tips':
|
'clusters.form.serverUrl.tips':
|
||||||
'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack Server directly.',
|
'Specify an externally accessible MesaStack service URL if the worker cannot access MesaStack Server directly.',
|
||||||
'clusters.form.setDefault': 'Set as Default',
|
'clusters.form.setDefault': 'Set as Default',
|
||||||
'clusters.form.setDefault.tips': 'Default for deployment.',
|
'clusters.form.setDefault.tips': 'Default for deployment.',
|
||||||
'clusters.addworker.noClusters': 'No available Docker clusters found',
|
'clusters.addworker.noClusters': 'No available Docker clusters found',
|
||||||
@@ -141,7 +144,7 @@ export default {
|
|||||||
'clusters.addworker.theadNotes-02':
|
'clusters.addworker.theadNotes-02':
|
||||||
'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the <span class="bold-text">/var/run/cdi</span> directory to be available for CDI generation.',
|
'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the <span class="bold-text">/var/run/cdi</span> directory to be available for CDI generation.',
|
||||||
'clusters.addworker.nvidiaNotes':
|
'clusters.addworker.nvidiaNotes':
|
||||||
'The built-in inference backends in GPUStack v2.1 require <span class="bold-text">CUDA 12.6+</span>. Please ensure your NVIDIA driver version is <span class="bold-text">560</span> or newer.',
|
'The built-in inference backends in MesaStack require <span class="bold-text">CUDA 12.8+</span>. Please ensure your NVIDIA driver version is <span class="bold-text">570</span> or newer.',
|
||||||
'clusters.volume.title': 'Volume Mounts',
|
'clusters.volume.title': 'Volume Mounts',
|
||||||
'clusters.volume.name': 'Volume Name',
|
'clusters.volume.name': 'Volume Name',
|
||||||
'clusters.volume.mountPath': 'Container Path',
|
'clusters.volume.mountPath': 'Container Path',
|
||||||
@@ -168,7 +171,7 @@ export default {
|
|||||||
'clusters.volume.add': 'Add Volume Mount',
|
'clusters.volume.add': 'Add Volume Mount',
|
||||||
'clusters.systemDefaultContainerRegistry.title': 'Default Container Registry',
|
'clusters.systemDefaultContainerRegistry.title': 'Default Container Registry',
|
||||||
'clusters.systemDefaultContainerRegistry.tip':
|
'clusters.systemDefaultContainerRegistry.tip':
|
||||||
'Default registry used to resolve GPUStack images for this cluster. Falls back to the server default when unset.',
|
'Default registry used to resolve MesaStack images for this cluster. Falls back to the server default when unset.',
|
||||||
'clusters.k8sOptions.title': 'Kubernetes Deployment Options',
|
'clusters.k8sOptions.title': 'Kubernetes Deployment Options',
|
||||||
'clusters.imageCredentials.title': 'Image Credentials',
|
'clusters.imageCredentials.title': 'Image Credentials',
|
||||||
'clusters.imageCredentials.add': 'Add Credential',
|
'clusters.imageCredentials.add': 'Add Credential',
|
||||||
@@ -180,7 +183,7 @@ export default {
|
|||||||
'Pod nodeSelector applied to every worker DaemonSet — only nodes whose labels match are eligible to run the worker.',
|
'Pod nodeSelector applied to every worker DaemonSet — only nodes whose labels match are eligible to run the worker.',
|
||||||
'clusters.operatorImage.title': 'Operator Image',
|
'clusters.operatorImage.title': 'Operator Image',
|
||||||
'clusters.operatorImage.tip':
|
'clusters.operatorImage.tip':
|
||||||
'Override for the GPUStack Operator container image. Leave empty to use the server default.',
|
'Override for the MesaStack Operator container image. Leave empty to use the server default.',
|
||||||
'clusters.namespace.title': 'Namespace',
|
'clusters.namespace.title': 'Namespace',
|
||||||
'clusters.namespace.tip':
|
'clusters.namespace.tip':
|
||||||
'Kubernetes namespace the cluster’s manifests render into. Leave empty to use gpustack-system.',
|
'Kubernetes namespace the cluster’s manifests render into. Leave empty to use gpustack-system.',
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export default {
|
|||||||
'common.button.enabled': 'Enabled',
|
'common.button.enabled': 'Enabled',
|
||||||
'common.button.disabled': 'Disabled',
|
'common.button.disabled': 'Disabled',
|
||||||
'common.button.upgrade': 'Upgrade',
|
'common.button.upgrade': 'Upgrade',
|
||||||
'common.enterprise.feature': 'Available in GPUStack Enterprise',
|
'common.enterprise.feature': 'Available in MesaStack Enterprise',
|
||||||
'common.input.holder': 'Please enter',
|
'common.input.holder': 'Please enter',
|
||||||
'common.validate.value': '{name} value is required',
|
'common.validate.value': '{name} value is required',
|
||||||
'common.button.edit': 'Edit',
|
'common.button.edit': 'Edit',
|
||||||
@@ -169,6 +169,7 @@ export default {
|
|||||||
'common.time.hour': 'hour',
|
'common.time.hour': 'hour',
|
||||||
'common.time.minute': 'minutes',
|
'common.time.minute': 'minutes',
|
||||||
'common.issue.report': 'Report an issue',
|
'common.issue.report': 'Report an issue',
|
||||||
|
'common.github.star.tooltip': 'Star us on GitHub',
|
||||||
'common.social.discord': 'Join Our Discord',
|
'common.social.discord': 'Join Our Discord',
|
||||||
'common.table.mark': 'Comment',
|
'common.table.mark': 'Comment',
|
||||||
'common.table.rollback.mark': 'Rollback Comment',
|
'common.table.rollback.mark': 'Rollback Comment',
|
||||||
@@ -197,6 +198,8 @@ export default {
|
|||||||
'common.table.user': 'User',
|
'common.table.user': 'User',
|
||||||
'common.settings.instructions': 'Instructions',
|
'common.settings.instructions': 'Instructions',
|
||||||
'common.settings.language': 'Language',
|
'common.settings.language': 'Language',
|
||||||
|
'common.settings.language.tips':
|
||||||
|
'Set the display language for the interface.',
|
||||||
'common.delete.confirm':
|
'common.delete.confirm':
|
||||||
'Are you sure you want to delete the selected {type}?',
|
'Are you sure you want to delete the selected {type}?',
|
||||||
'common.delete.single.confirm':
|
'common.delete.single.confirm':
|
||||||
@@ -211,7 +214,7 @@ export default {
|
|||||||
'common.form.password': 'Password',
|
'common.form.password': 'Password',
|
||||||
'common.form.username': 'Username',
|
'common.form.username': 'Username',
|
||||||
'common.login.rember': 'Remember me',
|
'common.login.rember': 'Remember me',
|
||||||
'settings.company': 'GPUStack.ai',
|
'settings.company': 'MesaStack',
|
||||||
'common.button.help': 'Help',
|
'common.button.help': 'Help',
|
||||||
'common.button.feedback': 'Feedback',
|
'common.button.feedback': 'Feedback',
|
||||||
'common.button.docs': 'Documentation',
|
'common.button.docs': 'Documentation',
|
||||||
@@ -250,6 +253,11 @@ export default {
|
|||||||
'common.appearance.tips': 'Default follows system preference.',
|
'common.appearance.tips': 'Default follows system preference.',
|
||||||
'common.button.forgotpassword': 'Forgot password?',
|
'common.button.forgotpassword': 'Forgot password?',
|
||||||
'common.appearance.theme': 'Theme',
|
'common.appearance.theme': 'Theme',
|
||||||
|
'common.appearance.description':
|
||||||
|
'Customize how the interface looks on your device.',
|
||||||
|
'common.security': 'Security',
|
||||||
|
'common.security.description':
|
||||||
|
'Manage the password used to sign in to your account.',
|
||||||
'common.page.wentwrong': 'Something went wrong.',
|
'common.page.wentwrong': 'Something went wrong.',
|
||||||
'common.page.refresh.tips':
|
'common.page.refresh.tips':
|
||||||
'The page may need to be updated. Try refreshing it!',
|
'The page may need to be updated. Try refreshing it!',
|
||||||
@@ -260,6 +268,10 @@ export default {
|
|||||||
'common.login.auth': 'Authenticating...',
|
'common.login.auth': 'Authenticating...',
|
||||||
'common.login.auth.failed': 'Authentication failed',
|
'common.login.auth.failed': 'Authentication failed',
|
||||||
'common.login.password': 'Log in with Password',
|
'common.login.password': 'Log in with Password',
|
||||||
|
'common.login.username.holder': 'Please enter username',
|
||||||
|
'common.login.password.holder': 'Please enter password',
|
||||||
|
'common.login.newpassword.holder': 'Please enter new password',
|
||||||
|
'common.login.confirm.holder': 'Please enter password again',
|
||||||
'common.external.login': 'Log in with {type}',
|
'common.external.login': 'Log in with {type}',
|
||||||
'common.sso.noConfig':
|
'common.sso.noConfig':
|
||||||
'Single sign-on is not enabled on this system. Please contact your administrator.',
|
'Single sign-on is not enabled on this system. Please contact your administrator.',
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ export default {
|
|||||||
'gpuservice.publicKey': 'SSH Public Key',
|
'gpuservice.publicKey': 'SSH Public Key',
|
||||||
'gpuservice.publicKey.add': 'Add SSH Public Key',
|
'gpuservice.publicKey.add': 'Add SSH Public Key',
|
||||||
'gpuservice.publicKey.edit': 'Edit SSH Public Key',
|
'gpuservice.publicKey.edit': 'Edit SSH Public Key',
|
||||||
|
'gpuservice.publicKey.delete.tips':
|
||||||
|
'Deleting an SSH Public Key will not revoke access for existing attached Instances. To remove access, edit those Instances separately.',
|
||||||
'gpuservice.publicKey.filter.name': 'Search by name',
|
'gpuservice.publicKey.filter.name': 'Search by name',
|
||||||
'gpuservice.publicKey.label': 'SSH Public Key',
|
'gpuservice.publicKey.label': 'SSH Public Key',
|
||||||
'gpuservice.instance.ssh.enable': 'Enable SSH Access',
|
'gpuservice.instance.ssh.enable': 'Enable SSH Access',
|
||||||
@@ -120,6 +122,8 @@ export default {
|
|||||||
'gpuservice.instance.sliced': 'Sliced',
|
'gpuservice.instance.sliced': 'Sliced',
|
||||||
'gpuservice.instance.memory': 'VRAM',
|
'gpuservice.instance.memory': 'VRAM',
|
||||||
'gpuservice.instance.ram': 'RAM',
|
'gpuservice.instance.ram': 'RAM',
|
||||||
|
'gpuservice.instance.os': 'OS',
|
||||||
|
'gpuservice.instance.arch': 'Arch',
|
||||||
'gpuservice.instance.disk': 'Disk',
|
'gpuservice.instance.disk': 'Disk',
|
||||||
'gpuservice.table.count': 'Count',
|
'gpuservice.table.count': 'Count',
|
||||||
'gpuservice.instance.disk.system': 'System Disk',
|
'gpuservice.instance.disk.system': 'System Disk',
|
||||||
@@ -172,5 +176,9 @@ export default {
|
|||||||
'Please enter the temporary storage capacity',
|
'Please enter the temporary storage capacity',
|
||||||
'gpuservice.form.rule.name':
|
'gpuservice.form.rule.name':
|
||||||
"Lowercase letters, numbers, and '-'. Start and end with a letter or number, no consecutive '-', max 63 characters.",
|
"Lowercase letters, numbers, and '-'. Start and end with a letter or number, no consecutive '-', max 63 characters.",
|
||||||
'gpuservice.form.storage.select': 'Select Storage'
|
'gpuservice.form.storage.select': 'Select Storage',
|
||||||
|
'gpuservice.creator': 'Creator',
|
||||||
|
'gpuservice.owner.global': 'Global',
|
||||||
|
'gpuservice.template.group.yours': 'Your Templates',
|
||||||
|
'gpuservice.template.group.global': 'Global Templates'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export default {
|
|||||||
'menu.usage.usage': 'Usage',
|
'menu.usage.usage': 'Usage',
|
||||||
'menu.billingAndUsage': 'Usage & Billing',
|
'menu.billingAndUsage': 'Usage & Billing',
|
||||||
'menu.billingAndUsage.usage': 'Usage',
|
'menu.billingAndUsage.usage': 'Usage',
|
||||||
|
'menu.billingAndUsage.billing': 'Billing',
|
||||||
'menu.404': '404',
|
'menu.404': '404',
|
||||||
'menu.resources.clusters': 'Clusters',
|
'menu.resources.clusters': 'Clusters',
|
||||||
'menu.resources.credentials': 'Cloud Credentials',
|
'menu.resources.credentials': 'Cloud Credentials',
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export default {
|
|||||||
'models.form.env': 'Environment Variables',
|
'models.form.env': 'Environment Variables',
|
||||||
'models.form.configurations': 'Configurations',
|
'models.form.configurations': 'Configurations',
|
||||||
'models.form.s3address': 'S3 Address',
|
'models.form.s3address': 'S3 Address',
|
||||||
'models.form.partialoffload.tips': `When CPU offloading is enabled, GPUStack will allocate CPU memory if GPU resources are insufficient. You must correctly configure the inference backend to use hybrid CPU+GPU or full CPU inference.`,
|
'models.form.partialoffload.tips': `When CPU offloading is enabled, MesaStack will allocate CPU memory if GPU resources are insufficient. You must correctly configure the inference backend to use hybrid CPU+GPU or full CPU inference.`,
|
||||||
'models.form.distribution.tips': `Allows for offloading part of the model's layers to single or multiple remote workers when the resources of a worker are insufficient.`,
|
'models.form.distribution.tips': `Allows for offloading part of the model's layers to single or multiple remote workers when the resources of a worker are insufficient.`,
|
||||||
'models.openinplayground': 'Open in Playground',
|
'models.openinplayground': 'Open in Playground',
|
||||||
'models.instances': 'instances',
|
'models.instances': 'instances',
|
||||||
@@ -24,7 +24,7 @@ export default {
|
|||||||
'model.deploy.sort': 'Sort',
|
'model.deploy.sort': 'Sort',
|
||||||
'model.deploy.search.placeholder': 'Type <kbd>/</kbd> to search models',
|
'model.deploy.search.placeholder': 'Type <kbd>/</kbd> to search models',
|
||||||
'model.form.ollamatips':
|
'model.form.ollamatips':
|
||||||
'Tip: The following are the preconfigured Ollama models in GPUStack. Please select the model you want, or directly enter the model you wish to deploy in the 【{name}】 input box on the right.',
|
'Tip: The following are the preconfigured Ollama models in MesaStack. Please select the model you want, or directly enter the model you wish to deploy in the 【{name}】 input box on the right.',
|
||||||
'models.sort.name': 'Name',
|
'models.sort.name': 'Name',
|
||||||
'models.sort.size': 'Size',
|
'models.sort.size': 'Size',
|
||||||
'models.sort.likes': 'Likes',
|
'models.sort.likes': 'Likes',
|
||||||
@@ -87,7 +87,7 @@ export default {
|
|||||||
'models.form.filePath': 'Model Path',
|
'models.form.filePath': 'Model Path',
|
||||||
'models.form.backendVersion': 'Backend Version',
|
'models.form.backendVersion': 'Backend Version',
|
||||||
'models.form.backendVersion.tips':
|
'models.form.backendVersion.tips':
|
||||||
'To use the desired version of {backend}{version}, the system will automatically create a virtual environment in the online environment to install the corresponding version. After a GPUStack upgrade, the backend version will remain fixed. {link}',
|
'To use the desired version of {backend}{version}, the system will automatically create a virtual environment in the online environment to install the corresponding version. After a MesaStack upgrade, the backend version will remain fixed. {link}',
|
||||||
'models.form.gpuselector': 'GPU Selector',
|
'models.form.gpuselector': 'GPU Selector',
|
||||||
'models.form.backend.llamabox':
|
'models.form.backend.llamabox':
|
||||||
'For GGUF format models, supports Linux, macOS, and Windows.',
|
'For GGUF format models, supports Linux, macOS, and Windows.',
|
||||||
@@ -277,7 +277,7 @@ export default {
|
|||||||
'models.form.backendVersions.tips': `To use more versions, go to the {link} page and edit the backend to add versions.`,
|
'models.form.backendVersions.tips': `To use more versions, go to the {link} page and edit the backend to add versions.`,
|
||||||
'models.catalog.nogpus.tips':
|
'models.catalog.nogpus.tips':
|
||||||
'No compatible GPUs are available in the selected cluster for this model.',
|
'No compatible GPUs are available in the selected cluster for this model.',
|
||||||
'models.form.modelfile.notfound': `The model file path you specified does not exist on the GPUStack server. It's recommended to place the model file at the same path on both the GPUStack server and GPUStack workers. This helps GPUStack make better decisions.`,
|
'models.form.modelfile.notfound': `The model file path you specified does not exist on the MesaStack server. It's recommended to place the model file at the same path on both the MesaStack server and MesaStack workers. This helps MesaStack make better decisions.`,
|
||||||
'models.form.readyWorkers': 'workers ready',
|
'models.form.readyWorkers': 'workers ready',
|
||||||
'models.form.maxContextLength': 'Maximum Context Length',
|
'models.form.maxContextLength': 'Maximum Context Length',
|
||||||
'models.form.backend.helperText':
|
'models.form.backend.helperText':
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
'organizations.upsell.title': 'Organizations are an Enterprise feature',
|
'organizations.upsell.title': 'Organizations are an Enterprise feature',
|
||||||
'organizations.upsell.subtitle':
|
'organizations.upsell.subtitle':
|
||||||
'Multi-tenancy lets you isolate users, resources, and quotas across teams. Upgrade to GPUStack Enterprise to manage organizations.',
|
'Multi-tenancy lets you isolate users, resources, and quotas across teams. Upgrade to MesaStack Enterprise to manage organizations.',
|
||||||
'organizations.upsell.featuresTitle': 'What you get in Enterprise',
|
'organizations.upsell.featuresTitle': 'What you get in Enterprise',
|
||||||
'organizations.upsell.feature.orgs':
|
'organizations.upsell.feature.orgs':
|
||||||
'Create organizations to group users and isolate workloads',
|
'Create organizations to group users and isolate workloads',
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export default {
|
|||||||
'resources.worker.container.supported': 'Do not support macOS or Windows.',
|
'resources.worker.container.supported': 'Do not support macOS or Windows.',
|
||||||
'resources.worker.current.version': 'Current version is {version}.',
|
'resources.worker.current.version': 'Current version is {version}.',
|
||||||
'resources.worker.driver.install':
|
'resources.worker.driver.install':
|
||||||
'Install <a href="https://docs.gpustack.ai/latest/installation/installation-requirements/" target="_blank">required drivers and libraries</a> prior to GPUStack installation.',
|
'Install <a href="https://docs.gpustack.ai/latest/installation/installation-requirements/" target="_blank">required drivers and libraries</a> prior to MesaStack installation.',
|
||||||
'resources.worker.select.command':
|
'resources.worker.select.command':
|
||||||
'Select a label to generate the command and copy it using the copy button.',
|
'Select a label to generate the command and copy it using the copy button.',
|
||||||
'resources.worker.script.install': 'Script Installation',
|
'resources.worker.script.install': 'Script Installation',
|
||||||
@@ -89,7 +89,7 @@ export default {
|
|||||||
'Paste the <span class="bold-text">Token</span>.',
|
'Paste the <span class="bold-text">Token</span>.',
|
||||||
'resources.register.worker.step7':
|
'resources.register.worker.step7':
|
||||||
'Click <span class="bold-text">Restart</span> to apply the settings.',
|
'Click <span class="bold-text">Restart</span> to apply the settings.',
|
||||||
'resources.register.install.title': 'Install GPUStack on {os}',
|
'resources.register.install.title': 'Install MesaStack on {os}',
|
||||||
'resources.register.download':
|
'resources.register.download':
|
||||||
'Download and install the <a href={url} target="_blank">installer</a>. Only supported: {versions}.',
|
'Download and install the <a href={url} target="_blank">installer</a>. Only supported: {versions}.',
|
||||||
'resource.register.maos.support': 'Apple Silicon (M series), macOS 14+',
|
'resource.register.maos.support': 'Apple Silicon (M series), macOS 14+',
|
||||||
@@ -111,7 +111,7 @@ export default {
|
|||||||
'No available clusters. Please create a cluster before adding a node.',
|
'No available clusters. Please create a cluster before adding a node.',
|
||||||
'resources.metrics.details': 'Monitoring',
|
'resources.metrics.details': 'Monitoring',
|
||||||
'resoureces.worker.upgrade.tips':
|
'resoureces.worker.upgrade.tips':
|
||||||
'Please upgrade to match the GPUStack Server version.',
|
'Please upgrade to match the MesaStack Server version.',
|
||||||
'resources.worker.version': 'Worker Version: {version}',
|
'resources.worker.version': 'Worker Version: {version}',
|
||||||
'resources.server.version': 'Server Version: {version}',
|
'resources.server.version': 'Server Version: {version}',
|
||||||
'resources.worker.currentVersion': 'Current Version: {version}',
|
'resources.worker.currentVersion': 'Current Version: {version}',
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ export default {
|
|||||||
// --- Resource events ---
|
// --- Resource events ---
|
||||||
'usage.events.resourceType': 'Resource type',
|
'usage.events.resourceType': 'Resource type',
|
||||||
'usage.events.eventType': 'Event type',
|
'usage.events.eventType': 'Event type',
|
||||||
|
'usage.events.resourceName': 'Filter by name',
|
||||||
'usage.events.col.time': 'Time',
|
'usage.events.col.time': 'Time',
|
||||||
'usage.events.col.resource': 'Resource',
|
'usage.events.col.resource': 'Resource',
|
||||||
'usage.events.col.event': 'Event',
|
'usage.events.col.event': 'Event',
|
||||||
|
|||||||
@@ -28,16 +28,18 @@ export default {
|
|||||||
'users.password.modify.title': 'Modify Password',
|
'users.password.modify.title': 'Modify Password',
|
||||||
'users.password.modify.description':
|
'users.password.modify.description':
|
||||||
"For your account's security, please change your initial password.",
|
"For your account's security, please change your initial password.",
|
||||||
|
'users.password.modify.tips':
|
||||||
|
'Regularly updating your password helps keep your account secure.',
|
||||||
'users.password.confirm': 'Confirm New Password',
|
'users.password.confirm': 'Confirm New Password',
|
||||||
'users.password.confirm.empty': 'Please confirm the new password.',
|
'users.password.confirm.empty': 'Please confirm the new password.',
|
||||||
'users.password.confirm.error': 'The two passwords entered do not match.',
|
'users.password.confirm.error': 'The two passwords entered do not match.',
|
||||||
'users.login.title': 'Log in to',
|
'users.login.title': 'Log in to',
|
||||||
'users.version.islatest': 'GPUStack {version} is the latest version',
|
'users.version.islatest': 'MesaStack {version} is the latest version',
|
||||||
'users.version.update': 'GPUStack {version} is available',
|
'users.version.update': 'MesaStack {version} is available',
|
||||||
'users.settings.title': 'User Settings',
|
'users.settings.title': 'User Settings',
|
||||||
'users.status.activate': 'Activate Account',
|
'users.status.activate': 'Activate Account',
|
||||||
'users.status.deactivate': 'Deactivate Account',
|
'users.status.deactivate': 'Deactivate Account',
|
||||||
'users.status.inactiveAccount': 'Inactive Account',
|
'users.status.inactiveAccount': 'Inactive Account',
|
||||||
'users.login.getInitialPassword':
|
'users.login.getInitialPassword':
|
||||||
'Run the following command on your GPUStack Server to retrieve the initial admin password.'
|
'Run the following command on your MesaStack Server to retrieve the initial admin password.'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default {
|
|||||||
'ai.provider.ollama': 'Ollama',
|
'ai.provider.ollama': 'Ollama',
|
||||||
'ai.provider.openai': 'OpenAI',
|
'ai.provider.openai': 'OpenAI',
|
||||||
'ai.provider.openrouter': 'OpenRouter',
|
'ai.provider.openrouter': 'OpenRouter',
|
||||||
'ai.provider.qwen': 'Qwen',
|
'ai.provider.qwen': 'Alibaba Cloud Model Studio',
|
||||||
'ai.provider.spark': 'Spark',
|
'ai.provider.spark': 'Spark',
|
||||||
'ai.provider.stepfun': 'StepFun',
|
'ai.provider.stepfun': 'StepFun',
|
||||||
'ai.provider.together-ai': 'TogetherAI',
|
'ai.provider.together-ai': 'TogetherAI',
|
||||||
|
|||||||
@@ -23,11 +23,12 @@ export default {
|
|||||||
'backend.form.defaultExecuteCommand': 'Default Execution Command',
|
'backend.form.defaultExecuteCommand': 'Default Execution Command',
|
||||||
'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}', '{{'port'}}', '{{'worker_ip'}}' and '{{'model_name'}}' are placeholders that will be substituted with the actual values during deployment.`,
|
'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}', '{{'port'}}', '{{'worker_ip'}}' and '{{'model_name'}}' are placeholders that will be substituted with the actual values during deployment.`,
|
||||||
'backend.form.defaultBackendParameters': 'Default Backend Parameters',
|
'backend.form.defaultBackendParameters': 'Default Backend Parameters',
|
||||||
'backend.form.parameterFormat': 'パラメータ形式',
|
'backend.form.flagFormat': 'フラグ形式',
|
||||||
'backend.form.parameterFormat.default': 'バックエンドのデフォルト',
|
'backend.form.flagFormat.tips':
|
||||||
'backend.form.parameterFormat.space': 'スペース区切り (--key value)',
|
'オプションとその値を連結する形式。空欄の場合は各パラメータを入力されたまま保持し、形式を統一しません。',
|
||||||
'backend.form.parameterFormat.equal': 'イコール連結 (--key=value)',
|
'backend.form.flagFormat.space': 'スペース区切り (--key value)',
|
||||||
'backend.form.commonParameters': 'よく使うパラメータ',
|
'backend.form.flagFormat.equal': 'イコール記号 (--key=value)',
|
||||||
|
'backend.form.commonParameters': 'よく使うバックエンドパラメータ',
|
||||||
'backend.form.commonParameters.tips':
|
'backend.form.commonParameters.tips':
|
||||||
'モデルのデプロイ時にバックエンドパラメータ入力欄の候補として表示されます。',
|
'モデルのデプロイ時にバックエンドパラメータ入力欄の候補として表示されます。',
|
||||||
'backend.form.versionConfig': 'Versions Config',
|
'backend.form.versionConfig': 'Versions Config',
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ export default {
|
|||||||
'Stress test for long-context handling. Evaluates KV cache behavior, memory usage, and backend stability.',
|
'Stress test for long-context handling. Evaluates KV cache behavior, memory usage, and backend stability.',
|
||||||
'benchmark.form.profile.heavy.tips':
|
'benchmark.form.profile.heavy.tips':
|
||||||
'Decode-heavy generation benchmark. Measures sustained decoding speed and output token throughput.',
|
'Decode-heavy generation benchmark. Measures sustained decoding speed and output token throughput.',
|
||||||
'benchmark.table.filter.bygpu': 'Filter by GPU',
|
'benchmark.table.filter.bygpu': 'GPU 検索',
|
||||||
'benchmark.table.filter.bymodel': 'Filter by Model',
|
'benchmark.table.filter.bymodel': 'モデル検索',
|
||||||
'benchmark.table.filter.bydataset': 'Filter by Dataset',
|
'benchmark.table.filter.bydataset': 'Filter by Dataset',
|
||||||
'benchmark.table.filter.byProfile': 'Filter by Profile',
|
'benchmark.table.filter.byProfile': 'Filter by Profile',
|
||||||
'benchmark.table.avg': 'Avg',
|
'benchmark.table.avg': 'Avg',
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
export default {
|
||||||
|
'billing.upsell.title': 'Billing is an Enterprise feature',
|
||||||
|
'billing.upsell.subtitle':
|
||||||
|
'Track spend, generate invoices, and enforce budgets across teams. Upgrade to MesaStack Enterprise to manage billing.',
|
||||||
|
'billing.upsell.featuresTitle': 'What you get in Enterprise',
|
||||||
|
'billing.upsell.feature.usage':
|
||||||
|
'See cost breakdowns by organization, user, and model',
|
||||||
|
'billing.upsell.feature.invoices':
|
||||||
|
'Generate invoices and export billing reports',
|
||||||
|
'billing.upsell.feature.budgets':
|
||||||
|
'Set budgets and spending limits with alerts',
|
||||||
|
'billing.upsell.feature.chargeback':
|
||||||
|
'Attribute and charge back usage to teams and projects',
|
||||||
|
'billing.upsell.cta': 'Learn about Enterprise'
|
||||||
|
};
|
||||||
@@ -70,8 +70,13 @@ export default {
|
|||||||
'For <span class="bold-text">non-Docker</span> clusters, please register clusters or manage worker pools from the Clusters page.',
|
'For <span class="bold-text">non-Docker</span> clusters, please register clusters or manage worker pools from the Clusters page.',
|
||||||
'clusters.addworker.selectGPU': 'Select GPU Vendor',
|
'clusters.addworker.selectGPU': 'Select GPU Vendor',
|
||||||
'clusters.addworker.selectGPU.multiTag': 'Multi-select',
|
'clusters.addworker.selectGPU.multiTag': 'Multi-select',
|
||||||
|
'clusters.addworker.selectGPU.subtitle':
|
||||||
|
'複数の GPU ベンダーを選択するか、CPU クラスター専用の場合は選択不要です',
|
||||||
'clusters.addworker.checkEnv': 'Check Environment',
|
'clusters.addworker.checkEnv': 'Check Environment',
|
||||||
|
'clusters.addworker.checkEnv.cpuOnlyTips':
|
||||||
|
'以下のコマンドを使用して、Kubernetes クラスターに少なくとも 1 つのレディーノードがあることを確認してください。CPU クラスターを登録しています。',
|
||||||
'clusters.addworker.specifyArgs': 'Specify Arguments',
|
'clusters.addworker.specifyArgs': 'Specify Arguments',
|
||||||
|
'clusters.addworker.dtkVersion': 'DTK バージョン',
|
||||||
'clusters.addworker.runCommand': 'Run Command',
|
'clusters.addworker.runCommand': 'Run Command',
|
||||||
'clusters.addworker.specifyWorkerIP': 'Worker IP',
|
'clusters.addworker.specifyWorkerIP': 'Worker IP',
|
||||||
'clusters.addworker.detectWorkerIP': 'Worker IP を自動検出',
|
'clusters.addworker.detectWorkerIP': 'Worker IP を自動検出',
|
||||||
@@ -108,22 +113,20 @@ export default {
|
|||||||
'{count} new worker has been added to the cluster.',
|
'{count} new worker has been added to the cluster.',
|
||||||
'clusters.addworker.message.success_multiple':
|
'clusters.addworker.message.success_multiple':
|
||||||
'{count} new workers have been added to the cluster.',
|
'{count} new workers have been added to the cluster.',
|
||||||
'clusters.create.serverUrl': 'GPUStack Server URL',
|
'clusters.create.serverUrl': 'MesaStack Server URL',
|
||||||
'clusters.create.workerConfig': 'Worker Configuration',
|
'clusters.create.workerConfig': 'Worker Configuration',
|
||||||
'clusters.edit.k8sOptions.changed.tip':
|
'clusters.edit.k8sOptions.changed.tip':
|
||||||
'Kubernetes オプションを変更しました。変更を有効にするには、対象クラスターで登録コマンドを再実行してください。',
|
'Kubernetes オプションを変更しました。変更を有効にするには、対象クラスターで登録コマンドを再実行してください。',
|
||||||
'clusters.edit.workerConfig.tip':
|
|
||||||
'ワーカー設定の変更は、対象のワーカーを再起動した後に有効になります。',
|
|
||||||
'clusters.addworker.containerName': 'Worker Container Name',
|
'clusters.addworker.containerName': 'Worker Container Name',
|
||||||
'clusters.addworker.containerName.tips':
|
'clusters.addworker.containerName.tips':
|
||||||
'Specify a name for the worker container.',
|
'Specify a name for the worker container.',
|
||||||
'clusters.addworker.dataVolume': 'GPUStack Data Volume',
|
'clusters.addworker.dataVolume': 'MesaStack Data Volume',
|
||||||
'clusters.addworker.dataVolume.tips':
|
'clusters.addworker.dataVolume.tips':
|
||||||
'Specify a data storage path for GPUStack.',
|
'Specify a data storage path for MesaStack.',
|
||||||
'clusters.table.ip.internal': 'Internal',
|
'clusters.table.ip.internal': 'Internal',
|
||||||
'clusters.table.ip.external': 'External',
|
'clusters.table.ip.external': 'External',
|
||||||
'clusters.form.serverUrl.tips':
|
'clusters.form.serverUrl.tips':
|
||||||
'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack Server directly.',
|
'Specify an externally accessible MesaStack service URL if the worker cannot access MesaStack Server directly.',
|
||||||
'clusters.form.setDefault': 'Set as Default',
|
'clusters.form.setDefault': 'Set as Default',
|
||||||
'clusters.form.setDefault.tips': 'Default for deployment.',
|
'clusters.form.setDefault.tips': 'Default for deployment.',
|
||||||
'clusters.addworker.noClusters': 'No available Docker clusters found',
|
'clusters.addworker.noClusters': 'No available Docker clusters found',
|
||||||
@@ -141,7 +144,7 @@ export default {
|
|||||||
'clusters.addworker.theadNotes-02':
|
'clusters.addworker.theadNotes-02':
|
||||||
'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the <span class="bold-text">/var/run/cdi</span> directory to be available for CDI generation.',
|
'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the <span class="bold-text">/var/run/cdi</span> directory to be available for CDI generation.',
|
||||||
'clusters.addworker.nvidiaNotes':
|
'clusters.addworker.nvidiaNotes':
|
||||||
'The built-in inference backends in GPUStack v2.1 require <span class="bold-text">CUDA 12.6+</span>. Please ensure your NVIDIA driver version is <span class="bold-text">560</span> or newer.',
|
'The built-in inference backends in MesaStack require <span class="bold-text">CUDA 12.8+</span>. Please ensure your NVIDIA driver version is <span class="bold-text">570</span> or newer.',
|
||||||
'clusters.volume.title': 'Volume Mounts',
|
'clusters.volume.title': 'Volume Mounts',
|
||||||
'clusters.volume.name': 'Volume Name',
|
'clusters.volume.name': 'Volume Name',
|
||||||
'clusters.volume.mountPath': 'Container Path',
|
'clusters.volume.mountPath': 'Container Path',
|
||||||
@@ -168,7 +171,7 @@ export default {
|
|||||||
'clusters.volume.add': 'Add Volume Mount',
|
'clusters.volume.add': 'Add Volume Mount',
|
||||||
'clusters.systemDefaultContainerRegistry.title': 'Default Container Registry',
|
'clusters.systemDefaultContainerRegistry.title': 'Default Container Registry',
|
||||||
'clusters.systemDefaultContainerRegistry.tip':
|
'clusters.systemDefaultContainerRegistry.tip':
|
||||||
'Default registry used to resolve GPUStack images for this cluster. Falls back to the server default when unset.',
|
'Default registry used to resolve MesaStack images for this cluster. Falls back to the server default when unset.',
|
||||||
'clusters.k8sOptions.title': 'Kubernetes Deployment Options',
|
'clusters.k8sOptions.title': 'Kubernetes Deployment Options',
|
||||||
'clusters.imageCredentials.title': 'Image Credentials',
|
'clusters.imageCredentials.title': 'Image Credentials',
|
||||||
'clusters.imageCredentials.add': 'Add Credential',
|
'clusters.imageCredentials.add': 'Add Credential',
|
||||||
@@ -180,7 +183,7 @@ export default {
|
|||||||
'Pod nodeSelector applied to every worker DaemonSet — only nodes whose labels match are eligible to run the worker.',
|
'Pod nodeSelector applied to every worker DaemonSet — only nodes whose labels match are eligible to run the worker.',
|
||||||
'clusters.operatorImage.title': 'Operator Image',
|
'clusters.operatorImage.title': 'Operator Image',
|
||||||
'clusters.operatorImage.tip':
|
'clusters.operatorImage.tip':
|
||||||
'Override for the GPUStack Operator container image. Leave empty to use the server default.',
|
'Override for the MesaStack Operator container image. Leave empty to use the server default.',
|
||||||
'clusters.namespace.title': 'Namespace',
|
'clusters.namespace.title': 'Namespace',
|
||||||
'clusters.namespace.tip':
|
'clusters.namespace.tip':
|
||||||
'Kubernetes namespace the cluster’s manifests render into. Leave empty to use gpustack-system.',
|
'Kubernetes namespace the cluster’s manifests render into. Leave empty to use gpustack-system.',
|
||||||
@@ -273,15 +276,15 @@ export default {
|
|||||||
// 73. 'clusters.addworker.cacheVolume.holder': 'e.g. /data/cache (path must start with /)',
|
// 73. 'clusters.addworker.cacheVolume.holder': 'e.g. /data/cache (path must start with /)',
|
||||||
// 74. 'clusters.addworker.message.success_single': '{count} new worker has been added to the cluster.',
|
// 74. 'clusters.addworker.message.success_single': '{count} new worker has been added to the cluster.',
|
||||||
// 75. 'clusters.addworker.message.success_multiple': '{count} new workers have been added to the cluster.',
|
// 75. 'clusters.addworker.message.success_multiple': '{count} new workers have been added to the cluster.',
|
||||||
// 76. 'clusters.create.serverUrl': 'GPUStack Server URL',
|
// 76. 'clusters.create.serverUrl': 'MesaStack Server URL',
|
||||||
// 77. 'clusters.create.workerConfig': 'Worker Configuration'
|
// 77. 'clusters.create.workerConfig': 'Worker Configuration'
|
||||||
// 78. 'clusters.addworker.containerName': 'Worker Container Name',
|
// 78. 'clusters.addworker.containerName': 'Worker Container Name',
|
||||||
// 79. 'clusters.addworker.containerName.tips':'Specify a name for the worker container.',
|
// 79. 'clusters.addworker.containerName.tips':'Specify a name for the worker container.',
|
||||||
// 77. 'clusters.addworker.dataVolume': 'GPUStack Data Volume',
|
// 77. 'clusters.addworker.dataVolume': 'MesaStack Data Volume',
|
||||||
// 78. 'clusters.addworker.dataVolume.tips': 'Specify a data storage path for GPUStack.',
|
// 78. 'clusters.addworker.dataVolume.tips': 'Specify a data storage path for MesaStack.',
|
||||||
// 79. 'clusters.table.ip.internal': 'Internal',
|
// 79. 'clusters.table.ip.internal': 'Internal',
|
||||||
// 80. 'clusters.table.ip.external': 'External',
|
// 80. 'clusters.table.ip.external': 'External',
|
||||||
// 81. 'clusters.form.serverUrl.tips': 'Specify an externally accessible GPUStack service URL if the worker cannot access GPUStack Server directly.',
|
// 81. 'clusters.form.serverUrl.tips': 'Specify an externally accessible MesaStack service URL if the worker cannot access MesaStack Server directly.',
|
||||||
// 82. 'clusters.addworker.externalIP.tips': 'Specify an external IP if the worker is in a VPC or private network.',
|
// 82. 'clusters.addworker.externalIP.tips': 'Specify an external IP if the worker is in a VPC or private network.',
|
||||||
// 83. 'clusters.form.setDefault': 'Set as Default',
|
// 83. 'clusters.form.setDefault': 'Set as Default',
|
||||||
// 84. 'clusters.form.setDefault.tips': 'Default for deployment',
|
// 84. 'clusters.form.setDefault.tips': 'Default for deployment',
|
||||||
@@ -297,5 +300,5 @@ export default {
|
|||||||
// 94. 'clusters.create.steps.configure': 'Configure',
|
// 94. 'clusters.create.steps.configure': 'Configure',
|
||||||
// 99. 'clusters.addworker.theadNotes': 'If the <span class="bold-text>/usr/local/PPU_SDK</span> directory does not exist, please create a symbolic link pointing to the T-Head PPU SDK installed path: <span class="bold-text>ln -s /path/to/PPU_SDK /usr/local/PPU_SDK</span>',
|
// 99. 'clusters.addworker.theadNotes': 'If the <span class="bold-text>/usr/local/PPU_SDK</span> directory does not exist, please create a symbolic link pointing to the T-Head PPU SDK installed path: <span class="bold-text>ln -s /path/to/PPU_SDK /usr/local/PPU_SDK</span>',
|
||||||
// 100. 'clusters.addworker.theadNotes-02': 'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the <span class="bold-text">/var/run/cdi</span> directory to be available for CDI generation.',
|
// 100. 'clusters.addworker.theadNotes-02': 'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the <span class="bold-text">/var/run/cdi</span> directory to be available for CDI generation.',
|
||||||
// 101. 'clusters.addworker.nvidiaNotes': 'The built-in inference backends in GPUStack v2.1 require <span class="bold-text">CUDA 12.6+</span>. Please ensure your NVIDIA driver version is <span class="bold-text">560</span> or newer.'
|
// 101. 'clusters.addworker.nvidiaNotes': 'The built-in inference backends in MesaStack v2.1 require <span class="bold-text">CUDA 12.6+</span>. Please ensure your NVIDIA driver version is <span class="bold-text">560</span> or newer.'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export default {
|
|||||||
'common.button.enabled': '有効',
|
'common.button.enabled': '有効',
|
||||||
'common.button.disabled': '無効',
|
'common.button.disabled': '無効',
|
||||||
'common.button.upgrade': 'アップグレード',
|
'common.button.upgrade': 'アップグレード',
|
||||||
'common.enterprise.feature': 'Available in GPUStack Enterprise',
|
'common.enterprise.feature': 'Available in MesaStack Enterprise',
|
||||||
'common.input.holder': '入力してください',
|
'common.input.holder': '入力してください',
|
||||||
'common.validate.value': '{name} の値は必須です',
|
'common.validate.value': '{name} の値は必須です',
|
||||||
'common.button.edit': '編集',
|
'common.button.edit': '編集',
|
||||||
@@ -170,6 +170,7 @@ export default {
|
|||||||
'common.time.hour': '時間',
|
'common.time.hour': '時間',
|
||||||
'common.time.minute': '分',
|
'common.time.minute': '分',
|
||||||
'common.issue.report': '問題を報告',
|
'common.issue.report': '問題を報告',
|
||||||
|
'common.github.star.tooltip': 'GitHub でスターをつける',
|
||||||
'common.social.discord': 'Discordに参加',
|
'common.social.discord': 'Discordに参加',
|
||||||
'common.table.mark': 'コメント',
|
'common.table.mark': 'コメント',
|
||||||
'common.table.rollback.mark': 'ロールバックコメント',
|
'common.table.rollback.mark': 'ロールバックコメント',
|
||||||
@@ -198,6 +199,7 @@ export default {
|
|||||||
'common.table.user': 'ユーザー',
|
'common.table.user': 'ユーザー',
|
||||||
'common.settings.instructions': '手順',
|
'common.settings.instructions': '手順',
|
||||||
'common.settings.language': '言語',
|
'common.settings.language': '言語',
|
||||||
|
'common.settings.language.tips': 'インターフェースの表示言語を設定します。',
|
||||||
'common.delete.confirm': '選択した {type} を削除してもよろしいですか?',
|
'common.delete.confirm': '選択した {type} を削除してもよろしいですか?',
|
||||||
'common.delete.single.confirm':
|
'common.delete.single.confirm':
|
||||||
'<span style="font-size: 13px;font-weight: 700">{name}</span> を削除してもよろしいですか?',
|
'<span style="font-size: 13px;font-weight: 700">{name}</span> を削除してもよろしいですか?',
|
||||||
@@ -211,7 +213,7 @@ export default {
|
|||||||
'common.form.password': 'パスワード',
|
'common.form.password': 'パスワード',
|
||||||
'common.form.username': 'ユーザー名',
|
'common.form.username': 'ユーザー名',
|
||||||
'common.login.rember': 'ログイン状態を保持',
|
'common.login.rember': 'ログイン状態を保持',
|
||||||
'settings.company': 'GPUStack.ai',
|
'settings.company': 'MesaStack',
|
||||||
'common.button.help': 'ヘルプ',
|
'common.button.help': 'ヘルプ',
|
||||||
'common.button.feedback': 'フィードバック',
|
'common.button.feedback': 'フィードバック',
|
||||||
'common.button.docs': 'ドキュメント',
|
'common.button.docs': 'ドキュメント',
|
||||||
@@ -250,6 +252,11 @@ export default {
|
|||||||
'common.appearance.tips': 'Default follows system preference.',
|
'common.appearance.tips': 'Default follows system preference.',
|
||||||
'common.button.forgotpassword': 'Forgot password?',
|
'common.button.forgotpassword': 'Forgot password?',
|
||||||
'common.appearance.theme': 'Theme',
|
'common.appearance.theme': 'Theme',
|
||||||
|
'common.appearance.description':
|
||||||
|
'デバイス上でのインターフェースの表示をカスタマイズします。',
|
||||||
|
'common.security': 'セキュリティ',
|
||||||
|
'common.security.description':
|
||||||
|
'アカウントへのログインに使用するパスワードを管理します。',
|
||||||
'common.page.wentwrong': 'Something went wrong.',
|
'common.page.wentwrong': 'Something went wrong.',
|
||||||
'common.page.refresh.tips':
|
'common.page.refresh.tips':
|
||||||
'The page may need to be updated. Try refreshing it!',
|
'The page may need to be updated. Try refreshing it!',
|
||||||
@@ -260,6 +267,10 @@ export default {
|
|||||||
'common.login.auth': 'Authenticating...',
|
'common.login.auth': 'Authenticating...',
|
||||||
'common.login.auth.failed': 'Authentication failed',
|
'common.login.auth.failed': 'Authentication failed',
|
||||||
'common.login.password': 'Log in with Password',
|
'common.login.password': 'Log in with Password',
|
||||||
|
'common.login.username.holder': 'Please enter username',
|
||||||
|
'common.login.password.holder': 'Please enter password',
|
||||||
|
'common.login.newpassword.holder': 'Please enter new password',
|
||||||
|
'common.login.confirm.holder': 'Please enter password again',
|
||||||
'common.external.login': 'Log in with {type}',
|
'common.external.login': 'Log in with {type}',
|
||||||
'common.sso.noConfig':
|
'common.sso.noConfig':
|
||||||
'Single sign-on is not enabled on this system. Please contact your administrator.',
|
'Single sign-on is not enabled on this system. Please contact your administrator.',
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ export default {
|
|||||||
'gpuservice.publicKey': 'SSH 公開鍵',
|
'gpuservice.publicKey': 'SSH 公開鍵',
|
||||||
'gpuservice.publicKey.add': 'SSH 公開鍵を追加',
|
'gpuservice.publicKey.add': 'SSH 公開鍵を追加',
|
||||||
'gpuservice.publicKey.edit': 'SSH 公開鍵を編集',
|
'gpuservice.publicKey.edit': 'SSH 公開鍵を編集',
|
||||||
|
'gpuservice.publicKey.delete.tips':
|
||||||
|
'SSH 公開鍵を削除しても、既にアタッチされているインスタンスのアクセス権は取り消されません。アクセス権を削除するには、対象のインスタンスを個別に編集してください。',
|
||||||
'gpuservice.publicKey.filter.name': '名前で検索',
|
'gpuservice.publicKey.filter.name': '名前で検索',
|
||||||
'gpuservice.publicKey.label': 'SSH 公開鍵',
|
'gpuservice.publicKey.label': 'SSH 公開鍵',
|
||||||
'gpuservice.instance.ssh.enable': 'SSH アクセスを有効化',
|
'gpuservice.instance.ssh.enable': 'SSH アクセスを有効化',
|
||||||
@@ -119,6 +121,8 @@ export default {
|
|||||||
'gpuservice.instance.sliced': '分割',
|
'gpuservice.instance.sliced': '分割',
|
||||||
'gpuservice.instance.memory': 'VRAM',
|
'gpuservice.instance.memory': 'VRAM',
|
||||||
'gpuservice.instance.ram': 'RAM',
|
'gpuservice.instance.ram': 'RAM',
|
||||||
|
'gpuservice.instance.os': 'OS',
|
||||||
|
'gpuservice.instance.arch': 'アーキテクチャ',
|
||||||
'gpuservice.instance.disk': 'ディスク',
|
'gpuservice.instance.disk': 'ディスク',
|
||||||
'gpuservice.table.count': '数量',
|
'gpuservice.table.count': '数量',
|
||||||
'gpuservice.instance.disk.system': 'システムディスク',
|
'gpuservice.instance.disk.system': 'システムディスク',
|
||||||
@@ -172,5 +176,9 @@ export default {
|
|||||||
'Data is cleared when the instance stops.',
|
'Data is cleared when the instance stops.',
|
||||||
'gpuservice.storage.persistentVolume.tips':
|
'gpuservice.storage.persistentVolume.tips':
|
||||||
'Data persists across instance restarts. Persistent volumes remain intact after instance termination and can be shared by multiple instances.',
|
'Data persists across instance restarts. Persistent volumes remain intact after instance termination and can be shared by multiple instances.',
|
||||||
'gpuservice.form.storage.select': 'ストレージを選択'
|
'gpuservice.form.storage.select': 'ストレージを選択',
|
||||||
|
'gpuservice.creator': '作成者',
|
||||||
|
'gpuservice.owner.global': 'グローバル',
|
||||||
|
'gpuservice.template.group.yours': '自分のテンプレート',
|
||||||
|
'gpuservice.template.group.global': 'グローバルテンプレート'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export default {
|
|||||||
'menu.usage.usage': '使用状況',
|
'menu.usage.usage': '使用状況',
|
||||||
'menu.billingAndUsage': '使用状況と請求',
|
'menu.billingAndUsage': '使用状況と請求',
|
||||||
'menu.billingAndUsage.usage': '使用状況',
|
'menu.billingAndUsage.usage': '使用状況',
|
||||||
|
'menu.billingAndUsage.billing': '請求',
|
||||||
'menu.404': '404',
|
'menu.404': '404',
|
||||||
'menu.settings': 'Settings',
|
'menu.settings': 'Settings',
|
||||||
'menu.resources.workers': 'Workers',
|
'menu.resources.workers': 'Workers',
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export default {
|
|||||||
'models.form.env': '環境変数',
|
'models.form.env': '環境変数',
|
||||||
'models.form.configurations': '設定',
|
'models.form.configurations': '設定',
|
||||||
'models.form.s3address': 'S3アドレス',
|
'models.form.s3address': 'S3アドレス',
|
||||||
'models.form.partialoffload.tips': `When CPU offloading is enabled, GPUStack will allocate CPU memory if GPU resources are insufficient. You must correctly configure the inference backend to use hybrid CPU+GPU or full CPU inference.`,
|
'models.form.partialoffload.tips': `When CPU offloading is enabled, MesaStack will allocate CPU memory if GPU resources are insufficient. You must correctly configure the inference backend to use hybrid CPU+GPU or full CPU inference.`,
|
||||||
'models.form.distribution.tips':
|
'models.form.distribution.tips':
|
||||||
'ワーカーのリソースが不足している場合、モデルの一部のレイヤーを単一または複数のリモートワーカーにオフロードすることができます。',
|
'ワーカーのリソースが不足している場合、モデルの一部のレイヤーを単一または複数のリモートワーカーにオフロードすることができます。',
|
||||||
'models.openinplayground': 'プレイグラウンドで開く',
|
'models.openinplayground': 'プレイグラウンドで開く',
|
||||||
@@ -25,7 +25,7 @@ export default {
|
|||||||
'model.deploy.sort': '並び替え',
|
'model.deploy.sort': '並び替え',
|
||||||
'model.deploy.search.placeholder': '<kbd>/</kbd>を入力してモデルを検索',
|
'model.deploy.search.placeholder': '<kbd>/</kbd>を入力してモデルを検索',
|
||||||
'model.form.ollamatips':
|
'model.form.ollamatips':
|
||||||
'ヒント: 以下はGPUStackで事前設定されたOllamaモデルです。希望するモデルを選択するか、右側の【{name}】入力ボックスにデプロイしたいモデルを直接入力してください。',
|
'ヒント: 以下はMesaStackで事前設定されたOllamaモデルです。希望するモデルを選択するか、右側の【{name}】入力ボックスにデプロイしたいモデルを直接入力してください。',
|
||||||
'models.sort.name': '名前',
|
'models.sort.name': '名前',
|
||||||
'models.sort.size': 'サイズ',
|
'models.sort.size': 'サイズ',
|
||||||
'models.sort.likes': 'いいね',
|
'models.sort.likes': 'いいね',
|
||||||
@@ -88,7 +88,7 @@ export default {
|
|||||||
'models.form.filePath': 'モデルパス',
|
'models.form.filePath': 'モデルパス',
|
||||||
'models.form.backendVersion': 'バックエンドバージョン',
|
'models.form.backendVersion': 'バックエンドバージョン',
|
||||||
'models.form.backendVersion.tips':
|
'models.form.backendVersion.tips':
|
||||||
'希望する{backend}{version}バージョンを使用するには、システムがオンライン環境で対応するバージョンをインストールする仮想環境を自動的に作成します。GPUStackのアップグレード後もバックエンドバージョンは固定されます。{link}',
|
'希望する{backend}{version}バージョンを使用するには、システムがオンライン環境で対応するバージョンをインストールする仮想環境を自動的に作成します。MesaStackのアップグレード後もバックエンドバージョンは固定されます。{link}',
|
||||||
'models.form.gpuselector': 'GPUセレクター',
|
'models.form.gpuselector': 'GPUセレクター',
|
||||||
'models.form.backend.llamabox':
|
'models.form.backend.llamabox':
|
||||||
'GGUF形式のモデル用(Linux、macOS、Windowsをサポート)。',
|
'GGUF形式のモデル用(Linux、macOS、Windowsをサポート)。',
|
||||||
@@ -277,7 +277,7 @@ export default {
|
|||||||
'models.form.backendVersions.tips': `To use more versions, go to the {link} page and edit the backend to add versions.`,
|
'models.form.backendVersions.tips': `To use more versions, go to the {link} page and edit the backend to add versions.`,
|
||||||
'models.catalog.nogpus.tips':
|
'models.catalog.nogpus.tips':
|
||||||
'No compatible GPUs are available in the selected cluster for this model.',
|
'No compatible GPUs are available in the selected cluster for this model.',
|
||||||
'models.form.modelfile.notfound': `The model file path you specified does not exist on the GPUStack server. It's recommended to place the model file at the same path on both the GPUStack server and GPUStack workers. This helps GPUStack make better decisions.`,
|
'models.form.modelfile.notfound': `The model file path you specified does not exist on the MesaStack server. It's recommended to place the model file at the same path on both the MesaStack server and MesaStack workers. This helps MesaStack make better decisions.`,
|
||||||
'models.form.readyWorkers': 'workers ready',
|
'models.form.readyWorkers': 'workers ready',
|
||||||
'models.form.maxContextLength': 'Maximum Context Length',
|
'models.form.maxContextLength': 'Maximum Context Length',
|
||||||
'models.form.backend.helperText':
|
'models.form.backend.helperText':
|
||||||
@@ -381,7 +381,7 @@ export default {
|
|||||||
// 62. 'models.form.backend_parameters.vllm.tips': 'For more details about {backend} parameters, see <a href={link} target="_blank">here</a>.',
|
// 62. 'models.form.backend_parameters.vllm.tips': 'For more details about {backend} parameters, see <a href={link} target="_blank">here</a>.',
|
||||||
// 63. 'models.button.accessSettings.tips': 'Changes to access settings take effect after one minute.',
|
// 63. 'models.button.accessSettings.tips': 'Changes to access settings take effect after one minute.',
|
||||||
// 64. 'models.table.userSelection.tips': 'Admin users can access all models by default.',
|
// 64. 'models.table.userSelection.tips': 'Admin users can access all models by default.',
|
||||||
// 65. 'models.form.partialoffload.tips': `When CPU offloading is enabled, GPUStack will allocate CPU memory if GPU resources are insufficient. You must correctly configure the inference backend to use hybrid CPU+GPU or full CPU inference.`,
|
// 65. 'models.form.partialoffload.tips': `When CPU offloading is enabled, MesaStack will allocate CPU memory if GPU resources are insufficient. You must correctly configure the inference backend to use hybrid CPU+GPU or full CPU inference.`,
|
||||||
// 66. 'models.form.backend.warning': 'The selected backend does not support GGUF models. Please add a backend with GGUF support in the Inference Backend.',
|
// 66. 'models.form.backend.warning': 'The selected backend does not support GGUF models. Please add a backend with GGUF support in the Inference Backend.',
|
||||||
// 67. 'models.form.backend.warning.gguf': 'Please ensure that the selected custom backend supports GGUF models.',,
|
// 67. 'models.form.backend.warning.gguf': 'Please ensure that the selected custom backend supports GGUF models.',,
|
||||||
// 68. 'models.form.backendVersion.deprecated': 'Deprecated',
|
// 68. 'models.form.backendVersion.deprecated': 'Deprecated',
|
||||||
@@ -390,7 +390,7 @@ export default {
|
|||||||
// 71.'models.accessSettings.allowedUsers.tips': 'Only designated users can access the model.',
|
// 71.'models.accessSettings.allowedUsers.tips': 'Only designated users can access the model.',
|
||||||
// 72. 'models.form.backendVersions.tips': `To use more versions, go to the {link} page and edit the backend to add versions.`,
|
// 72. 'models.form.backendVersions.tips': `To use more versions, go to the {link} page and edit the backend to add versions.`,
|
||||||
// 73. 'models.catalog.nogpus.tips': 'No compatible GPUs are available in the selected cluster for this model.',
|
// 73. 'models.catalog.nogpus.tips': 'No compatible GPUs are available in the selected cluster for this model.',
|
||||||
// 74. 'models.form.modelfile.notfound': `The model file path you specified does not exist on the GPUStack server. It's recommended to place the model file at the same path on both the GPUStack server and GPUStack workers. This helps GPUStack make better decisions.`,
|
// 74. 'models.form.modelfile.notfound': `The model file path you specified does not exist on the MesaStack server. It's recommended to place the model file at the same path on both the MesaStack server and MesaStack workers. This helps MesaStack make better decisions.`,
|
||||||
// 75. 'models.form.readyWorkers': 'workers ready',
|
// 75. 'models.form.readyWorkers': 'workers ready',
|
||||||
// 76. 'models.form.maxContextLength': 'Maximum Context Length',
|
// 76. 'models.form.maxContextLength': 'Maximum Context Length',
|
||||||
// 77. 'models.form.backend.helperText': 'Not enabled yet. Will be enabled after deployment. ',
|
// 77. 'models.form.backend.helperText': 'Not enabled yet. Will be enabled after deployment. ',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
'organizations.upsell.title': 'Organizations are an Enterprise feature',
|
'organizations.upsell.title': 'Organizations are an Enterprise feature',
|
||||||
'organizations.upsell.subtitle':
|
'organizations.upsell.subtitle':
|
||||||
'Multi-tenancy lets you isolate users, resources, and quotas across teams. Upgrade to GPUStack Enterprise to manage organizations.',
|
'Multi-tenancy lets you isolate users, resources, and quotas across teams. Upgrade to MesaStack Enterprise to manage organizations.',
|
||||||
'organizations.upsell.featuresTitle': 'What you get in Enterprise',
|
'organizations.upsell.featuresTitle': 'What you get in Enterprise',
|
||||||
'organizations.upsell.feature.orgs':
|
'organizations.upsell.feature.orgs':
|
||||||
'Create organizations to group users and isolate workloads',
|
'Create organizations to group users and isolate workloads',
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export default {
|
|||||||
'MacOSまたはWindowsはサポートされていません。',
|
'MacOSまたはWindowsはサポートされていません。',
|
||||||
'resources.worker.current.version': '現在のバージョンは {version} です。',
|
'resources.worker.current.version': '現在のバージョンは {version} です。',
|
||||||
'resources.worker.driver.install':
|
'resources.worker.driver.install':
|
||||||
'<a href="https://docs.gpustack.ai/latest/installation/installation-requirements/" target="_blank">必要なドライバとライブラリ</a> をGPUStackのインストール前にインストールしてください。',
|
'<a href="https://docs.gpustack.ai/latest/installation/installation-requirements/" target="_blank">必要なドライバとライブラリ</a> をMesaStackのインストール前にインストールしてください。',
|
||||||
'resources.worker.select.command':
|
'resources.worker.select.command':
|
||||||
'ラベルを選択してコマンドを生成し、コピーを使用してコマンドをコピーします。',
|
'ラベルを選択してコマンドを生成し、コピーを使用してコマンドをコピーします。',
|
||||||
'resources.worker.script.install': 'スクリプトインストール',
|
'resources.worker.script.install': 'スクリプトインストール',
|
||||||
@@ -89,7 +89,7 @@ export default {
|
|||||||
'Paste the <span class="bold-text">Token</span>.',
|
'Paste the <span class="bold-text">Token</span>.',
|
||||||
'resources.register.worker.step7':
|
'resources.register.worker.step7':
|
||||||
'Click <span class="bold-text">Restart</span> to apply the settings.',
|
'Click <span class="bold-text">Restart</span> to apply the settings.',
|
||||||
'resources.register.install.title': 'Install GPUStack on {os}',
|
'resources.register.install.title': 'Install MesaStack on {os}',
|
||||||
'resources.register.download':
|
'resources.register.download':
|
||||||
'Download and install the <a href={url} target="_blank">installer</a>. Only supported: {versions}.',
|
'Download and install the <a href={url} target="_blank">installer</a>. Only supported: {versions}.',
|
||||||
'resource.register.maos.support': 'Apple Silicon (M series), macOS 14+',
|
'resource.register.maos.support': 'Apple Silicon (M series), macOS 14+',
|
||||||
@@ -112,7 +112,7 @@ export default {
|
|||||||
'No available clusters. Please create a cluster before adding a node.',
|
'No available clusters. Please create a cluster before adding a node.',
|
||||||
'resources.metrics.details': 'Monitoring',
|
'resources.metrics.details': 'Monitoring',
|
||||||
'resoureces.worker.upgrade.tips':
|
'resoureces.worker.upgrade.tips':
|
||||||
'Please upgrade to match the GPUStack Server version.',
|
'Please upgrade to match the MesaStack Server version.',
|
||||||
'resources.worker.version': 'Worker Version: {version}',
|
'resources.worker.version': 'Worker Version: {version}',
|
||||||
'resources.server.version': 'Server Version: {version}',
|
'resources.server.version': 'Server Version: {version}',
|
||||||
'resources.worker.currentVersion': 'Current Version: {version}',
|
'resources.worker.currentVersion': 'Current Version: {version}',
|
||||||
@@ -128,7 +128,7 @@ export default {
|
|||||||
// 5. 'resources.register.worker.step5': 'Enter the <span class="bold-text">Server URL</span>: {url}.',
|
// 5. 'resources.register.worker.step5': 'Enter the <span class="bold-text">Server URL</span>: {url}.',
|
||||||
// 6. 'resources.register.worker.step6': 'Paste the <span class="bold-text">Token</span>.',
|
// 6. 'resources.register.worker.step6': 'Paste the <span class="bold-text">Token</span>.',
|
||||||
// 7. 'resources.register.worker.step7': 'Click <span class="bold-text">Restart</span> to apply the settings.',
|
// 7. 'resources.register.worker.step7': 'Click <span class="bold-text">Restart</span> to apply the settings.',
|
||||||
// 8. 'resources.register.install.title': 'Install GPUStack on {os}',
|
// 8. 'resources.register.install.title': 'Install MesaStack on {os}',
|
||||||
// 9. 'resources.register.download':'Download and install the <a>installer</a>. Only supported: {versions}.',
|
// 9. 'resources.register.download':'Download and install the <a>installer</a>. Only supported: {versions}.',
|
||||||
// 10. 'resource.register.maos.support': 'Apple Silicon (M series), macOS 14+',
|
// 10. 'resource.register.maos.support': 'Apple Silicon (M series), macOS 14+',
|
||||||
// 11. 'resource.register.windows.support': 'win 10, win 11',
|
// 11. 'resource.register.windows.support': 'win 10, win 11',
|
||||||
@@ -145,5 +145,5 @@ export default {
|
|||||||
// 22. 'resources.worker.maintenance.remark.rules': 'Please enter maintenance remarks',
|
// 22. 'resources.worker.maintenance.remark.rules': 'Please enter maintenance remarks',
|
||||||
// 23. 'resources.worker.maintenance.tips': 'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
|
// 23. 'resources.worker.maintenance.tips': 'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
|
||||||
// 24. 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.'
|
// 24. 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.'
|
||||||
// 25. 'resoureces.worker.upgrade.tips': 'Please upgrade to match the GPUStack Server version.'
|
// 25. 'resoureces.worker.upgrade.tips': 'Please upgrade to match the MesaStack Server version.'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ export default {
|
|||||||
// --- Resource events ---
|
// --- Resource events ---
|
||||||
'usage.events.resourceType': 'リソースタイプ',
|
'usage.events.resourceType': 'リソースタイプ',
|
||||||
'usage.events.eventType': 'イベントタイプ',
|
'usage.events.eventType': 'イベントタイプ',
|
||||||
|
'usage.events.resourceName': '名前で絞り込み',
|
||||||
'usage.events.col.time': '時刻',
|
'usage.events.col.time': '時刻',
|
||||||
'usage.events.col.resource': 'リソース',
|
'usage.events.col.resource': 'リソース',
|
||||||
'usage.events.col.event': 'イベント',
|
'usage.events.col.event': 'イベント',
|
||||||
|
|||||||
@@ -29,18 +29,20 @@ export default {
|
|||||||
'users.password.modify.title': 'パスワードを変更',
|
'users.password.modify.title': 'パスワードを変更',
|
||||||
'users.password.modify.description':
|
'users.password.modify.description':
|
||||||
'アカウントのセキュリティのため、初期パスワードを変更してください。',
|
'アカウントのセキュリティのため、初期パスワードを変更してください。',
|
||||||
|
'users.password.modify.tips':
|
||||||
|
'パスワードを定期的に更新すると、アカウントの安全を保てます。',
|
||||||
'users.password.confirm': '新しいパスワードを確認',
|
'users.password.confirm': '新しいパスワードを確認',
|
||||||
'users.password.confirm.empty': '新しいパスワードを確認してください。',
|
'users.password.confirm.empty': '新しいパスワードを確認してください。',
|
||||||
'users.password.confirm.error': '入力された2つのパスワードが一致しません。',
|
'users.password.confirm.error': '入力された2つのパスワードが一致しません。',
|
||||||
'users.login.title': 'ログイン',
|
'users.login.title': 'ログイン',
|
||||||
'users.version.islatest': 'GPUStack {version} は最新バージョンです',
|
'users.version.islatest': 'MesaStack {version} は最新バージョンです',
|
||||||
'users.version.update': 'GPUStack {version} が利用可能です',
|
'users.version.update': 'MesaStack {version} が利用可能です',
|
||||||
'users.settings.title': 'User Settings',
|
'users.settings.title': 'User Settings',
|
||||||
'users.status.activate': 'Activate Account',
|
'users.status.activate': 'Activate Account',
|
||||||
'users.status.deactivate': 'Deactivate Account',
|
'users.status.deactivate': 'Deactivate Account',
|
||||||
'users.status.inactiveAccount': 'Inactive Account',
|
'users.status.inactiveAccount': 'Inactive Account',
|
||||||
'users.login.getInitialPassword':
|
'users.login.getInitialPassword':
|
||||||
'Run the following command on your GPUStack Server to retrieve the initial admin password.'
|
'Run the following command on your MesaStack Server to retrieve the initial admin password.'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
@@ -48,5 +50,5 @@ export default {
|
|||||||
// 2. 'users.status.activate': 'Activate Account',
|
// 2. 'users.status.activate': 'Activate Account',
|
||||||
// 3. 'users.status.deactivate': 'Deactivate Account',
|
// 3. 'users.status.deactivate': 'Deactivate Account',
|
||||||
// 4. 'users.status.inactiveAccount': 'Inactive Account',
|
// 4. 'users.status.inactiveAccount': 'Inactive Account',
|
||||||
// 5. 'users.login.getInitialPassword': 'Run the following command on your GPUStack Server to retrieve the initial admin password.'
|
// 5. 'users.login.getInitialPassword': 'Run the following command on your MesaStack Server to retrieve the initial admin password.'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default {
|
|||||||
'ai.provider.ollama': 'Ollama',
|
'ai.provider.ollama': 'Ollama',
|
||||||
'ai.provider.openai': 'OpenAI',
|
'ai.provider.openai': 'OpenAI',
|
||||||
'ai.provider.openrouter': 'OpenRouter',
|
'ai.provider.openrouter': 'OpenRouter',
|
||||||
'ai.provider.qwen': 'Qwen',
|
'ai.provider.qwen': 'Alibaba Cloud Model Studio',
|
||||||
'ai.provider.spark': 'Spark',
|
'ai.provider.spark': 'Spark',
|
||||||
'ai.provider.stepfun': 'StepFun',
|
'ai.provider.stepfun': 'StepFun',
|
||||||
'ai.provider.together-ai': 'TogetherAI',
|
'ai.provider.together-ai': 'TogetherAI',
|
||||||
|
|||||||
@@ -23,11 +23,12 @@ export default {
|
|||||||
'backend.form.defaultExecuteCommand': 'Команда выполнения по умолчанию',
|
'backend.form.defaultExecuteCommand': 'Команда выполнения по умолчанию',
|
||||||
'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}', '{{'port'}}', '{{'worker_ip'}}' и '{{'model_name'}}' заполняются реальными значениями во время запуска`,
|
'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}', '{{'port'}}', '{{'worker_ip'}}' и '{{'model_name'}}' заполняются реальными значениями во время запуска`,
|
||||||
'backend.form.defaultBackendParameters': 'Параметры бэкенда по умолчанию',
|
'backend.form.defaultBackendParameters': 'Параметры бэкенда по умолчанию',
|
||||||
'backend.form.parameterFormat': 'Формат параметров',
|
'backend.form.flagFormat': 'Формат флага',
|
||||||
'backend.form.parameterFormat.default': 'По умолчанию бэкенда',
|
'backend.form.flagFormat.tips':
|
||||||
'backend.form.parameterFormat.space': 'Пробел (--key value)',
|
'Формат соединения опции и её значения. Оставьте пустым, чтобы сохранить каждый параметр в исходном виде, без приведения к единому формату.',
|
||||||
'backend.form.parameterFormat.equal': 'Знак равенства (--key=value)',
|
'backend.form.flagFormat.space': 'Разделение пробелом (--key value)',
|
||||||
'backend.form.commonParameters': 'Часто используемые параметры',
|
'backend.form.flagFormat.equal': 'Знак равенства (--key=value)',
|
||||||
|
'backend.form.commonParameters': 'Общие параметры бэкенда',
|
||||||
'backend.form.commonParameters.tips':
|
'backend.form.commonParameters.tips':
|
||||||
'Отображаются как подсказки в поле параметров бэкенда при развёртывании.',
|
'Отображаются как подсказки в поле параметров бэкенда при развёртывании.',
|
||||||
'backend.form.versionConfig': 'Конфигурация версий',
|
'backend.form.versionConfig': 'Конфигурация версий',
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ export default {
|
|||||||
'Stress test for long-context handling. Evaluates KV cache behavior, memory usage, and backend stability.',
|
'Stress test for long-context handling. Evaluates KV cache behavior, memory usage, and backend stability.',
|
||||||
'benchmark.form.profile.heavy.tips':
|
'benchmark.form.profile.heavy.tips':
|
||||||
'Decode-heavy generation benchmark. Measures sustained decoding speed and output token throughput.',
|
'Decode-heavy generation benchmark. Measures sustained decoding speed and output token throughput.',
|
||||||
'benchmark.table.filter.bygpu': 'Filter by GPU',
|
'benchmark.table.filter.bygpu': 'Поиск GPU',
|
||||||
'benchmark.table.filter.bymodel': 'Filter by Model',
|
'benchmark.table.filter.bymodel': 'Поиск модели',
|
||||||
'benchmark.table.filter.bydataset': 'Filter by Dataset',
|
'benchmark.table.filter.bydataset': 'Filter by Dataset',
|
||||||
'benchmark.table.filter.byProfile': 'Filter by Profile',
|
'benchmark.table.filter.byProfile': 'Filter by Profile',
|
||||||
'benchmark.table.avg': 'Avg',
|
'benchmark.table.avg': 'Avg',
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
export default {
|
||||||
|
'billing.upsell.title': 'Billing is an Enterprise feature',
|
||||||
|
'billing.upsell.subtitle':
|
||||||
|
'Track spend, generate invoices, and enforce budgets across teams. Upgrade to MesaStack Enterprise to manage billing.',
|
||||||
|
'billing.upsell.featuresTitle': 'What you get in Enterprise',
|
||||||
|
'billing.upsell.feature.usage':
|
||||||
|
'See cost breakdowns by organization, user, and model',
|
||||||
|
'billing.upsell.feature.invoices':
|
||||||
|
'Generate invoices and export billing reports',
|
||||||
|
'billing.upsell.feature.budgets':
|
||||||
|
'Set budgets and spending limits with alerts',
|
||||||
|
'billing.upsell.feature.chargeback':
|
||||||
|
'Attribute and charge back usage to teams and projects',
|
||||||
|
'billing.upsell.cta': 'Learn about Enterprise'
|
||||||
|
};
|
||||||
@@ -70,8 +70,13 @@ export default {
|
|||||||
'Для <span class="bold-text">не-Docker</span> кластеров, пожалуйста, регистрируйте кластеры или управляйте пулами воркеров на странице Кластеры.',
|
'Для <span class="bold-text">не-Docker</span> кластеров, пожалуйста, регистрируйте кластеры или управляйте пулами воркеров на странице Кластеры.',
|
||||||
'clusters.addworker.selectGPU': 'Выбрать производителя GPU',
|
'clusters.addworker.selectGPU': 'Выбрать производителя GPU',
|
||||||
'clusters.addworker.selectGPU.multiTag': 'Multi-select',
|
'clusters.addworker.selectGPU.multiTag': 'Multi-select',
|
||||||
|
'clusters.addworker.selectGPU.subtitle':
|
||||||
|
'Вы можете выбрать несколько производителей GPU или не выбирать для кластера только с CPU',
|
||||||
'clusters.addworker.checkEnv': 'Проверить окружение',
|
'clusters.addworker.checkEnv': 'Проверить окружение',
|
||||||
|
'clusters.addworker.checkEnv.cpuOnlyTips':
|
||||||
|
'Используйте следующую команду, чтобы убедиться, что в кластере Kubernetes есть хотя бы один готовый узел. Вы регистрируете кластер только с CPU.',
|
||||||
'clusters.addworker.specifyArgs': 'Указать аргументы',
|
'clusters.addworker.specifyArgs': 'Указать аргументы',
|
||||||
|
'clusters.addworker.dtkVersion': 'Версия DTK',
|
||||||
'clusters.addworker.runCommand': 'Выполнить команду',
|
'clusters.addworker.runCommand': 'Выполнить команду',
|
||||||
'clusters.addworker.specifyWorkerIP': 'Указать IP воркера',
|
'clusters.addworker.specifyWorkerIP': 'Указать IP воркера',
|
||||||
'clusters.addworker.detectWorkerIP': 'Автоматически определить IP воркера',
|
'clusters.addworker.detectWorkerIP': 'Автоматически определить IP воркера',
|
||||||
@@ -108,22 +113,20 @@ export default {
|
|||||||
'{count} новый воркер был добавлен в кластер.',
|
'{count} новый воркер был добавлен в кластер.',
|
||||||
'clusters.addworker.message.success_multiple':
|
'clusters.addworker.message.success_multiple':
|
||||||
'{count} новых воркеров были добавлены в кластер.',
|
'{count} новых воркеров были добавлены в кластер.',
|
||||||
'clusters.create.serverUrl': 'URL сервера GPUStack',
|
'clusters.create.serverUrl': 'URL сервера MesaStack',
|
||||||
'clusters.create.workerConfig': 'Конфигурация воркера',
|
'clusters.create.workerConfig': 'Конфигурация воркера',
|
||||||
'clusters.edit.k8sOptions.changed.tip':
|
'clusters.edit.k8sOptions.changed.tip':
|
||||||
'Вы изменили параметры Kubernetes. Чтобы изменения вступили в силу, повторно выполните команду регистрации в целевом кластере.',
|
'Вы изменили параметры Kubernetes. Чтобы изменения вступили в силу, повторно выполните команду регистрации в целевом кластере.',
|
||||||
'clusters.edit.workerConfig.tip':
|
|
||||||
'Изменения конфигурации воркера вступают в силу только после перезапуска соответствующих воркеров.',
|
|
||||||
'clusters.addworker.containerName': 'Имя контейнера воркера',
|
'clusters.addworker.containerName': 'Имя контейнера воркера',
|
||||||
'clusters.addworker.containerName.tips':
|
'clusters.addworker.containerName.tips':
|
||||||
'Укажите имя для контейнера воркера.',
|
'Укажите имя для контейнера воркера.',
|
||||||
'clusters.addworker.dataVolume': 'Том данных GPUStack',
|
'clusters.addworker.dataVolume': 'Том данных MesaStack',
|
||||||
'clusters.addworker.dataVolume.tips':
|
'clusters.addworker.dataVolume.tips':
|
||||||
'Укажите путь для хранения данных GPUStack.',
|
'Укажите путь для хранения данных MesaStack.',
|
||||||
'clusters.table.ip.internal': 'Внутренний',
|
'clusters.table.ip.internal': 'Внутренний',
|
||||||
'clusters.table.ip.external': 'Внешний',
|
'clusters.table.ip.external': 'Внешний',
|
||||||
'clusters.form.serverUrl.tips':
|
'clusters.form.serverUrl.tips':
|
||||||
'Если рабочий узел не может напрямую получить доступ к GPUStack Server, укажите внешний URL службы GPUStack Server.',
|
'Если рабочий узел не может напрямую получить доступ к MesaStack Server, укажите внешний URL службы MesaStack Server.',
|
||||||
'clusters.form.setDefault': 'Установить по умолчанию',
|
'clusters.form.setDefault': 'Установить по умолчанию',
|
||||||
'clusters.form.setDefault.tips':
|
'clusters.form.setDefault.tips':
|
||||||
'Использовать по умолчанию для развертывания.',
|
'Использовать по умолчанию для развертывания.',
|
||||||
@@ -142,7 +145,7 @@ export default {
|
|||||||
'clusters.addworker.theadNotes-02':
|
'clusters.addworker.theadNotes-02':
|
||||||
'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the <span class="bold-text">/var/run/cdi</span> directory to be available for CDI generation.',
|
'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the <span class="bold-text">/var/run/cdi</span> directory to be available for CDI generation.',
|
||||||
'clusters.addworker.nvidiaNotes':
|
'clusters.addworker.nvidiaNotes':
|
||||||
'The built-in inference backends in GPUStack v2.1 require <span class="bold-text">CUDA 12.6+</span>. Please ensure your NVIDIA driver version is <span class="bold-text">560</span> or newer.',
|
'The built-in inference backends in MesaStack require <span class="bold-text">CUDA 12.8+</span>. Please ensure your NVIDIA driver version is <span class="bold-text">570</span> or newer.',
|
||||||
'clusters.volume.title': 'Volume Mounts',
|
'clusters.volume.title': 'Volume Mounts',
|
||||||
'clusters.volume.name': 'Volume Name',
|
'clusters.volume.name': 'Volume Name',
|
||||||
'clusters.volume.mountPath': 'Container Path',
|
'clusters.volume.mountPath': 'Container Path',
|
||||||
@@ -169,7 +172,7 @@ export default {
|
|||||||
'clusters.volume.add': 'Add Volume Mount',
|
'clusters.volume.add': 'Add Volume Mount',
|
||||||
'clusters.systemDefaultContainerRegistry.title': 'Default Container Registry',
|
'clusters.systemDefaultContainerRegistry.title': 'Default Container Registry',
|
||||||
'clusters.systemDefaultContainerRegistry.tip':
|
'clusters.systemDefaultContainerRegistry.tip':
|
||||||
'Default registry used to resolve GPUStack images for this cluster. Falls back to the server default when unset.',
|
'Default registry used to resolve MesaStack images for this cluster. Falls back to the server default when unset.',
|
||||||
'clusters.k8sOptions.title': 'Kubernetes Deployment Options',
|
'clusters.k8sOptions.title': 'Kubernetes Deployment Options',
|
||||||
'clusters.imageCredentials.title': 'Image Credentials',
|
'clusters.imageCredentials.title': 'Image Credentials',
|
||||||
'clusters.imageCredentials.add': 'Add Credential',
|
'clusters.imageCredentials.add': 'Add Credential',
|
||||||
@@ -181,7 +184,7 @@ export default {
|
|||||||
'Pod nodeSelector applied to every worker DaemonSet — only nodes whose labels match are eligible to run the worker.',
|
'Pod nodeSelector applied to every worker DaemonSet — only nodes whose labels match are eligible to run the worker.',
|
||||||
'clusters.operatorImage.title': 'Operator Image',
|
'clusters.operatorImage.title': 'Operator Image',
|
||||||
'clusters.operatorImage.tip':
|
'clusters.operatorImage.tip':
|
||||||
'Override for the GPUStack Operator container image. Leave empty to use the server default.',
|
'Override for the MesaStack Operator container image. Leave empty to use the server default.',
|
||||||
'clusters.namespace.title': 'Namespace',
|
'clusters.namespace.title': 'Namespace',
|
||||||
'clusters.namespace.tip':
|
'clusters.namespace.tip':
|
||||||
'Kubernetes namespace the cluster’s manifests render into. Leave empty to use gpustack-system.',
|
'Kubernetes namespace the cluster’s manifests render into. Leave empty to use gpustack-system.',
|
||||||
@@ -210,5 +213,5 @@ export default {
|
|||||||
// 10. 'clusters.addworker.theadNotes': 'If the <span class="bold-text>/usr/local/PPU_SDK</span> directory does not exist, please create a symbolic link pointing to the T-Head PPU SDK installed path: <span class="bold-text>ln -s /path/to/PPU_SDK /usr/local/PPU_SDK</span>',
|
// 10. 'clusters.addworker.theadNotes': 'If the <span class="bold-text>/usr/local/PPU_SDK</span> directory does not exist, please create a symbolic link pointing to the T-Head PPU SDK installed path: <span class="bold-text>ln -s /path/to/PPU_SDK /usr/local/PPU_SDK</span>',
|
||||||
// 11. 'clusters.addworker.theadNotes-02': 'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the <span class="bold-text">/var/run/cdi</span> directory to be available for CDI generation.'
|
// 11. 'clusters.addworker.theadNotes-02': 'T-Head PPU uses the Container Device Interface (CDI) for device injection and requires the <span class="bold-text">/var/run/cdi</span> directory to be available for CDI generation.'
|
||||||
// 12. 'clusters.addworker.metaxNotes': `If the <span class="bold-text">/opt/mxdriver</span> or <span class="bold-text">/opt/maca</span> directory does not exist, create a symbolic link to the MetaX driver and SDK installation path: <span class="desc-fill">ln -s /path/to/mxdriver /opt/mxdriver</span><span class="desc-fill">ln -s /path/to/maca /opt/maca</span>.`,
|
// 12. 'clusters.addworker.metaxNotes': `If the <span class="bold-text">/opt/mxdriver</span> or <span class="bold-text">/opt/maca</span> directory does not exist, create a symbolic link to the MetaX driver and SDK installation path: <span class="desc-fill">ln -s /path/to/mxdriver /opt/mxdriver</span><span class="desc-fill">ln -s /path/to/maca /opt/maca</span>.`,
|
||||||
// 13. 'clusters.addworker.nvidiaNotes': 'The built-in inference backends in GPUStack v2.1 require <span class="bold-text">CUDA 12.6+</span>. Please ensure your NVIDIA driver version is <span class="bold-text">560</span> or newer.'
|
// 13. 'clusters.addworker.nvidiaNotes': 'The built-in inference backends in MesaStack v2.1 require <span class="bold-text">CUDA 12.6+</span>. Please ensure your NVIDIA driver version is <span class="bold-text">560</span> or newer.'
|
||||||
// ================================================================
|
// ================================================================
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export default {
|
|||||||
'common.button.enabled': 'Активно',
|
'common.button.enabled': 'Активно',
|
||||||
'common.button.disabled': 'Отключено',
|
'common.button.disabled': 'Отключено',
|
||||||
'common.button.upgrade': 'Обновить',
|
'common.button.upgrade': 'Обновить',
|
||||||
'common.enterprise.feature': 'Available in GPUStack Enterprise',
|
'common.enterprise.feature': 'Available in MesaStack Enterprise',
|
||||||
'common.input.holder': 'Введите значение',
|
'common.input.holder': 'Введите значение',
|
||||||
'common.validate.value': 'Поле {name} обязательно',
|
'common.validate.value': 'Поле {name} обязательно',
|
||||||
'common.button.edit': 'Редактировать',
|
'common.button.edit': 'Редактировать',
|
||||||
@@ -167,6 +167,7 @@ export default {
|
|||||||
'common.time.hour': 'Час',
|
'common.time.hour': 'Час',
|
||||||
'common.time.minute': 'Минута',
|
'common.time.minute': 'Минута',
|
||||||
'common.issue.report': 'Сообщить о проблеме',
|
'common.issue.report': 'Сообщить о проблеме',
|
||||||
|
'common.github.star.tooltip': 'Поставьте нам звезду на GitHub',
|
||||||
'common.social.discord': 'Присоединиться к Discord',
|
'common.social.discord': 'Присоединиться к Discord',
|
||||||
'common.table.mark': 'Комментарий',
|
'common.table.mark': 'Комментарий',
|
||||||
'common.table.rollback.mark': 'Комментарий к откату',
|
'common.table.rollback.mark': 'Комментарий к откату',
|
||||||
@@ -196,6 +197,7 @@ export default {
|
|||||||
'common.table.user': 'Пользователь',
|
'common.table.user': 'Пользователь',
|
||||||
'common.settings.instructions': 'Инструкции',
|
'common.settings.instructions': 'Инструкции',
|
||||||
'common.settings.language': 'Язык',
|
'common.settings.language': 'Язык',
|
||||||
|
'common.settings.language.tips': 'Задайте язык отображения интерфейса.',
|
||||||
'common.delete.confirm': 'Вы уверены, что хотите удалить выбранный {type}?',
|
'common.delete.confirm': 'Вы уверены, что хотите удалить выбранный {type}?',
|
||||||
'common.delete.single.confirm':
|
'common.delete.single.confirm':
|
||||||
'Вы уверены, что хотите удалить <span style="font-size: 13px;font-weight: 700">{name}</span>?',
|
'Вы уверены, что хотите удалить <span style="font-size: 13px;font-weight: 700">{name}</span>?',
|
||||||
@@ -209,7 +211,7 @@ export default {
|
|||||||
'common.form.password': 'Пароль',
|
'common.form.password': 'Пароль',
|
||||||
'common.form.username': 'Имя пользователя',
|
'common.form.username': 'Имя пользователя',
|
||||||
'common.login.rember': 'Запомнить меня',
|
'common.login.rember': 'Запомнить меня',
|
||||||
'settings.company': 'GPUStack.ai',
|
'settings.company': 'MesaStack',
|
||||||
'common.button.help': 'Помощь',
|
'common.button.help': 'Помощь',
|
||||||
'common.button.feedback': 'Обратная связь',
|
'common.button.feedback': 'Обратная связь',
|
||||||
'common.button.docs': 'Документация',
|
'common.button.docs': 'Документация',
|
||||||
@@ -249,6 +251,11 @@ export default {
|
|||||||
'common.appearance.tips': 'По умолчанию соответствует системным настройкам.',
|
'common.appearance.tips': 'По умолчанию соответствует системным настройкам.',
|
||||||
'common.button.forgotpassword': 'Забыли пароль?',
|
'common.button.forgotpassword': 'Забыли пароль?',
|
||||||
'common.appearance.theme': 'Тема',
|
'common.appearance.theme': 'Тема',
|
||||||
|
'common.appearance.description':
|
||||||
|
'Настройте внешний вид интерфейса на вашем устройстве.',
|
||||||
|
'common.security': 'Безопасность',
|
||||||
|
'common.security.description':
|
||||||
|
'Управляйте паролем для входа в учётную запись.',
|
||||||
'common.page.wentwrong': 'Что-то пошло не так.',
|
'common.page.wentwrong': 'Что-то пошло не так.',
|
||||||
'common.page.refresh.tips':
|
'common.page.refresh.tips':
|
||||||
'Страница может нуждаться в обновлении. Попробуйте обновить её!',
|
'Страница может нуждаться в обновлении. Попробуйте обновить её!',
|
||||||
@@ -259,6 +266,10 @@ export default {
|
|||||||
'common.login.auth': 'Аутентификация...',
|
'common.login.auth': 'Аутентификация...',
|
||||||
'common.login.auth.failed': 'Ошибка аутентификации',
|
'common.login.auth.failed': 'Ошибка аутентификации',
|
||||||
'common.login.password': 'Войти с паролем',
|
'common.login.password': 'Войти с паролем',
|
||||||
|
'common.login.username.holder': 'Введите имя пользователя',
|
||||||
|
'common.login.password.holder': 'Введите пароль',
|
||||||
|
'common.login.newpassword.holder': 'Введите новый пароль',
|
||||||
|
'common.login.confirm.holder': 'Введите пароль ещё раз',
|
||||||
'common.external.login': 'Войти через {type}',
|
'common.external.login': 'Войти через {type}',
|
||||||
'common.sso.noConfig':
|
'common.sso.noConfig':
|
||||||
'Единый вход не настроен в этой системе. Пожалуйста, обратитесь к администратору.',
|
'Единый вход не настроен в этой системе. Пожалуйста, обратитесь к администратору.',
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ export default {
|
|||||||
'gpuservice.publicKey': 'Открытый ключ SSH',
|
'gpuservice.publicKey': 'Открытый ключ SSH',
|
||||||
'gpuservice.publicKey.add': 'Добавить открытый ключ SSH',
|
'gpuservice.publicKey.add': 'Добавить открытый ключ SSH',
|
||||||
'gpuservice.publicKey.edit': 'Изменить открытый ключ SSH',
|
'gpuservice.publicKey.edit': 'Изменить открытый ключ SSH',
|
||||||
|
'gpuservice.publicKey.delete.tips':
|
||||||
|
'Удаление открытого ключа SSH не отзывает доступ для уже подключённых экземпляров. Чтобы удалить доступ, отредактируйте эти экземпляры отдельно.',
|
||||||
'gpuservice.publicKey.filter.name': 'Поиск по имени',
|
'gpuservice.publicKey.filter.name': 'Поиск по имени',
|
||||||
'gpuservice.publicKey.label': 'Открытый ключ SSH',
|
'gpuservice.publicKey.label': 'Открытый ключ SSH',
|
||||||
'gpuservice.instance.ssh.enable': 'Включить SSH-доступ',
|
'gpuservice.instance.ssh.enable': 'Включить SSH-доступ',
|
||||||
@@ -118,6 +120,8 @@ export default {
|
|||||||
'gpuservice.instance.sliced': 'Разделено',
|
'gpuservice.instance.sliced': 'Разделено',
|
||||||
'gpuservice.instance.memory': 'VRAM',
|
'gpuservice.instance.memory': 'VRAM',
|
||||||
'gpuservice.instance.ram': 'RAM',
|
'gpuservice.instance.ram': 'RAM',
|
||||||
|
'gpuservice.instance.os': 'ОС',
|
||||||
|
'gpuservice.instance.arch': 'Архитектура',
|
||||||
'gpuservice.instance.disk': 'Диск',
|
'gpuservice.instance.disk': 'Диск',
|
||||||
'gpuservice.table.count': 'Количество',
|
'gpuservice.table.count': 'Количество',
|
||||||
'gpuservice.instance.disk.system': 'Системный диск',
|
'gpuservice.instance.disk.system': 'Системный диск',
|
||||||
@@ -169,5 +173,9 @@ export default {
|
|||||||
'Data is cleared when the instance stops.',
|
'Data is cleared when the instance stops.',
|
||||||
'gpuservice.storage.persistentVolume.tips':
|
'gpuservice.storage.persistentVolume.tips':
|
||||||
'Data persists across instance restarts. Persistent volumes remain intact after instance termination and can be shared by multiple instances.',
|
'Data persists across instance restarts. Persistent volumes remain intact after instance termination and can be shared by multiple instances.',
|
||||||
'gpuservice.form.storage.select': 'Выберите хранилище'
|
'gpuservice.form.storage.select': 'Выберите хранилище',
|
||||||
|
'gpuservice.creator': 'Создатель',
|
||||||
|
'gpuservice.owner.global': 'Глобальный',
|
||||||
|
'gpuservice.template.group.yours': 'Ваши шаблоны',
|
||||||
|
'gpuservice.template.group.global': 'Глобальные шаблоны'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export default {
|
|||||||
'menu.usage.usage': 'Использование',
|
'menu.usage.usage': 'Использование',
|
||||||
'menu.billingAndUsage': 'Использование и биллинг',
|
'menu.billingAndUsage': 'Использование и биллинг',
|
||||||
'menu.billingAndUsage.usage': 'Использование',
|
'menu.billingAndUsage.usage': 'Использование',
|
||||||
|
'menu.billingAndUsage.billing': 'Биллинг',
|
||||||
'menu.404': 'Ошибка 404',
|
'menu.404': 'Ошибка 404',
|
||||||
'menu.resources.workers': 'Воркеры',
|
'menu.resources.workers': 'Воркеры',
|
||||||
'menu.resources.gpus': 'GPUs',
|
'menu.resources.gpus': 'GPUs',
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export default {
|
|||||||
'models.form.configurations': 'Конфигурации',
|
'models.form.configurations': 'Конфигурации',
|
||||||
'models.form.s3address': 'S3-адрес',
|
'models.form.s3address': 'S3-адрес',
|
||||||
'models.form.partialoffload.tips':
|
'models.form.partialoffload.tips':
|
||||||
'При включении CPU оффлоудинга GPUStack будет выделять оперативную память, если ресурсов GPU недостаточно. Вы должны правильно настроить бэкенд вывода для использования гибридного CPU+GPU или полного CPU вывода.',
|
'При включении CPU оффлоудинга MesaStack будет выделять оперативную память, если ресурсов GPU недостаточно. Вы должны правильно настроить бэкенд вывода для использования гибридного CPU+GPU или полного CPU вывода.',
|
||||||
'models.form.distribution.tips':
|
'models.form.distribution.tips':
|
||||||
'Позволяет переносить часть слоёв модели на один или несколько удалённых воркеров, когда ресурсов текущего воркера недостаточно.',
|
'Позволяет переносить часть слоёв модели на один или несколько удалённых воркеров, когда ресурсов текущего воркера недостаточно.',
|
||||||
'models.openinplayground': 'Открыть в Песочнице',
|
'models.openinplayground': 'Открыть в Песочнице',
|
||||||
@@ -26,7 +26,7 @@ export default {
|
|||||||
'model.deploy.sort': 'Сортировка',
|
'model.deploy.sort': 'Сортировка',
|
||||||
'model.deploy.search.placeholder': 'Введите <kbd>/</kbd> для поиска моделей',
|
'model.deploy.search.placeholder': 'Введите <kbd>/</kbd> для поиска моделей',
|
||||||
'model.form.ollamatips':
|
'model.form.ollamatips':
|
||||||
'Подсказка: ниже представлены предустановленные модели Ollama в GPUStack. Выберите нужную или введите модель для развертывания в поле 【{name}】 справа.',
|
'Подсказка: ниже представлены предустановленные модели Ollama в MesaStack. Выберите нужную или введите модель для развертывания в поле 【{name}】 справа.',
|
||||||
'models.sort.name': 'По имени',
|
'models.sort.name': 'По имени',
|
||||||
'models.sort.size': 'По размеру',
|
'models.sort.size': 'По размеру',
|
||||||
'models.sort.likes': 'По лайкам',
|
'models.sort.likes': 'По лайкам',
|
||||||
@@ -89,7 +89,7 @@ export default {
|
|||||||
'models.form.filePath': 'Путь к модели',
|
'models.form.filePath': 'Путь к модели',
|
||||||
'models.form.backendVersion': 'Версия бэкенда',
|
'models.form.backendVersion': 'Версия бэкенда',
|
||||||
'models.form.backendVersion.tips':
|
'models.form.backendVersion.tips':
|
||||||
'Чтобы использовать желаемую версию {backend} {version}, система автоматически создаст виртуальную среду в онлайн-окружении для установки соответствующей версии. После обновления GPUStack версия бэкенда останется зафиксированной. {link}',
|
'Чтобы использовать желаемую версию {backend} {version}, система автоматически создаст виртуальную среду в онлайн-окружении для установки соответствующей версии. После обновления MesaStack версия бэкенда останется зафиксированной. {link}',
|
||||||
'models.form.gpuselector': 'Селектор GPU',
|
'models.form.gpuselector': 'Селектор GPU',
|
||||||
'models.form.backend.llamabox':
|
'models.form.backend.llamabox':
|
||||||
'Для моделей формата GGUF. Поддержка Linux, macOS и Windows.',
|
'Для моделей формата GGUF. Поддержка Linux, macOS и Windows.',
|
||||||
@@ -281,7 +281,7 @@ export default {
|
|||||||
'models.form.backendVersions.tips': `Чтобы использовать больше версий, перейдите на страницу {link} и отредактируйте бэкенд для добавления версий.`,
|
'models.form.backendVersions.tips': `Чтобы использовать больше версий, перейдите на страницу {link} и отредактируйте бэкенд для добавления версий.`,
|
||||||
'models.catalog.nogpus.tips':
|
'models.catalog.nogpus.tips':
|
||||||
'В выбранном кластере нет доступных GPU, совместимых с этой моделью.',
|
'В выбранном кластере нет доступных GPU, совместимых с этой моделью.',
|
||||||
'models.form.modelfile.notfound': `Указанный путь к файлу модели не существует на сервере GPUStack. Рекомендуется размещать файл модели по одному и тому же пути как на сервере GPUStack, так и на воркерах GPUStack. Это поможет системе принимать лучшие решения по распределению ресурсов.`,
|
'models.form.modelfile.notfound': `Указанный путь к файлу модели не существует на сервере MesaStack. Рекомендуется размещать файл модели по одному и тому же пути как на сервере MesaStack, так и на воркерах MesaStack. Это поможет системе принимать лучшие решения по распределению ресурсов.`,
|
||||||
'models.form.readyWorkers': 'воркеров готово',
|
'models.form.readyWorkers': 'воркеров готово',
|
||||||
'models.form.maxContextLength': 'Maximum Context Length',
|
'models.form.maxContextLength': 'Maximum Context Length',
|
||||||
'models.form.backend.helperText':
|
'models.form.backend.helperText':
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
'organizations.upsell.title': 'Organizations are an Enterprise feature',
|
'organizations.upsell.title': 'Organizations are an Enterprise feature',
|
||||||
'organizations.upsell.subtitle':
|
'organizations.upsell.subtitle':
|
||||||
'Multi-tenancy lets you isolate users, resources, and quotas across teams. Upgrade to GPUStack Enterprise to manage organizations.',
|
'Multi-tenancy lets you isolate users, resources, and quotas across teams. Upgrade to MesaStack Enterprise to manage organizations.',
|
||||||
'organizations.upsell.featuresTitle': 'What you get in Enterprise',
|
'organizations.upsell.featuresTitle': 'What you get in Enterprise',
|
||||||
'organizations.upsell.feature.orgs':
|
'organizations.upsell.feature.orgs':
|
||||||
'Create organizations to group users and isolate workloads',
|
'Create organizations to group users and isolate workloads',
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export default {
|
|||||||
'resources.worker.container.supported': 'Только для Linux.',
|
'resources.worker.container.supported': 'Только для Linux.',
|
||||||
'resources.worker.current.version': 'Текущая версия: {version}',
|
'resources.worker.current.version': 'Текущая версия: {version}',
|
||||||
'resources.worker.driver.install':
|
'resources.worker.driver.install':
|
||||||
'Установите <a href="https://docs.gpustack.ai/latest/installation/installation-requirements/" target="_blank">необходимые драйверы и библиотеки</a> перед установкой GPUStack.', // Translated
|
'Установите <a href="https://docs.gpustack.ai/latest/installation/installation-requirements/" target="_blank">необходимые драйверы и библиотеки</a> перед установкой MesaStack.', // Translated
|
||||||
'resources.worker.select.command':
|
'resources.worker.select.command':
|
||||||
'Выберите метку для генерации команды и скопируйте её.',
|
'Выберите метку для генерации команды и скопируйте её.',
|
||||||
'resources.worker.script.install': 'Установка скриптом',
|
'resources.worker.script.install': 'Установка скриптом',
|
||||||
@@ -87,7 +87,7 @@ export default {
|
|||||||
'Вставьте <span class="bold-text">Токен</span>.',
|
'Вставьте <span class="bold-text">Токен</span>.',
|
||||||
'resources.register.worker.step7':
|
'resources.register.worker.step7':
|
||||||
'Нажмите <span class="bold-text">Перезапуск</span> для применения настроек.',
|
'Нажмите <span class="bold-text">Перезапуск</span> для применения настроек.',
|
||||||
'resources.register.install.title': 'Установка GPUStack на {os}',
|
'resources.register.install.title': 'Установка MesaStack на {os}',
|
||||||
'resources.register.download':
|
'resources.register.download':
|
||||||
'Скачайте и установите <a href={url} target="_blank">инсталлятор</a>. Поддерживаемые версии: {versions}.',
|
'Скачайте и установите <a href={url} target="_blank">инсталлятор</a>. Поддерживаемые версии: {versions}.',
|
||||||
'resource.register.maos.support': 'Apple Silicon (серия M), macOS 14+',
|
'resource.register.maos.support': 'Apple Silicon (серия M), macOS 14+',
|
||||||
@@ -110,7 +110,7 @@ export default {
|
|||||||
'No available clusters. Please create a cluster before adding a node.',
|
'No available clusters. Please create a cluster before adding a node.',
|
||||||
'resources.metrics.details': 'Monitoring',
|
'resources.metrics.details': 'Monitoring',
|
||||||
'resoureces.worker.upgrade.tips':
|
'resoureces.worker.upgrade.tips':
|
||||||
'Please upgrade to match the GPUStack Server version.',
|
'Please upgrade to match the MesaStack Server version.',
|
||||||
'resources.worker.version': 'Worker Version: {version}',
|
'resources.worker.version': 'Worker Version: {version}',
|
||||||
'resources.server.version': 'Server Version: {version}',
|
'resources.server.version': 'Server Version: {version}',
|
||||||
'resources.worker.currentVersion': 'Current Version: {version}',
|
'resources.worker.currentVersion': 'Current Version: {version}',
|
||||||
@@ -127,5 +127,5 @@ export default {
|
|||||||
// 7. 'resources.worker.maintenance.tips': 'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
|
// 7. 'resources.worker.maintenance.tips': 'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
|
||||||
// 8. 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.',
|
// 8. 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.',
|
||||||
// 9. 'resources.metrics.details': 'Monitoring',
|
// 9. 'resources.metrics.details': 'Monitoring',
|
||||||
// 10. 'resoureces.worker.upgrade.tips': 'Please upgrade to match the GPUStack Server version.'
|
// 10. 'resoureces.worker.upgrade.tips': 'Please upgrade to match the MesaStack Server version.'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ export default {
|
|||||||
// --- Resource events ---
|
// --- Resource events ---
|
||||||
'usage.events.resourceType': 'Тип ресурса',
|
'usage.events.resourceType': 'Тип ресурса',
|
||||||
'usage.events.eventType': 'Тип события',
|
'usage.events.eventType': 'Тип события',
|
||||||
|
'usage.events.resourceName': 'Фильтр по имени',
|
||||||
'usage.events.col.time': 'Время',
|
'usage.events.col.time': 'Время',
|
||||||
'usage.events.col.resource': 'Ресурс',
|
'usage.events.col.resource': 'Ресурс',
|
||||||
'usage.events.col.event': 'Событие',
|
'usage.events.col.event': 'Событие',
|
||||||
|
|||||||
@@ -29,12 +29,14 @@ export default {
|
|||||||
'users.password.modify.title': 'Смена пароля',
|
'users.password.modify.title': 'Смена пароля',
|
||||||
'users.password.modify.description':
|
'users.password.modify.description':
|
||||||
'В целях безопасности измените первоначальный пароль.',
|
'В целях безопасности измените первоначальный пароль.',
|
||||||
|
'users.password.modify.tips':
|
||||||
|
'Регулярное обновление пароля помогает защитить вашу учётную запись.',
|
||||||
'users.password.confirm': 'Подтвердите новый пароль',
|
'users.password.confirm': 'Подтвердите новый пароль',
|
||||||
'users.password.confirm.empty': 'Подтвердите новый пароль',
|
'users.password.confirm.empty': 'Подтвердите новый пароль',
|
||||||
'users.password.confirm.error': 'Пароли не совпадают',
|
'users.password.confirm.error': 'Пароли не совпадают',
|
||||||
'users.login.title': 'Вход в',
|
'users.login.title': 'Вход в',
|
||||||
'users.version.islatest': 'GPUStack {version} — последняя версия',
|
'users.version.islatest': 'MesaStack {version} — последняя версия',
|
||||||
'users.version.update': 'Доступно обновление GPUStack {version}',
|
'users.version.update': 'Доступно обновление MesaStack {version}',
|
||||||
'users.settings.title': 'Настройки пользователя',
|
'users.settings.title': 'Настройки пользователя',
|
||||||
'users.status.activate': 'Активировать аккаунт',
|
'users.status.activate': 'Активировать аккаунт',
|
||||||
'users.status.deactivate': 'Деактивировать аккаунт',
|
'users.status.deactivate': 'Деактивировать аккаунт',
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default {
|
|||||||
'ai.provider.ollama': 'Ollama',
|
'ai.provider.ollama': 'Ollama',
|
||||||
'ai.provider.openai': 'OpenAI',
|
'ai.provider.openai': 'OpenAI',
|
||||||
'ai.provider.openrouter': 'OpenRouter',
|
'ai.provider.openrouter': 'OpenRouter',
|
||||||
'ai.provider.qwen': 'Qwen',
|
'ai.provider.qwen': 'Alibaba Cloud Model Studio',
|
||||||
'ai.provider.spark': 'Spark',
|
'ai.provider.spark': 'Spark',
|
||||||
'ai.provider.stepfun': 'StepFun',
|
'ai.provider.stepfun': 'StepFun',
|
||||||
'ai.provider.together-ai': 'TogetherAI',
|
'ai.provider.together-ai': 'TogetherAI',
|
||||||
|
|||||||
@@ -23,11 +23,12 @@ export default {
|
|||||||
'backend.form.defaultExecuteCommand': 'Varsayılan Çalıştırma Komutu',
|
'backend.form.defaultExecuteCommand': 'Varsayılan Çalıştırma Komutu',
|
||||||
'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}', '{{'port'}}', '{{'worker_ip'}}' ve '{{'model_name'}}' dağıtım sırasında gerçek değerlerle değiştirilecek yer tutuculardır.`,
|
'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}', '{{'port'}}', '{{'worker_ip'}}' ve '{{'model_name'}}' dağıtım sırasında gerçek değerlerle değiştirilecek yer tutuculardır.`,
|
||||||
'backend.form.defaultBackendParameters': 'Varsayılan Altyapı Parametreleri',
|
'backend.form.defaultBackendParameters': 'Varsayılan Altyapı Parametreleri',
|
||||||
'backend.form.parameterFormat': 'Parametre Biçimi',
|
'backend.form.flagFormat': 'Bayrak Biçimi',
|
||||||
'backend.form.parameterFormat.default': 'Varsayılan',
|
'backend.form.flagFormat.tips':
|
||||||
'backend.form.parameterFormat.space': 'Boşluk (--key value)',
|
'Bir seçenek ile değerinin birleştirilme biçimi. Boş bırakılırsa her parametre girildiği biçimde korunur, biçim birleştirilmez.',
|
||||||
'backend.form.parameterFormat.equal': 'Eşittir (--key=value)',
|
'backend.form.flagFormat.space': 'Boşlukla Ayır (--key value)',
|
||||||
'backend.form.commonParameters': 'Yaygın Parametreler',
|
'backend.form.flagFormat.equal': 'Eşittir İşareti (--key=value)',
|
||||||
|
'backend.form.commonParameters': 'Ortak Altyapı Parametreleri',
|
||||||
'backend.form.commonParameters.tips':
|
'backend.form.commonParameters.tips':
|
||||||
'Dağıtım sırasında altyapı parametreleri girişinde öneri olarak gösterilir.',
|
'Dağıtım sırasında altyapı parametreleri girişinde öneri olarak gösterilir.',
|
||||||
'backend.form.versionConfig': 'Sürüm Yapılandırması',
|
'backend.form.versionConfig': 'Sürüm Yapılandırması',
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ export default {
|
|||||||
'Uzun bağlam işleme için stres testi. KV önbellek davranışını, bellek kullanımını ve altyapı kararlılığını değerlendirir.',
|
'Uzun bağlam işleme için stres testi. KV önbellek davranışını, bellek kullanımını ve altyapı kararlılığını değerlendirir.',
|
||||||
'benchmark.form.profile.heavy.tips':
|
'benchmark.form.profile.heavy.tips':
|
||||||
'Çözümleme ağırlıklı üretim kıyaslaması. Sürekli çözümleme hızını ve çıkış token verimini ölçer.',
|
'Çözümleme ağırlıklı üretim kıyaslaması. Sürekli çözümleme hızını ve çıkış token verimini ölçer.',
|
||||||
'benchmark.table.filter.bygpu': "GPU'ya göre filtrele",
|
'benchmark.table.filter.bygpu': 'GPU ara',
|
||||||
'benchmark.table.filter.bymodel': 'Modele göre filtrele',
|
'benchmark.table.filter.bymodel': 'Model ara',
|
||||||
'benchmark.table.filter.bydataset': 'Veri Kümesine göre filtrele',
|
'benchmark.table.filter.bydataset': 'Veri Kümesine göre filtrele',
|
||||||
'benchmark.table.filter.byProfile': 'Profile göre filtrele',
|
'benchmark.table.filter.byProfile': 'Profile göre filtrele',
|
||||||
'benchmark.table.avg': 'Ort.',
|
'benchmark.table.avg': 'Ort.',
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
export default {
|
||||||
|
'billing.upsell.title': 'Billing is an Enterprise feature',
|
||||||
|
'billing.upsell.subtitle':
|
||||||
|
'Track spend, generate invoices, and enforce budgets across teams. Upgrade to MesaStack Enterprise to manage billing.',
|
||||||
|
'billing.upsell.featuresTitle': 'What you get in Enterprise',
|
||||||
|
'billing.upsell.feature.usage':
|
||||||
|
'See cost breakdowns by organization, user, and model',
|
||||||
|
'billing.upsell.feature.invoices':
|
||||||
|
'Generate invoices and export billing reports',
|
||||||
|
'billing.upsell.feature.budgets':
|
||||||
|
'Set budgets and spending limits with alerts',
|
||||||
|
'billing.upsell.feature.chargeback':
|
||||||
|
'Attribute and charge back usage to teams and projects',
|
||||||
|
'billing.upsell.cta': 'Learn about Enterprise'
|
||||||
|
};
|
||||||
@@ -70,8 +70,13 @@ export default {
|
|||||||
'<span class="bold-text">Docker dışı</span> kümeler için lütfen Kümeler sayfasından küme kaydı oluşturun veya işçi havuzlarını yönetin.',
|
'<span class="bold-text">Docker dışı</span> kümeler için lütfen Kümeler sayfasından küme kaydı oluşturun veya işçi havuzlarını yönetin.',
|
||||||
'clusters.addworker.selectGPU': 'GPU Üreticisi Seç',
|
'clusters.addworker.selectGPU': 'GPU Üreticisi Seç',
|
||||||
'clusters.addworker.selectGPU.multiTag': 'Multi-select',
|
'clusters.addworker.selectGPU.multiTag': 'Multi-select',
|
||||||
|
'clusters.addworker.selectGPU.subtitle':
|
||||||
|
'Birden fazla GPU Üreticisi seçebilir veya yalnızca CPU kümeleri için hiçbirini seçmeyebilirsiniz',
|
||||||
'clusters.addworker.checkEnv': 'Ortamı Kontrol Et',
|
'clusters.addworker.checkEnv': 'Ortamı Kontrol Et',
|
||||||
|
'clusters.addworker.checkEnv.cpuOnlyTips':
|
||||||
|
'Kubernetes kümesinde en az bir hazır düğüm olduğunu doğrulamak için aşağıdaki komutu kullanın. Yalnızca CPU kümelerini kaydediyorsunuz.',
|
||||||
'clusters.addworker.specifyArgs': 'Argümanları Belirle',
|
'clusters.addworker.specifyArgs': 'Argümanları Belirle',
|
||||||
|
'clusters.addworker.dtkVersion': 'DTK Sürümü',
|
||||||
'clusters.addworker.runCommand': 'Komutu Çalıştır',
|
'clusters.addworker.runCommand': 'Komutu Çalıştır',
|
||||||
'clusters.addworker.specifyWorkerIP': "İşçi Düğüm IP'si",
|
'clusters.addworker.specifyWorkerIP': "İşçi Düğüm IP'si",
|
||||||
'clusters.addworker.detectWorkerIP': "İşçi Düğüm IP'sini Otomatik Algıla",
|
'clusters.addworker.detectWorkerIP': "İşçi Düğüm IP'sini Otomatik Algıla",
|
||||||
@@ -80,7 +85,7 @@ export default {
|
|||||||
'clusters.addworker.detectWorkerAddress.tips':
|
'clusters.addworker.detectWorkerAddress.tips':
|
||||||
"Belirtilmezse İşçi Düğüm IP'si varsayılır.",
|
"Belirtilmezse İşçi Düğüm IP'si varsayılır.",
|
||||||
'clusters.addworker.externalIP.tips':
|
'clusters.addworker.externalIP.tips':
|
||||||
'VPC veya özel ağda çalıştırılıyorsa, lütfen GPUStack Sunucusuna erişilebilir İşçi Düğüm harici adresini belirtin.',
|
'VPC veya özel ağda çalıştırılıyorsa, lütfen MesaStack Sunucusuna erişilebilir İşçi Düğüm harici adresini belirtin.',
|
||||||
'clusters.addworker.enterWorkerIP': "İşçi düğüm IP'sini girin",
|
'clusters.addworker.enterWorkerIP': "İşçi düğüm IP'sini girin",
|
||||||
'clusters.addworker.enterWorkerIP.error': "Lütfen işçi düğüm IP'sini girin.",
|
'clusters.addworker.enterWorkerIP.error': "Lütfen işçi düğüm IP'sini girin.",
|
||||||
'clusters.addworker.enterWorkerAddress': 'İşçi düğüm harici adresini girin',
|
'clusters.addworker.enterWorkerAddress': 'İşçi düğüm harici adresini girin',
|
||||||
@@ -108,22 +113,20 @@ export default {
|
|||||||
'{count} yeni işçi düğüm kümeye eklendi.',
|
'{count} yeni işçi düğüm kümeye eklendi.',
|
||||||
'clusters.addworker.message.success_multiple':
|
'clusters.addworker.message.success_multiple':
|
||||||
'{count} yeni işçi düğüm kümeye eklendi.',
|
'{count} yeni işçi düğüm kümeye eklendi.',
|
||||||
'clusters.create.serverUrl': "GPUStack Sunucu URL'si",
|
'clusters.create.serverUrl': "MesaStack Sunucu URL'si",
|
||||||
'clusters.create.workerConfig': 'İşçi Düğüm Yapılandırması',
|
'clusters.create.workerConfig': 'İşçi Düğüm Yapılandırması',
|
||||||
'clusters.edit.k8sOptions.changed.tip':
|
'clusters.edit.k8sOptions.changed.tip':
|
||||||
'Kubernetes seçeneklerini değiştirdiniz. Değişikliklerin etkili olması için kayıt komutunu hedef kümede yeniden çalıştırın.',
|
'Kubernetes seçeneklerini değiştirdiniz. Değişikliklerin etkili olması için kayıt komutunu hedef kümede yeniden çalıştırın.',
|
||||||
'clusters.edit.workerConfig.tip':
|
|
||||||
'İşçi düğüm yapılandırmasındaki değişiklikler yalnızca ilgili işçi düğümleri yeniden başlatıldıktan sonra etkili olur.',
|
|
||||||
'clusters.addworker.containerName': 'İşçi Düğüm Konteyner Adı',
|
'clusters.addworker.containerName': 'İşçi Düğüm Konteyner Adı',
|
||||||
'clusters.addworker.containerName.tips':
|
'clusters.addworker.containerName.tips':
|
||||||
'İşçi düğüm konteyneri için bir ad belirtin.',
|
'İşçi düğüm konteyneri için bir ad belirtin.',
|
||||||
'clusters.addworker.dataVolume': 'GPUStack Veri Birimi',
|
'clusters.addworker.dataVolume': 'MesaStack Veri Birimi',
|
||||||
'clusters.addworker.dataVolume.tips':
|
'clusters.addworker.dataVolume.tips':
|
||||||
'GPUStack için veri depolama yolu belirtin.',
|
'MesaStack için veri depolama yolu belirtin.',
|
||||||
'clusters.table.ip.internal': 'Dahili',
|
'clusters.table.ip.internal': 'Dahili',
|
||||||
'clusters.table.ip.external': 'Harici',
|
'clusters.table.ip.external': 'Harici',
|
||||||
'clusters.form.serverUrl.tips':
|
'clusters.form.serverUrl.tips':
|
||||||
"İşçi düğüm GPUStack Sunucusuna doğrudan erişemiyorsa, harici olarak erişilebilir bir GPUStack hizmet URL'si belirtin.",
|
"İşçi düğüm MesaStack Sunucusuna doğrudan erişemiyorsa, harici olarak erişilebilir bir MesaStack hizmet URL'si belirtin.",
|
||||||
'clusters.form.setDefault': 'Varsayılan Olarak Ayarla',
|
'clusters.form.setDefault': 'Varsayılan Olarak Ayarla',
|
||||||
'clusters.form.setDefault.tips': 'Dağıtım için varsayılan.',
|
'clusters.form.setDefault.tips': 'Dağıtım için varsayılan.',
|
||||||
'clusters.addworker.noClusters': 'Kullanılabilir Docker kümesi bulunamadı',
|
'clusters.addworker.noClusters': 'Kullanılabilir Docker kümesi bulunamadı',
|
||||||
@@ -142,7 +145,7 @@ export default {
|
|||||||
'clusters.addworker.theadNotes-02':
|
'clusters.addworker.theadNotes-02':
|
||||||
'T-Head PPU, cihaz enjeksiyonu için Container Device Interface (CDI) kullanır ve CDI oluşturma için <span class="bold-text">/var/run/cdi</span> dizininin kullanılabilir olmasını gerektirir.',
|
'T-Head PPU, cihaz enjeksiyonu için Container Device Interface (CDI) kullanır ve CDI oluşturma için <span class="bold-text">/var/run/cdi</span> dizininin kullanılabilir olmasını gerektirir.',
|
||||||
'clusters.addworker.nvidiaNotes':
|
'clusters.addworker.nvidiaNotes':
|
||||||
'GPUStack v2.1\'deki yerleşik çıkarım altyapıları <span class="bold-text">CUDA 12.6+</span> gerektirir. Lütfen NVIDIA sürücü sürümünüzün <span class="bold-text">560</span> veya daha yeni olduğundan emin olun.',
|
'MesaStack\'teki yerleşik çıkarım altyapıları <span class="bold-text">CUDA 12.8+</span> gerektirir. Lütfen NVIDIA sürücü sürümünüzün <span class="bold-text">570</span> veya daha yeni olduğundan emin olun.',
|
||||||
'clusters.volume.title': 'Volume Mounts',
|
'clusters.volume.title': 'Volume Mounts',
|
||||||
'clusters.volume.name': 'Volume Name',
|
'clusters.volume.name': 'Volume Name',
|
||||||
'clusters.volume.mountPath': 'Container Path',
|
'clusters.volume.mountPath': 'Container Path',
|
||||||
@@ -169,7 +172,7 @@ export default {
|
|||||||
'clusters.volume.add': 'Add Volume Mount',
|
'clusters.volume.add': 'Add Volume Mount',
|
||||||
'clusters.systemDefaultContainerRegistry.title': 'Default Container Registry',
|
'clusters.systemDefaultContainerRegistry.title': 'Default Container Registry',
|
||||||
'clusters.systemDefaultContainerRegistry.tip':
|
'clusters.systemDefaultContainerRegistry.tip':
|
||||||
'Default registry used to resolve GPUStack images for this cluster. Falls back to the server default when unset.',
|
'Default registry used to resolve MesaStack images for this cluster. Falls back to the server default when unset.',
|
||||||
'clusters.k8sOptions.title': 'Kubernetes Deployment Options',
|
'clusters.k8sOptions.title': 'Kubernetes Deployment Options',
|
||||||
'clusters.imageCredentials.title': 'Image Credentials',
|
'clusters.imageCredentials.title': 'Image Credentials',
|
||||||
'clusters.imageCredentials.add': 'Add Credential',
|
'clusters.imageCredentials.add': 'Add Credential',
|
||||||
@@ -181,7 +184,7 @@ export default {
|
|||||||
'Pod nodeSelector applied to every worker DaemonSet — only nodes whose labels match are eligible to run the worker.',
|
'Pod nodeSelector applied to every worker DaemonSet — only nodes whose labels match are eligible to run the worker.',
|
||||||
'clusters.operatorImage.title': 'Operator Image',
|
'clusters.operatorImage.title': 'Operator Image',
|
||||||
'clusters.operatorImage.tip':
|
'clusters.operatorImage.tip':
|
||||||
'Override for the GPUStack Operator container image. Leave empty to use the server default.',
|
'Override for the MesaStack Operator container image. Leave empty to use the server default.',
|
||||||
'clusters.namespace.title': 'Namespace',
|
'clusters.namespace.title': 'Namespace',
|
||||||
'clusters.namespace.tip':
|
'clusters.namespace.tip':
|
||||||
'Kubernetes namespace the cluster’s manifests render into. Leave empty to use gpustack-system.',
|
'Kubernetes namespace the cluster’s manifests render into. Leave empty to use gpustack-system.',
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export default {
|
|||||||
'common.button.enabled': 'Etkin',
|
'common.button.enabled': 'Etkin',
|
||||||
'common.button.disabled': 'Devre dışı',
|
'common.button.disabled': 'Devre dışı',
|
||||||
'common.button.upgrade': 'Yükselt',
|
'common.button.upgrade': 'Yükselt',
|
||||||
'common.enterprise.feature': 'Available in GPUStack Enterprise',
|
'common.enterprise.feature': 'Available in MesaStack Enterprise',
|
||||||
'common.input.holder': 'Lütfen girin',
|
'common.input.holder': 'Lütfen girin',
|
||||||
'common.validate.value': '{name} değeri gereklidir',
|
'common.validate.value': '{name} değeri gereklidir',
|
||||||
'common.button.edit': 'Düzenle',
|
'common.button.edit': 'Düzenle',
|
||||||
@@ -167,6 +167,7 @@ export default {
|
|||||||
'common.time.hour': 'saat',
|
'common.time.hour': 'saat',
|
||||||
'common.time.minute': 'dakika',
|
'common.time.minute': 'dakika',
|
||||||
'common.issue.report': 'Sorun bildir',
|
'common.issue.report': 'Sorun bildir',
|
||||||
|
'common.github.star.tooltip': "GitHub'da bize yıldız verin",
|
||||||
'common.social.discord': "Discord'umuza Katılın",
|
'common.social.discord': "Discord'umuza Katılın",
|
||||||
'common.table.mark': 'Yorum',
|
'common.table.mark': 'Yorum',
|
||||||
'common.table.rollback.mark': 'Geri Alma Yorumu',
|
'common.table.rollback.mark': 'Geri Alma Yorumu',
|
||||||
@@ -198,6 +199,7 @@ export default {
|
|||||||
'common.table.user': 'Kullanıcı',
|
'common.table.user': 'Kullanıcı',
|
||||||
'common.settings.instructions': 'Talimatlar',
|
'common.settings.instructions': 'Talimatlar',
|
||||||
'common.settings.language': 'Dil',
|
'common.settings.language': 'Dil',
|
||||||
|
'common.settings.language.tips': 'Arayüzün görüntüleme dilini ayarlayın.',
|
||||||
'common.delete.confirm':
|
'common.delete.confirm':
|
||||||
'Seçili {type} öğesini silmek istediğinizden emin misiniz?',
|
'Seçili {type} öğesini silmek istediğinizden emin misiniz?',
|
||||||
'common.delete.single.confirm':
|
'common.delete.single.confirm':
|
||||||
@@ -214,7 +216,7 @@ export default {
|
|||||||
'common.form.password': 'Şifre',
|
'common.form.password': 'Şifre',
|
||||||
'common.form.username': 'Kullanıcı adı',
|
'common.form.username': 'Kullanıcı adı',
|
||||||
'common.login.rember': 'Beni hatırla',
|
'common.login.rember': 'Beni hatırla',
|
||||||
'settings.company': 'GPUStack.ai',
|
'settings.company': 'MesaStack',
|
||||||
'common.button.help': 'Yardım',
|
'common.button.help': 'Yardım',
|
||||||
'common.button.feedback': 'Geri Bildirim',
|
'common.button.feedback': 'Geri Bildirim',
|
||||||
'common.button.docs': 'Dokümantasyon',
|
'common.button.docs': 'Dokümantasyon',
|
||||||
@@ -253,6 +255,11 @@ export default {
|
|||||||
'common.appearance.tips': 'Varsayılan olarak sistem tercihini takip eder.',
|
'common.appearance.tips': 'Varsayılan olarak sistem tercihini takip eder.',
|
||||||
'common.button.forgotpassword': 'Şifrenizi mi unuttunuz?',
|
'common.button.forgotpassword': 'Şifrenizi mi unuttunuz?',
|
||||||
'common.appearance.theme': 'Tema',
|
'common.appearance.theme': 'Tema',
|
||||||
|
'common.appearance.description':
|
||||||
|
'Arayüzün cihazınızdaki görünümünü özelleştirin.',
|
||||||
|
'common.security': 'Güvenlik',
|
||||||
|
'common.security.description':
|
||||||
|
'Hesabınıza giriş yapmak için kullanılan parolayı yönetin.',
|
||||||
'common.page.wentwrong': 'Bir şeyler ters gitti.',
|
'common.page.wentwrong': 'Bir şeyler ters gitti.',
|
||||||
'common.page.refresh.tips':
|
'common.page.refresh.tips':
|
||||||
'Sayfanın güncellenmesi gerekebilir. Yenilemeyi deneyin!',
|
'Sayfanın güncellenmesi gerekebilir. Yenilemeyi deneyin!',
|
||||||
@@ -263,6 +270,10 @@ export default {
|
|||||||
'common.login.auth': 'Kimlik doğrulanıyor...',
|
'common.login.auth': 'Kimlik doğrulanıyor...',
|
||||||
'common.login.auth.failed': 'Kimlik doğrulama başarısız',
|
'common.login.auth.failed': 'Kimlik doğrulama başarısız',
|
||||||
'common.login.password': 'Şifre ile giriş yap',
|
'common.login.password': 'Şifre ile giriş yap',
|
||||||
|
'common.login.username.holder': 'Lütfen kullanıcı adını girin',
|
||||||
|
'common.login.password.holder': 'Lütfen şifreyi girin',
|
||||||
|
'common.login.newpassword.holder': 'Lütfen yeni şifreyi girin',
|
||||||
|
'common.login.confirm.holder': 'Lütfen şifreyi tekrar girin',
|
||||||
'common.external.login': '{type} ile giriş yap',
|
'common.external.login': '{type} ile giriş yap',
|
||||||
'common.sso.noConfig':
|
'common.sso.noConfig':
|
||||||
'Bu sistemde çoklu oturum açma etkinleştirilmemiş. Lütfen yöneticinize başvurun.',
|
'Bu sistemde çoklu oturum açma etkinleştirilmemiş. Lütfen yöneticinize başvurun.',
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ export default {
|
|||||||
'gpuservice.publicKey': 'SSH Açık Anahtarı',
|
'gpuservice.publicKey': 'SSH Açık Anahtarı',
|
||||||
'gpuservice.publicKey.add': 'SSH Açık Anahtarı Ekle',
|
'gpuservice.publicKey.add': 'SSH Açık Anahtarı Ekle',
|
||||||
'gpuservice.publicKey.edit': 'SSH Açık Anahtarını Düzenle',
|
'gpuservice.publicKey.edit': 'SSH Açık Anahtarını Düzenle',
|
||||||
|
'gpuservice.publicKey.delete.tips':
|
||||||
|
'Bir SSH Açık Anahtarını silmek, mevcut bağlı Örneklerin erişimini iptal etmez. Erişimi kaldırmak için ilgili Örnekleri ayrı ayrı düzenleyin.',
|
||||||
'gpuservice.publicKey.filter.name': 'Ada göre ara',
|
'gpuservice.publicKey.filter.name': 'Ada göre ara',
|
||||||
'gpuservice.publicKey.label': 'SSH Açık Anahtarı',
|
'gpuservice.publicKey.label': 'SSH Açık Anahtarı',
|
||||||
'gpuservice.instance.ssh.enable': 'SSH Erişimini Etkinleştir',
|
'gpuservice.instance.ssh.enable': 'SSH Erişimini Etkinleştir',
|
||||||
@@ -114,6 +116,8 @@ export default {
|
|||||||
'gpuservice.instance.sliced': 'Bölünmüş',
|
'gpuservice.instance.sliced': 'Bölünmüş',
|
||||||
'gpuservice.instance.memory': 'VRAM',
|
'gpuservice.instance.memory': 'VRAM',
|
||||||
'gpuservice.instance.ram': 'RAM',
|
'gpuservice.instance.ram': 'RAM',
|
||||||
|
'gpuservice.instance.os': 'OS',
|
||||||
|
'gpuservice.instance.arch': 'Mimari',
|
||||||
'gpuservice.instance.disk': 'Disk',
|
'gpuservice.instance.disk': 'Disk',
|
||||||
'gpuservice.table.count': 'Sayı',
|
'gpuservice.table.count': 'Sayı',
|
||||||
'gpuservice.instance.disk.system': 'Sistem Diski',
|
'gpuservice.instance.disk.system': 'Sistem Diski',
|
||||||
@@ -167,5 +171,9 @@ export default {
|
|||||||
'Data is cleared when the instance stops.',
|
'Data is cleared when the instance stops.',
|
||||||
'gpuservice.storage.persistentVolume.tips':
|
'gpuservice.storage.persistentVolume.tips':
|
||||||
'Data persists across instance restarts. Persistent volumes remain intact after instance termination and can be shared by multiple instances.',
|
'Data persists across instance restarts. Persistent volumes remain intact after instance termination and can be shared by multiple instances.',
|
||||||
'gpuservice.form.storage.select': 'Depolamayı Seç'
|
'gpuservice.form.storage.select': 'Depolamayı Seç',
|
||||||
|
'gpuservice.creator': 'Oluşturan',
|
||||||
|
'gpuservice.owner.global': 'Genel',
|
||||||
|
'gpuservice.template.group.yours': 'Şablonlarınız',
|
||||||
|
'gpuservice.template.group.global': 'Genel Şablonlar'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export default {
|
|||||||
'menu.usage.usage': 'Kullanım',
|
'menu.usage.usage': 'Kullanım',
|
||||||
'menu.billingAndUsage': 'Kullanım ve Faturalandırma',
|
'menu.billingAndUsage': 'Kullanım ve Faturalandırma',
|
||||||
'menu.billingAndUsage.usage': 'Kullanım',
|
'menu.billingAndUsage.usage': 'Kullanım',
|
||||||
|
'menu.billingAndUsage.billing': 'Faturalandırma',
|
||||||
'menu.404': '404',
|
'menu.404': '404',
|
||||||
'menu.resources.clusters': 'Kümeler',
|
'menu.resources.clusters': 'Kümeler',
|
||||||
'menu.resources.credentials': 'Bulut Kimlik Bilgileri',
|
'menu.resources.credentials': 'Bulut Kimlik Bilgileri',
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export default {
|
|||||||
'models.form.env': 'Ortam Değişkenleri',
|
'models.form.env': 'Ortam Değişkenleri',
|
||||||
'models.form.configurations': 'Yapılandırmalar',
|
'models.form.configurations': 'Yapılandırmalar',
|
||||||
'models.form.s3address': 'S3 Adresi',
|
'models.form.s3address': 'S3 Adresi',
|
||||||
'models.form.partialoffload.tips': `CPU aktarımı etkinleştirildiğinde, GPU kaynakları yetersiz olduğunda GPUStack CPU belleği ayırır. Hibrit CPU+GPU veya tam CPU çıkarımı kullanmak için çıkarım altyapısını doğru şekilde yapılandırmanız gerekir.`,
|
'models.form.partialoffload.tips': `CPU aktarımı etkinleştirildiğinde, GPU kaynakları yetersiz olduğunda MesaStack CPU belleği ayırır. Hibrit CPU+GPU veya tam CPU çıkarımı kullanmak için çıkarım altyapısını doğru şekilde yapılandırmanız gerekir.`,
|
||||||
'models.form.distribution.tips': `Bir işçi düğümün kaynakları yetersiz olduğunda, modelin katmanlarının bir kısmının tekli veya çoklu uzak işçi düğümlere aktarılmasına olanak tanır.`,
|
'models.form.distribution.tips': `Bir işçi düğümün kaynakları yetersiz olduğunda, modelin katmanlarının bir kısmının tekli veya çoklu uzak işçi düğümlere aktarılmasına olanak tanır.`,
|
||||||
'models.openinplayground': 'Deneme Alanında Aç',
|
'models.openinplayground': 'Deneme Alanında Aç',
|
||||||
'models.instances': 'örnekler',
|
'models.instances': 'örnekler',
|
||||||
@@ -24,7 +24,7 @@ export default {
|
|||||||
'model.deploy.sort': 'Sırala',
|
'model.deploy.sort': 'Sırala',
|
||||||
'model.deploy.search.placeholder': 'Modelleri aramak için <kbd>/</kbd> yazın',
|
'model.deploy.search.placeholder': 'Modelleri aramak için <kbd>/</kbd> yazın',
|
||||||
'model.form.ollamatips':
|
'model.form.ollamatips':
|
||||||
"İpucu: Aşağıdakiler GPUStack'te önceden yapılandırılmış Ollama modelleridir. İstediğiniz modeli seçin veya dağıtmak istediğiniz modeli doğrudan sağdaki 【{name}】 giriş kutusuna yazın.",
|
"İpucu: Aşağıdakiler MesaStack'te önceden yapılandırılmış Ollama modelleridir. İstediğiniz modeli seçin veya dağıtmak istediğiniz modeli doğrudan sağdaki 【{name}】 giriş kutusuna yazın.",
|
||||||
'models.sort.name': 'Ad',
|
'models.sort.name': 'Ad',
|
||||||
'models.sort.size': 'Boyut',
|
'models.sort.size': 'Boyut',
|
||||||
'models.sort.likes': 'Beğeniler',
|
'models.sort.likes': 'Beğeniler',
|
||||||
@@ -87,7 +87,7 @@ export default {
|
|||||||
'models.form.filePath': 'Model Yolu',
|
'models.form.filePath': 'Model Yolu',
|
||||||
'models.form.backendVersion': 'Altyapı Sürümü',
|
'models.form.backendVersion': 'Altyapı Sürümü',
|
||||||
'models.form.backendVersion.tips':
|
'models.form.backendVersion.tips':
|
||||||
'{backend}{version} sürümünü kullanmak için sistem, ilgili sürümü yüklemek üzere çevrimiçi ortamda otomatik olarak sanal ortam oluşturur. GPUStack yükseltmesinden sonra altyapı sürümü sabit kalır. {link}',
|
'{backend}{version} sürümünü kullanmak için sistem, ilgili sürümü yüklemek üzere çevrimiçi ortamda otomatik olarak sanal ortam oluşturur. MesaStack yükseltmesinden sonra altyapı sürümü sabit kalır. {link}',
|
||||||
'models.form.gpuselector': 'GPU Seçici',
|
'models.form.gpuselector': 'GPU Seçici',
|
||||||
'models.form.backend.llamabox':
|
'models.form.backend.llamabox':
|
||||||
'GGUF format modeller için, Linux, macOS ve Windows destekler.',
|
'GGUF format modeller için, Linux, macOS ve Windows destekler.',
|
||||||
@@ -277,7 +277,7 @@ export default {
|
|||||||
'models.form.backendVersions.tips': `Daha fazla sürüm kullanmak için {link} sayfasına gidin ve sürüm eklemek üzere altyapıyı düzenleyin.`,
|
'models.form.backendVersions.tips': `Daha fazla sürüm kullanmak için {link} sayfasına gidin ve sürüm eklemek üzere altyapıyı düzenleyin.`,
|
||||||
'models.catalog.nogpus.tips':
|
'models.catalog.nogpus.tips':
|
||||||
'Seçili kümede bu model için uyumlu GPU bulunmuyor.',
|
'Seçili kümede bu model için uyumlu GPU bulunmuyor.',
|
||||||
'models.form.modelfile.notfound': `Belirttiğiniz model dosyası yolu GPUStack sunucusunda mevcut değil. Model dosyasını hem GPUStack sunucusunda hem de GPUStack işçi düğümlerinde aynı yola yerleştirmeniz önerilir. Bu, GPUStack'in daha iyi kararlar almasına yardımcı olur.`,
|
'models.form.modelfile.notfound': `Belirttiğiniz model dosyası yolu MesaStack sunucusunda mevcut değil. Model dosyasını hem MesaStack sunucusunda hem de MesaStack işçi düğümlerinde aynı yola yerleştirmeniz önerilir. Bu, MesaStack'in daha iyi kararlar almasına yardımcı olur.`,
|
||||||
'models.form.readyWorkers': 'hazır işçi düğüm',
|
'models.form.readyWorkers': 'hazır işçi düğüm',
|
||||||
'models.form.maxContextLength': 'Maksimum Bağlam Uzunluğu',
|
'models.form.maxContextLength': 'Maksimum Bağlam Uzunluğu',
|
||||||
'models.form.backend.helperText':
|
'models.form.backend.helperText':
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
'organizations.upsell.title': 'Organizations are an Enterprise feature',
|
'organizations.upsell.title': 'Organizations are an Enterprise feature',
|
||||||
'organizations.upsell.subtitle':
|
'organizations.upsell.subtitle':
|
||||||
'Multi-tenancy lets you isolate users, resources, and quotas across teams. Upgrade to GPUStack Enterprise to manage organizations.',
|
'Multi-tenancy lets you isolate users, resources, and quotas across teams. Upgrade to MesaStack Enterprise to manage organizations.',
|
||||||
'organizations.upsell.featuresTitle': 'What you get in Enterprise',
|
'organizations.upsell.featuresTitle': 'What you get in Enterprise',
|
||||||
'organizations.upsell.feature.orgs':
|
'organizations.upsell.feature.orgs':
|
||||||
'Create organizations to group users and isolate workloads',
|
'Create organizations to group users and isolate workloads',
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export default {
|
|||||||
'resources.worker.container.supported': 'macOS veya Windows desteklenmez.',
|
'resources.worker.container.supported': 'macOS veya Windows desteklenmez.',
|
||||||
'resources.worker.current.version': 'Mevcut sürüm: {version}.',
|
'resources.worker.current.version': 'Mevcut sürüm: {version}.',
|
||||||
'resources.worker.driver.install':
|
'resources.worker.driver.install':
|
||||||
'GPUStack kurulumundan önce <a href="https://docs.gpustack.ai/latest/installation/installation-requirements/" target="_blank">gerekli sürücüleri ve kütüphaneleri</a> yükleyin.',
|
'MesaStack kurulumundan önce <a href="https://docs.gpustack.ai/latest/installation/installation-requirements/" target="_blank">gerekli sürücüleri ve kütüphaneleri</a> yükleyin.',
|
||||||
'resources.worker.select.command':
|
'resources.worker.select.command':
|
||||||
'Komutu oluşturmak için bir etiket seçin ve kopyala düğmesiyle kopyalayın.',
|
'Komutu oluşturmak için bir etiket seçin ve kopyala düğmesiyle kopyalayın.',
|
||||||
'resources.worker.script.install': 'Betik Kurulumu',
|
'resources.worker.script.install': 'Betik Kurulumu',
|
||||||
@@ -89,7 +89,7 @@ export default {
|
|||||||
'<span class="bold-text">Token</span>\'ı yapıştırın.',
|
'<span class="bold-text">Token</span>\'ı yapıştırın.',
|
||||||
'resources.register.worker.step7':
|
'resources.register.worker.step7':
|
||||||
'Ayarları uygulamak için <span class="bold-text">Yeniden Başlat</span>\'a tıklayın.',
|
'Ayarları uygulamak için <span class="bold-text">Yeniden Başlat</span>\'a tıklayın.',
|
||||||
'resources.register.install.title': '{os} üzerine GPUStack kur',
|
'resources.register.install.title': '{os} üzerine MesaStack kur',
|
||||||
'resources.register.download':
|
'resources.register.download':
|
||||||
'<a href={url} target="_blank">Yükleyiciyi</a> indirip kurun. Yalnızca desteklenen: {versions}.',
|
'<a href={url} target="_blank">Yükleyiciyi</a> indirip kurun. Yalnızca desteklenen: {versions}.',
|
||||||
'resource.register.maos.support': 'Apple Silicon (M serisi), macOS 14+',
|
'resource.register.maos.support': 'Apple Silicon (M serisi), macOS 14+',
|
||||||
@@ -110,7 +110,7 @@ export default {
|
|||||||
'Kullanılabilir küme yok. Lütfen düğüm eklemeden önce bir küme oluşturun.',
|
'Kullanılabilir küme yok. Lütfen düğüm eklemeden önce bir küme oluşturun.',
|
||||||
'resources.metrics.details': 'İzleme',
|
'resources.metrics.details': 'İzleme',
|
||||||
'resoureces.worker.upgrade.tips':
|
'resoureces.worker.upgrade.tips':
|
||||||
'Please upgrade to match the GPUStack Server version.',
|
'Please upgrade to match the MesaStack Server version.',
|
||||||
'resources.worker.version': 'Worker Version: {version}',
|
'resources.worker.version': 'Worker Version: {version}',
|
||||||
'resources.server.version': 'Server Version: {version}',
|
'resources.server.version': 'Server Version: {version}',
|
||||||
'resources.worker.currentVersion': 'Current Version: {version}',
|
'resources.worker.currentVersion': 'Current Version: {version}',
|
||||||
@@ -119,5 +119,5 @@ export default {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
// 1. 'resoureces.worker.upgrade.tips': 'Please upgrade to match the GPUStack Server version.'
|
// 1. 'resoureces.worker.upgrade.tips': 'Please upgrade to match the MesaStack Server version.'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ export default {
|
|||||||
// --- Resource events ---
|
// --- Resource events ---
|
||||||
'usage.events.resourceType': 'Kaynak türü',
|
'usage.events.resourceType': 'Kaynak türü',
|
||||||
'usage.events.eventType': 'Olay türü',
|
'usage.events.eventType': 'Olay türü',
|
||||||
|
'usage.events.resourceName': 'Ada göre filtrele',
|
||||||
'usage.events.col.time': 'Zaman',
|
'usage.events.col.time': 'Zaman',
|
||||||
'usage.events.col.resource': 'Kaynak',
|
'usage.events.col.resource': 'Kaynak',
|
||||||
'usage.events.col.event': 'Olay',
|
'usage.events.col.event': 'Olay',
|
||||||
|
|||||||
@@ -29,16 +29,18 @@ export default {
|
|||||||
'users.password.modify.title': 'Şifreyi Değiştir',
|
'users.password.modify.title': 'Şifreyi Değiştir',
|
||||||
'users.password.modify.description':
|
'users.password.modify.description':
|
||||||
'Hesabınızın güvenliği için lütfen başlangıç şifrenizi değiştirin.',
|
'Hesabınızın güvenliği için lütfen başlangıç şifrenizi değiştirin.',
|
||||||
|
'users.password.modify.tips':
|
||||||
|
'Parolanızı düzenli olarak güncellemek hesabınızın güvenliğini korumaya yardımcı olur.',
|
||||||
'users.password.confirm': 'Yeni Şifreyi Onayla',
|
'users.password.confirm': 'Yeni Şifreyi Onayla',
|
||||||
'users.password.confirm.empty': 'Lütfen yeni şifreyi tekrar girin.',
|
'users.password.confirm.empty': 'Lütfen yeni şifreyi tekrar girin.',
|
||||||
'users.password.confirm.error': 'Girilen iki şifre eşleşmiyor.',
|
'users.password.confirm.error': 'Girilen iki şifre eşleşmiyor.',
|
||||||
'users.login.title': 'Giriş yap:',
|
'users.login.title': 'Giriş yap:',
|
||||||
'users.version.islatest': 'GPUStack {version} en güncel sürümdür',
|
'users.version.islatest': 'MesaStack {version} en güncel sürümdür',
|
||||||
'users.version.update': 'GPUStack {version} kullanılabilir',
|
'users.version.update': 'MesaStack {version} kullanılabilir',
|
||||||
'users.settings.title': 'Kullanıcı Ayarları',
|
'users.settings.title': 'Kullanıcı Ayarları',
|
||||||
'users.status.activate': 'Hesabı Etkinleştir',
|
'users.status.activate': 'Hesabı Etkinleştir',
|
||||||
'users.status.deactivate': 'Hesabı Devre Dışı Bırak',
|
'users.status.deactivate': 'Hesabı Devre Dışı Bırak',
|
||||||
'users.status.inactiveAccount': 'Pasif Hesap',
|
'users.status.inactiveAccount': 'Pasif Hesap',
|
||||||
'users.login.getInitialPassword':
|
'users.login.getInitialPassword':
|
||||||
'Başlangıç yönetici şifresini almak için GPUStack Sunucunuzda aşağıdaki komutu çalıştırın.'
|
'Başlangıç yönetici şifresini almak için MesaStack Sunucunuzda aşağıdaki komutu çalıştırın.'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default {
|
|||||||
'ai.provider.ollama': 'Ollama',
|
'ai.provider.ollama': 'Ollama',
|
||||||
'ai.provider.openai': 'OpenAI',
|
'ai.provider.openai': 'OpenAI',
|
||||||
'ai.provider.openrouter': 'OpenRouter',
|
'ai.provider.openrouter': 'OpenRouter',
|
||||||
'ai.provider.qwen': '通义千问',
|
'ai.provider.qwen': '阿里云百炼',
|
||||||
'ai.provider.spark': '讯飞星火',
|
'ai.provider.spark': '讯飞星火',
|
||||||
'ai.provider.stepfun': '阶跃星辰',
|
'ai.provider.stepfun': '阶跃星辰',
|
||||||
'ai.provider.together-ai': 'Together AI',
|
'ai.provider.together-ai': 'Together AI',
|
||||||
|
|||||||
@@ -23,11 +23,12 @@ export default {
|
|||||||
'backend.form.defaultExecuteCommand': '默认执行命令',
|
'backend.form.defaultExecuteCommand': '默认执行命令',
|
||||||
'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}'、'{{'port'}}'、'{{'worker_ip'}}' 和 '{{'model_name'}}' 都是占位符,在部署过程中会被替换为实际的值。`,
|
'backend.form.defaultExecuteCommand.tips': `'{{'model_path'}}'、'{{'port'}}'、'{{'worker_ip'}}' 和 '{{'model_name'}}' 都是占位符,在部署过程中会被替换为实际的值。`,
|
||||||
'backend.form.defaultBackendParameters': '默认后端参数',
|
'backend.form.defaultBackendParameters': '默认后端参数',
|
||||||
'backend.form.parameterFormat': '参数输出格式',
|
'backend.form.flagFormat': '参数格式',
|
||||||
'backend.form.parameterFormat.default': '后端默认',
|
'backend.form.flagFormat.tips':
|
||||||
'backend.form.parameterFormat.space': '空格分隔 (--key value)',
|
'选项名与取值之间使用的连接格式。留空则保留每个参数原本的写法,不做统一转换。',
|
||||||
'backend.form.parameterFormat.equal': '等号连接 (--key=value)',
|
'backend.form.flagFormat.space': '空格分隔 (--key value)',
|
||||||
'backend.form.commonParameters': '常用参数',
|
'backend.form.flagFormat.equal': '等号连接 (--key=value)',
|
||||||
|
'backend.form.commonParameters': '常用后端参数',
|
||||||
'backend.form.commonParameters.tips': '部署模型时作为后端参数候选项展示。',
|
'backend.form.commonParameters.tips': '部署模型时作为后端参数候选项展示。',
|
||||||
'backend.form.versionConfig': '版本配置',
|
'backend.form.versionConfig': '版本配置',
|
||||||
'backend.form.addParameter': '添加参数',
|
'backend.form.addParameter': '添加参数',
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ export default {
|
|||||||
'长上下文压力测试。评估 KV Cache 行为、内存占用及后端稳定性。',
|
'长上下文压力测试。评估 KV Cache 行为、内存占用及后端稳定性。',
|
||||||
'benchmark.form.profile.heavy.tips':
|
'benchmark.form.profile.heavy.tips':
|
||||||
'以解码为主的生成测试。衡量持续解码速度与输出 Token 吞吐能力。',
|
'以解码为主的生成测试。衡量持续解码速度与输出 Token 吞吐能力。',
|
||||||
'benchmark.table.filter.bygpu': '按 GPU 过滤',
|
'benchmark.table.filter.bygpu': 'GPU 查询',
|
||||||
'benchmark.table.filter.bymodel': '按模型过滤',
|
'benchmark.table.filter.bymodel': '模型查询',
|
||||||
'benchmark.table.filter.bydataset': '按数据集过滤',
|
'benchmark.table.filter.bydataset': '按数据集过滤',
|
||||||
'benchmark.table.filter.byProfile': '按模式过滤',
|
'benchmark.table.filter.byProfile': '按模式过滤',
|
||||||
'benchmark.table.avg': '均值',
|
'benchmark.table.avg': '均值',
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export default {
|
||||||
|
'billing.upsell.title': '计费是企业版功能',
|
||||||
|
'billing.upsell.subtitle':
|
||||||
|
'在团队间跟踪花费、生成账单并执行预算。升级到 MesaStack 企业版即可管理计费。',
|
||||||
|
'billing.upsell.featuresTitle': '企业版包含的能力',
|
||||||
|
'billing.upsell.feature.usage': '按组织、用户与模型查看成本明细',
|
||||||
|
'billing.upsell.feature.invoices': '生成账单并导出计费报表',
|
||||||
|
'billing.upsell.feature.budgets': '设置预算与花费上限并触发告警',
|
||||||
|
'billing.upsell.feature.chargeback': '将用量归属并分摊到团队与项目',
|
||||||
|
'billing.upsell.cta': '了解企业版'
|
||||||
|
};
|
||||||
@@ -68,8 +68,13 @@ export default {
|
|||||||
'<span class="bold-text">非 Docker</span> 集群请前往集群页面注册集群或管理节点池。',
|
'<span class="bold-text">非 Docker</span> 集群请前往集群页面注册集群或管理节点池。',
|
||||||
'clusters.addworker.selectGPU': '选择 GPU 厂商',
|
'clusters.addworker.selectGPU': '选择 GPU 厂商',
|
||||||
'clusters.addworker.selectGPU.multiTag': '可多选',
|
'clusters.addworker.selectGPU.multiTag': '可多选',
|
||||||
|
'clusters.addworker.selectGPU.subtitle':
|
||||||
|
'可选择多个 GPU 厂商,或不选择以用于仅 CPU 的集群',
|
||||||
'clusters.addworker.checkEnv': '检查环境',
|
'clusters.addworker.checkEnv': '检查环境',
|
||||||
|
'clusters.addworker.checkEnv.cpuOnlyTips':
|
||||||
|
'使用以下命令验证 Kubernetes 集群中至少有一个就绪节点。你正在注册仅 CPU 的集群。',
|
||||||
'clusters.addworker.specifyArgs': '指定参数',
|
'clusters.addworker.specifyArgs': '指定参数',
|
||||||
|
'clusters.addworker.dtkVersion': 'DTK 版本',
|
||||||
'clusters.addworker.runCommand': '运行指令',
|
'clusters.addworker.runCommand': '运行指令',
|
||||||
'clusters.addworker.specifyWorkerIP': '节点 IP',
|
'clusters.addworker.specifyWorkerIP': '节点 IP',
|
||||||
'clusters.addworker.detectWorkerIP': '自动检测节点 IP',
|
'clusters.addworker.detectWorkerIP': '自动检测节点 IP',
|
||||||
@@ -78,7 +83,7 @@ export default {
|
|||||||
'clusters.addworker.detectWorkerAddress.tips':
|
'clusters.addworker.detectWorkerAddress.tips':
|
||||||
'如果未指定,则默认为节点 IP。',
|
'如果未指定,则默认为节点 IP。',
|
||||||
'clusters.addworker.externalIP.tips':
|
'clusters.addworker.externalIP.tips':
|
||||||
'如运行在 VPC 或私有网络时,请指定 GPUStack Server 可达的节点外部地址。',
|
'如运行在 VPC 或私有网络时,请指定 MesaStack Server 可达的节点外部地址。',
|
||||||
'clusters.addworker.enterWorkerIP': '输入节点 IP',
|
'clusters.addworker.enterWorkerIP': '输入节点 IP',
|
||||||
'clusters.addworker.enterWorkerIP.error': '请输入节点 IP',
|
'clusters.addworker.enterWorkerIP.error': '请输入节点 IP',
|
||||||
'clusters.addworker.enterWorkerAddress': '输入节点外部地址',
|
'clusters.addworker.enterWorkerAddress': '输入节点外部地址',
|
||||||
@@ -106,20 +111,18 @@ export default {
|
|||||||
'已将 {count} 个新节点添加到集群中。',
|
'已将 {count} 个新节点添加到集群中。',
|
||||||
'clusters.addworker.message.success_multiple':
|
'clusters.addworker.message.success_multiple':
|
||||||
'已将 {count} 个新节点添加到集群中。',
|
'已将 {count} 个新节点添加到集群中。',
|
||||||
'clusters.create.serverUrl': 'GPUStack Server 节点地址',
|
'clusters.create.serverUrl': 'MesaStack Server 节点地址',
|
||||||
'clusters.create.workerConfig': '节点配置',
|
'clusters.create.workerConfig': '节点配置',
|
||||||
'clusters.edit.k8sOptions.changed.tip':
|
'clusters.edit.k8sOptions.changed.tip':
|
||||||
'您已修改 Kubernetes 选项,需要在目标集群上重新运行注册命令才会生效。',
|
'您已修改 Kubernetes 选项,需要在目标集群上重新运行注册命令才会生效。',
|
||||||
'clusters.edit.workerConfig.tip':
|
|
||||||
'修改节点配置后,需要重启对应节点才会生效。',
|
|
||||||
'clusters.addworker.containerName': '节点容器名称',
|
'clusters.addworker.containerName': '节点容器名称',
|
||||||
'clusters.addworker.containerName.tips': '为节点容器指定一个名称。',
|
'clusters.addworker.containerName.tips': '为节点容器指定一个名称。',
|
||||||
'clusters.addworker.dataVolume': 'GPUStack 数据卷',
|
'clusters.addworker.dataVolume': 'MesaStack 数据卷',
|
||||||
'clusters.addworker.dataVolume.tips': '为 GPUStack 指定数据存储路径。',
|
'clusters.addworker.dataVolume.tips': '为 MesaStack 指定数据存储路径。',
|
||||||
'clusters.table.ip.internal': '内',
|
'clusters.table.ip.internal': '内',
|
||||||
'clusters.table.ip.external': '外',
|
'clusters.table.ip.external': '外',
|
||||||
'clusters.form.serverUrl.tips':
|
'clusters.form.serverUrl.tips':
|
||||||
'如果节点无法直接访问 GPUStack Server,则指定一个可访问的外部 GPUStack Server 地址。',
|
'如果节点无法直接访问 MesaStack Server,则指定一个可访问的外部 MesaStack Server 地址。',
|
||||||
'clusters.form.setDefault': '设为默认',
|
'clusters.form.setDefault': '设为默认',
|
||||||
'clusters.form.setDefault.tips': '部署时的默认集群。',
|
'clusters.form.setDefault.tips': '部署时的默认集群。',
|
||||||
'clusters.addworker.noClusters': '无可用的 Docker 集群',
|
'clusters.addworker.noClusters': '无可用的 Docker 集群',
|
||||||
@@ -135,7 +138,7 @@ export default {
|
|||||||
'clusters.addworker.theadNotes-02':
|
'clusters.addworker.theadNotes-02':
|
||||||
'平头哥(T-Head)PPU 使用容器设备接口(CDI)进行设备注入,因此需要确保 <span class="bold-text">/var/run/cdi</span> 目录可用以生成 CDI。',
|
'平头哥(T-Head)PPU 使用容器设备接口(CDI)进行设备注入,因此需要确保 <span class="bold-text">/var/run/cdi</span> 目录可用以生成 CDI。',
|
||||||
'clusters.addworker.nvidiaNotes':
|
'clusters.addworker.nvidiaNotes':
|
||||||
'GPUStack v2.1 内置推理后端依赖 <span class="bold-text">CUDA 12.6</span> 及以上版本,请确保 NVIDIA 驱动版本为 <span class="bold-text">560</span> 或以上。',
|
'MesaStack 内置推理后端依赖 <span class="bold-text">CUDA 12.8</span> 及以上版本,请确保 NVIDIA 驱动版本为 <span class="bold-text">570</span> 或以上。',
|
||||||
'clusters.volume.title': '卷挂载',
|
'clusters.volume.title': '卷挂载',
|
||||||
'clusters.volume.name': '卷名称',
|
'clusters.volume.name': '卷名称',
|
||||||
'clusters.volume.mountPath': '容器内路径',
|
'clusters.volume.mountPath': '容器内路径',
|
||||||
@@ -161,7 +164,7 @@ export default {
|
|||||||
'clusters.volume.add': '添加卷挂载',
|
'clusters.volume.add': '添加卷挂载',
|
||||||
'clusters.systemDefaultContainerRegistry.title': '默认容器镜像仓库',
|
'clusters.systemDefaultContainerRegistry.title': '默认容器镜像仓库',
|
||||||
'clusters.systemDefaultContainerRegistry.tip':
|
'clusters.systemDefaultContainerRegistry.tip':
|
||||||
'用于解析该集群 GPUStack 镜像的默认镜像仓库。未设置时回退到服务端默认值。',
|
'用于解析该集群 MesaStack 镜像的默认镜像仓库。未设置时回退到服务端默认值。',
|
||||||
'clusters.k8sOptions.title': 'Kubernetes 部署选项',
|
'clusters.k8sOptions.title': 'Kubernetes 部署选项',
|
||||||
'clusters.imageCredentials.title': '镜像仓库凭证',
|
'clusters.imageCredentials.title': '镜像仓库凭证',
|
||||||
'clusters.imageCredentials.add': '添加凭证',
|
'clusters.imageCredentials.add': '添加凭证',
|
||||||
@@ -173,7 +176,7 @@ export default {
|
|||||||
'应用到每个 worker DaemonSet 的 Pod nodeSelector,只有标签匹配的节点才会被调度运行 worker。',
|
'应用到每个 worker DaemonSet 的 Pod nodeSelector,只有标签匹配的节点才会被调度运行 worker。',
|
||||||
'clusters.operatorImage.title': 'Operator 镜像',
|
'clusters.operatorImage.title': 'Operator 镜像',
|
||||||
'clusters.operatorImage.tip':
|
'clusters.operatorImage.tip':
|
||||||
'GPUStack Operator 容器镜像的覆盖值。留空则使用服务端默认值。',
|
'MesaStack Operator 容器镜像的覆盖值。留空则使用服务端默认值。',
|
||||||
'clusters.namespace.title': '命名空间',
|
'clusters.namespace.title': '命名空间',
|
||||||
'clusters.namespace.tip':
|
'clusters.namespace.tip':
|
||||||
'集群清单渲染所使用的 Kubernetes 命名空间。留空则使用 gpustack-system。',
|
'集群清单渲染所使用的 Kubernetes 命名空间。留空则使用 gpustack-system。',
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export default {
|
|||||||
'common.button.rollback': '回滚',
|
'common.button.rollback': '回滚',
|
||||||
'common.button.new': '新建{ text }',
|
'common.button.new': '新建{ text }',
|
||||||
'common.button.upgrade': '升级',
|
'common.button.upgrade': '升级',
|
||||||
'common.enterprise.feature': 'GPUStack 企业版可用',
|
'common.enterprise.feature': 'MesaStack 企业版可用',
|
||||||
'common.input.holder': '请输入',
|
'common.input.holder': '请输入',
|
||||||
'common.holder.search': '搜索',
|
'common.holder.search': '搜索',
|
||||||
'common.button.edit': '编辑',
|
'common.button.edit': '编辑',
|
||||||
@@ -161,6 +161,7 @@ export default {
|
|||||||
'common.time.hour': '小时',
|
'common.time.hour': '小时',
|
||||||
'common.time.minute': '分钟',
|
'common.time.minute': '分钟',
|
||||||
'common.issue.report': '问题反馈',
|
'common.issue.report': '问题反馈',
|
||||||
|
'common.github.star.tooltip': '在 GitHub 上 Star 我们',
|
||||||
'common.social.discord': '加入我们的Discord',
|
'common.social.discord': '加入我们的Discord',
|
||||||
'common.table.mark': '备注',
|
'common.table.mark': '备注',
|
||||||
'common.table.rollback.mark': '回滚备注',
|
'common.table.rollback.mark': '回滚备注',
|
||||||
@@ -189,6 +190,7 @@ export default {
|
|||||||
'common.table.user': '用户',
|
'common.table.user': '用户',
|
||||||
'common.settings.instructions': '操作指引',
|
'common.settings.instructions': '操作指引',
|
||||||
'common.settings.language': '语言',
|
'common.settings.language': '语言',
|
||||||
|
'common.settings.language.tips': '设置界面的显示语言。',
|
||||||
'common.delete.confirm': '确定删除选中的{type}吗?',
|
'common.delete.confirm': '确定删除选中的{type}吗?',
|
||||||
'common.delete.single.confirm':
|
'common.delete.single.confirm':
|
||||||
'确定删除以下内容?\n <span style="font-size: 13px;font-weight: 700">{name}</span>',
|
'确定删除以下内容?\n <span style="font-size: 13px;font-weight: 700">{name}</span>',
|
||||||
@@ -202,7 +204,7 @@ export default {
|
|||||||
'common.form.password': '密码',
|
'common.form.password': '密码',
|
||||||
'common.form.username': '用户名',
|
'common.form.username': '用户名',
|
||||||
'common.login.rember': '记住我',
|
'common.login.rember': '记住我',
|
||||||
'settings.company': '数澈软件',
|
'settings.company': 'MesaStack',
|
||||||
'common.button.help': '帮助',
|
'common.button.help': '帮助',
|
||||||
'common.button.feedback': '反馈',
|
'common.button.feedback': '反馈',
|
||||||
'common.button.docs': '文档',
|
'common.button.docs': '文档',
|
||||||
@@ -245,6 +247,9 @@ export default {
|
|||||||
'common.appearance.tips': '默认跟随系统设置',
|
'common.appearance.tips': '默认跟随系统设置',
|
||||||
'common.button.forgotpassword': '忘记密码?',
|
'common.button.forgotpassword': '忘记密码?',
|
||||||
'common.appearance.theme': '主题',
|
'common.appearance.theme': '主题',
|
||||||
|
'common.appearance.description': '自定义界面在您设备上的视觉表现。',
|
||||||
|
'common.security': '安全设置',
|
||||||
|
'common.security.description': '管理用于登录账户的密码。',
|
||||||
'common.page.wentwrong': '哎呀,出了点问题',
|
'common.page.wentwrong': '哎呀,出了点问题',
|
||||||
'common.page.refresh.tips': '页面似乎需要更新,刷新一下试试吧!',
|
'common.page.refresh.tips': '页面似乎需要更新,刷新一下试试吧!',
|
||||||
'common.tips.escape.disable': '请点击「取消」按钮或右上角 X 关闭窗口',
|
'common.tips.escape.disable': '请点击「取消」按钮或右上角 X 关闭窗口',
|
||||||
@@ -253,6 +258,10 @@ export default {
|
|||||||
'common.login.auth': '认证中...',
|
'common.login.auth': '认证中...',
|
||||||
'common.login.auth.failed': '认证失败',
|
'common.login.auth.failed': '认证失败',
|
||||||
'common.login.password': '使用密码登录',
|
'common.login.password': '使用密码登录',
|
||||||
|
'common.login.username.holder': '请输入用户名',
|
||||||
|
'common.login.password.holder': '请输入密码',
|
||||||
|
'common.login.newpassword.holder': '请输入新密码',
|
||||||
|
'common.login.confirm.holder': '请再次输入密码',
|
||||||
'common.external.login': '使用 {type} 登录',
|
'common.external.login': '使用 {type} 登录',
|
||||||
'common.sso.noConfig': '该系统未启用单点登录,请联系管理员。',
|
'common.sso.noConfig': '该系统未启用单点登录,请联系管理员。',
|
||||||
'common.button.edit.item': '编辑 {name}',
|
'common.button.edit.item': '编辑 {name}',
|
||||||
@@ -260,7 +269,7 @@ export default {
|
|||||||
'common.button.terminal': '终端',
|
'common.button.terminal': '终端',
|
||||||
'common.button.addItem': '添加项',
|
'common.button.addItem': '添加项',
|
||||||
'common.help.default': '默认: {content}',
|
'common.help.default': '默认: {content}',
|
||||||
'common.filter.status': '按状态筛选',
|
'common.filter.status': '按状态过滤',
|
||||||
'common.form.rule.selectInput': '请选择或输入{name}',
|
'common.form.rule.selectInput': '请选择或输入{name}',
|
||||||
'common.tag.experimental': '实验性',
|
'common.tag.experimental': '实验性',
|
||||||
'common.title.example': '示例',
|
'common.title.example': '示例',
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ export default {
|
|||||||
'gpuservice.publicKey': 'SSH 公钥',
|
'gpuservice.publicKey': 'SSH 公钥',
|
||||||
'gpuservice.publicKey.add': '添加 SSH 公钥',
|
'gpuservice.publicKey.add': '添加 SSH 公钥',
|
||||||
'gpuservice.publicKey.edit': '编辑 SSH 公钥',
|
'gpuservice.publicKey.edit': '编辑 SSH 公钥',
|
||||||
|
'gpuservice.publicKey.delete.tips':
|
||||||
|
'删除 SSH Public Key 不会撤销已挂载 GPU 实例的访问权限。如需移除访问权限,请分别编辑对应的 GPU 实例。',
|
||||||
'gpuservice.publicKey.filter.name': '按名称搜索',
|
'gpuservice.publicKey.filter.name': '按名称搜索',
|
||||||
'gpuservice.publicKey.label': 'SSH 公钥',
|
'gpuservice.publicKey.label': 'SSH 公钥',
|
||||||
'gpuservice.instance.ssh.enable': '启用 SSH 访问',
|
'gpuservice.instance.ssh.enable': '启用 SSH 访问',
|
||||||
@@ -109,6 +111,8 @@ export default {
|
|||||||
'gpuservice.instance.sliced': '切分',
|
'gpuservice.instance.sliced': '切分',
|
||||||
'gpuservice.instance.memory': '显存',
|
'gpuservice.instance.memory': '显存',
|
||||||
'gpuservice.instance.ram': '内存',
|
'gpuservice.instance.ram': '内存',
|
||||||
|
'gpuservice.instance.os': '系统',
|
||||||
|
'gpuservice.instance.arch': '架构',
|
||||||
'gpuservice.instance.disk': '磁盘',
|
'gpuservice.instance.disk': '磁盘',
|
||||||
'gpuservice.table.count': '数量',
|
'gpuservice.table.count': '数量',
|
||||||
'gpuservice.instance.disk.system': '系统盘',
|
'gpuservice.instance.disk.system': '系统盘',
|
||||||
@@ -156,5 +160,9 @@ export default {
|
|||||||
'gpuservice.storage.tempCapacity.required': '请输入临时存储容量',
|
'gpuservice.storage.tempCapacity.required': '请输入临时存储容量',
|
||||||
'gpuservice.form.rule.name':
|
'gpuservice.form.rule.name':
|
||||||
'由小写字母、数字和 "-" 组成,以字母或数字开头和结尾,不能包含连续的 "-",最多 63 个字符。',
|
'由小写字母、数字和 "-" 组成,以字母或数字开头和结尾,不能包含连续的 "-",最多 63 个字符。',
|
||||||
'gpuservice.form.storage.select': '选择存储'
|
'gpuservice.form.storage.select': '选择存储',
|
||||||
|
'gpuservice.creator': '创建者',
|
||||||
|
'gpuservice.owner.global': '全局',
|
||||||
|
'gpuservice.template.group.yours': '我的模板',
|
||||||
|
'gpuservice.template.group.global': '全局模板'
|
||||||
};
|
};
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user