claudeup 1.8.0 → 3.3.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/bin/claudeup.js +20 -2
- package/package.json +10 -19
- package/src/data/cli-tools.js +123 -0
- package/src/data/cli-tools.ts +140 -0
- package/{dist → src}/data/marketplaces.js +23 -24
- package/src/data/marketplaces.ts +95 -0
- package/src/data/mcp-servers.js +509 -0
- package/src/data/mcp-servers.ts +526 -0
- package/src/data/statuslines.js +159 -0
- package/src/data/statuslines.ts +188 -0
- package/src/index.js +4 -0
- package/src/index.ts +5 -0
- package/{dist → src}/main.js +46 -47
- package/src/main.tsx +145 -0
- package/src/opentui.d.ts +191 -0
- package/{dist → src}/prerunner/index.js +31 -41
- package/src/prerunner/index.ts +124 -0
- package/{dist → src}/services/claude-runner.js +9 -10
- package/src/services/claude-runner.ts +31 -0
- package/{dist → src}/services/claude-settings.js +72 -33
- package/src/services/claude-settings.ts +934 -0
- package/src/services/local-marketplace.js +339 -0
- package/src/services/local-marketplace.ts +489 -0
- package/{dist → src}/services/mcp-registry.js +13 -14
- package/src/services/mcp-registry.ts +105 -0
- package/{dist → src}/services/plugin-manager.js +61 -13
- package/src/services/plugin-manager.ts +693 -0
- package/{dist → src}/services/plugin-mcp-config.js +19 -18
- package/src/services/plugin-mcp-config.ts +242 -0
- package/{dist → src}/services/update-cache.js +0 -1
- package/src/services/update-cache.ts +78 -0
- package/{dist → src}/services/version-check.js +15 -14
- package/src/services/version-check.ts +122 -0
- package/src/types/index.js +1 -0
- package/src/types/index.ts +141 -0
- package/src/ui/App.js +213 -0
- package/src/ui/App.tsx +359 -0
- package/src/ui/components/CategoryHeader.js +9 -0
- package/src/ui/components/CategoryHeader.tsx +41 -0
- package/{dist → src}/ui/components/ScrollableList.js +19 -6
- package/src/ui/components/ScrollableList.tsx +98 -0
- package/src/ui/components/SearchInput.js +19 -0
- package/src/ui/components/SearchInput.tsx +56 -0
- package/src/ui/components/StyledText.js +39 -0
- package/src/ui/components/StyledText.tsx +70 -0
- package/src/ui/components/TabBar.js +38 -0
- package/src/ui/components/TabBar.tsx +88 -0
- package/src/ui/components/layout/Panel.js +6 -0
- package/src/ui/components/layout/Panel.tsx +62 -0
- package/src/ui/components/layout/ProgressBar.js +14 -0
- package/src/ui/components/layout/ProgressBar.tsx +47 -0
- package/src/ui/components/layout/ScopeTabs.js +6 -0
- package/src/ui/components/layout/ScopeTabs.tsx +53 -0
- package/src/ui/components/layout/ScreenLayout.js +21 -0
- package/src/ui/components/layout/ScreenLayout.tsx +147 -0
- package/src/ui/components/layout/index.js +4 -0
- package/src/ui/components/layout/index.ts +4 -0
- package/src/ui/components/modals/ConfirmModal.js +14 -0
- package/src/ui/components/modals/ConfirmModal.tsx +59 -0
- package/src/ui/components/modals/InputModal.js +16 -0
- package/src/ui/components/modals/InputModal.tsx +68 -0
- package/src/ui/components/modals/LoadingModal.js +14 -0
- package/src/ui/components/modals/LoadingModal.tsx +40 -0
- package/src/ui/components/modals/MessageModal.js +16 -0
- package/src/ui/components/modals/MessageModal.tsx +64 -0
- package/src/ui/components/modals/ModalContainer.js +56 -0
- package/src/ui/components/modals/ModalContainer.tsx +104 -0
- package/src/ui/components/modals/SelectModal.js +26 -0
- package/src/ui/components/modals/SelectModal.tsx +82 -0
- package/src/ui/components/modals/index.js +6 -0
- package/src/ui/components/modals/index.ts +6 -0
- package/src/ui/hooks/index.js +3 -0
- package/src/ui/hooks/index.ts +3 -0
- package/{dist → src}/ui/hooks/useAsyncData.js +21 -22
- package/src/ui/hooks/useAsyncData.ts +127 -0
- package/src/ui/hooks/useKeyboard.js +13 -0
- package/src/ui/hooks/useKeyboard.ts +26 -0
- package/src/ui/hooks/useKeyboardHandler.js +39 -0
- package/src/ui/hooks/useKeyboardHandler.ts +63 -0
- package/{dist → src}/ui/screens/CliToolsScreen.js +60 -54
- package/src/ui/screens/CliToolsScreen.tsx +468 -0
- package/src/ui/screens/EnvVarsScreen.js +154 -0
- package/src/ui/screens/EnvVarsScreen.tsx +269 -0
- package/{dist → src}/ui/screens/McpRegistryScreen.js +56 -55
- package/src/ui/screens/McpRegistryScreen.tsx +331 -0
- package/{dist → src}/ui/screens/McpScreen.js +46 -47
- package/src/ui/screens/McpScreen.tsx +392 -0
- package/src/ui/screens/ModelSelectorScreen.js +292 -0
- package/src/ui/screens/ModelSelectorScreen.tsx +441 -0
- package/{dist → src}/ui/screens/PluginsScreen.js +305 -293
- package/src/ui/screens/PluginsScreen.tsx +1231 -0
- package/src/ui/screens/StatusLineScreen.js +200 -0
- package/src/ui/screens/StatusLineScreen.tsx +411 -0
- package/src/ui/screens/index.js +7 -0
- package/src/ui/screens/index.ts +7 -0
- package/src/ui/state/AnimationContext.js +34 -0
- package/src/ui/state/AnimationContext.tsx +76 -0
- package/{dist → src}/ui/state/AppContext.js +31 -32
- package/src/ui/state/AppContext.tsx +235 -0
- package/{dist → src}/ui/state/DimensionsContext.js +16 -17
- package/src/ui/state/DimensionsContext.tsx +144 -0
- package/{dist → src}/ui/state/reducer.js +89 -90
- package/src/ui/state/reducer.ts +467 -0
- package/src/ui/state/types.js +1 -0
- package/src/ui/state/types.ts +273 -0
- package/{dist → src}/utils/command-utils.js +3 -4
- package/src/utils/command-utils.ts +20 -0
- package/{dist → src}/utils/fuzzy-search.js +2 -3
- package/src/utils/fuzzy-search.ts +138 -0
- package/{dist → src}/utils/string-utils.js +6 -6
- package/src/utils/string-utils.ts +88 -0
- package/dist/data/cli-tools.d.ts +0 -13
- package/dist/data/cli-tools.d.ts.map +0 -1
- package/dist/data/cli-tools.js +0 -124
- package/dist/data/cli-tools.js.map +0 -1
- package/dist/data/marketplaces.d.ts +0 -6
- package/dist/data/marketplaces.d.ts.map +0 -1
- package/dist/data/marketplaces.js.map +0 -1
- package/dist/data/mcp-servers.d.ts +0 -8
- package/dist/data/mcp-servers.d.ts.map +0 -1
- package/dist/data/mcp-servers.js +0 -503
- package/dist/data/mcp-servers.js.map +0 -1
- package/dist/data/statuslines.d.ts +0 -10
- package/dist/data/statuslines.d.ts.map +0 -1
- package/dist/data/statuslines.js +0 -160
- package/dist/data/statuslines.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -90
- package/dist/index.js.map +0 -1
- package/dist/main.d.ts +0 -3
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/prerunner/index.d.ts +0 -7
- package/dist/prerunner/index.d.ts.map +0 -1
- package/dist/prerunner/index.js.map +0 -1
- package/dist/services/claude-runner.d.ts +0 -7
- package/dist/services/claude-runner.d.ts.map +0 -1
- package/dist/services/claude-runner.js.map +0 -1
- package/dist/services/claude-settings.d.ts +0 -73
- package/dist/services/claude-settings.d.ts.map +0 -1
- package/dist/services/claude-settings.js.map +0 -1
- package/dist/services/local-marketplace.d.ts +0 -111
- package/dist/services/local-marketplace.d.ts.map +0 -1
- package/dist/services/local-marketplace.js +0 -599
- package/dist/services/local-marketplace.js.map +0 -1
- package/dist/services/mcp-registry.d.ts +0 -10
- package/dist/services/mcp-registry.d.ts.map +0 -1
- package/dist/services/mcp-registry.js.map +0 -1
- package/dist/services/plugin-manager.d.ts +0 -65
- package/dist/services/plugin-manager.d.ts.map +0 -1
- package/dist/services/plugin-manager.js.map +0 -1
- package/dist/services/plugin-mcp-config.d.ts +0 -52
- package/dist/services/plugin-mcp-config.d.ts.map +0 -1
- package/dist/services/plugin-mcp-config.js.map +0 -1
- package/dist/services/update-cache.d.ts +0 -21
- package/dist/services/update-cache.d.ts.map +0 -1
- package/dist/services/update-cache.js.map +0 -1
- package/dist/services/version-check.d.ts +0 -20
- package/dist/services/version-check.d.ts.map +0 -1
- package/dist/services/version-check.js.map +0 -1
- package/dist/types/index.d.ts +0 -105
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -2
- package/dist/types/index.js.map +0 -1
- package/dist/ui/InkApp.d.ts +0 -5
- package/dist/ui/InkApp.d.ts.map +0 -1
- package/dist/ui/InkApp.js +0 -188
- package/dist/ui/InkApp.js.map +0 -1
- package/dist/ui/components/CategoryHeader.d.ts +0 -16
- package/dist/ui/components/CategoryHeader.d.ts.map +0 -1
- package/dist/ui/components/CategoryHeader.js +0 -11
- package/dist/ui/components/CategoryHeader.js.map +0 -1
- package/dist/ui/components/ScrollableList.d.ts +0 -16
- package/dist/ui/components/ScrollableList.d.ts.map +0 -1
- package/dist/ui/components/ScrollableList.js.map +0 -1
- package/dist/ui/components/SearchInput.d.ts +0 -18
- package/dist/ui/components/SearchInput.d.ts.map +0 -1
- package/dist/ui/components/SearchInput.js +0 -30
- package/dist/ui/components/SearchInput.js.map +0 -1
- package/dist/ui/components/TabBar.d.ts +0 -8
- package/dist/ui/components/TabBar.d.ts.map +0 -1
- package/dist/ui/components/TabBar.js +0 -18
- package/dist/ui/components/TabBar.js.map +0 -1
- package/dist/ui/components/layout/Footer.d.ts +0 -14
- package/dist/ui/components/layout/Footer.d.ts.map +0 -1
- package/dist/ui/components/layout/Footer.js +0 -23
- package/dist/ui/components/layout/Footer.js.map +0 -1
- package/dist/ui/components/layout/Header.d.ts +0 -4
- package/dist/ui/components/layout/Header.d.ts.map +0 -1
- package/dist/ui/components/layout/Header.js +0 -25
- package/dist/ui/components/layout/Header.js.map +0 -1
- package/dist/ui/components/layout/Panel.d.ts +0 -22
- package/dist/ui/components/layout/Panel.d.ts.map +0 -1
- package/dist/ui/components/layout/Panel.js +0 -8
- package/dist/ui/components/layout/Panel.js.map +0 -1
- package/dist/ui/components/layout/ProgressBar.d.ts +0 -12
- package/dist/ui/components/layout/ProgressBar.d.ts.map +0 -1
- package/dist/ui/components/layout/ProgressBar.js +0 -16
- package/dist/ui/components/layout/ProgressBar.js.map +0 -1
- package/dist/ui/components/layout/ScopeTabs.d.ts +0 -12
- package/dist/ui/components/layout/ScopeTabs.d.ts.map +0 -1
- package/dist/ui/components/layout/ScopeTabs.js +0 -8
- package/dist/ui/components/layout/ScopeTabs.js.map +0 -1
- package/dist/ui/components/layout/ScreenLayout.d.ts +0 -30
- package/dist/ui/components/layout/ScreenLayout.d.ts.map +0 -1
- package/dist/ui/components/layout/ScreenLayout.js +0 -23
- package/dist/ui/components/layout/ScreenLayout.js.map +0 -1
- package/dist/ui/components/layout/index.d.ts +0 -7
- package/dist/ui/components/layout/index.d.ts.map +0 -1
- package/dist/ui/components/layout/index.js +0 -7
- package/dist/ui/components/layout/index.js.map +0 -1
- package/dist/ui/components/modals/ConfirmModal.d.ts +0 -14
- package/dist/ui/components/modals/ConfirmModal.d.ts.map +0 -1
- package/dist/ui/components/modals/ConfirmModal.js +0 -15
- package/dist/ui/components/modals/ConfirmModal.js.map +0 -1
- package/dist/ui/components/modals/InputModal.d.ts +0 -16
- package/dist/ui/components/modals/InputModal.d.ts.map +0 -1
- package/dist/ui/components/modals/InputModal.js +0 -23
- package/dist/ui/components/modals/InputModal.js.map +0 -1
- package/dist/ui/components/modals/LoadingModal.d.ts +0 -8
- package/dist/ui/components/modals/LoadingModal.d.ts.map +0 -1
- package/dist/ui/components/modals/LoadingModal.js +0 -8
- package/dist/ui/components/modals/LoadingModal.js.map +0 -1
- package/dist/ui/components/modals/MessageModal.d.ts +0 -14
- package/dist/ui/components/modals/MessageModal.d.ts.map +0 -1
- package/dist/ui/components/modals/MessageModal.js +0 -17
- package/dist/ui/components/modals/MessageModal.js.map +0 -1
- package/dist/ui/components/modals/ModalContainer.d.ts +0 -7
- package/dist/ui/components/modals/ModalContainer.d.ts.map +0 -1
- package/dist/ui/components/modals/ModalContainer.js +0 -38
- package/dist/ui/components/modals/ModalContainer.js.map +0 -1
- package/dist/ui/components/modals/SelectModal.d.ts +0 -17
- package/dist/ui/components/modals/SelectModal.d.ts.map +0 -1
- package/dist/ui/components/modals/SelectModal.js +0 -33
- package/dist/ui/components/modals/SelectModal.js.map +0 -1
- package/dist/ui/components/modals/index.d.ts +0 -7
- package/dist/ui/components/modals/index.d.ts.map +0 -1
- package/dist/ui/components/modals/index.js +0 -7
- package/dist/ui/components/modals/index.js.map +0 -1
- package/dist/ui/hooks/index.d.ts +0 -3
- package/dist/ui/hooks/index.d.ts.map +0 -1
- package/dist/ui/hooks/index.js +0 -3
- package/dist/ui/hooks/index.js.map +0 -1
- package/dist/ui/hooks/useAsyncData.d.ts +0 -40
- package/dist/ui/hooks/useAsyncData.d.ts.map +0 -1
- package/dist/ui/hooks/useAsyncData.js.map +0 -1
- package/dist/ui/hooks/useKeyboardNavigation.d.ts +0 -27
- package/dist/ui/hooks/useKeyboardNavigation.d.ts.map +0 -1
- package/dist/ui/hooks/useKeyboardNavigation.js +0 -82
- package/dist/ui/hooks/useKeyboardNavigation.js.map +0 -1
- package/dist/ui/screens/CliToolsScreen.d.ts +0 -4
- package/dist/ui/screens/CliToolsScreen.d.ts.map +0 -1
- package/dist/ui/screens/CliToolsScreen.js.map +0 -1
- package/dist/ui/screens/EnvVarsScreen.d.ts +0 -4
- package/dist/ui/screens/EnvVarsScreen.d.ts.map +0 -1
- package/dist/ui/screens/EnvVarsScreen.js +0 -145
- package/dist/ui/screens/EnvVarsScreen.js.map +0 -1
- package/dist/ui/screens/McpRegistryScreen.d.ts +0 -4
- package/dist/ui/screens/McpRegistryScreen.d.ts.map +0 -1
- package/dist/ui/screens/McpRegistryScreen.js.map +0 -1
- package/dist/ui/screens/McpScreen.d.ts +0 -4
- package/dist/ui/screens/McpScreen.d.ts.map +0 -1
- package/dist/ui/screens/McpScreen.js.map +0 -1
- package/dist/ui/screens/ModelSelectorScreen.d.ts +0 -4
- package/dist/ui/screens/ModelSelectorScreen.d.ts.map +0 -1
- package/dist/ui/screens/ModelSelectorScreen.js +0 -143
- package/dist/ui/screens/ModelSelectorScreen.js.map +0 -1
- package/dist/ui/screens/PluginsScreen.d.ts +0 -4
- package/dist/ui/screens/PluginsScreen.d.ts.map +0 -1
- package/dist/ui/screens/PluginsScreen.js.map +0 -1
- package/dist/ui/screens/StatusLineScreen.d.ts +0 -4
- package/dist/ui/screens/StatusLineScreen.d.ts.map +0 -1
- package/dist/ui/screens/StatusLineScreen.js +0 -197
- package/dist/ui/screens/StatusLineScreen.js.map +0 -1
- package/dist/ui/screens/index.d.ts +0 -8
- package/dist/ui/screens/index.d.ts.map +0 -1
- package/dist/ui/screens/index.js +0 -8
- package/dist/ui/screens/index.js.map +0 -1
- package/dist/ui/state/AppContext.d.ts +0 -40
- package/dist/ui/state/AppContext.d.ts.map +0 -1
- package/dist/ui/state/AppContext.js.map +0 -1
- package/dist/ui/state/DimensionsContext.d.ts +0 -27
- package/dist/ui/state/DimensionsContext.d.ts.map +0 -1
- package/dist/ui/state/DimensionsContext.js.map +0 -1
- package/dist/ui/state/reducer.d.ts +0 -4
- package/dist/ui/state/reducer.d.ts.map +0 -1
- package/dist/ui/state/reducer.js.map +0 -1
- package/dist/ui/state/types.d.ts +0 -266
- package/dist/ui/state/types.d.ts.map +0 -1
- package/dist/ui/state/types.js +0 -2
- package/dist/ui/state/types.js.map +0 -1
- package/dist/utils/command-utils.d.ts +0 -8
- package/dist/utils/command-utils.d.ts.map +0 -1
- package/dist/utils/command-utils.js.map +0 -1
- package/dist/utils/fuzzy-search.d.ts +0 -33
- package/dist/utils/fuzzy-search.d.ts.map +0 -1
- package/dist/utils/fuzzy-search.js.map +0 -1
- package/dist/utils/string-utils.d.ts +0 -24
- package/dist/utils/string-utils.d.ts.map +0 -1
- package/dist/utils/string-utils.js.map +0 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
export interface McpServer {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
// Command-based MCP server
|
|
5
|
+
command?: string;
|
|
6
|
+
args?: string[];
|
|
7
|
+
env?: Record<string, string>;
|
|
8
|
+
// HTTP-based MCP server
|
|
9
|
+
type?: "http";
|
|
10
|
+
url?: string;
|
|
11
|
+
// Common fields
|
|
12
|
+
category:
|
|
13
|
+
| "browser"
|
|
14
|
+
| "ai"
|
|
15
|
+
| "design"
|
|
16
|
+
| "dev-tools"
|
|
17
|
+
| "cloud"
|
|
18
|
+
| "database"
|
|
19
|
+
| "productivity"
|
|
20
|
+
| "seo";
|
|
21
|
+
requiresConfig?: boolean;
|
|
22
|
+
configFields?: ConfigField[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ConfigField {
|
|
26
|
+
name: string;
|
|
27
|
+
label: string;
|
|
28
|
+
type: "string" | "path" | "url" | "boolean";
|
|
29
|
+
required: boolean;
|
|
30
|
+
default?: string;
|
|
31
|
+
envVar?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface Marketplace {
|
|
35
|
+
name: string;
|
|
36
|
+
displayName: string;
|
|
37
|
+
source: {
|
|
38
|
+
source: "github";
|
|
39
|
+
repo: string;
|
|
40
|
+
};
|
|
41
|
+
description: string;
|
|
42
|
+
official?: boolean;
|
|
43
|
+
featured?: boolean; // Featured marketplaces have plugins fetched by default (like official)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface DiscoveredMarketplace {
|
|
47
|
+
name: string;
|
|
48
|
+
source: "default" | "configured" | "inferred";
|
|
49
|
+
config?: MarketplaceSource;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface Plugin {
|
|
53
|
+
name: string;
|
|
54
|
+
version: string;
|
|
55
|
+
description: string;
|
|
56
|
+
marketplace: string;
|
|
57
|
+
installed: boolean;
|
|
58
|
+
availableVersion?: string;
|
|
59
|
+
hasUpdate?: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface StatusLineConfig {
|
|
63
|
+
name: string;
|
|
64
|
+
description: string;
|
|
65
|
+
template: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface MarketplaceSource {
|
|
69
|
+
source: {
|
|
70
|
+
source: "github";
|
|
71
|
+
repo: string;
|
|
72
|
+
};
|
|
73
|
+
autoUpdate?: boolean; // Enable auto-update for this marketplace (default: true for new marketplaces)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface ClaudeSettings {
|
|
77
|
+
enabledMcpServers?: Record<string, boolean>;
|
|
78
|
+
mcpServers?: Record<string, McpServerConfig>;
|
|
79
|
+
enabledPlugins?: Record<string, boolean>;
|
|
80
|
+
extraKnownMarketplaces?: Record<string, MarketplaceSource>;
|
|
81
|
+
installedPluginVersions?: Record<string, string>;
|
|
82
|
+
statusLine?: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface McpServerConfig {
|
|
86
|
+
// Command-based
|
|
87
|
+
command?: string;
|
|
88
|
+
args?: string[];
|
|
89
|
+
env?: Record<string, string>;
|
|
90
|
+
// HTTP-based
|
|
91
|
+
type?: "http";
|
|
92
|
+
url?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface ClaudeLocalSettings extends ClaudeSettings {
|
|
96
|
+
allowMcp?: boolean;
|
|
97
|
+
enabledMcpjsonServers?: string[];
|
|
98
|
+
enableAllProjectMcpServers?: boolean;
|
|
99
|
+
env?: Record<string, string>;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export type Screen =
|
|
103
|
+
| "main"
|
|
104
|
+
| "mcp"
|
|
105
|
+
| "mcp-registry"
|
|
106
|
+
| "plugins"
|
|
107
|
+
| "statusline"
|
|
108
|
+
| "cli-tools"
|
|
109
|
+
| "env-vars";
|
|
110
|
+
|
|
111
|
+
// MCP Registry Types (registry.modelcontextprotocol.io)
|
|
112
|
+
export interface McpRegistryServer {
|
|
113
|
+
name: string;
|
|
114
|
+
url: string;
|
|
115
|
+
short_description: string;
|
|
116
|
+
version?: string;
|
|
117
|
+
source_code_url?: string;
|
|
118
|
+
package_registry?: string;
|
|
119
|
+
published_at?: string;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export interface McpRegistryResponse {
|
|
123
|
+
servers: McpRegistryServer[];
|
|
124
|
+
next_cursor?: string;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// installed_plugins.json registry types
|
|
128
|
+
export interface InstalledPluginEntry {
|
|
129
|
+
scope: "user" | "project" | "local";
|
|
130
|
+
projectPath?: string;
|
|
131
|
+
installPath: string;
|
|
132
|
+
version: string;
|
|
133
|
+
installedAt: string;
|
|
134
|
+
lastUpdated: string;
|
|
135
|
+
gitCommitSha?: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface InstalledPluginsRegistry {
|
|
139
|
+
version: number;
|
|
140
|
+
plugins: Record<string, InstalledPluginEntry[]>;
|
|
141
|
+
}
|
package/src/ui/App.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { useRenderer } from "@opentui/react";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import { AppProvider, useApp, useNavigation, useModal, } from "./state/AppContext.js";
|
|
6
|
+
import { DimensionsProvider, useDimensions, } from "./state/DimensionsContext.js";
|
|
7
|
+
import { ModalContainer } from "./components/modals/index.js";
|
|
8
|
+
import { PluginsScreen, McpScreen, McpRegistryScreen, StatusLineScreen, EnvVarsScreen, CliToolsScreen, ModelSelectorScreen, } from "./screens/index.js";
|
|
9
|
+
import { repairAllMarketplaces } from "../services/local-marketplace.js";
|
|
10
|
+
import { checkForUpdates, getCurrentVersion, } from "../services/version-check.js";
|
|
11
|
+
import { useKeyboardHandler } from "./hooks/useKeyboardHandler.js";
|
|
12
|
+
import { ProgressBar } from "./components/layout/ProgressBar.js";
|
|
13
|
+
export const VERSION = getCurrentVersion();
|
|
14
|
+
/**
|
|
15
|
+
* Router Component
|
|
16
|
+
* Renders the current screen based on route
|
|
17
|
+
*/
|
|
18
|
+
function Router() {
|
|
19
|
+
const { state } = useApp();
|
|
20
|
+
const { currentRoute } = state;
|
|
21
|
+
switch (currentRoute.screen) {
|
|
22
|
+
case "plugins":
|
|
23
|
+
return _jsx(PluginsScreen, {});
|
|
24
|
+
case "mcp":
|
|
25
|
+
return _jsx(McpScreen, {});
|
|
26
|
+
case "mcp-registry":
|
|
27
|
+
return _jsx(McpRegistryScreen, {});
|
|
28
|
+
case "statusline":
|
|
29
|
+
return _jsx(StatusLineScreen, {});
|
|
30
|
+
case "env-vars":
|
|
31
|
+
return _jsx(EnvVarsScreen, {});
|
|
32
|
+
case "cli-tools":
|
|
33
|
+
return _jsx(CliToolsScreen, {});
|
|
34
|
+
case "model-selector":
|
|
35
|
+
return _jsx(ModelSelectorScreen, {});
|
|
36
|
+
default:
|
|
37
|
+
return _jsx(PluginsScreen, {});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* GlobalKeyHandler Component
|
|
42
|
+
* Handles global keyboard shortcuts (1-5, Tab, Escape, q, ?, Shift+D)
|
|
43
|
+
* Does not render anything (returns null)
|
|
44
|
+
*/
|
|
45
|
+
function GlobalKeyHandler({ onDebugToggle, onExit, }) {
|
|
46
|
+
const { state } = useApp();
|
|
47
|
+
const { navigateToScreen } = useNavigation();
|
|
48
|
+
const modal = useModal();
|
|
49
|
+
const renderer = useRenderer();
|
|
50
|
+
useKeyboardHandler((input, key) => {
|
|
51
|
+
// Debug key (Shift+D) - always available
|
|
52
|
+
if (input === "D" && key.shift) {
|
|
53
|
+
onDebugToggle();
|
|
54
|
+
// Write debug info to file
|
|
55
|
+
const debugInfo = {
|
|
56
|
+
timestamp: new Date().toISOString(),
|
|
57
|
+
terminal: { rows: renderer.height, columns: renderer.width },
|
|
58
|
+
state: {
|
|
59
|
+
currentRoute: state.currentRoute,
|
|
60
|
+
isSearching: state.isSearching,
|
|
61
|
+
modal: state.modal ? { type: state.modal.type } : null,
|
|
62
|
+
plugins: {
|
|
63
|
+
scope: state.plugins.scope,
|
|
64
|
+
selectedIndex: state.plugins.selectedIndex,
|
|
65
|
+
searchQuery: state.plugins.searchQuery,
|
|
66
|
+
marketplacesStatus: state.plugins.marketplaces.status,
|
|
67
|
+
pluginsStatus: state.plugins.plugins.status,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
fs.writeFileSync("/tmp/claudeup-debug.json", JSON.stringify(debugInfo, null, 2));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
// Don't handle keys when modal is open or searching
|
|
75
|
+
if (state.modal || state.isSearching)
|
|
76
|
+
return;
|
|
77
|
+
// Global navigation shortcuts (1-5) - include mcp-registry as it's a sub-screen of mcp
|
|
78
|
+
const isTopLevel = [
|
|
79
|
+
"plugins",
|
|
80
|
+
"mcp",
|
|
81
|
+
"mcp-registry",
|
|
82
|
+
"statusline",
|
|
83
|
+
"env-vars",
|
|
84
|
+
"cli-tools",
|
|
85
|
+
"model-selector",
|
|
86
|
+
].includes(state.currentRoute.screen);
|
|
87
|
+
if (isTopLevel) {
|
|
88
|
+
if (input === "1")
|
|
89
|
+
navigateToScreen("plugins");
|
|
90
|
+
else if (input === "2")
|
|
91
|
+
navigateToScreen("mcp");
|
|
92
|
+
else if (input === "3")
|
|
93
|
+
navigateToScreen("statusline");
|
|
94
|
+
else if (input === "4")
|
|
95
|
+
navigateToScreen("env-vars");
|
|
96
|
+
else if (input === "5")
|
|
97
|
+
navigateToScreen("cli-tools");
|
|
98
|
+
// Tab navigation cycling
|
|
99
|
+
if (key.tab) {
|
|
100
|
+
const screens = [
|
|
101
|
+
"plugins",
|
|
102
|
+
"mcp",
|
|
103
|
+
"statusline",
|
|
104
|
+
"env-vars",
|
|
105
|
+
"cli-tools",
|
|
106
|
+
];
|
|
107
|
+
const currentIndex = screens.indexOf(state.currentRoute.screen);
|
|
108
|
+
if (currentIndex !== -1) {
|
|
109
|
+
const nextIndex = key.shift
|
|
110
|
+
? (currentIndex - 1 + screens.length) % screens.length
|
|
111
|
+
: (currentIndex + 1) % screens.length;
|
|
112
|
+
navigateToScreen(screens[nextIndex]);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Escape/q to go back or exit
|
|
117
|
+
if (key.escape || input === "q") {
|
|
118
|
+
if (state.currentRoute.screen === "plugins") {
|
|
119
|
+
// On home screen, exit immediately
|
|
120
|
+
onExit();
|
|
121
|
+
}
|
|
122
|
+
else if (state.currentRoute.screen === "mcp-registry") {
|
|
123
|
+
// Go back to MCP from registry
|
|
124
|
+
navigateToScreen("mcp");
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// Go back to plugins (home)
|
|
128
|
+
navigateToScreen("plugins");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// ? for help
|
|
132
|
+
if (input === "?") {
|
|
133
|
+
modal.message("claudeup Help", `Navigation
|
|
134
|
+
↑/↓ or j/k Move selection
|
|
135
|
+
Enter Select / Toggle
|
|
136
|
+
Escape or q Back / Quit
|
|
137
|
+
? This help
|
|
138
|
+
|
|
139
|
+
Quick Navigation
|
|
140
|
+
1 Plugins 4 Env Vars
|
|
141
|
+
2 MCP Servers 5 CLI Tools
|
|
142
|
+
3 Status Line
|
|
143
|
+
|
|
144
|
+
Plugin Actions
|
|
145
|
+
u Update d Uninstall
|
|
146
|
+
a Update All r Refresh
|
|
147
|
+
|
|
148
|
+
MCP Servers
|
|
149
|
+
/ Search local + remote
|
|
150
|
+
r Browse MCP registry`, "info");
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* UpdateBanner Component
|
|
157
|
+
* Shows version update notification
|
|
158
|
+
*/
|
|
159
|
+
function UpdateBanner({ result, }) {
|
|
160
|
+
if (!result.updateAvailable)
|
|
161
|
+
return null;
|
|
162
|
+
return (_jsxs("box", { paddingLeft: 1, paddingRight: 1, children: [_jsx("text", { bg: "yellow", fg: "black", children: _jsx("strong", { children: " UPDATE " }) }), _jsxs("text", { fg: "yellow", children: [" ", "v", result.currentVersion, " \u2192 v", result.latestVersion] }), _jsx("text", { fg: "gray", children: " Run: " }), _jsx("text", { fg: "cyan", children: "npm i -g claudeup" })] }));
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* ProgressIndicator Component
|
|
166
|
+
* Shows progress bar when operations are running
|
|
167
|
+
*/
|
|
168
|
+
function ProgressIndicator({ message, current, total, }) {
|
|
169
|
+
return (_jsx("box", { paddingLeft: 1, paddingRight: 1, children: _jsx(ProgressBar, { message: message, current: current, total: total }) }));
|
|
170
|
+
}
|
|
171
|
+
function AppContentInner({ showDebug, onDebugToggle, updateInfo, onExit, }) {
|
|
172
|
+
const { state, dispatch } = useApp();
|
|
173
|
+
const { progress } = state;
|
|
174
|
+
const dimensions = useDimensions();
|
|
175
|
+
// Auto-refresh marketplaces on startup
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
const noRefresh = process.argv.includes("--no-refresh");
|
|
178
|
+
if (noRefresh)
|
|
179
|
+
return;
|
|
180
|
+
dispatch({
|
|
181
|
+
type: "SHOW_PROGRESS",
|
|
182
|
+
state: { message: "Scanning marketplaces..." },
|
|
183
|
+
});
|
|
184
|
+
// Note: Marketplace updates should be done via Claude Code's /plugin marketplace update
|
|
185
|
+
// Just repair plugin.json files
|
|
186
|
+
repairAllMarketplaces()
|
|
187
|
+
.then(async () => {
|
|
188
|
+
dispatch({ type: "HIDE_PROGRESS" });
|
|
189
|
+
dispatch({ type: "DATA_REFRESH_COMPLETE" });
|
|
190
|
+
})
|
|
191
|
+
.catch(() => {
|
|
192
|
+
dispatch({ type: "HIDE_PROGRESS" });
|
|
193
|
+
});
|
|
194
|
+
}, [dispatch]);
|
|
195
|
+
return (_jsxs("box", { flexDirection: "column", height: dimensions.terminalHeight, children: [updateInfo?.updateAvailable && _jsx(UpdateBanner, { result: updateInfo }), showDebug && (_jsx("box", { paddingLeft: 1, paddingRight: 1, children: _jsxs("text", { fg: "#888888", children: ["DEBUG: ", dimensions.terminalWidth, "x", dimensions.terminalHeight, " | content=", dimensions.contentHeight, " | screen=", state.currentRoute.screen] }) })), progress && _jsx(ProgressIndicator, { ...progress }), _jsx("box", { flexDirection: "column", height: dimensions.contentHeight, paddingLeft: 1, paddingRight: 1, children: _jsx(Router, {}) }), _jsx(GlobalKeyHandler, { onDebugToggle: onDebugToggle, onExit: onExit }), _jsx(ModalContainer, {})] }));
|
|
196
|
+
}
|
|
197
|
+
function AppContent({ onExit }) {
|
|
198
|
+
const { state } = useApp();
|
|
199
|
+
const { progress } = state;
|
|
200
|
+
const [showDebug, setShowDebug] = useState(false);
|
|
201
|
+
const [updateInfo, setUpdateInfo] = useState(null);
|
|
202
|
+
// Check for updates on startup (non-blocking)
|
|
203
|
+
useEffect(() => {
|
|
204
|
+
checkForUpdates()
|
|
205
|
+
.then(setUpdateInfo)
|
|
206
|
+
.catch(() => { });
|
|
207
|
+
}, []);
|
|
208
|
+
return (_jsx(DimensionsProvider, { showProgress: !!progress, showDebug: showDebug, showUpdateBanner: !!updateInfo?.updateAvailable, children: _jsx(AppContentInner, { showDebug: showDebug, onDebugToggle: () => setShowDebug((s) => !s), updateInfo: updateInfo, onExit: onExit }) }));
|
|
209
|
+
}
|
|
210
|
+
export function App({ onExit }) {
|
|
211
|
+
return (_jsx(AppProvider, { children: _jsx(AppContent, { onExit: onExit }) }));
|
|
212
|
+
}
|
|
213
|
+
export default App;
|
package/src/ui/App.tsx
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { useRenderer } from "@opentui/react";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import {
|
|
5
|
+
AppProvider,
|
|
6
|
+
useApp,
|
|
7
|
+
useNavigation,
|
|
8
|
+
useModal,
|
|
9
|
+
} from "./state/AppContext.js";
|
|
10
|
+
import {
|
|
11
|
+
DimensionsProvider,
|
|
12
|
+
useDimensions,
|
|
13
|
+
} from "./state/DimensionsContext.js";
|
|
14
|
+
import { ModalContainer } from "./components/modals/index.js";
|
|
15
|
+
import {
|
|
16
|
+
PluginsScreen,
|
|
17
|
+
McpScreen,
|
|
18
|
+
McpRegistryScreen,
|
|
19
|
+
StatusLineScreen,
|
|
20
|
+
EnvVarsScreen,
|
|
21
|
+
CliToolsScreen,
|
|
22
|
+
ModelSelectorScreen,
|
|
23
|
+
} from "./screens/index.js";
|
|
24
|
+
import type { Screen } from "./state/types.js";
|
|
25
|
+
import { repairAllMarketplaces } from "../services/local-marketplace.js";
|
|
26
|
+
import {
|
|
27
|
+
checkForUpdates,
|
|
28
|
+
getCurrentVersion,
|
|
29
|
+
type VersionCheckResult,
|
|
30
|
+
} from "../services/version-check.js";
|
|
31
|
+
import { useKeyboardHandler } from "./hooks/useKeyboardHandler.js";
|
|
32
|
+
import { ProgressBar } from "./components/layout/ProgressBar.js";
|
|
33
|
+
|
|
34
|
+
export const VERSION = getCurrentVersion();
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Router Component
|
|
38
|
+
* Renders the current screen based on route
|
|
39
|
+
*/
|
|
40
|
+
function Router() {
|
|
41
|
+
const { state } = useApp();
|
|
42
|
+
const { currentRoute } = state;
|
|
43
|
+
|
|
44
|
+
switch (currentRoute.screen) {
|
|
45
|
+
case "plugins":
|
|
46
|
+
return <PluginsScreen />;
|
|
47
|
+
case "mcp":
|
|
48
|
+
return <McpScreen />;
|
|
49
|
+
case "mcp-registry":
|
|
50
|
+
return <McpRegistryScreen />;
|
|
51
|
+
case "statusline":
|
|
52
|
+
return <StatusLineScreen />;
|
|
53
|
+
case "env-vars":
|
|
54
|
+
return <EnvVarsScreen />;
|
|
55
|
+
case "cli-tools":
|
|
56
|
+
return <CliToolsScreen />;
|
|
57
|
+
case "model-selector":
|
|
58
|
+
return <ModelSelectorScreen />;
|
|
59
|
+
default:
|
|
60
|
+
return <PluginsScreen />;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* GlobalKeyHandler Component
|
|
66
|
+
* Handles global keyboard shortcuts (1-5, Tab, Escape, q, ?, Shift+D)
|
|
67
|
+
* Does not render anything (returns null)
|
|
68
|
+
*/
|
|
69
|
+
function GlobalKeyHandler({
|
|
70
|
+
onDebugToggle,
|
|
71
|
+
onExit,
|
|
72
|
+
}: { onDebugToggle: () => void; onExit: () => void }): null {
|
|
73
|
+
const { state } = useApp();
|
|
74
|
+
const { navigateToScreen } = useNavigation();
|
|
75
|
+
const modal = useModal();
|
|
76
|
+
const renderer = useRenderer();
|
|
77
|
+
|
|
78
|
+
useKeyboardHandler((input, key) => {
|
|
79
|
+
// Debug key (Shift+D) - always available
|
|
80
|
+
if (input === "D" && key.shift) {
|
|
81
|
+
onDebugToggle();
|
|
82
|
+
// Write debug info to file
|
|
83
|
+
const debugInfo = {
|
|
84
|
+
timestamp: new Date().toISOString(),
|
|
85
|
+
terminal: { rows: renderer.height, columns: renderer.width },
|
|
86
|
+
state: {
|
|
87
|
+
currentRoute: state.currentRoute,
|
|
88
|
+
isSearching: state.isSearching,
|
|
89
|
+
modal: state.modal ? { type: state.modal.type } : null,
|
|
90
|
+
plugins: {
|
|
91
|
+
scope: state.plugins.scope,
|
|
92
|
+
selectedIndex: state.plugins.selectedIndex,
|
|
93
|
+
searchQuery: state.plugins.searchQuery,
|
|
94
|
+
marketplacesStatus: state.plugins.marketplaces.status,
|
|
95
|
+
pluginsStatus: state.plugins.plugins.status,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
fs.writeFileSync(
|
|
100
|
+
"/tmp/claudeup-debug.json",
|
|
101
|
+
JSON.stringify(debugInfo, null, 2),
|
|
102
|
+
);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Don't handle keys when modal is open or searching
|
|
107
|
+
if (state.modal || state.isSearching) return;
|
|
108
|
+
|
|
109
|
+
// Global navigation shortcuts (1-5) - include mcp-registry as it's a sub-screen of mcp
|
|
110
|
+
const isTopLevel = [
|
|
111
|
+
"plugins",
|
|
112
|
+
"mcp",
|
|
113
|
+
"mcp-registry",
|
|
114
|
+
"statusline",
|
|
115
|
+
"env-vars",
|
|
116
|
+
"cli-tools",
|
|
117
|
+
"model-selector",
|
|
118
|
+
].includes(state.currentRoute.screen);
|
|
119
|
+
|
|
120
|
+
if (isTopLevel) {
|
|
121
|
+
if (input === "1") navigateToScreen("plugins");
|
|
122
|
+
else if (input === "2") navigateToScreen("mcp");
|
|
123
|
+
else if (input === "3") navigateToScreen("statusline");
|
|
124
|
+
else if (input === "4") navigateToScreen("env-vars");
|
|
125
|
+
else if (input === "5") navigateToScreen("cli-tools");
|
|
126
|
+
|
|
127
|
+
// Tab navigation cycling
|
|
128
|
+
if (key.tab) {
|
|
129
|
+
const screens: Screen[] = [
|
|
130
|
+
"plugins",
|
|
131
|
+
"mcp",
|
|
132
|
+
"statusline",
|
|
133
|
+
"env-vars",
|
|
134
|
+
"cli-tools",
|
|
135
|
+
];
|
|
136
|
+
const currentIndex = screens.indexOf(
|
|
137
|
+
state.currentRoute.screen as Screen,
|
|
138
|
+
);
|
|
139
|
+
if (currentIndex !== -1) {
|
|
140
|
+
const nextIndex = key.shift
|
|
141
|
+
? (currentIndex - 1 + screens.length) % screens.length
|
|
142
|
+
: (currentIndex + 1) % screens.length;
|
|
143
|
+
navigateToScreen(screens[nextIndex]);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Escape/q to go back or exit
|
|
149
|
+
if (key.escape || input === "q") {
|
|
150
|
+
if (state.currentRoute.screen === "plugins") {
|
|
151
|
+
// On home screen, exit immediately
|
|
152
|
+
onExit();
|
|
153
|
+
} else if (state.currentRoute.screen === "mcp-registry") {
|
|
154
|
+
// Go back to MCP from registry
|
|
155
|
+
navigateToScreen("mcp");
|
|
156
|
+
} else {
|
|
157
|
+
// Go back to plugins (home)
|
|
158
|
+
navigateToScreen("plugins");
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ? for help
|
|
163
|
+
if (input === "?") {
|
|
164
|
+
modal.message(
|
|
165
|
+
"claudeup Help",
|
|
166
|
+
`Navigation
|
|
167
|
+
↑/↓ or j/k Move selection
|
|
168
|
+
Enter Select / Toggle
|
|
169
|
+
Escape or q Back / Quit
|
|
170
|
+
? This help
|
|
171
|
+
|
|
172
|
+
Quick Navigation
|
|
173
|
+
1 Plugins 4 Env Vars
|
|
174
|
+
2 MCP Servers 5 CLI Tools
|
|
175
|
+
3 Status Line
|
|
176
|
+
|
|
177
|
+
Plugin Actions
|
|
178
|
+
u Update d Uninstall
|
|
179
|
+
a Update All r Refresh
|
|
180
|
+
|
|
181
|
+
MCP Servers
|
|
182
|
+
/ Search local + remote
|
|
183
|
+
r Browse MCP registry`,
|
|
184
|
+
"info",
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* UpdateBanner Component
|
|
194
|
+
* Shows version update notification
|
|
195
|
+
*/
|
|
196
|
+
function UpdateBanner({
|
|
197
|
+
result,
|
|
198
|
+
}: { result: VersionCheckResult }) {
|
|
199
|
+
if (!result.updateAvailable) return null;
|
|
200
|
+
|
|
201
|
+
return (
|
|
202
|
+
<box paddingLeft={1} paddingRight={1} >
|
|
203
|
+
<text bg="yellow" fg="black">
|
|
204
|
+
<strong> UPDATE </strong>
|
|
205
|
+
</text>
|
|
206
|
+
<text fg="yellow">
|
|
207
|
+
{" "}
|
|
208
|
+
v{result.currentVersion} → v{result.latestVersion}
|
|
209
|
+
</text>
|
|
210
|
+
<text fg="gray"> Run: </text>
|
|
211
|
+
<text fg="cyan">npm i -g claudeup</text>
|
|
212
|
+
</box>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* ProgressIndicator Component
|
|
218
|
+
* Shows progress bar when operations are running
|
|
219
|
+
*/
|
|
220
|
+
function ProgressIndicator({
|
|
221
|
+
message,
|
|
222
|
+
current,
|
|
223
|
+
total,
|
|
224
|
+
}: {
|
|
225
|
+
message: string;
|
|
226
|
+
current?: number;
|
|
227
|
+
total?: number;
|
|
228
|
+
}) {
|
|
229
|
+
return (
|
|
230
|
+
<box paddingLeft={1} paddingRight={1}>
|
|
231
|
+
<ProgressBar message={message} current={current} total={total} />
|
|
232
|
+
</box>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* AppContentInner Component
|
|
238
|
+
* Main app layout with all UI elements
|
|
239
|
+
*/
|
|
240
|
+
interface AppContentInnerProps {
|
|
241
|
+
showDebug: boolean;
|
|
242
|
+
onDebugToggle: () => void;
|
|
243
|
+
updateInfo: VersionCheckResult | null;
|
|
244
|
+
onExit: () => void;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function AppContentInner({
|
|
248
|
+
showDebug,
|
|
249
|
+
onDebugToggle,
|
|
250
|
+
updateInfo,
|
|
251
|
+
onExit,
|
|
252
|
+
}: AppContentInnerProps) {
|
|
253
|
+
const { state, dispatch } = useApp();
|
|
254
|
+
const { progress } = state;
|
|
255
|
+
const dimensions = useDimensions();
|
|
256
|
+
|
|
257
|
+
// Auto-refresh marketplaces on startup
|
|
258
|
+
useEffect(() => {
|
|
259
|
+
const noRefresh = process.argv.includes("--no-refresh");
|
|
260
|
+
if (noRefresh) return;
|
|
261
|
+
|
|
262
|
+
dispatch({
|
|
263
|
+
type: "SHOW_PROGRESS",
|
|
264
|
+
state: { message: "Scanning marketplaces..." },
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// Note: Marketplace updates should be done via Claude Code's /plugin marketplace update
|
|
268
|
+
// Just repair plugin.json files
|
|
269
|
+
repairAllMarketplaces()
|
|
270
|
+
.then(async () => {
|
|
271
|
+
dispatch({ type: "HIDE_PROGRESS" });
|
|
272
|
+
dispatch({ type: "DATA_REFRESH_COMPLETE" });
|
|
273
|
+
})
|
|
274
|
+
.catch(() => {
|
|
275
|
+
dispatch({ type: "HIDE_PROGRESS" });
|
|
276
|
+
});
|
|
277
|
+
}, [dispatch]);
|
|
278
|
+
|
|
279
|
+
return (
|
|
280
|
+
<box flexDirection="column" height={dimensions.terminalHeight}>
|
|
281
|
+
{updateInfo?.updateAvailable && <UpdateBanner result={updateInfo} />}
|
|
282
|
+
{showDebug && (
|
|
283
|
+
<box paddingLeft={1} paddingRight={1}>
|
|
284
|
+
<text fg="#888888">
|
|
285
|
+
DEBUG: {dimensions.terminalWidth}x{dimensions.terminalHeight} |
|
|
286
|
+
content={dimensions.contentHeight} | screen=
|
|
287
|
+
{state.currentRoute.screen}
|
|
288
|
+
</text>
|
|
289
|
+
</box>
|
|
290
|
+
)}
|
|
291
|
+
{progress && <ProgressIndicator {...progress} />}
|
|
292
|
+
<box
|
|
293
|
+
flexDirection="column"
|
|
294
|
+
height={dimensions.contentHeight}
|
|
295
|
+
paddingLeft={1} paddingRight={1}
|
|
296
|
+
>
|
|
297
|
+
<Router />
|
|
298
|
+
</box>
|
|
299
|
+
<GlobalKeyHandler onDebugToggle={onDebugToggle} onExit={onExit} />
|
|
300
|
+
<ModalContainer />
|
|
301
|
+
</box>
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* AppContent Component
|
|
307
|
+
* Wraps app with DimensionsProvider and manages state for debug/updates
|
|
308
|
+
*/
|
|
309
|
+
interface AppContentProps {
|
|
310
|
+
onExit: () => void;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function AppContent({ onExit }: AppContentProps) {
|
|
314
|
+
const { state } = useApp();
|
|
315
|
+
const { progress } = state;
|
|
316
|
+
const [showDebug, setShowDebug] = useState(false);
|
|
317
|
+
const [updateInfo, setUpdateInfo] = useState<VersionCheckResult | null>(null);
|
|
318
|
+
|
|
319
|
+
// Check for updates on startup (non-blocking)
|
|
320
|
+
useEffect(() => {
|
|
321
|
+
checkForUpdates()
|
|
322
|
+
.then(setUpdateInfo)
|
|
323
|
+
.catch(() => {});
|
|
324
|
+
}, []);
|
|
325
|
+
|
|
326
|
+
return (
|
|
327
|
+
<DimensionsProvider
|
|
328
|
+
showProgress={!!progress}
|
|
329
|
+
showDebug={showDebug}
|
|
330
|
+
showUpdateBanner={!!updateInfo?.updateAvailable}
|
|
331
|
+
>
|
|
332
|
+
<AppContentInner
|
|
333
|
+
showDebug={showDebug}
|
|
334
|
+
onDebugToggle={() => setShowDebug((s) => !s)}
|
|
335
|
+
updateInfo={updateInfo}
|
|
336
|
+
onExit={onExit}
|
|
337
|
+
/>
|
|
338
|
+
</DimensionsProvider>
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* App Component (Root)
|
|
344
|
+
* Entry point for the OpenTUI application
|
|
345
|
+
* Wraps everything with AppProvider
|
|
346
|
+
*/
|
|
347
|
+
interface AppProps {
|
|
348
|
+
onExit: () => void;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export function App({ onExit }: AppProps) {
|
|
352
|
+
return (
|
|
353
|
+
<AppProvider>
|
|
354
|
+
<AppContent onExit={onExit} />
|
|
355
|
+
</AppProvider>
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export default App;
|