magus-cli 7.3.0 → 7.4.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/scripts/build-binaries.ts +4 -2
- package/src/__tests__/blind/c1-npm-package.test.ts +206 -0
- package/src/__tests__/blind/c10-colour-roles.test.ts +265 -0
- package/src/__tests__/blind/c11-cli-parse-refusal.test.ts +454 -0
- package/src/__tests__/blind/c12-skill-frontmatter.test.ts +323 -0
- package/src/__tests__/blind/c13-wrong-shape.test.ts +603 -0
- package/src/__tests__/blind/c14-cli-row-label.test.ts +259 -0
- package/src/__tests__/blind/c15-probe-ownership.test.ts +533 -0
- package/src/__tests__/blind/c16-nested-wrong-shape.test.ts +297 -0
- package/src/__tests__/blind/c17-enter-label.test.ts +625 -0
- package/src/__tests__/blind/c18-hook-shape.test.ts +354 -0
- package/src/__tests__/blind/c2-settings-parse.test.ts +350 -0
- package/src/__tests__/blind/c4-key-dispatch.test.ts +397 -0
- package/src/__tests__/blind/c5-keymap.test.ts +461 -0
- package/src/__tests__/blind/c6-request-gate.test.ts +133 -0
- package/src/__tests__/blind/c7-tab-tiers.test.ts +320 -0
- package/src/__tests__/blind/c8-text-width.test.ts +137 -0
- package/src/__tests__/blind/c9-cli-tool-version.test.ts +239 -0
- package/src/__tests__/blind/child-run.ts +114 -0
- package/src/__tests__/cli-tools-adapter.test.ts +5 -2
- package/src/__tests__/component-badge.test.ts +20 -36
- package/src/__tests__/footer-hints.test.ts +1 -1
- package/src/__tests__/manifest.test.ts +25 -17
- package/src/__tests__/marketplace-badge.test.ts +4 -4
- package/src/__tests__/models-screen-state.test.ts +36 -13
- package/src/__tests__/npm-package-name-api.test.ts +111 -0
- package/src/__tests__/npm-package-name.test.ts +280 -0
- package/src/__tests__/scope-squares.test.tsx +28 -114
- package/src/__tests__/shutdown.test.ts +578 -0
- package/src/__tests__/styles-manager.test.ts +4 -4
- package/src/__tests__/styles-screen-state.test.ts +26 -12
- package/src/__tests__/tabbar-layout.test.ts +44 -32
- package/src/__tests__/theme-adaptive-colors.test.ts +6 -59
- package/src/__tests__/tool-probe.test.ts +47 -22
- package/src/__tests__/upgrade-spawn.test.ts +355 -0
- package/src/__tests__/uppercase-keybindings.test.ts +25 -12
- package/src/cli/ansi.ts +2 -2
- package/src/cli/bootstrap.ts +33 -2
- package/src/cli/doctor.ts +105 -14
- package/src/cli/install.ts +8 -2
- package/src/cli/profile.ts +18 -1
- package/src/cli/router.ts +31 -18
- package/src/cli/update-view.ts +1 -1
- package/src/cli/upgrade.ts +37 -9
- package/src/data/cli-tools.ts +13 -2
- package/src/data/npm-package.ts +15 -0
- package/src/services/claude-settings.ts +151 -73
- package/src/services/cli-tool-commands.ts +15 -5
- package/src/services/cli-tool-version.ts +101 -0
- package/src/services/hook-registration.ts +23 -6
- package/src/services/manifest.ts +117 -52
- package/src/services/plugin-manager.ts +19 -5
- package/src/services/profile-adopt.ts +7 -2
- package/src/services/profile-startup.ts +87 -7
- package/src/services/profiles.ts +36 -23
- package/src/services/settings-file.ts +158 -4
- package/src/services/settings-manager.ts +19 -5
- package/src/services/skills-manager.ts +46 -0
- package/src/services/tool-probe.ts +272 -45
- package/src/services/toolchain.ts +39 -0
- package/src/services/update-engine.ts +5 -0
- package/src/services/update-plan.ts +9 -0
- package/src/services/version-check.ts +20 -10
- package/src/tui.tsx +48 -21
- package/src/ui/App.tsx +58 -197
- package/src/ui/adapters/cliToolsAdapter.ts +141 -12
- package/src/ui/adapters/pluginsAdapter.ts +10 -7
- package/src/ui/adapters/settingsAdapter.ts +0 -21
- package/src/ui/adapters/skillsAdapter.ts +27 -8
- package/src/ui/adapters/stylesAdapter.ts +15 -11
- package/src/ui/components/CategoryHeader.tsx +7 -1
- package/src/ui/components/EmptyFilterState.tsx +2 -2
- package/src/ui/components/FlagDetailEditor.tsx +0 -0
- package/src/ui/components/ScreenErrorBoundary.tsx +105 -0
- package/src/ui/components/TabBar.tsx +93 -21
- package/src/ui/components/layout/FooterHints.tsx +6 -27
- package/src/ui/components/layout/ScreenLayout.tsx +68 -42
- package/src/ui/components/layout/index.ts +1 -5
- package/src/ui/components/modals/ConfirmModal.tsx +2 -19
- package/src/ui/components/modals/HelpOverlay.tsx +186 -0
- package/src/ui/components/modals/MessageModal.tsx +3 -15
- package/src/ui/components/modals/ModalContainer.tsx +99 -60
- package/src/ui/components/primitives/ErrorNotice.tsx +38 -0
- package/src/ui/components/primitives/ListCategoryRow.tsx +18 -7
- package/src/ui/components/primitives/MetaText.tsx +1 -1
- package/src/ui/components/primitives/ScopeDetail.tsx +31 -26
- package/src/ui/components/primitives/ScopeSquares.tsx +23 -28
- package/src/ui/components/primitives/SelectableRow.tsx +24 -1
- package/src/ui/components/primitives/index.ts +4 -3
- package/src/ui/hooks/useProfileStartupModal.ts +15 -3
- package/src/ui/input/KeyRouter.tsx +180 -0
- package/src/ui/input/key-dispatch.ts +149 -0
- package/src/ui/keymap.ts +898 -0
- package/src/ui/renderers/cliToolRenderers.tsx +128 -66
- package/src/ui/renderers/gitignoreRenderers.tsx +41 -43
- package/src/ui/renderers/markdownRenderer.tsx +2 -2
- package/src/ui/renderers/mcpRenderers.tsx +28 -14
- package/src/ui/renderers/modelRenderers.tsx +12 -13
- package/src/ui/renderers/modelVisuals.tsx +0 -2
- package/src/ui/renderers/pluginRenderers.tsx +47 -54
- package/src/ui/renderers/profileRenderers.tsx +32 -37
- package/src/ui/renderers/settingsRenderers.tsx +84 -55
- package/src/ui/renderers/skillRenderers.tsx +237 -190
- package/src/ui/renderers/styleRenderers.tsx +13 -2
- package/src/ui/runtime/shutdown.ts +268 -0
- package/src/ui/screens/AliasScreen.tsx +118 -100
- package/src/ui/screens/CliToolsScreen.tsx +98 -87
- package/src/ui/screens/EnvVarsScreen.tsx +44 -42
- package/src/ui/screens/GitignoreScreen.tsx +50 -55
- package/src/ui/screens/McpRegistryScreen.tsx +52 -86
- package/src/ui/screens/McpScreen.tsx +47 -33
- package/src/ui/screens/ModelsScreen.tsx +59 -104
- package/src/ui/screens/PluginsScreen.tsx +123 -127
- package/src/ui/screens/ProfilesScreen.tsx +49 -46
- package/src/ui/screens/SkillsScreen.tsx +184 -204
- package/src/ui/screens/StylesScreen.tsx +104 -157
- package/src/ui/state/AppContext.tsx +6 -0
- package/src/ui/state/DimensionsContext.tsx +1 -10
- package/src/ui/state/reducer.ts +5 -8
- package/src/ui/state/types.ts +11 -9
- package/src/ui/text-width.ts +341 -0
- package/src/ui/theme-mode.ts +34 -71
- package/src/ui/theme.ts +50 -28
- package/src/utils/request-gate.ts +37 -0
- package/src/ui/components/ScopeIndicator.tsx +0 -63
- package/src/ui/components/SearchInput.tsx +0 -57
- package/src/ui/hooks/index.ts +0 -2
- package/src/ui/hooks/useKeyboard.ts +0 -24
- package/src/ui/hooks/useKeyboardHandler.ts +0 -63
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { type UiColor, theme } from "../theme.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Scope indicator for list items.
|
|
6
|
-
* Shows colored letter badges when installed, empty space when not.
|
|
7
|
-
*
|
|
8
|
-
* Installed in user+project: u p
|
|
9
|
-
* Installed in project only: p
|
|
10
|
-
* Not installed: (3 spaces)
|
|
11
|
-
*
|
|
12
|
-
* Colors match the detail panel: cyan=user, green=project, yellow=local
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
export function scopeIndicatorText(
|
|
16
|
-
user?: boolean,
|
|
17
|
-
project?: boolean,
|
|
18
|
-
local?: boolean,
|
|
19
|
-
): {
|
|
20
|
-
text: string;
|
|
21
|
-
segments: Array<{ char: string; bg: UiColor; fg: UiColor }>;
|
|
22
|
-
} {
|
|
23
|
-
const segments: Array<{ char: string; bg: UiColor; fg: UiColor }> = [
|
|
24
|
-
user
|
|
25
|
-
? { char: "u", bg: theme.colors.info, fg: theme.hints.fg }
|
|
26
|
-
: { char: " ", bg: "", fg: "" },
|
|
27
|
-
project
|
|
28
|
-
? { char: "p", bg: theme.colors.success, fg: theme.hints.fg }
|
|
29
|
-
: { char: " ", bg: "", fg: "" },
|
|
30
|
-
local
|
|
31
|
-
? { char: "l", bg: theme.colors.warning, fg: theme.hints.fg }
|
|
32
|
-
: { char: " ", bg: "", fg: "" },
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
const text = segments.map((s) => s.char).join("");
|
|
36
|
-
return { text, segments };
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
interface ScopeIndicatorProps {
|
|
40
|
-
user?: boolean;
|
|
41
|
-
project?: boolean;
|
|
42
|
-
local?: boolean;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function ScopeIndicator({ user, project, local }: ScopeIndicatorProps) {
|
|
46
|
-
const { segments } = scopeIndicatorText(user, project, local);
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<text fg={theme.colors.text}>
|
|
50
|
-
{segments.map((s, i) =>
|
|
51
|
-
s.bg ? (
|
|
52
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: segments are fixed-position scope squares (user/project/local); the slot is the identity and the list never reorders
|
|
53
|
-
<span key={i} bg={s.bg} fg={s.fg}>
|
|
54
|
-
{s.char}
|
|
55
|
-
</span>
|
|
56
|
-
) : (
|
|
57
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: same fixed-slot list as above
|
|
58
|
-
<span key={i}> </span>
|
|
59
|
-
),
|
|
60
|
-
)}
|
|
61
|
-
</text>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { useKeyboardHandler } from "../hooks/useKeyboardHandler.js";
|
|
3
|
-
import { theme } from "../theme.js";
|
|
4
|
-
|
|
5
|
-
interface SearchInputProps {
|
|
6
|
-
/** Current search value */
|
|
7
|
-
value: string;
|
|
8
|
-
/** Called when value changes */
|
|
9
|
-
onChange: (value: string) => void;
|
|
10
|
-
/** Placeholder text when empty */
|
|
11
|
-
placeholder?: string;
|
|
12
|
-
/** Whether the input is focused/active */
|
|
13
|
-
isActive: boolean;
|
|
14
|
-
/** Called when user presses escape to exit search */
|
|
15
|
-
onExit?: () => void;
|
|
16
|
-
/** Called when user presses enter */
|
|
17
|
-
onSubmit?: () => void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function SearchInput({
|
|
21
|
-
value,
|
|
22
|
-
onChange,
|
|
23
|
-
placeholder = "Search...",
|
|
24
|
-
isActive,
|
|
25
|
-
onExit,
|
|
26
|
-
onSubmit,
|
|
27
|
-
}: SearchInputProps) {
|
|
28
|
-
// Handle keyboard shortcuts when active
|
|
29
|
-
useKeyboardHandler((_input, key) => {
|
|
30
|
-
if (!isActive) return;
|
|
31
|
-
|
|
32
|
-
if (key.escape) {
|
|
33
|
-
onExit?.();
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (key.return) {
|
|
38
|
-
onSubmit?.();
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
return (
|
|
44
|
-
<box flexDirection="row">
|
|
45
|
-
<text fg={theme.colors.info}>❯ </text>
|
|
46
|
-
<input
|
|
47
|
-
value={value}
|
|
48
|
-
onChange={onChange}
|
|
49
|
-
placeholder={placeholder}
|
|
50
|
-
focused={isActive}
|
|
51
|
-
width={40}
|
|
52
|
-
/>
|
|
53
|
-
</box>
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export default SearchInput;
|
package/src/ui/hooks/index.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { useKeyboard as useOpenTUIKeyboard } from "@opentui/react";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* OpenTUI keyboard event type
|
|
5
|
-
*/
|
|
6
|
-
export interface KeyEvent {
|
|
7
|
-
name: string;
|
|
8
|
-
ctrl?: boolean;
|
|
9
|
-
shift?: boolean;
|
|
10
|
-
meta?: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Simple re-export of OpenTUI's useKeyboard hook
|
|
15
|
-
* Used by modals for direct keyboard event handling
|
|
16
|
-
*
|
|
17
|
-
* Key names in OpenTUI:
|
|
18
|
-
* - Single characters: "a", "1", etc.
|
|
19
|
-
* - Arrow keys: "up", "down", "left", "right"
|
|
20
|
-
* - Special: "enter", "escape", "tab", "backspace", "delete"
|
|
21
|
-
*/
|
|
22
|
-
export function useKeyboard(handler: (event: KeyEvent) => void): void {
|
|
23
|
-
useOpenTUIKeyboard(handler);
|
|
24
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { useKeyboard as useOpenTUIKeyboard } from "@opentui/react";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Wrapper hook for OpenTUI's useKeyboard that provides an Ink-like API
|
|
5
|
-
* Maps Ink key names to OpenTUI key names for easier migration
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export interface InkLikeKey {
|
|
9
|
-
name: string;
|
|
10
|
-
ctrl: boolean;
|
|
11
|
-
shift: boolean;
|
|
12
|
-
meta: boolean;
|
|
13
|
-
return?: boolean;
|
|
14
|
-
upArrow?: boolean;
|
|
15
|
-
downArrow?: boolean;
|
|
16
|
-
leftArrow?: boolean;
|
|
17
|
-
rightArrow?: boolean;
|
|
18
|
-
escape?: boolean;
|
|
19
|
-
tab?: boolean;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
type KeyHandler = (input: string, key: InkLikeKey) => void;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* useKeyboardHandler hook
|
|
26
|
-
* Provides Ink-like API for keyboard events
|
|
27
|
-
*
|
|
28
|
-
* @param handler - Callback function with Ink-compatible signature
|
|
29
|
-
*
|
|
30
|
-
* @example
|
|
31
|
-
* ```tsx
|
|
32
|
-
* useKeyboardHandler((input, key) => {
|
|
33
|
-
* if (key.return) handleEnter();
|
|
34
|
-
* if (key.upArrow) handleUp();
|
|
35
|
-
* if (key.escape) handleEscape();
|
|
36
|
-
* if (input === 'q') handleQuit();
|
|
37
|
-
* });
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
export function useKeyboardHandler(handler: KeyHandler): void {
|
|
41
|
-
useOpenTUIKeyboard((event) => {
|
|
42
|
-
// Map OpenTUI key names to Ink-like key names
|
|
43
|
-
const key: InkLikeKey = {
|
|
44
|
-
name: event.name,
|
|
45
|
-
ctrl: event.ctrl || false,
|
|
46
|
-
shift: event.shift || false,
|
|
47
|
-
meta: event.meta || false,
|
|
48
|
-
return: event.name === "enter" || event.name === "return",
|
|
49
|
-
upArrow: event.name === "up",
|
|
50
|
-
downArrow: event.name === "down",
|
|
51
|
-
leftArrow: event.name === "left",
|
|
52
|
-
rightArrow: event.name === "right",
|
|
53
|
-
escape: event.name === "escape",
|
|
54
|
-
tab: event.name === "tab",
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// For printable characters, pass the character as input
|
|
58
|
-
// For special keys, pass empty string
|
|
59
|
-
const input = event.name.length === 1 ? event.name : "";
|
|
60
|
-
|
|
61
|
-
handler(input, key);
|
|
62
|
-
});
|
|
63
|
-
}
|