aman-intelligence 0.1.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/LICENSE +21 -0
- package/README.md +116 -0
- package/dist/bin/aman.d.ts +2 -0
- package/dist/bin/aman.js +165 -0
- package/dist/cli/global-install.d.ts +7 -0
- package/dist/cli/global-install.js +36 -0
- package/dist/cli/help-text.d.ts +1 -0
- package/dist/cli/help-text.js +62 -0
- package/dist/cli/version.d.ts +1 -0
- package/dist/cli/version.js +6 -0
- package/dist/commands/backup.d.ts +11 -0
- package/dist/commands/backup.js +262 -0
- package/dist/commands/browse.d.ts +11 -0
- package/dist/commands/browse.js +641 -0
- package/dist/commands/cache.d.ts +1 -0
- package/dist/commands/cache.js +38 -0
- package/dist/commands/config.d.ts +4 -0
- package/dist/commands/config.js +146 -0
- package/dist/commands/dashboard.d.ts +1 -0
- package/dist/commands/dashboard.js +1004 -0
- package/dist/commands/doctor.d.ts +4 -0
- package/dist/commands/doctor.js +54 -0
- package/dist/commands/export.d.ts +1 -0
- package/dist/commands/export.js +137 -0
- package/dist/commands/help.d.ts +1 -0
- package/dist/commands/help.js +47 -0
- package/dist/commands/import-wizard.d.ts +7 -0
- package/dist/commands/import-wizard.js +374 -0
- package/dist/commands/import.d.ts +9 -0
- package/dist/commands/import.js +351 -0
- package/dist/commands/info.d.ts +1 -0
- package/dist/commands/info.js +174 -0
- package/dist/commands/init.d.ts +20 -0
- package/dist/commands/init.js +146 -0
- package/dist/commands/install.d.ts +10 -0
- package/dist/commands/install.js +342 -0
- package/dist/commands/pack.d.ts +23 -0
- package/dist/commands/pack.js +331 -0
- package/dist/commands/registry.d.ts +6 -0
- package/dist/commands/registry.js +218 -0
- package/dist/commands/remove.d.ts +1 -0
- package/dist/commands/remove.js +76 -0
- package/dist/commands/search.d.ts +7 -0
- package/dist/commands/search.js +295 -0
- package/dist/commands/stack.d.ts +18 -0
- package/dist/commands/stack.js +327 -0
- package/dist/commands/sync.d.ts +9 -0
- package/dist/commands/sync.js +428 -0
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.js +97 -0
- package/dist/config/features.d.ts +2 -0
- package/dist/config/features.js +2 -0
- package/dist/config/index.d.ts +13 -0
- package/dist/config/index.js +80 -0
- package/dist/config/paths.d.ts +23 -0
- package/dist/config/paths.js +45 -0
- package/dist/import/adapters.d.ts +14 -0
- package/dist/import/adapters.js +580 -0
- package/dist/import/discovery.service.d.ts +8 -0
- package/dist/import/discovery.service.js +26 -0
- package/dist/import/import.service.d.ts +7 -0
- package/dist/import/import.service.js +259 -0
- package/dist/import/types.d.ts +71 -0
- package/dist/import/types.js +1 -0
- package/dist/import/utils.d.ts +36 -0
- package/dist/import/utils.js +428 -0
- package/dist/marketplace/cache.d.ts +18 -0
- package/dist/marketplace/cache.js +141 -0
- package/dist/marketplace/github-search.d.ts +17 -0
- package/dist/marketplace/github-search.js +268 -0
- package/dist/marketplace/install-from-candidate.d.ts +6 -0
- package/dist/marketplace/install-from-candidate.js +14 -0
- package/dist/marketplace/install.d.ts +15 -0
- package/dist/marketplace/install.js +54 -0
- package/dist/marketplace/metadata-validator.d.ts +8 -0
- package/dist/marketplace/metadata-validator.js +79 -0
- package/dist/marketplace/types.d.ts +34 -0
- package/dist/marketplace/types.js +1 -0
- package/dist/providers/local.provider.d.ts +9 -0
- package/dist/providers/local.provider.js +51 -0
- package/dist/providers/provider.interface.d.ts +7 -0
- package/dist/providers/provider.interface.js +1 -0
- package/dist/providers/registry.provider.d.ts +2 -0
- package/dist/providers/registry.provider.js +42 -0
- package/dist/providers/skills-sh.provider.d.ts +11 -0
- package/dist/providers/skills-sh.provider.js +56 -0
- package/dist/registry/adapter.interface.d.ts +16 -0
- package/dist/registry/adapter.interface.js +1 -0
- package/dist/registry/errors.d.ts +5 -0
- package/dist/registry/errors.js +8 -0
- package/dist/registry/filesystem-registry.adapter.d.ts +25 -0
- package/dist/registry/filesystem-registry.adapter.js +288 -0
- package/dist/registry/github-registry.adapter.d.ts +11 -0
- package/dist/registry/github-registry.adapter.js +32 -0
- package/dist/registry/index.d.ts +8 -0
- package/dist/registry/index.js +8 -0
- package/dist/registry/local-registry.adapter.d.ts +6 -0
- package/dist/registry/local-registry.adapter.js +9 -0
- package/dist/registry/registry.service.d.ts +44 -0
- package/dist/registry/registry.service.js +163 -0
- package/dist/registry/slug-utils.d.ts +12 -0
- package/dist/registry/slug-utils.js +51 -0
- package/dist/registry/types.d.ts +160 -0
- package/dist/registry/types.js +1 -0
- package/dist/services/asset.service.d.ts +12 -0
- package/dist/services/asset.service.js +142 -0
- package/dist/services/backup.service.d.ts +8 -0
- package/dist/services/backup.service.js +169 -0
- package/dist/services/classification.service.d.ts +31 -0
- package/dist/services/classification.service.js +271 -0
- package/dist/services/config.service.d.ts +9 -0
- package/dist/services/config.service.js +20 -0
- package/dist/services/doctor.service.d.ts +5 -0
- package/dist/services/doctor.service.js +186 -0
- package/dist/services/environment.service.d.ts +42 -0
- package/dist/services/environment.service.js +227 -0
- package/dist/services/github.service.d.ts +7 -0
- package/dist/services/github.service.js +42 -0
- package/dist/services/lock.service.d.ts +12 -0
- package/dist/services/lock.service.js +71 -0
- package/dist/services/marketplace.service.d.ts +40 -0
- package/dist/services/marketplace.service.js +225 -0
- package/dist/services/pack.service.d.ts +9 -0
- package/dist/services/pack.service.js +193 -0
- package/dist/services/stack.service.d.ts +9 -0
- package/dist/services/stack.service.js +94 -0
- package/dist/storage/asset-layout.d.ts +46 -0
- package/dist/storage/asset-layout.js +277 -0
- package/dist/storage/filesystem.d.ts +12 -0
- package/dist/storage/filesystem.js +113 -0
- package/dist/storage/scan-by-type.d.ts +2 -0
- package/dist/storage/scan-by-type.js +8 -0
- package/dist/storage/scanner.d.ts +11 -0
- package/dist/storage/scanner.js +188 -0
- package/dist/types/asset-metadata.d.ts +84 -0
- package/dist/types/asset-metadata.js +104 -0
- package/dist/types/index.d.ts +212 -0
- package/dist/types/index.js +1 -0
- package/dist/ui/animations/ErrorIndicator.d.ts +5 -0
- package/dist/ui/animations/ErrorIndicator.js +6 -0
- package/dist/ui/animations/GithubIndicator.d.ts +6 -0
- package/dist/ui/animations/GithubIndicator.js +9 -0
- package/dist/ui/animations/ProgressBar.d.ts +5 -0
- package/dist/ui/animations/ProgressBar.js +15 -0
- package/dist/ui/animations/Spinner.d.ts +5 -0
- package/dist/ui/animations/Spinner.js +21 -0
- package/dist/ui/animations/SuccessIndicator.d.ts +5 -0
- package/dist/ui/animations/SuccessIndicator.js +6 -0
- package/dist/ui/animations/SyncActivity.d.ts +5 -0
- package/dist/ui/animations/SyncActivity.js +21 -0
- package/dist/ui/animations/TransitionScreen.d.ts +7 -0
- package/dist/ui/animations/TransitionScreen.js +25 -0
- package/dist/ui/animations/useAnimationMode.d.ts +1 -0
- package/dist/ui/animations/useAnimationMode.js +16 -0
- package/dist/ui/assetDisplay.d.ts +19 -0
- package/dist/ui/assetDisplay.js +59 -0
- package/dist/ui/components/Confirm.d.ts +8 -0
- package/dist/ui/components/Confirm.js +14 -0
- package/dist/ui/components/CustomSelect.d.ts +19 -0
- package/dist/ui/components/CustomSelect.js +13 -0
- package/dist/ui/components/Header.d.ts +6 -0
- package/dist/ui/components/Header.js +9 -0
- package/dist/ui/components/HealthReport.d.ts +7 -0
- package/dist/ui/components/HealthReport.js +13 -0
- package/dist/ui/components/MarketplaceInstallConfirm.d.ts +19 -0
- package/dist/ui/components/MarketplaceInstallConfirm.js +23 -0
- package/dist/ui/components/Narrator.d.ts +9 -0
- package/dist/ui/components/Narrator.js +26 -0
- package/dist/ui/components/ScopePrompt.d.ts +8 -0
- package/dist/ui/components/ScopePrompt.js +23 -0
- package/dist/ui/components/TooSmallScreen.d.ts +8 -0
- package/dist/ui/components/TooSmallScreen.js +6 -0
- package/dist/ui/date.d.ts +2 -0
- package/dist/ui/date.js +33 -0
- package/dist/ui/layout.d.ts +23 -0
- package/dist/ui/layout.js +44 -0
- package/dist/ui/list-item.d.ts +12 -0
- package/dist/ui/list-item.js +1 -0
- package/dist/ui/marketplaceDisplay.d.ts +10 -0
- package/dist/ui/marketplaceDisplay.js +36 -0
- package/dist/ui/theme.d.ts +42 -0
- package/dist/ui/theme.js +47 -0
- package/dist/utils/asset-list-fields.d.ts +11 -0
- package/dist/utils/asset-list-fields.js +28 -0
- package/dist/utils/error-message.d.ts +2 -0
- package/dist/utils/error-message.js +6 -0
- package/dist/utils/integrity.d.ts +9 -0
- package/dist/utils/integrity.js +23 -0
- package/dist/utils/lock-migrate.d.ts +25 -0
- package/dist/utils/lock-migrate.js +93 -0
- package/dist/utils/mcp-local.d.ts +15 -0
- package/dist/utils/mcp-local.js +129 -0
- package/dist/utils/slug.d.ts +6 -0
- package/dist/utils/slug.js +13 -0
- package/dist/utils/stack-normalize.d.ts +3 -0
- package/dist/utils/stack-normalize.js +43 -0
- package/package.json +77 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState, useCallback } from 'react';
|
|
3
|
+
import { render, Box, Text, useApp, useInput } from 'ink';
|
|
4
|
+
import { CustomSelectInput } from '../ui/components/CustomSelect.js';
|
|
5
|
+
import TextInput from 'ink-text-input';
|
|
6
|
+
import { environmentService } from '../services/environment.service.js';
|
|
7
|
+
import { lockService } from '../services/lock.service.js';
|
|
8
|
+
import { exists } from '../storage/filesystem.js';
|
|
9
|
+
import { Narrator } from '../ui/components/Narrator.js';
|
|
10
|
+
import { Header } from '../ui/components/Header.js';
|
|
11
|
+
import { theme } from '../ui/theme.js';
|
|
12
|
+
import { execFileSync } from 'child_process';
|
|
13
|
+
import { useResponsiveLayout, MIN_COLUMNS, MIN_ROWS } from '../ui/layout.js';
|
|
14
|
+
import { TooSmallScreen } from '../ui/components/TooSmallScreen.js';
|
|
15
|
+
import { ProgressBar } from '../ui/animations/ProgressBar.js';
|
|
16
|
+
import { TransitionScreen } from '../ui/animations/TransitionScreen.js';
|
|
17
|
+
function parseGitError(err) {
|
|
18
|
+
const stderr = err.stderr ? err.stderr.toString() : err.message || '';
|
|
19
|
+
if (stderr.includes('Repository not found') || stderr.includes('does not exist')) {
|
|
20
|
+
return 'GitHub Repository not found. Verify the repo name or run "gh repo create" to establish it.';
|
|
21
|
+
}
|
|
22
|
+
if (stderr.includes('Permission to') && stderr.includes('denied')) {
|
|
23
|
+
return 'Permission denied. Ensure your GitHub CLI account has push access to this repository.';
|
|
24
|
+
}
|
|
25
|
+
if (stderr.includes('Authentication failed') || stderr.includes('Could not read from remote repository')) {
|
|
26
|
+
return 'GitHub Authentication failed. Please run "gh auth login" to refresh your session.';
|
|
27
|
+
}
|
|
28
|
+
if (stderr.includes('detached HEAD')) {
|
|
29
|
+
return 'Git is in a detached HEAD state. Run "git checkout main" manually in the environment directory first.';
|
|
30
|
+
}
|
|
31
|
+
if (stderr.includes('conflict') || stderr.includes('non-fast-forward') || stderr.includes('Updates were rejected')) {
|
|
32
|
+
return 'Push conflict: remote changes exist. Run "aman sync pull" first to merge differences.';
|
|
33
|
+
}
|
|
34
|
+
if (stderr.includes('branch') && (stderr.includes('does not exist') || stderr.includes('not found'))) {
|
|
35
|
+
return 'Target branch does not exist on the remote repository.';
|
|
36
|
+
}
|
|
37
|
+
if (stderr.includes('remote rejected')) {
|
|
38
|
+
return 'Remote repository rejected the push. Check remote branch restrictions or permissions.';
|
|
39
|
+
}
|
|
40
|
+
if (stderr.includes('Could not resolve host') || stderr.includes('network') || stderr.includes('connection')) {
|
|
41
|
+
return 'Network failure. Check your internet connection and try again.';
|
|
42
|
+
}
|
|
43
|
+
return stderr.trim() || 'Git operation failed';
|
|
44
|
+
}
|
|
45
|
+
export const SyncApp = ({ action, onBack }) => {
|
|
46
|
+
const { exit } = useApp();
|
|
47
|
+
const { rows, isTooSmall, physicalColumns, physicalRows } = useResponsiveLayout();
|
|
48
|
+
const [progress, setProgress] = useState(0);
|
|
49
|
+
const handleExit = useCallback(() => {
|
|
50
|
+
if (onBack)
|
|
51
|
+
onBack();
|
|
52
|
+
else
|
|
53
|
+
exit();
|
|
54
|
+
}, [onBack, exit]);
|
|
55
|
+
const [screenState, setScreenState] = useState('checking');
|
|
56
|
+
const [githubMode, setGithubMode] = useState('create');
|
|
57
|
+
const [repoName, setRepoName] = useState('');
|
|
58
|
+
const [repoError, setRepoError] = useState();
|
|
59
|
+
const [setupState, setSetupState] = useState('idle');
|
|
60
|
+
const [setupMessage, setSetupMessage] = useState('');
|
|
61
|
+
if (isTooSmall) {
|
|
62
|
+
return _jsx(TooSmallScreen, { columns: physicalColumns, rows: physicalRows, minColumns: MIN_COLUMNS, minRows: MIN_ROWS });
|
|
63
|
+
}
|
|
64
|
+
const [mochiState, setMochiState] = useState('searching');
|
|
65
|
+
const [message, setMessage] = useState('');
|
|
66
|
+
useInput((input, key) => {
|
|
67
|
+
if (key.escape || input === 'q') {
|
|
68
|
+
if (screenState === 'mode_select') {
|
|
69
|
+
setScreenState('not_connected_menu');
|
|
70
|
+
}
|
|
71
|
+
else if (screenState === 'repo_input') {
|
|
72
|
+
setScreenState('mode_select');
|
|
73
|
+
}
|
|
74
|
+
else if (screenState === 'gh_cli_required') {
|
|
75
|
+
setScreenState('not_connected_menu');
|
|
76
|
+
}
|
|
77
|
+
else if (screenState === 'not_connected_menu' ||
|
|
78
|
+
screenState === 'local_storage_info' ||
|
|
79
|
+
screenState === 'done') {
|
|
80
|
+
handleExit();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// Check connection on start
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (screenState === 'checking') {
|
|
87
|
+
const storage = environmentService.getStorage();
|
|
88
|
+
if (storage.type === 'github' && storage.repository) {
|
|
89
|
+
setScreenState('sync_loading');
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
setScreenState('not_connected_menu');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}, [screenState]);
|
|
96
|
+
// Handle local storage info auto-exit
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
if (screenState === 'local_storage_info') {
|
|
99
|
+
const t = setTimeout(() => handleExit(), 3000);
|
|
100
|
+
return () => clearTimeout(t);
|
|
101
|
+
}
|
|
102
|
+
}, [screenState, handleExit]);
|
|
103
|
+
async function handleSetupAndSync(repo) {
|
|
104
|
+
setScreenState('setup_loading');
|
|
105
|
+
setSetupState('installing');
|
|
106
|
+
setSetupMessage(`Setting up GitHub repository: ${repo}...`);
|
|
107
|
+
try {
|
|
108
|
+
await environmentService.initGithub({ repository: repo, mode: githubMode });
|
|
109
|
+
setSetupState('success');
|
|
110
|
+
setSetupMessage('GitHub connected successfully! Starting sync...');
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
setScreenState('sync_loading');
|
|
113
|
+
}, 1200);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
setSetupState('error');
|
|
117
|
+
setSetupMessage(`Setup failed: ${err.message}`);
|
|
118
|
+
setTimeout(() => {
|
|
119
|
+
handleExit();
|
|
120
|
+
}, 2500);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
async function runSync() {
|
|
125
|
+
try {
|
|
126
|
+
setProgress(10);
|
|
127
|
+
const storage = environmentService.getStorage();
|
|
128
|
+
if (storage.type !== 'github' || !storage.repository) {
|
|
129
|
+
setMochiState('error');
|
|
130
|
+
setMessage('No GitHub storage configured.');
|
|
131
|
+
setScreenState('done');
|
|
132
|
+
setTimeout(() => handleExit(), 2000);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const repoDir = environmentService.getActiveEnvironmentDir();
|
|
136
|
+
if (!exists(repoDir)) {
|
|
137
|
+
setMochiState('error');
|
|
138
|
+
setMessage(`Active environment directory does not exist: ${repoDir}`);
|
|
139
|
+
setScreenState('done');
|
|
140
|
+
setTimeout(() => handleExit(), 2000);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
setProgress(25);
|
|
144
|
+
// Verify git is installed and directory is git repo
|
|
145
|
+
try {
|
|
146
|
+
execFileSync('git', ['-C', repoDir, 'status'], { stdio: 'ignore' });
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// Initialize git repo if not already
|
|
150
|
+
try {
|
|
151
|
+
execFileSync('git', ['-C', repoDir, 'init'], { stdio: 'ignore' });
|
|
152
|
+
execFileSync('git', ['-C', repoDir, 'remote', 'add', 'origin', `https://github.com/${storage.repository}.git`], { stdio: 'ignore' });
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
setMochiState('error');
|
|
156
|
+
setMessage('Git is not installed or configured correctly in the environment directory.');
|
|
157
|
+
setScreenState('done');
|
|
158
|
+
setTimeout(() => handleExit(), 2000);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
setProgress(35);
|
|
163
|
+
// Read lockfile to count assets before sync
|
|
164
|
+
const beforeLock = await lockService.read('global');
|
|
165
|
+
const beforeSkills = beforeLock.assets.filter((a) => a.type === 'skill').length;
|
|
166
|
+
const beforePrompts = beforeLock.assets.filter((a) => a.type === 'prompt').length;
|
|
167
|
+
const beforeMcps = beforeLock.assets.filter((a) => a.type === 'mcp').length;
|
|
168
|
+
if (action === 'push') {
|
|
169
|
+
setMochiState('syncing');
|
|
170
|
+
setMessage(`Pushing to ${storage.repository}...`);
|
|
171
|
+
setProgress(50);
|
|
172
|
+
try {
|
|
173
|
+
execFileSync('git', ['-C', repoDir, 'add', '.'], { stdio: 'ignore' });
|
|
174
|
+
// Check if there is anything to commit
|
|
175
|
+
let hasChanges = true;
|
|
176
|
+
try {
|
|
177
|
+
execFileSync('git', ['-C', repoDir, 'diff', '--cached', '--quiet'], { stdio: 'ignore' });
|
|
178
|
+
hasChanges = false;
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// diff returns non-zero when there are changes, so this is expected
|
|
182
|
+
}
|
|
183
|
+
setProgress(65);
|
|
184
|
+
if (hasChanges) {
|
|
185
|
+
const timestamp = new Date().toISOString().replace('T', ' ').substring(0, 19);
|
|
186
|
+
execFileSync('git', ['-C', repoDir, 'commit', '-m', `Sync environment: ${timestamp}`], { stdio: 'ignore' });
|
|
187
|
+
}
|
|
188
|
+
setProgress(80);
|
|
189
|
+
// Push origin main/master
|
|
190
|
+
let pushSuccess = false;
|
|
191
|
+
let lastErr = null;
|
|
192
|
+
for (const branch of ['main', 'master']) {
|
|
193
|
+
try {
|
|
194
|
+
execFileSync('git', ['-C', repoDir, 'push', 'origin', branch], { stdio: 'pipe' });
|
|
195
|
+
pushSuccess = true;
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
lastErr = err;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (!pushSuccess) {
|
|
203
|
+
try {
|
|
204
|
+
execFileSync('git', ['-C', repoDir, 'push', '-u', 'origin', 'HEAD'], { stdio: 'pipe' });
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
throw lastErr || err;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
setProgress(100);
|
|
211
|
+
setMochiState('success');
|
|
212
|
+
setMessage(`Synced ${beforeMcps} MCP${beforeMcps !== 1 ? 's' : ''}, ${beforePrompts} prompt${beforePrompts !== 1 ? 's' : ''}, ${beforeSkills} skill${beforeSkills !== 1 ? 's' : ''}`);
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
throw new Error(parseGitError(err));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else if (action === 'pull') {
|
|
219
|
+
setMochiState('syncing');
|
|
220
|
+
setMessage(`Pulling from ${storage.repository}...`);
|
|
221
|
+
setProgress(50);
|
|
222
|
+
try {
|
|
223
|
+
let pullSuccess = false;
|
|
224
|
+
let lastErr = null;
|
|
225
|
+
for (const branch of ['main', 'master']) {
|
|
226
|
+
try {
|
|
227
|
+
execFileSync('git', ['-C', repoDir, 'pull', '--rebase', 'origin', branch], { stdio: 'pipe' });
|
|
228
|
+
pullSuccess = true;
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
lastErr = err;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
setProgress(80);
|
|
236
|
+
if (!pullSuccess) {
|
|
237
|
+
try {
|
|
238
|
+
execFileSync('git', ['-C', repoDir, 'pull', '--rebase', 'origin', 'HEAD'], { stdio: 'pipe' });
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
throw lastErr || err;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// Read lockfile again after pull
|
|
245
|
+
const afterLock = await lockService.read('global');
|
|
246
|
+
const afterSkills = afterLock.assets.filter((a) => a.type === 'skill').length;
|
|
247
|
+
const afterPrompts = afterLock.assets.filter((a) => a.type === 'prompt').length;
|
|
248
|
+
const afterMcps = afterLock.assets.filter((a) => a.type === 'mcp').length;
|
|
249
|
+
setProgress(100);
|
|
250
|
+
setMochiState('success');
|
|
251
|
+
setMessage(`Pulled ${afterMcps} MCP${afterMcps !== 1 ? 's' : ''}, ${afterPrompts} prompt${afterPrompts !== 1 ? 's' : ''}, ${afterSkills} skill${afterSkills !== 1 ? 's' : ''}`);
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
throw new Error(parseGitError(err));
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
setScreenState('done');
|
|
258
|
+
setTimeout(() => handleExit(), 1500);
|
|
259
|
+
}
|
|
260
|
+
catch (err) {
|
|
261
|
+
setProgress(0);
|
|
262
|
+
setMochiState('error');
|
|
263
|
+
setMessage(`Sync error: ${err.message}`);
|
|
264
|
+
setScreenState('done');
|
|
265
|
+
setTimeout(() => handleExit(), 2500);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (screenState === 'sync_loading') {
|
|
269
|
+
runSync();
|
|
270
|
+
}
|
|
271
|
+
}, [screenState, action, handleExit]);
|
|
272
|
+
if (screenState === 'checking') {
|
|
273
|
+
return (_jsx(Box, { paddingX: 1, height: rows, justifyContent: "center", alignItems: "center", children: _jsx(Narrator, { state: "searching", message: "Checking connection..." }) }));
|
|
274
|
+
}
|
|
275
|
+
if (screenState === 'not_connected_menu') {
|
|
276
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, height: rows, justifyContent: "space-between", children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, { compact: true }), _jsx(Text, { bold: true, color: theme.accent, children: "GitHub is not connected." }), _jsx(Box, { marginTop: 1, children: _jsx(CustomSelectInput, { items: [
|
|
277
|
+
{ label: 'Connect GitHub', value: 'connect' },
|
|
278
|
+
{ label: 'Use Local Storage Only', value: 'local' },
|
|
279
|
+
{ label: 'Back', value: 'back' },
|
|
280
|
+
], onSelect: async (item) => {
|
|
281
|
+
if (item.value === 'connect') {
|
|
282
|
+
if (!environmentService.isGithubCliAvailable()) {
|
|
283
|
+
setScreenState('gh_cli_required');
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
setScreenState('mode_select');
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
else if (item.value === 'local') {
|
|
290
|
+
setScreenState('local_storage_info');
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
handleExit();
|
|
294
|
+
}
|
|
295
|
+
} }) })] }), _jsx(Box, { children: _jsx(Text, { color: theme.dim, children: "press enter to select \u00B7 esc exit" }) })] }));
|
|
296
|
+
}
|
|
297
|
+
if (screenState === 'gh_cli_required') {
|
|
298
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, height: rows, justifyContent: "space-between", children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, { compact: true }), _jsx(Text, { bold: true, color: theme.error, children: "GitHub CLI is required." }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { children: "Please install it via https://cli.github.com or using your package manager:" }) }), _jsxs(Box, { flexDirection: "column", marginTop: 1, marginLeft: 2, children: [_jsx(Text, { color: theme.secondary, children: "\u2022 Windows: winget install GitHub.cli" }), _jsx(Text, { color: theme.secondary, children: "\u2022 macOS: brew install gh" }), _jsx(Text, { color: theme.secondary, children: "\u2022 Linux: sudo apt install gh" })] }), _jsx(Box, { marginTop: 1, children: _jsx(CustomSelectInput, { items: [
|
|
299
|
+
{ label: 'Continue With Local Storage', value: 'local' },
|
|
300
|
+
{ label: 'Back', value: 'back' },
|
|
301
|
+
], onSelect: async (item) => {
|
|
302
|
+
if (item.value === 'local') {
|
|
303
|
+
setScreenState('setup_loading');
|
|
304
|
+
setSetupState('installing');
|
|
305
|
+
setSetupMessage('Configuring local folder...');
|
|
306
|
+
try {
|
|
307
|
+
await environmentService.initLocal({});
|
|
308
|
+
setSetupState('success');
|
|
309
|
+
setSetupMessage('Local environment initialized!');
|
|
310
|
+
setTimeout(() => {
|
|
311
|
+
setScreenState('local_storage_info');
|
|
312
|
+
}, 1200);
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
setSetupState('error');
|
|
316
|
+
setSetupMessage(`Setup failed: ${err.message}`);
|
|
317
|
+
setTimeout(() => {
|
|
318
|
+
handleExit();
|
|
319
|
+
}, 2500);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
setScreenState('not_connected_menu');
|
|
324
|
+
}
|
|
325
|
+
} }) })] }), _jsx(Box, { children: _jsx(Text, { color: theme.dim, children: "press enter to select" }) })] }));
|
|
326
|
+
}
|
|
327
|
+
if (screenState === 'mode_select') {
|
|
328
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, height: rows, justifyContent: "space-between", children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, { compact: true }), _jsx(Text, { bold: true, color: theme.accent, children: "Connect GitHub" }), _jsx(Box, { marginTop: 1, children: _jsx(CustomSelectInput, { items: [
|
|
329
|
+
{ label: 'Create New Repository', value: 'create' },
|
|
330
|
+
{ label: 'Use Existing Repository', value: 'existing' },
|
|
331
|
+
], onSelect: (item) => {
|
|
332
|
+
setGithubMode(item.value);
|
|
333
|
+
setScreenState('repo_input');
|
|
334
|
+
} }) })] }), _jsx(Box, { children: _jsx(Text, { color: theme.dim, children: "press enter to select \u00B7 esc go back" }) })] }));
|
|
335
|
+
}
|
|
336
|
+
if (screenState === 'repo_input') {
|
|
337
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, height: rows, justifyContent: "space-between", children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, { compact: true }), _jsx(Text, { bold: true, color: theme.accent, children: githubMode === 'existing' ? 'Which GitHub repo should aman use?' : 'Name your aman GitHub repo.' }), _jsxs(Box, { marginTop: 1, flexDirection: "row", children: [_jsx(Text, { color: theme.primary, children: "Repository Name: " }), _jsx(TextInput, { value: repoName, onChange: (val) => {
|
|
338
|
+
setRepoName(val);
|
|
339
|
+
setRepoError(undefined);
|
|
340
|
+
}, placeholder: githubMode === 'existing' ? 'github-user/repo' : 'aman-environment', onSubmit: async (val) => {
|
|
341
|
+
const trimmed = val.trim();
|
|
342
|
+
if (!trimmed) {
|
|
343
|
+
setRepoError('Enter a repository name to continue.');
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
await handleSetupAndSync(trimmed);
|
|
347
|
+
} })] }), repoError && _jsx(Text, { color: theme.error, children: repoError })] }), _jsx(Box, { children: _jsx(Text, { color: theme.dim, children: "press enter to submit \u00B7 esc go back" }) })] }));
|
|
348
|
+
}
|
|
349
|
+
if (screenState === 'setup_loading') {
|
|
350
|
+
return (_jsx(Box, { flexDirection: "column", paddingX: 1, height: rows, justifyContent: "space-between", children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Header, { compact: true }), _jsx(Narrator, { state: setupState, message: setupMessage })] }) }));
|
|
351
|
+
}
|
|
352
|
+
if (screenState === 'local_storage_info') {
|
|
353
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, height: rows, justifyContent: "space-between", children: [_jsxs(Box, { flexDirection: "column", children: [_jsx(Header, { compact: true }), _jsx(Text, { color: theme.warning, children: "Local storage does not support cloud sync." }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.dim, children: "Please connect a GitHub repository to enable push/pull workflows." }) })] }), _jsx(Box, { children: _jsx(Text, { color: theme.dim, children: "press esc or q to exit" }) })] }));
|
|
354
|
+
}
|
|
355
|
+
if (screenState === 'sync_loading') {
|
|
356
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, height: rows, children: [_jsx(Header, { compact: true }), _jsx(Narrator, { state: mochiState, message: message }), _jsx(Box, { marginTop: 1, children: _jsx(ProgressBar, { progress: progress }) })] }));
|
|
357
|
+
}
|
|
358
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, height: rows, children: [_jsx(Header, { compact: true }), _jsx(Narrator, { state: mochiState, message: message })] }));
|
|
359
|
+
};
|
|
360
|
+
export async function syncCommand(args) {
|
|
361
|
+
const action = args[0];
|
|
362
|
+
if (action !== 'push' && action !== 'pull') {
|
|
363
|
+
console.log(' Usage: aman sync <push|pull>');
|
|
364
|
+
process.exit(1);
|
|
365
|
+
}
|
|
366
|
+
if (!process.stdin.isTTY) {
|
|
367
|
+
console.log(` ◌ Non-interactive mode: executing sync ${action}...`);
|
|
368
|
+
try {
|
|
369
|
+
const storage = environmentService.getStorage();
|
|
370
|
+
if (storage.type !== 'github' || !storage.repository) {
|
|
371
|
+
console.log(' ✗ Sync error: No GitHub storage configured. Run "aman init" first.');
|
|
372
|
+
process.exit(1);
|
|
373
|
+
}
|
|
374
|
+
const repoDir = environmentService.getActiveEnvironmentDir();
|
|
375
|
+
if (action === 'push') {
|
|
376
|
+
execFileSync('git', ['-C', repoDir, 'add', '.'], { stdio: 'ignore' });
|
|
377
|
+
try {
|
|
378
|
+
execFileSync('git', ['-C', repoDir, 'diff', '--cached', '--quiet'], { stdio: 'ignore' });
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
const timestamp = new Date().toISOString().replace('T', ' ').substring(0, 19);
|
|
382
|
+
execFileSync('git', ['-C', repoDir, 'commit', '-m', `Sync environment: ${timestamp}`], { stdio: 'ignore' });
|
|
383
|
+
}
|
|
384
|
+
let pushSuccess = false;
|
|
385
|
+
let lastErr = null;
|
|
386
|
+
for (const branch of ['main', 'master']) {
|
|
387
|
+
try {
|
|
388
|
+
execFileSync('git', ['-C', repoDir, 'push', 'origin', branch], { stdio: 'pipe' });
|
|
389
|
+
pushSuccess = true;
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
catch (err) {
|
|
393
|
+
lastErr = err;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (!pushSuccess && lastErr) {
|
|
397
|
+
throw lastErr;
|
|
398
|
+
}
|
|
399
|
+
console.log(` ✓ Synced environment to ${storage.repository}`);
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
let pullSuccess = false;
|
|
403
|
+
let lastErr = null;
|
|
404
|
+
for (const branch of ['main', 'master']) {
|
|
405
|
+
try {
|
|
406
|
+
execFileSync('git', ['-C', repoDir, 'pull', '--rebase', 'origin', branch], { stdio: 'pipe' });
|
|
407
|
+
pullSuccess = true;
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
catch (err) {
|
|
411
|
+
lastErr = err;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if (!pullSuccess && lastErr) {
|
|
415
|
+
throw lastErr;
|
|
416
|
+
}
|
|
417
|
+
console.log(` ✓ Pulled environment changes from ${storage.repository}`);
|
|
418
|
+
}
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
catch (err) {
|
|
422
|
+
console.log(` ✗ Sync error: ${parseGitError(err)}`);
|
|
423
|
+
process.exit(1);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
const { waitUntilExit } = render(_jsx(TransitionScreen, { message: `Starting repository sync (${action})...`, children: _jsx(SyncApp, { action: action }) }));
|
|
427
|
+
await waitUntilExit();
|
|
428
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function updateCommand(args: string[], options?: any): Promise<void>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { render, Box, Text, useApp } from 'ink';
|
|
4
|
+
import { assetService } from '../services/asset.service.js';
|
|
5
|
+
import { lockService } from '../services/lock.service.js';
|
|
6
|
+
import { marketplaceService } from '../services/marketplace.service.js';
|
|
7
|
+
import { Header } from '../ui/components/Header.js';
|
|
8
|
+
import { theme } from '../ui/theme.js';
|
|
9
|
+
import { titleize } from '../ui/marketplaceDisplay.js';
|
|
10
|
+
import { Spinner } from '../ui/animations/Spinner.js';
|
|
11
|
+
import { TransitionScreen } from '../ui/animations/TransitionScreen.js';
|
|
12
|
+
import { installFromCandidate } from '../marketplace/install-from-candidate.js';
|
|
13
|
+
const UpdateApp = ({ names, scope }) => {
|
|
14
|
+
const { exit } = useApp();
|
|
15
|
+
const [results, setResults] = useState([]);
|
|
16
|
+
const [current, setCurrent] = useState('');
|
|
17
|
+
const [done, setDone] = useState(false);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
async function doUpdate() {
|
|
20
|
+
const updateResults = [];
|
|
21
|
+
for (const name of names) {
|
|
22
|
+
setCurrent(name);
|
|
23
|
+
const candidate = await marketplaceService.findInstallCandidate(name);
|
|
24
|
+
if (!candidate) {
|
|
25
|
+
updateResults.push({ name, success: false });
|
|
26
|
+
setResults([...updateResults]);
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
await assetService.install(candidate.name, candidate.type, scope, candidate.sourcePath, candidate.source);
|
|
31
|
+
updateResults.push({ name, success: true });
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
updateResults.push({ name, success: false });
|
|
35
|
+
}
|
|
36
|
+
setResults([...updateResults]);
|
|
37
|
+
}
|
|
38
|
+
setDone(true);
|
|
39
|
+
setTimeout(() => exit(), 1000);
|
|
40
|
+
}
|
|
41
|
+
doUpdate();
|
|
42
|
+
}, [exit, names, scope]);
|
|
43
|
+
const passed = results.filter((r) => r.success).length;
|
|
44
|
+
const failed = results.filter((r) => !r.success).length;
|
|
45
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Header, { compact: true }), results.map((r) => (_jsxs(Text, { children: [_jsxs(Text, { color: r.success ? theme.success : theme.error, bold: true, children: [r.success ? '✓' : '✗', ' '] }), _jsx(Text, { children: titleize(r.name) }), !r.success && _jsx(Text, { color: theme.dim, children: " (source not found)" })] }, r.name))), !done && current && (_jsx(Spinner, { label: `Updating ${titleize(current)}...` })), done && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: theme.dim, children: ["Updated ", passed, failed > 0 ? `, failed ${failed}` : ''] }) }))] }));
|
|
46
|
+
};
|
|
47
|
+
async function installedNames(scope) {
|
|
48
|
+
const lockfile = await lockService.read(scope);
|
|
49
|
+
return lockfile.assets.map((entry) => entry.localName);
|
|
50
|
+
}
|
|
51
|
+
export async function updateCommand(args, options = {}) {
|
|
52
|
+
const scope = options.project || options.p ? 'project' : 'global';
|
|
53
|
+
const specificName = args.find((arg) => !arg.startsWith('--'));
|
|
54
|
+
let names;
|
|
55
|
+
if (specificName) {
|
|
56
|
+
names = [specificName];
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// No name = update all
|
|
60
|
+
names = await installedNames(scope);
|
|
61
|
+
if (names.length === 0) {
|
|
62
|
+
console.log(` No installed items in ${scope}.`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
67
|
+
let passed = 0;
|
|
68
|
+
let failed = 0;
|
|
69
|
+
for (const name of names) {
|
|
70
|
+
const candidate = await marketplaceService.findInstallCandidate(name);
|
|
71
|
+
if (!candidate) {
|
|
72
|
+
console.log(` ✗ ${titleize(name)} (not found)`);
|
|
73
|
+
failed++;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
if (candidate.marketplaceAsset) {
|
|
78
|
+
await installFromCandidate(candidate, scope);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
await assetService.install(candidate.name, candidate.type, scope, candidate.sourcePath, candidate.source);
|
|
82
|
+
}
|
|
83
|
+
console.log(` ✓ ${titleize(name)}`);
|
|
84
|
+
passed++;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
console.log(` ✗ ${titleize(name)}`);
|
|
88
|
+
failed++;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
console.log(`\n Updated ${passed}${failed > 0 ? `, failed ${failed}` : ''}\n`);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
console.log(` Updating ${names.length} item${names.length !== 1 ? 's' : ''}...\n`);
|
|
95
|
+
const { waitUntilExit } = render(_jsx(TransitionScreen, { message: "Scanning for updates...", children: _jsx(UpdateApp, { names: names, scope: scope }) }));
|
|
96
|
+
await waitUntilExit();
|
|
97
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AmanConfig } from '../types/index.js';
|
|
2
|
+
declare class ConfigManager {
|
|
3
|
+
private globalConf;
|
|
4
|
+
constructor();
|
|
5
|
+
load(): AmanConfig;
|
|
6
|
+
get<K extends keyof AmanConfig>(key: K): AmanConfig[K];
|
|
7
|
+
set<K extends keyof AmanConfig>(key: K, value: AmanConfig[K]): void;
|
|
8
|
+
reset(): void;
|
|
9
|
+
getTheme(): 'dark' | 'light';
|
|
10
|
+
onDidChange<K extends keyof AmanConfig>(key: K, callback: (value?: AmanConfig[K]) => void): () => void;
|
|
11
|
+
}
|
|
12
|
+
export declare const config: ConfigManager;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import Conf from 'conf';
|
|
3
|
+
import { GLOBAL_CONFIG_DIR } from './paths.js';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
const defaultConfig = {
|
|
6
|
+
theme: 'auto',
|
|
7
|
+
defaultScope: 'global',
|
|
8
|
+
environmentPath: undefined,
|
|
9
|
+
storage: undefined,
|
|
10
|
+
marketplaces: ['skills.sh'],
|
|
11
|
+
animationMode: 'normal',
|
|
12
|
+
};
|
|
13
|
+
class ConfigManager {
|
|
14
|
+
globalConf;
|
|
15
|
+
constructor() {
|
|
16
|
+
try {
|
|
17
|
+
this.globalConf = new Conf({
|
|
18
|
+
projectName: 'aman',
|
|
19
|
+
cwd: GLOBAL_CONFIG_DIR,
|
|
20
|
+
configName: 'aman',
|
|
21
|
+
defaults: defaultConfig,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
const configPath = path.join(GLOBAL_CONFIG_DIR, 'aman.json');
|
|
26
|
+
if (fs.existsSync(configPath)) {
|
|
27
|
+
const timestamp = new Date().toISOString().slice(0, 10);
|
|
28
|
+
const backupPath = path.join(GLOBAL_CONFIG_DIR, `aman.json.corrupted-${timestamp}`);
|
|
29
|
+
try {
|
|
30
|
+
fs.renameSync(configPath, backupPath);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Ignore
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
console.error('\n \x1b[31;1mConfiguration file was corrupted.\x1b[0m');
|
|
37
|
+
console.error(' \x1b[33mA backup was created.\x1b[0m');
|
|
38
|
+
console.error(' \x1b[32mDefaults have been restored.\x1b[0m\n');
|
|
39
|
+
this.globalConf = new Conf({
|
|
40
|
+
projectName: 'aman',
|
|
41
|
+
cwd: GLOBAL_CONFIG_DIR,
|
|
42
|
+
configName: 'aman',
|
|
43
|
+
defaults: defaultConfig,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
load() {
|
|
48
|
+
return this.globalConf.store;
|
|
49
|
+
}
|
|
50
|
+
get(key) {
|
|
51
|
+
return this.globalConf.get(key);
|
|
52
|
+
}
|
|
53
|
+
set(key, value) {
|
|
54
|
+
this.globalConf.set(key, value);
|
|
55
|
+
}
|
|
56
|
+
reset() {
|
|
57
|
+
this.globalConf.clear();
|
|
58
|
+
this.globalConf.store = defaultConfig;
|
|
59
|
+
}
|
|
60
|
+
getTheme() {
|
|
61
|
+
const theme = this.get('theme');
|
|
62
|
+
if (theme === 'auto') {
|
|
63
|
+
const colorfgbg = process.env.COLORFGBG;
|
|
64
|
+
if (colorfgbg) {
|
|
65
|
+
const parts = colorfgbg.split(';');
|
|
66
|
+
const bg = parts[parts.length - 1];
|
|
67
|
+
const bgNum = parseInt(bg, 10);
|
|
68
|
+
if (!isNaN(bgNum)) {
|
|
69
|
+
return bgNum >= 7 && bgNum !== 8 ? 'light' : 'dark';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return 'dark';
|
|
73
|
+
}
|
|
74
|
+
return theme;
|
|
75
|
+
}
|
|
76
|
+
onDidChange(key, callback) {
|
|
77
|
+
return this.globalConf.onDidChange(key, callback);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
export const config = new ConfigManager();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const GLOBAL_DIR: string;
|
|
2
|
+
export declare const GLOBAL_SKILLS: string;
|
|
3
|
+
export declare const GLOBAL_PROMPTS: string;
|
|
4
|
+
export declare const GLOBAL_MCPS: string;
|
|
5
|
+
export declare const GLOBAL_STACKS: string;
|
|
6
|
+
export declare const GLOBAL_CACHE: string;
|
|
7
|
+
export declare const GLOBAL_BACKUPS: string;
|
|
8
|
+
export declare const GLOBAL_REGISTRY_DIR: string;
|
|
9
|
+
export declare const GLOBAL_CONFIG_DIR: string;
|
|
10
|
+
export declare const GLOBAL_CONFIG_FILE: string;
|
|
11
|
+
export declare const LOCAL_DIR = ".aman";
|
|
12
|
+
export declare const LOCAL_CONFIG_FILE: string;
|
|
13
|
+
export declare const LOCAL_LOCKFILE: string;
|
|
14
|
+
export declare const PROJECT_ROOT: string;
|
|
15
|
+
export declare const BUNDLED_SKILLS: string;
|
|
16
|
+
export declare const BUNDLED_PROMPTS: string;
|
|
17
|
+
export declare const BUNDLED_MCPS: string;
|
|
18
|
+
/**
|
|
19
|
+
* Creates all `~/.aman/` subdirectories.
|
|
20
|
+
* This is used during setup and doctor checks.
|
|
21
|
+
*/
|
|
22
|
+
export declare function ensureGlobalDirs(): Promise<void>;
|
|
23
|
+
export declare function ensureProjectDirs(): Promise<void>;
|