magus-cli 7.6.0 → 7.7.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/package.json +4 -4
- package/src/__tests__/format-update-outcome.test.ts +9 -8
- package/src/__tests__/gitignore-profile.test.ts +9 -5
- package/src/__tests__/notices-rules.test.ts +476 -0
- package/src/__tests__/notices.test.tsx +604 -0
- package/src/__tests__/update-apply.test.ts +3 -3
- package/src/__tests__/useStaleLoadModal.test.ts +27 -12
- package/src/services/gitignore-service.ts +0 -19
- package/src/services/profile-absorb.ts +9 -0
- package/src/services/profile-activate.ts +2 -1
- package/src/services/profile-startup.ts +45 -17
- package/src/services/profile-state.ts +9 -0
- package/src/ui/App.tsx +216 -97
- package/src/ui/adapters/pluginsAdapter.ts +28 -9
- package/src/ui/components/modals/MessageModal.tsx +1 -2
- package/src/ui/hooks/useGitignoreModal.ts +45 -23
- package/src/ui/hooks/useProfileStartupModal.ts +112 -84
- package/src/ui/hooks/useStaleLoadModal.ts +38 -28
- package/src/ui/screens/AliasScreen.tsx +7 -6
- package/src/ui/screens/CliToolsScreen.tsx +19 -16
- package/src/ui/screens/EnvVarsScreen.tsx +4 -1
- package/src/ui/screens/GitignoreScreen.tsx +20 -27
- package/src/ui/screens/McpRegistryScreen.tsx +9 -6
- package/src/ui/screens/McpScreen.tsx +16 -12
- package/src/ui/screens/PluginsScreen.tsx +35 -56
- package/src/ui/screens/ProfilesScreen.tsx +27 -51
- package/src/ui/state/AppContext.tsx +46 -3
- package/src/ui/state/reducer.ts +100 -1
- package/src/ui/state/types.ts +53 -2
package/src/ui/state/types.ts
CHANGED
|
@@ -122,10 +122,15 @@ export type ModalState =
|
|
|
122
122
|
cancellable?: boolean;
|
|
123
123
|
}
|
|
124
124
|
| {
|
|
125
|
+
/**
|
|
126
|
+
* A dialog the user dismisses. No "success" variant, deliberately: a
|
|
127
|
+
* result the screen already shows needs nothing, and one it does not
|
|
128
|
+
* is a notice (see {@link Notice}), which never takes a key.
|
|
129
|
+
*/
|
|
125
130
|
type: "message";
|
|
126
131
|
title: string;
|
|
127
132
|
message: string;
|
|
128
|
-
variant: "info" | "
|
|
133
|
+
variant: "info" | "error";
|
|
129
134
|
onDismiss: () => void;
|
|
130
135
|
}
|
|
131
136
|
| {
|
|
@@ -138,6 +143,28 @@ export type ModalState =
|
|
|
138
143
|
screen: Screen;
|
|
139
144
|
};
|
|
140
145
|
|
|
146
|
+
// ============================================================================
|
|
147
|
+
// Notice Types
|
|
148
|
+
// ============================================================================
|
|
149
|
+
|
|
150
|
+
/** A warning is something the user may need to act on, so it stays longer. */
|
|
151
|
+
export type NoticeTone = "success" | "warning";
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* One line of the app-level notice banner: the result of an action, shown
|
|
155
|
+
* without taking the modal slot or any key, and gone by itself at `expiresAt`.
|
|
156
|
+
*/
|
|
157
|
+
export interface Notice {
|
|
158
|
+
id: number;
|
|
159
|
+
text: string;
|
|
160
|
+
tone: NoticeTone;
|
|
161
|
+
/** Epoch ms after which the banner drops it. */
|
|
162
|
+
expiresAt: number;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** A notice as a pure function words it, before `notify` stamps it. */
|
|
166
|
+
export type NoticeLine = Pick<Notice, "text" | "tone">;
|
|
167
|
+
|
|
141
168
|
// ============================================================================
|
|
142
169
|
// Progress Types
|
|
143
170
|
// ============================================================================
|
|
@@ -352,6 +379,14 @@ export interface AppState {
|
|
|
352
379
|
|
|
353
380
|
// Global UI state
|
|
354
381
|
modal: ModalState | null;
|
|
382
|
+
/** The notice banner, oldest first. Never occupies the modal slot. */
|
|
383
|
+
notices: Notice[];
|
|
384
|
+
/**
|
|
385
|
+
* When the notices stopped running down, or null while they run. They are
|
|
386
|
+
* held while a modal is open: a line posted under a startup question, or
|
|
387
|
+
* just before one, would otherwise expire behind it unread.
|
|
388
|
+
*/
|
|
389
|
+
noticesPausedAt: number | null;
|
|
355
390
|
progress: ProgressState | null;
|
|
356
391
|
/**
|
|
357
392
|
* The current screen's search box has focus. It decides what the box draws
|
|
@@ -364,6 +399,14 @@ export interface AppState {
|
|
|
364
399
|
// Screens can watch this to know when to refetch data
|
|
365
400
|
dataRefreshVersion: number;
|
|
366
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Bumped to ask the app for a fresh gitignore check. The app shell owns the
|
|
404
|
+
* check and its question (ui/App.tsx); anything that makes generated files
|
|
405
|
+
* appear — a profile activating — asks through this rather than reaching
|
|
406
|
+
* into the shell.
|
|
407
|
+
*/
|
|
408
|
+
gitignoreCheckRequest: number;
|
|
409
|
+
|
|
367
410
|
// Screen-specific state
|
|
368
411
|
plugins: PluginsScreenState;
|
|
369
412
|
mcp: McpScreenState;
|
|
@@ -449,6 +492,12 @@ export type AppAction =
|
|
|
449
492
|
| { type: "SHOW_MODAL"; modal: ModalState }
|
|
450
493
|
| { type: "HIDE_MODAL" }
|
|
451
494
|
|
|
495
|
+
// Notices
|
|
496
|
+
| { type: "NOTIFY"; notice: Notice }
|
|
497
|
+
| { type: "EXPIRE_NOTICES"; now: number }
|
|
498
|
+
| { type: "PAUSE_NOTICES"; now: number }
|
|
499
|
+
| { type: "RESUME_NOTICES"; now: number }
|
|
500
|
+
|
|
452
501
|
// Progress
|
|
453
502
|
| { type: "SHOW_PROGRESS"; state: ProgressState }
|
|
454
503
|
| { type: "UPDATE_PROGRESS"; state: ProgressState }
|
|
@@ -520,4 +569,6 @@ export type AppAction =
|
|
|
520
569
|
| { type: "MODELS_CATALOG_LOADED"; catalog: CatalogModel[] }
|
|
521
570
|
|
|
522
571
|
// Data refresh - triggers screens to refetch
|
|
523
|
-
| { type: "DATA_REFRESH_COMPLETE" }
|
|
572
|
+
| { type: "DATA_REFRESH_COMPLETE" }
|
|
573
|
+
// A profile became active: screens refetch, and the gitignore check re-runs
|
|
574
|
+
| { type: "PROFILE_ACTIVATED" };
|