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,259 @@
|
|
|
1
|
+
import os from 'os';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { promises as fs } from 'fs';
|
|
4
|
+
import { exists, ensureDir, readJson, writeJson, removeDir, copyDir } from '../storage/filesystem.js';
|
|
5
|
+
import { assetService } from '../services/asset.service.js';
|
|
6
|
+
import { environmentService } from '../services/environment.service.js';
|
|
7
|
+
import { codexBlockToMcpJson, extractMcpServerMap, parseCodexMcpBlocks, slugifyImportName, } from './utils.js';
|
|
8
|
+
function buildProvenanceSource(adapterId, originLabel) {
|
|
9
|
+
return `import:${adapterId}:${originLabel}`;
|
|
10
|
+
}
|
|
11
|
+
export function isGithubDestinationAvailable() {
|
|
12
|
+
const storage = environmentService.getStorage();
|
|
13
|
+
return storage.type === 'github' && Boolean(storage.repository);
|
|
14
|
+
}
|
|
15
|
+
export async function detectImportConflicts(items, scope) {
|
|
16
|
+
const conflicts = [];
|
|
17
|
+
for (const item of items) {
|
|
18
|
+
const existing = await assetService.list(item.type, scope);
|
|
19
|
+
const match = existing.find((e) => e.name === item.name);
|
|
20
|
+
if (match) {
|
|
21
|
+
conflicts.push({
|
|
22
|
+
asset: item,
|
|
23
|
+
existingLocalName: match.name,
|
|
24
|
+
resolution: 'skip',
|
|
25
|
+
resolvedName: item.name,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return conflicts;
|
|
30
|
+
}
|
|
31
|
+
async function stageMcpAsset(item, stagingRoot) {
|
|
32
|
+
const dest = path.join(stagingRoot, item.id);
|
|
33
|
+
await ensureDir(dest);
|
|
34
|
+
if (item.adapterId === 'codex' && item.mcpServerName && item.sourcePath.endsWith('.toml')) {
|
|
35
|
+
const text = await fs.readFile(item.sourcePath, 'utf-8');
|
|
36
|
+
const block = parseCodexMcpBlocks(text).find((b) => b.name === item.mcpServerName);
|
|
37
|
+
if (!block)
|
|
38
|
+
throw new Error(`Codex MCP block not found: ${item.mcpServerName}`);
|
|
39
|
+
const mcpJson = codexBlockToMcpJson(block);
|
|
40
|
+
await writeJson(path.join(dest, 'mcp.json'), mcpJson);
|
|
41
|
+
await separateMcpSecrets(dest);
|
|
42
|
+
return dest;
|
|
43
|
+
}
|
|
44
|
+
if (item.mcpServerName) {
|
|
45
|
+
const raw = await readJson(item.sourcePath);
|
|
46
|
+
if (!raw)
|
|
47
|
+
throw new Error(`Invalid MCP config: ${item.sourcePath}`);
|
|
48
|
+
const servers = extractMcpServerMap(raw);
|
|
49
|
+
const serverConfig = servers[item.mcpServerName];
|
|
50
|
+
if (!serverConfig)
|
|
51
|
+
throw new Error(`MCP server "${item.mcpServerName}" not found in ${item.sourcePath}`);
|
|
52
|
+
await writeJson(path.join(dest, 'mcp.json'), { mcpServers: { [item.mcpServerName]: serverConfig } });
|
|
53
|
+
await separateMcpSecrets(dest);
|
|
54
|
+
return dest;
|
|
55
|
+
}
|
|
56
|
+
if (exists(path.join(item.sourcePath, 'mcp.json'))) {
|
|
57
|
+
await copyDir(item.sourcePath, dest);
|
|
58
|
+
await separateMcpSecrets(dest);
|
|
59
|
+
return dest;
|
|
60
|
+
}
|
|
61
|
+
if (item.sourcePath.endsWith('.json') && exists(item.sourcePath)) {
|
|
62
|
+
const raw = await readJson(item.sourcePath);
|
|
63
|
+
if (raw && extractMcpServerMap(raw)) {
|
|
64
|
+
await writeJson(path.join(dest, 'mcp.json'), raw.mcpServers ? raw : { mcpServers: extractMcpServerMap(raw) });
|
|
65
|
+
await separateMcpSecrets(dest);
|
|
66
|
+
return dest;
|
|
67
|
+
}
|
|
68
|
+
await fs.copyFile(item.sourcePath, path.join(dest, 'mcp.json'));
|
|
69
|
+
await separateMcpSecrets(dest);
|
|
70
|
+
return dest;
|
|
71
|
+
}
|
|
72
|
+
throw new Error(`Cannot stage MCP from ${item.originLabel}`);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Separate machine-specific secrets from portable mcp.json.
|
|
76
|
+
* Reads env vars, moves actual values to mcp.local.json,
|
|
77
|
+
* replaces them with placeholders in mcp.json.
|
|
78
|
+
*/
|
|
79
|
+
async function separateMcpSecrets(assetDir) {
|
|
80
|
+
const mcpPath = path.join(assetDir, 'mcp.json');
|
|
81
|
+
const localPath = path.join(assetDir, 'mcp.local.json');
|
|
82
|
+
if (!exists(mcpPath) || exists(localPath))
|
|
83
|
+
return;
|
|
84
|
+
const mcpData = await readJson(mcpPath);
|
|
85
|
+
if (!mcpData)
|
|
86
|
+
return;
|
|
87
|
+
const localValues = {};
|
|
88
|
+
let modified = false;
|
|
89
|
+
// Walk mcpServers.*.env to find non-placeholder values
|
|
90
|
+
const mcpServers = mcpData.mcpServers;
|
|
91
|
+
if (mcpServers && typeof mcpServers === 'object') {
|
|
92
|
+
for (const [, serverCfg] of Object.entries(mcpServers)) {
|
|
93
|
+
if (!serverCfg || typeof serverCfg !== 'object')
|
|
94
|
+
continue;
|
|
95
|
+
const env = serverCfg.env;
|
|
96
|
+
if (!env || typeof env !== 'object' || Array.isArray(env))
|
|
97
|
+
continue;
|
|
98
|
+
for (const [key, value] of Object.entries(env)) {
|
|
99
|
+
if (typeof value !== 'string')
|
|
100
|
+
continue;
|
|
101
|
+
// Detect actual secret values (not already placeholders)
|
|
102
|
+
const isPlaceholder = /^\$\{[A-Z0-9_]+\}$|^\{\{[A-Z0-9_]+\}\}$|^\$[A-Z][A-Z0-9_]*$/.test(value.trim());
|
|
103
|
+
const isEmpty = value.trim() === '';
|
|
104
|
+
if (!isPlaceholder && !isEmpty && looksLikeSecret(key, value)) {
|
|
105
|
+
localValues[key] = value;
|
|
106
|
+
env[key] = `\${${key}}`;
|
|
107
|
+
modified = true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (modified) {
|
|
113
|
+
await writeJson(mcpPath, mcpData);
|
|
114
|
+
await writeJson(localPath, {
|
|
115
|
+
_comment: 'Fill in local values for this MCP. This file is gitignored and never synced.',
|
|
116
|
+
...localValues,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/** Heuristic: keys named token, key, secret, password, auth etc. with non-trivial values. */
|
|
121
|
+
function looksLikeSecret(key, value) {
|
|
122
|
+
const secretish = /token|key|secret|password|auth|credential|api.?key/i;
|
|
123
|
+
if (secretish.test(key))
|
|
124
|
+
return true;
|
|
125
|
+
// Long opaque strings (API keys, tokens) — 20+ chars, no spaces
|
|
126
|
+
if (value.length >= 20 && !/\s/.test(value) && /[a-zA-Z0-9\-_]/.test(value))
|
|
127
|
+
return true;
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
async function stageAssetSource(item, stagingRoot) {
|
|
131
|
+
if (item.type === 'mcp') {
|
|
132
|
+
return stageMcpAsset(item, stagingRoot);
|
|
133
|
+
}
|
|
134
|
+
if (item.type === 'skill') {
|
|
135
|
+
// Canonical skill directory (has SKILL.md)
|
|
136
|
+
if (exists(path.join(item.sourcePath, 'SKILL.md'))) {
|
|
137
|
+
const dest = path.join(stagingRoot, item.id);
|
|
138
|
+
await copyDir(item.sourcePath, dest);
|
|
139
|
+
return dest;
|
|
140
|
+
}
|
|
141
|
+
// Single rule file (.md, .mdc) → convert to SKILL.md
|
|
142
|
+
if ((item.sourcePath.endsWith('.md') || item.sourcePath.endsWith('.mdc')) && exists(item.sourcePath)) {
|
|
143
|
+
const dest = path.join(stagingRoot, item.id);
|
|
144
|
+
await ensureDir(dest);
|
|
145
|
+
await fs.copyFile(item.sourcePath, path.join(dest, 'SKILL.md'));
|
|
146
|
+
return dest;
|
|
147
|
+
}
|
|
148
|
+
throw new Error(`Invalid skill source: ${item.sourcePath}`);
|
|
149
|
+
}
|
|
150
|
+
if (item.type === 'prompt') {
|
|
151
|
+
const dest = path.join(stagingRoot, item.id);
|
|
152
|
+
await ensureDir(dest);
|
|
153
|
+
if (exists(path.join(item.sourcePath, 'PROMPT.md'))) {
|
|
154
|
+
await copyDir(item.sourcePath, dest);
|
|
155
|
+
return dest;
|
|
156
|
+
}
|
|
157
|
+
if ((item.sourcePath.endsWith('.md') || item.sourcePath.endsWith('.prompt')) && exists(item.sourcePath)) {
|
|
158
|
+
await fs.copyFile(item.sourcePath, path.join(dest, 'PROMPT.md'));
|
|
159
|
+
return dest;
|
|
160
|
+
}
|
|
161
|
+
throw new Error(`Invalid prompt source: ${item.sourcePath}`);
|
|
162
|
+
}
|
|
163
|
+
throw new Error(`Unsupported asset type: ${item.type}`);
|
|
164
|
+
}
|
|
165
|
+
export async function executeImportPlan(plan) {
|
|
166
|
+
if (plan.destination === 'github' && !isGithubDestinationAvailable()) {
|
|
167
|
+
throw new Error('GitHub is not configured. Run `aman init --github` or connect GitHub first.');
|
|
168
|
+
}
|
|
169
|
+
if (!environmentService.isEnvironmentInitialized(plan.scope)) {
|
|
170
|
+
throw new Error('Environment not initialized. Run `aman init --local` first.');
|
|
171
|
+
}
|
|
172
|
+
const stagingRoot = path.join(os.tmpdir(), `aman-import-exec-${Date.now()}`);
|
|
173
|
+
await ensureDir(stagingRoot);
|
|
174
|
+
const result = {
|
|
175
|
+
imported: 0,
|
|
176
|
+
skipped: 0,
|
|
177
|
+
renamed: 0,
|
|
178
|
+
overwritten: 0,
|
|
179
|
+
errors: [],
|
|
180
|
+
};
|
|
181
|
+
const installed = [];
|
|
182
|
+
try {
|
|
183
|
+
for (const item of plan.items) {
|
|
184
|
+
const conflict = plan.conflicts.find((c) => c.asset.id === item.id);
|
|
185
|
+
if (conflict?.resolution === 'skip') {
|
|
186
|
+
result.skipped++;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
let localName = item.name;
|
|
190
|
+
if (conflict?.resolution === 'rename') {
|
|
191
|
+
localName = conflict.resolvedName;
|
|
192
|
+
if (localName !== item.name)
|
|
193
|
+
result.renamed++;
|
|
194
|
+
}
|
|
195
|
+
else if (conflict?.resolution === 'overwrite') {
|
|
196
|
+
await assetService.remove(conflict.existingLocalName, item.type, plan.scope);
|
|
197
|
+
localName = conflict.existingLocalName;
|
|
198
|
+
result.overwritten++;
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
const stagedPath = await stageAssetSource(item, stagingRoot);
|
|
202
|
+
const provenanceRef = buildProvenanceSource(plan.sourceId, item.originLabel);
|
|
203
|
+
const installedAt = new Date().toISOString();
|
|
204
|
+
const provenance = item.provenance ?? {
|
|
205
|
+
tool: plan.sourceId,
|
|
206
|
+
sourcePath: item.sourcePath,
|
|
207
|
+
importedAt: installedAt,
|
|
208
|
+
};
|
|
209
|
+
await assetService.install(localName, item.type, plan.scope, stagedPath, provenanceRef, {
|
|
210
|
+
description: item.description,
|
|
211
|
+
originalName: item.name !== localName ? item.name : undefined,
|
|
212
|
+
tags: [`imported-from-${plan.sourceId}`],
|
|
213
|
+
installedAt,
|
|
214
|
+
provenance,
|
|
215
|
+
});
|
|
216
|
+
installed.push({ type: item.type, name: localName, scope: plan.scope });
|
|
217
|
+
result.imported++;
|
|
218
|
+
}
|
|
219
|
+
catch (err) {
|
|
220
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
221
|
+
result.errors.push(`${item.type}/${item.name}: ${msg}`);
|
|
222
|
+
throw new Error(`Import failed at ${item.name}: ${msg}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
for (const entry of [...installed].reverse()) {
|
|
228
|
+
await assetService.remove(entry.name, entry.type, entry.scope).catch(() => { });
|
|
229
|
+
}
|
|
230
|
+
throw err;
|
|
231
|
+
}
|
|
232
|
+
finally {
|
|
233
|
+
await removeDir(stagingRoot).catch(() => { });
|
|
234
|
+
}
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
export function applyAutoRenameConflicts(conflicts, mode = 'suffix') {
|
|
238
|
+
return conflicts.map((c) => {
|
|
239
|
+
if (mode === 'skip')
|
|
240
|
+
return c;
|
|
241
|
+
let suffix = 1;
|
|
242
|
+
let candidate = `${c.asset.name}-imported`;
|
|
243
|
+
while (candidate === c.existingLocalName) {
|
|
244
|
+
candidate = `${c.asset.name}-imported-${suffix++}`;
|
|
245
|
+
}
|
|
246
|
+
return {
|
|
247
|
+
...c,
|
|
248
|
+
resolution: 'rename',
|
|
249
|
+
resolvedName: slugifyImportName(candidate),
|
|
250
|
+
};
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
export function summarizeByType(items) {
|
|
254
|
+
return {
|
|
255
|
+
skill: items.filter((i) => i.type === 'skill').length,
|
|
256
|
+
prompt: items.filter((i) => i.type === 'prompt').length,
|
|
257
|
+
mcp: items.filter((i) => i.type === 'mcp').length,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { AssetType, Scope } from '../types/index.js';
|
|
2
|
+
export type ImportSourceId = 'claude-code' | 'cursor' | 'windsurf' | 'continue' | 'vscode' | 'github-copilot' | 'codex' | 'local-folder' | 'custom-path' | 'aman-environment' | 'antigravity';
|
|
3
|
+
export type ImportCanonicalStatus = 'canonical' | 'convertible' | 'ambiguous' | 'unknown';
|
|
4
|
+
export type ImportDestination = 'local' | 'github';
|
|
5
|
+
export type TypeSelectionMode = 'all' | 'select' | 'skip';
|
|
6
|
+
export type ConflictResolution = 'skip' | 'rename' | 'overwrite';
|
|
7
|
+
export type ConflictBulkMode = 'ask' | 'rename-all' | 'skip-all' | 'replace-all';
|
|
8
|
+
export interface ImportProvenance {
|
|
9
|
+
tool: string;
|
|
10
|
+
sourcePath: string;
|
|
11
|
+
importedAt: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ImportAdapterDescriptor {
|
|
14
|
+
id: ImportSourceId;
|
|
15
|
+
label: string;
|
|
16
|
+
description: string;
|
|
17
|
+
available: boolean;
|
|
18
|
+
unavailableReason?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface DiscoveredImportAsset {
|
|
21
|
+
/** Stable id within a scan result */
|
|
22
|
+
id: string;
|
|
23
|
+
type: AssetType;
|
|
24
|
+
name: string;
|
|
25
|
+
description: string;
|
|
26
|
+
sourcePath: string;
|
|
27
|
+
originLabel: string;
|
|
28
|
+
canonicalStatus: ImportCanonicalStatus;
|
|
29
|
+
canonicalNote?: string;
|
|
30
|
+
confidence: number;
|
|
31
|
+
adapterId: ImportSourceId;
|
|
32
|
+
/** When sourcePath is a multi-server MCP config, the server key to extract */
|
|
33
|
+
mcpServerName?: string;
|
|
34
|
+
/** Provenance tracking for imported assets */
|
|
35
|
+
provenance?: ImportProvenance;
|
|
36
|
+
}
|
|
37
|
+
export interface TypeImportSelection {
|
|
38
|
+
mode: TypeSelectionMode;
|
|
39
|
+
selectedIds: Set<string>;
|
|
40
|
+
}
|
|
41
|
+
export interface ImportConflict {
|
|
42
|
+
asset: DiscoveredImportAsset;
|
|
43
|
+
existingLocalName: string;
|
|
44
|
+
resolution: ConflictResolution;
|
|
45
|
+
resolvedName: string;
|
|
46
|
+
}
|
|
47
|
+
export interface ImportPlan {
|
|
48
|
+
sourceId: ImportSourceId;
|
|
49
|
+
sourceLabel: string;
|
|
50
|
+
destination: ImportDestination;
|
|
51
|
+
scope: Scope;
|
|
52
|
+
items: DiscoveredImportAsset[];
|
|
53
|
+
conflicts: ImportConflict[];
|
|
54
|
+
}
|
|
55
|
+
export interface ImportResult {
|
|
56
|
+
imported: number;
|
|
57
|
+
skipped: number;
|
|
58
|
+
renamed: number;
|
|
59
|
+
overwritten: number;
|
|
60
|
+
errors: string[];
|
|
61
|
+
}
|
|
62
|
+
export interface ImportAdapter {
|
|
63
|
+
id: ImportSourceId;
|
|
64
|
+
label: string;
|
|
65
|
+
description: string;
|
|
66
|
+
isAvailable(): boolean;
|
|
67
|
+
unavailableReason(): string;
|
|
68
|
+
scan(options?: {
|
|
69
|
+
rootPath?: string;
|
|
70
|
+
}): Promise<DiscoveredImportAsset[]>;
|
|
71
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { DiscoveredImportAsset, ImportSourceId } from './types.js';
|
|
2
|
+
export declare function expandHome(inputPath: string): string;
|
|
3
|
+
export declare function vscodeUserMcpPath(): string;
|
|
4
|
+
export declare function slugifyImportName(name: string): string;
|
|
5
|
+
export declare function makeAssetId(): string;
|
|
6
|
+
export declare function discoverSkillDir(skillDir: string, adapterId: ImportSourceId, originLabel: string): Promise<DiscoveredImportAsset | null>;
|
|
7
|
+
export declare function discoverPromptFile(filePath: string, adapterId: ImportSourceId, originLabel: string, suggestedName?: string): Promise<DiscoveredImportAsset>;
|
|
8
|
+
export declare function listSkillDirs(root: string): Promise<string[]>;
|
|
9
|
+
export declare function extractMcpServerMap(raw: Record<string, unknown>): Record<string, unknown>;
|
|
10
|
+
export declare function discoverMcpFromJsonFile(filePath: string, adapterId: ImportSourceId, originPrefix: string): Promise<DiscoveredImportAsset[]>;
|
|
11
|
+
/** Minimal TOML [mcp_servers.name] block parser for Codex config.toml */
|
|
12
|
+
export declare function parseCodexMcpBlocks(tomlText: string): Array<{
|
|
13
|
+
name: string;
|
|
14
|
+
body: string;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function codexBlockToMcpJson(block: {
|
|
17
|
+
name: string;
|
|
18
|
+
body: string;
|
|
19
|
+
}): Record<string, unknown>;
|
|
20
|
+
/**
|
|
21
|
+
* Discover rules-style markdown files as skills.
|
|
22
|
+
* Used by Cursor (.cursor/rules/, .cursorrules) and Windsurf (.windsurf/rules/, .windsurfrules).
|
|
23
|
+
*/
|
|
24
|
+
export declare function discoverRulesAsSkills(rulePaths: string[], dotfilePaths: string[], adapterId: ImportSourceId, originPrefix: string): Promise<DiscoveredImportAsset[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Discover Continue.dev prompt files from ~/.continue/prompts/.
|
|
27
|
+
*/
|
|
28
|
+
export declare function discoverContinuePrompts(promptsDir: string, adapterId: ImportSourceId): Promise<DiscoveredImportAsset[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Discover MCP servers from Continue's config.json (legacy) or config.yaml.
|
|
31
|
+
*/
|
|
32
|
+
export declare function discoverContinueMcpFromConfig(configPath: string, adapterId: ImportSourceId): Promise<DiscoveredImportAsset[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Discover canonical assets from an existing Aman environment directory.
|
|
35
|
+
*/
|
|
36
|
+
export declare function discoverAmanEnvironmentAssets(envRoot: string, adapterId: ImportSourceId): Promise<DiscoveredImportAsset[]>;
|