@acarmisc/backstage-plugin-litellm 0.25.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -86,11 +86,12 @@ The **Models** tab lists every model the LiteLLM proxy exposes, with per-model i
86
86
  - `litellmPlugin` — the frontend plugin instance
87
87
  - `LiteLLMPage` — main plugin page (keys, usage, team context)
88
88
  - `LiteLLMHomeWidget` — homepage usage summary card
89
- - `GenerateKeyDialog` — shared "Generate New Key" dialog (surfaces failures inline, warns on duplicate aliases)
89
+ - `KeyFormDialog` — shared key form for both generating and editing a key (surfaces failures inline, warns on duplicate aliases, team-scoped model picker, unlimited-budget toggle when gated on)
90
+ - `GenerateKeyDialog` — deprecated wrapper around `KeyFormDialog` with `mode="create"`
90
91
  - `DashboardHeader`, `KeysTable`, `UsageStats`, `TeamUsage` — individual page sections, exported for composition
91
92
  - `LiteLlmApi`, `liteLlmApiRef` — API client and its Backstage API ref
92
93
 
93
- Note: `DashboardHeader` and `KeysTable` are composition pieces driven by `LiteLLMPage` and their props differ from older versions. `LiteLLMPage` is the supported entry point; composing the sections directly means keeping them in sync with the page's data wiring (keys, models, teams, and the `onGenerateKeyClick` callback).
94
+ Note: `DashboardHeader` and `KeysTable` are composition pieces driven by `LiteLLMPage` and their props differ from older versions. `LiteLLMPage` is the supported entry point; composing the sections directly means keeping them in sync with the page's data wiring (keys, models, teams, and the `onGenerateKeyClick`/`onEditKey` callbacks).
94
95
 
95
96
  ## License
96
97
 
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ /**
3
+ * The single "create a key" call-to-action used everywhere in the plugin —
4
+ * the plugin page (header, keys table) and the homepage budget card all
5
+ * render this instead of their own inline `Button`, so the copy, icon and
6
+ * styling stay identical.
7
+ */
8
+ export interface GenerateKeyButtonProps {
9
+ /** Deep-link target (e.g. `/litellm?generate=1`). Ignored when `onClick` is set. */
10
+ to?: string;
11
+ /** Click handler. Takes precedence over `to` when both are given. */
12
+ onClick?: () => void;
13
+ /** Override the default `Generate New Key` copy (e.g. empty-state variants). */
14
+ label?: string;
15
+ /** Button size — card footers use `small`, page headers the default. */
16
+ size?: 'small' | 'medium' | 'large';
17
+ }
18
+ export declare const GenerateKeyButton: React.FC<GenerateKeyButtonProps>;
@@ -1,20 +1,21 @@
1
1
  import React from 'react';
2
- import { VirtualKey, ModelInfo, TeamInfo, GenerateKeyRequest, GenerateKeyResponse, LiteLlmConfig } from '../types';
3
- interface GenerateKeyDialogProps {
2
+ import { GenerateKeyRequest, GenerateKeyResponse, LiteLlmConfig, ModelInfo, TeamInfo, VirtualKey } from '../types';
3
+ /**
4
+ * @deprecated Use {@link KeyFormDialog} with `mode="create"` instead — this
5
+ * wrapper only forwards props for backwards compatibility with the public
6
+ * entrypoint and will be removed in a future release.
7
+ */
8
+ export declare const GenerateKeyDialog: React.FC<{
4
9
  open: boolean;
5
10
  onClose: () => void;
6
11
  keys: VirtualKey[];
7
12
  models: ModelInfo[];
8
13
  teams: TeamInfo[];
9
- /** Current user's LiteLLM user id, used to pre-fill a default key alias. */
10
14
  username?: string;
11
- /** Controls for the "Generate New Key" form; see litellm.keyGeneration in app-config.yaml. */
12
15
  keyGenerationSettings?: {
13
16
  allowUnlimitedBudget: boolean;
14
17
  teamRequired: boolean;
15
18
  };
16
19
  onGenerateKey: (request: GenerateKeyRequest) => Promise<GenerateKeyResponse>;
17
20
  onGetConfig: () => Promise<LiteLlmConfig>;
18
- }
19
- export declare const GenerateKeyDialog: React.FC<GenerateKeyDialogProps>;
20
- export {};
21
+ }>;
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { VirtualKey, ModelInfo, TeamInfo, GenerateKeyRequest, GenerateKeyResponse, UpdateKeyRequest, LiteLlmConfig } from '../types';
3
+ /**
4
+ * Single form dialog for both key creation (`mode="create"`) and key editing
5
+ * (`mode="edit"`).
6
+ *
7
+ * Create mode: alias (pre-filled), team, models, duration, budget (+unlimited
8
+ * when gated on), TPM/RPM in the Advanced accordion, and the post-generation
9
+ * screen with copyable key + starter snippets.
10
+ *
11
+ * Edit mode: the same shared fields but no duration (expiry is immutable after
12
+ * creation) and no team switch (LiteLLM /key/update semantics); adds a masked
13
+ * key header and the Danger Zone (reset spend). Budget validation, the
14
+ * unlimited toggle and the team-scoped model filtering behave exactly as they
15
+ * do at creation time.
16
+ */
17
+ export type KeyFormDialogMode = 'create' | 'edit';
18
+ export interface KeyFormDialogProps {
19
+ open: boolean;
20
+ onClose: () => void;
21
+ /** `create` generates a new key; `edit` updates an existing one. */
22
+ mode: KeyFormDialogMode;
23
+ /** Key being edited (edit mode only). */
24
+ keyToEdit?: VirtualKey | null;
25
+ keys: VirtualKey[];
26
+ models: ModelInfo[];
27
+ teams: TeamInfo[];
28
+ /** Current user's LiteLLM user id, used to pre-fill a default key alias. */
29
+ username?: string;
30
+ /** Controls for the key form; see litellm.keyGeneration in app-config.yaml. */
31
+ keyGenerationSettings?: {
32
+ allowUnlimitedBudget: boolean;
33
+ teamRequired: boolean;
34
+ };
35
+ onCreateKey: (request: GenerateKeyRequest) => Promise<GenerateKeyResponse>;
36
+ onUpdateKey: (keyId: string, request: UpdateKeyRequest) => Promise<void>;
37
+ onResetKeySpend?: (keyId: string) => Promise<void>;
38
+ onGetConfig: () => Promise<LiteLlmConfig>;
39
+ }
40
+ export declare const KeyFormDialog: React.FC<KeyFormDialogProps>;
41
+ export declare function fmtCost(perToken?: number): string | null;
42
+ export declare function formatContextWindow(maxInput?: number, maxOutput?: number): string | null;
@@ -1,15 +1,14 @@
1
1
  import React from 'react';
2
- import { VirtualKey, ModelInfo, UpdateKeyRequest } from '../types';
2
+ import { VirtualKey } from '../types';
3
3
  interface KeysTableProps {
4
4
  keys: VirtualKey[];
5
- models: ModelInfo[];
6
- /** Opens the shared "Generate New Key" dialog (rendered at page level). */
5
+ /** Opens the shared key form dialog in create mode (rendered at page level). */
7
6
  onGenerateKeyClick: () => void;
7
+ /** Opens the shared key form dialog in edit mode for the given key. */
8
+ onEditKey: (key: VirtualKey) => void;
8
9
  loading: boolean;
9
- onUpdateKey: (keyId: string, request: UpdateKeyRequest) => Promise<void>;
10
10
  onBlockKey: (keyId: string) => Promise<void>;
11
11
  onUnblockKey: (keyId: string) => Promise<void>;
12
- onResetKeySpend: (keyId: string) => Promise<void>;
13
12
  onDeleteKey: (keyId: string) => Promise<void>;
14
13
  onPruneExpiredKeys: () => Promise<{
15
14
  pruned: number;
@@ -1,19 +1,26 @@
1
1
  /**
2
2
  * Condensed budget card for a homepage column: one ring gauge per
3
- * enforcement level (key → personal → team), each showing the limit nearest
4
- * its cap. Where the full `LiteLLMBudgetWidget` lists every limit as a
5
- * spend-vs-cap meter, this trades detail for density — a single row of rings
6
- * with a label and spend figure under each.
3
+ * enforcement level (key → personal → team) plus a month-to-date daily
4
+ * token-usage mini-chart, in a fixed four-column row. Each gauge shows the
5
+ * limit nearest its cap; where the full `LiteLLMBudgetWidget` lists every
6
+ * limit as a spend-vs-cap meter, this trades detail for density — a single
7
+ * row with a label and spend figure under each gauge, and the MTD token
8
+ * total under the chart.
7
9
  *
8
10
  * Gauges are always rendered in the same order, with an empty ring when the
9
11
  * user has no cap at that level, so the card keeps a stable shape as data
10
12
  * loads and across users. When a level holds several limits, the ring shows
11
13
  * the one closest to its cap and a "+N more" link counts the rest.
12
14
  *
13
- * The bottom action bar is composable: pass any subset of `ctas` — mint a new
14
- * key, open the LiteLLM module, or expand the full per-limit list in place —
15
- * in the order you want. `action` remains an escape hatch for a fully custom
16
- * node; when either is present it renders below a divider.
15
+ * The usage period is frozen to month-to-date (no period selector): the
16
+ * chart always covers the 1st of the current month through today.
17
+ *
18
+ * The bottom action bar is composable: pass any subset of `ctas` — generate
19
+ * a new key, open the LiteLLM module, or expand the full per-limit list in
20
+ * place — in the order you want. `action` remains an escape hatch for a
21
+ * fully custom node; when either is present it renders below a divider. The
22
+ * `new-key` CTA renders the shared `GenerateKeyButton`, identical to the
23
+ * one on the plugin page.
17
24
  */
18
25
  import React from 'react';
19
26
  /** Preset action-bar buttons. `label` overrides the default copy. */
@@ -35,8 +42,9 @@ export interface LiteLLMBudgetGaugesProps {
35
42
  /** Where the module CTA points. Defaults to the LiteLLM page. */
36
43
  moduleHref?: string;
37
44
  /**
38
- * Called when the "new key" CTA is used. When omitted, the CTA deep-links
39
- * to the module with `?generate=1`, which opens the generate-key dialog.
45
+ * Called when the "Generate New Key" CTA is used. When omitted, the CTA
46
+ * deep-links to the module with `?generate=1`, which opens the
47
+ * generate-key dialog.
40
48
  */
41
49
  onCreateKey?: () => void;
42
50
  /**
@@ -56,4 +64,9 @@ export interface LiteLLMBudgetGaugesProps {
56
64
  /** Fully custom node pinned below the CTAs, below a divider. */
57
65
  action?: React.ReactNode;
58
66
  }
67
+ /** Month-to-date range as `YYYY-MM-DD` strings: the 1st of the current month through today. */
68
+ export declare function monthToDateRange(now?: Date): {
69
+ startDate: string;
70
+ endDate: string;
71
+ };
59
72
  export declare const LiteLLMBudgetGauges: React.FC<LiteLLMBudgetGaugesProps>;