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.
Files changed (197) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +116 -0
  3. package/dist/bin/aman.d.ts +2 -0
  4. package/dist/bin/aman.js +165 -0
  5. package/dist/cli/global-install.d.ts +7 -0
  6. package/dist/cli/global-install.js +36 -0
  7. package/dist/cli/help-text.d.ts +1 -0
  8. package/dist/cli/help-text.js +62 -0
  9. package/dist/cli/version.d.ts +1 -0
  10. package/dist/cli/version.js +6 -0
  11. package/dist/commands/backup.d.ts +11 -0
  12. package/dist/commands/backup.js +262 -0
  13. package/dist/commands/browse.d.ts +11 -0
  14. package/dist/commands/browse.js +641 -0
  15. package/dist/commands/cache.d.ts +1 -0
  16. package/dist/commands/cache.js +38 -0
  17. package/dist/commands/config.d.ts +4 -0
  18. package/dist/commands/config.js +146 -0
  19. package/dist/commands/dashboard.d.ts +1 -0
  20. package/dist/commands/dashboard.js +1004 -0
  21. package/dist/commands/doctor.d.ts +4 -0
  22. package/dist/commands/doctor.js +54 -0
  23. package/dist/commands/export.d.ts +1 -0
  24. package/dist/commands/export.js +137 -0
  25. package/dist/commands/help.d.ts +1 -0
  26. package/dist/commands/help.js +47 -0
  27. package/dist/commands/import-wizard.d.ts +7 -0
  28. package/dist/commands/import-wizard.js +374 -0
  29. package/dist/commands/import.d.ts +9 -0
  30. package/dist/commands/import.js +351 -0
  31. package/dist/commands/info.d.ts +1 -0
  32. package/dist/commands/info.js +174 -0
  33. package/dist/commands/init.d.ts +20 -0
  34. package/dist/commands/init.js +146 -0
  35. package/dist/commands/install.d.ts +10 -0
  36. package/dist/commands/install.js +342 -0
  37. package/dist/commands/pack.d.ts +23 -0
  38. package/dist/commands/pack.js +331 -0
  39. package/dist/commands/registry.d.ts +6 -0
  40. package/dist/commands/registry.js +218 -0
  41. package/dist/commands/remove.d.ts +1 -0
  42. package/dist/commands/remove.js +76 -0
  43. package/dist/commands/search.d.ts +7 -0
  44. package/dist/commands/search.js +295 -0
  45. package/dist/commands/stack.d.ts +18 -0
  46. package/dist/commands/stack.js +327 -0
  47. package/dist/commands/sync.d.ts +9 -0
  48. package/dist/commands/sync.js +428 -0
  49. package/dist/commands/update.d.ts +1 -0
  50. package/dist/commands/update.js +97 -0
  51. package/dist/config/features.d.ts +2 -0
  52. package/dist/config/features.js +2 -0
  53. package/dist/config/index.d.ts +13 -0
  54. package/dist/config/index.js +80 -0
  55. package/dist/config/paths.d.ts +23 -0
  56. package/dist/config/paths.js +45 -0
  57. package/dist/import/adapters.d.ts +14 -0
  58. package/dist/import/adapters.js +580 -0
  59. package/dist/import/discovery.service.d.ts +8 -0
  60. package/dist/import/discovery.service.js +26 -0
  61. package/dist/import/import.service.d.ts +7 -0
  62. package/dist/import/import.service.js +259 -0
  63. package/dist/import/types.d.ts +71 -0
  64. package/dist/import/types.js +1 -0
  65. package/dist/import/utils.d.ts +36 -0
  66. package/dist/import/utils.js +428 -0
  67. package/dist/marketplace/cache.d.ts +18 -0
  68. package/dist/marketplace/cache.js +141 -0
  69. package/dist/marketplace/github-search.d.ts +17 -0
  70. package/dist/marketplace/github-search.js +268 -0
  71. package/dist/marketplace/install-from-candidate.d.ts +6 -0
  72. package/dist/marketplace/install-from-candidate.js +14 -0
  73. package/dist/marketplace/install.d.ts +15 -0
  74. package/dist/marketplace/install.js +54 -0
  75. package/dist/marketplace/metadata-validator.d.ts +8 -0
  76. package/dist/marketplace/metadata-validator.js +79 -0
  77. package/dist/marketplace/types.d.ts +34 -0
  78. package/dist/marketplace/types.js +1 -0
  79. package/dist/providers/local.provider.d.ts +9 -0
  80. package/dist/providers/local.provider.js +51 -0
  81. package/dist/providers/provider.interface.d.ts +7 -0
  82. package/dist/providers/provider.interface.js +1 -0
  83. package/dist/providers/registry.provider.d.ts +2 -0
  84. package/dist/providers/registry.provider.js +42 -0
  85. package/dist/providers/skills-sh.provider.d.ts +11 -0
  86. package/dist/providers/skills-sh.provider.js +56 -0
  87. package/dist/registry/adapter.interface.d.ts +16 -0
  88. package/dist/registry/adapter.interface.js +1 -0
  89. package/dist/registry/errors.d.ts +5 -0
  90. package/dist/registry/errors.js +8 -0
  91. package/dist/registry/filesystem-registry.adapter.d.ts +25 -0
  92. package/dist/registry/filesystem-registry.adapter.js +288 -0
  93. package/dist/registry/github-registry.adapter.d.ts +11 -0
  94. package/dist/registry/github-registry.adapter.js +32 -0
  95. package/dist/registry/index.d.ts +8 -0
  96. package/dist/registry/index.js +8 -0
  97. package/dist/registry/local-registry.adapter.d.ts +6 -0
  98. package/dist/registry/local-registry.adapter.js +9 -0
  99. package/dist/registry/registry.service.d.ts +44 -0
  100. package/dist/registry/registry.service.js +163 -0
  101. package/dist/registry/slug-utils.d.ts +12 -0
  102. package/dist/registry/slug-utils.js +51 -0
  103. package/dist/registry/types.d.ts +160 -0
  104. package/dist/registry/types.js +1 -0
  105. package/dist/services/asset.service.d.ts +12 -0
  106. package/dist/services/asset.service.js +142 -0
  107. package/dist/services/backup.service.d.ts +8 -0
  108. package/dist/services/backup.service.js +169 -0
  109. package/dist/services/classification.service.d.ts +31 -0
  110. package/dist/services/classification.service.js +271 -0
  111. package/dist/services/config.service.d.ts +9 -0
  112. package/dist/services/config.service.js +20 -0
  113. package/dist/services/doctor.service.d.ts +5 -0
  114. package/dist/services/doctor.service.js +186 -0
  115. package/dist/services/environment.service.d.ts +42 -0
  116. package/dist/services/environment.service.js +227 -0
  117. package/dist/services/github.service.d.ts +7 -0
  118. package/dist/services/github.service.js +42 -0
  119. package/dist/services/lock.service.d.ts +12 -0
  120. package/dist/services/lock.service.js +71 -0
  121. package/dist/services/marketplace.service.d.ts +40 -0
  122. package/dist/services/marketplace.service.js +225 -0
  123. package/dist/services/pack.service.d.ts +9 -0
  124. package/dist/services/pack.service.js +193 -0
  125. package/dist/services/stack.service.d.ts +9 -0
  126. package/dist/services/stack.service.js +94 -0
  127. package/dist/storage/asset-layout.d.ts +46 -0
  128. package/dist/storage/asset-layout.js +277 -0
  129. package/dist/storage/filesystem.d.ts +12 -0
  130. package/dist/storage/filesystem.js +113 -0
  131. package/dist/storage/scan-by-type.d.ts +2 -0
  132. package/dist/storage/scan-by-type.js +8 -0
  133. package/dist/storage/scanner.d.ts +11 -0
  134. package/dist/storage/scanner.js +188 -0
  135. package/dist/types/asset-metadata.d.ts +84 -0
  136. package/dist/types/asset-metadata.js +104 -0
  137. package/dist/types/index.d.ts +212 -0
  138. package/dist/types/index.js +1 -0
  139. package/dist/ui/animations/ErrorIndicator.d.ts +5 -0
  140. package/dist/ui/animations/ErrorIndicator.js +6 -0
  141. package/dist/ui/animations/GithubIndicator.d.ts +6 -0
  142. package/dist/ui/animations/GithubIndicator.js +9 -0
  143. package/dist/ui/animations/ProgressBar.d.ts +5 -0
  144. package/dist/ui/animations/ProgressBar.js +15 -0
  145. package/dist/ui/animations/Spinner.d.ts +5 -0
  146. package/dist/ui/animations/Spinner.js +21 -0
  147. package/dist/ui/animations/SuccessIndicator.d.ts +5 -0
  148. package/dist/ui/animations/SuccessIndicator.js +6 -0
  149. package/dist/ui/animations/SyncActivity.d.ts +5 -0
  150. package/dist/ui/animations/SyncActivity.js +21 -0
  151. package/dist/ui/animations/TransitionScreen.d.ts +7 -0
  152. package/dist/ui/animations/TransitionScreen.js +25 -0
  153. package/dist/ui/animations/useAnimationMode.d.ts +1 -0
  154. package/dist/ui/animations/useAnimationMode.js +16 -0
  155. package/dist/ui/assetDisplay.d.ts +19 -0
  156. package/dist/ui/assetDisplay.js +59 -0
  157. package/dist/ui/components/Confirm.d.ts +8 -0
  158. package/dist/ui/components/Confirm.js +14 -0
  159. package/dist/ui/components/CustomSelect.d.ts +19 -0
  160. package/dist/ui/components/CustomSelect.js +13 -0
  161. package/dist/ui/components/Header.d.ts +6 -0
  162. package/dist/ui/components/Header.js +9 -0
  163. package/dist/ui/components/HealthReport.d.ts +7 -0
  164. package/dist/ui/components/HealthReport.js +13 -0
  165. package/dist/ui/components/MarketplaceInstallConfirm.d.ts +19 -0
  166. package/dist/ui/components/MarketplaceInstallConfirm.js +23 -0
  167. package/dist/ui/components/Narrator.d.ts +9 -0
  168. package/dist/ui/components/Narrator.js +26 -0
  169. package/dist/ui/components/ScopePrompt.d.ts +8 -0
  170. package/dist/ui/components/ScopePrompt.js +23 -0
  171. package/dist/ui/components/TooSmallScreen.d.ts +8 -0
  172. package/dist/ui/components/TooSmallScreen.js +6 -0
  173. package/dist/ui/date.d.ts +2 -0
  174. package/dist/ui/date.js +33 -0
  175. package/dist/ui/layout.d.ts +23 -0
  176. package/dist/ui/layout.js +44 -0
  177. package/dist/ui/list-item.d.ts +12 -0
  178. package/dist/ui/list-item.js +1 -0
  179. package/dist/ui/marketplaceDisplay.d.ts +10 -0
  180. package/dist/ui/marketplaceDisplay.js +36 -0
  181. package/dist/ui/theme.d.ts +42 -0
  182. package/dist/ui/theme.js +47 -0
  183. package/dist/utils/asset-list-fields.d.ts +11 -0
  184. package/dist/utils/asset-list-fields.js +28 -0
  185. package/dist/utils/error-message.d.ts +2 -0
  186. package/dist/utils/error-message.js +6 -0
  187. package/dist/utils/integrity.d.ts +9 -0
  188. package/dist/utils/integrity.js +23 -0
  189. package/dist/utils/lock-migrate.d.ts +25 -0
  190. package/dist/utils/lock-migrate.js +93 -0
  191. package/dist/utils/mcp-local.d.ts +15 -0
  192. package/dist/utils/mcp-local.js +129 -0
  193. package/dist/utils/slug.d.ts +6 -0
  194. package/dist/utils/slug.js +13 -0
  195. package/dist/utils/stack-normalize.d.ts +3 -0
  196. package/dist/utils/stack-normalize.js +43 -0
  197. package/package.json +77 -0
@@ -0,0 +1,4 @@
1
+ export declare const DoctorApp: ({ onBack }: {
2
+ onBack?: () => void;
3
+ }) => import("react/jsx-runtime").JSX.Element;
4
+ export declare function doctorCommand(): Promise<void>;
@@ -0,0 +1,54 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { render, Box, Text, useApp, useInput } from 'ink';
4
+ import { doctorService } from '../services/doctor.service.js';
5
+ import { HealthReport } from '../ui/components/HealthReport.js';
6
+ import { Narrator } from '../ui/components/Narrator.js';
7
+ import { theme } from '../ui/theme.js';
8
+ import { useResponsiveLayout, MIN_COLUMNS, MIN_ROWS } from '../ui/layout.js';
9
+ export const DoctorApp = ({ onBack }) => {
10
+ const { exit } = useApp();
11
+ const [checks, setChecks] = useState(null);
12
+ const { rows, columns, isTooSmall, isCompact, physicalColumns, physicalRows } = useResponsiveLayout();
13
+ useEffect(() => {
14
+ doctorService.runChecks('global').then((result) => {
15
+ setChecks(result);
16
+ if (!onBack) {
17
+ setTimeout(() => exit(), 300);
18
+ }
19
+ });
20
+ }, [exit, onBack]);
21
+ useInput((input, key) => {
22
+ if (key.escape || input === 'q') {
23
+ if (onBack)
24
+ onBack();
25
+ else
26
+ exit();
27
+ }
28
+ });
29
+ if (!checks) {
30
+ return (_jsx(Box, { paddingX: 1, flexDirection: "column", height: rows, justifyContent: "space-between", children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Narrator, { state: "searching", compact: true }), _jsx(Box, { marginLeft: 1, children: _jsx(Text, { children: "Running health checks..." }) })] }) }));
31
+ }
32
+ return (_jsxs(Box, { paddingX: 1, flexDirection: "column", height: rows, justifyContent: "space-between", children: [_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, color: theme.accent, children: "Terminal" }), _jsx(Text, { color: theme.borderMuted, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }), _jsxs(Text, { children: ["Size: ", physicalColumns, "\u00D7", physicalRows] }), _jsxs(Text, { children: ["Mode: ", isCompact ? 'Compact' : 'Normal'] }), isTooSmall ? (_jsxs(Text, { color: theme.error, children: ["\u2717 Below minimum supported size (", MIN_COLUMNS, "x", MIN_ROWS, ")"] })) : (_jsx(Text, { color: theme.success, children: "\u2713 Supported" }))] }), _jsx(HealthReport, { checks: checks })] }), onBack && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.dim, children: "Press esc or q to go back" }) }))] }));
33
+ };
34
+ export async function doctorCommand() {
35
+ if (!process.stdin.isTTY) {
36
+ const checks = await doctorService.runChecks('global');
37
+ console.log('\n Aman Diagnostics (Non-TTY Fallback):\n');
38
+ let allPassed = true;
39
+ for (const check of checks) {
40
+ const statusSymbol = check.status === 'pass' ? '✓' : check.status === 'warn' ? '⚠' : '✗';
41
+ console.log(` ${statusSymbol} ${check.name}: ${check.message}`);
42
+ if (check.status === 'fail') {
43
+ allPassed = false;
44
+ }
45
+ }
46
+ console.log('');
47
+ if (!allPassed) {
48
+ process.exit(1);
49
+ }
50
+ return;
51
+ }
52
+ const { waitUntilExit } = render(_jsx(DoctorApp, {}));
53
+ await waitUntilExit();
54
+ }
@@ -0,0 +1 @@
1
+ export declare function exportCommand(args: string[], options: any): Promise<void>;
@@ -0,0 +1,137 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { render, Box, useApp } from 'ink';
4
+ import { packService } from '../services/pack.service.js';
5
+ import { Narrator } from '../ui/components/Narrator.js';
6
+ import { scanAll } from '../storage/scanner.js';
7
+ import { environmentService } from '../services/environment.service.js';
8
+ import { ASSET_TYPE_PLURAL } from '../ui/assetDisplay.js';
9
+ import path from 'path';
10
+ const ExportApp = ({ name, all, assetType }) => {
11
+ const { exit } = useApp();
12
+ const [state, setState] = useState('installing');
13
+ const [message, setMessage] = useState('Exporting...');
14
+ useEffect(() => {
15
+ async function doExport() {
16
+ try {
17
+ const envDir = environmentService.getActiveEnvironmentDir();
18
+ const data = await scanAll(envDir, 'global');
19
+ let skillsToExport = data.skills;
20
+ let promptsToExport = data.prompts;
21
+ let mcpsToExport = data.mcps;
22
+ let stacksToExport = data.stacks;
23
+ let exportName = name || 'aman-export';
24
+ if (assetType) {
25
+ if (assetType === 'skill') {
26
+ promptsToExport = [];
27
+ mcpsToExport = [];
28
+ }
29
+ else if (assetType === 'prompt') {
30
+ skillsToExport = [];
31
+ mcpsToExport = [];
32
+ }
33
+ else {
34
+ skillsToExport = [];
35
+ promptsToExport = [];
36
+ }
37
+ stacksToExport = [];
38
+ exportName = name || `${assetType}-export`;
39
+ }
40
+ if (name && !all && !assetType) {
41
+ skillsToExport = data.skills.filter((s) => s.name === name);
42
+ promptsToExport = data.prompts.filter((p) => p.name === name);
43
+ mcpsToExport = data.mcps.filter((m) => m.name === name);
44
+ stacksToExport = [];
45
+ exportName = name;
46
+ if (skillsToExport.length === 0 && promptsToExport.length === 0 && mcpsToExport.length === 0) {
47
+ setState('error');
48
+ setMessage(`Could not find asset "${name}"`);
49
+ setTimeout(() => exit(), 1200);
50
+ return;
51
+ }
52
+ }
53
+ const packDef = {
54
+ name: exportName,
55
+ version: '1.0.0',
56
+ description: all
57
+ ? 'Full environment export'
58
+ : assetType
59
+ ? `Export of all ${ASSET_TYPE_PLURAL[assetType].toLowerCase()}`
60
+ : `Export of ${exportName}`,
61
+ skills: skillsToExport.map((s) => s.name),
62
+ prompts: promptsToExport.map((p) => p.name),
63
+ mcps: mcpsToExport.map((m) => m.name),
64
+ stacks: stacksToExport.map((st) => st.name),
65
+ createdAt: new Date().toISOString(),
66
+ };
67
+ const outPath = path.resolve(process.cwd(), `${exportName}.amanpack`);
68
+ await packService.create(exportName, packDef, outPath);
69
+ const total = packDef.skills.length + packDef.prompts.length + packDef.mcps.length;
70
+ const typeLabel = assetType ? ASSET_TYPE_PLURAL[assetType] : 'assets';
71
+ setState('success');
72
+ setMessage(`Exported ${total} ${typeLabel.toLowerCase()} → ${exportName}.amanpack`);
73
+ }
74
+ catch (err) {
75
+ setState('error');
76
+ setMessage(`Error: ${err.message}`);
77
+ }
78
+ setTimeout(() => exit(), 1000);
79
+ }
80
+ doExport();
81
+ }, [all, assetType, exit, name]);
82
+ return (_jsx(Box, { flexDirection: "column", paddingX: 1, children: _jsx(Narrator, { state: state, message: message }) }));
83
+ };
84
+ function parseExportType(raw) {
85
+ if (!raw)
86
+ return undefined;
87
+ const t = raw.toLowerCase();
88
+ if (t === 'skill' || t === 'prompt' || t === 'mcp')
89
+ return t;
90
+ return undefined;
91
+ }
92
+ export async function exportCommand(args, options) {
93
+ const name = args[0];
94
+ const all = Boolean(options.all) || (!name && !options.type);
95
+ const assetType = parseExportType(options.type);
96
+ if (options.type && !assetType) {
97
+ console.log(' Usage: aman export [name] [--all] [--type skill|prompt|mcp]');
98
+ return;
99
+ }
100
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
101
+ const envDir = environmentService.getActiveEnvironmentDir();
102
+ const data = await scanAll(envDir, 'global');
103
+ const skills = assetType === 'prompt' || assetType === 'mcp' ? [] : data.skills;
104
+ const prompts = assetType === 'skill' || assetType === 'mcp' ? [] : data.prompts;
105
+ const mcps = assetType === 'skill' || assetType === 'prompt' ? [] : data.mcps;
106
+ const total = skills.length + prompts.length + mcps.length;
107
+ if (!all && name && total === 0) {
108
+ console.error(` No installed assets match "${name}".`);
109
+ process.exit(1);
110
+ }
111
+ if (all && total === 0) {
112
+ console.log(' No installed assets to export.');
113
+ return;
114
+ }
115
+ const packDef = {
116
+ name: name || 'aman-export',
117
+ version: '1.0.0',
118
+ description: 'CLI export',
119
+ skills: all ? skills.map((s) => s.name) : skills.filter((s) => s.name === name).map((s) => s.name),
120
+ prompts: all ? prompts.map((p) => p.name) : prompts.filter((p) => p.name === name).map((p) => p.name),
121
+ mcps: all ? mcps.map((m) => m.name) : mcps.filter((m) => m.name === name).map((m) => m.name),
122
+ stacks: [],
123
+ createdAt: new Date().toISOString(),
124
+ };
125
+ const exportTotal = packDef.skills.length + packDef.prompts.length + packDef.mcps.length;
126
+ if (exportTotal === 0) {
127
+ console.error(` Could not find asset "${name}" to export.`);
128
+ process.exit(1);
129
+ }
130
+ const outPath = path.resolve(process.cwd(), `${packDef.name}.amanpack`);
131
+ await packService.create(packDef.name, packDef, outPath);
132
+ console.log(` Exported ${exportTotal} asset(s) → ${outPath}`);
133
+ return;
134
+ }
135
+ const { waitUntilExit } = render(_jsx(ExportApp, { name: name, all: all, assetType: assetType }));
136
+ await waitUntilExit();
137
+ }
@@ -0,0 +1 @@
1
+ export declare function helpCommand(): Promise<void>;
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { render } from 'ink';
3
+ import { useEffect } from 'react';
4
+ import { Box, Text, useApp } from 'ink';
5
+ import { theme } from '../ui/theme.js';
6
+ import { Header } from '../ui/components/Header.js';
7
+ const HelpOutput = () => {
8
+ const { exit } = useApp();
9
+ useEffect(() => {
10
+ setTimeout(() => exit(), 100);
11
+ }, [exit]);
12
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, marginY: 1, children: [_jsx(Header, { compact: true }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { children: _jsx(Text, { bold: true, color: theme.accent, children: "Usage" }) }), _jsx(Box, { paddingLeft: 2, children: _jsx(Text, { children: "aman [command] [options]" }) })] }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { children: _jsx(Text, { bold: true, color: theme.accent, children: "Commands" }) }), [
13
+ ['(none)', 'Open dashboard'],
14
+ ['init', 'Set up local or GitHub-backed storage'],
15
+ ['browse', 'Browse assets — skills, prompts, and MCPs'],
16
+ ['search <query>', 'Universal search across all asset types'],
17
+ ['info <name>', 'View details for any asset type'],
18
+ ['install [name]', 'Install asset (wizard if no name). --type skill|prompt|mcp'],
19
+ ['remove <name>', 'Remove an installed item'],
20
+ ['update [name]', 'Update assets'],
21
+ ['import <source>', 'Import from GitHub or a local folder'],
22
+ ['export [name]', 'Export assets or environment (--all, --type skill|prompt|mcp)'],
23
+ ['pack <cmd>', 'Create, inspect, or install shareable packs'],
24
+ ['stack <cmd>', 'Manage workflow stacks'],
25
+ ['sync <push|pull>', 'Push or pull environment from GitHub'],
26
+ ['backup <cmd>', 'Save or restore your environment'],
27
+ ['doctor', 'Check environment health'],
28
+ ['config <cmd>', 'Manage settings'],
29
+ ['registry <cmd>', 'Publish and query the canonical asset registry'],
30
+ ['help', 'Show this help'],
31
+ ].map(([cmd, desc]) => (_jsxs(Box, { children: [_jsx(Box, { width: 22, paddingLeft: 2, children: _jsx(Text, { color: theme.primary, children: cmd }) }), _jsx(Box, { children: _jsx(Text, { color: theme.dim, children: desc }) })] }, cmd)))] }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { children: _jsx(Text, { bold: true, color: theme.accent, children: "Registry" }) }), _jsx(Box, { paddingLeft: 2, marginBottom: 1, children: _jsx(Text, { color: theme.dim, children: "Canonical store for published asset versions (slug, checksum, immutability)." }) }), [
32
+ ['registry publish', 'Publish an immutable asset version from a canonical directory'],
33
+ ['registry deprecate', 'Mark a published version deprecated without removing it'],
34
+ ['registry list', 'List all published versions for an asset slug'],
35
+ ['registry search', 'Search published assets by name, slug, tags, or description'],
36
+ ['registry resolve', 'Show metadata for an exact slug@version'],
37
+ ].map(([cmd, desc]) => (_jsxs(Box, { children: [_jsx(Box, { width: 22, paddingLeft: 2, children: _jsx(Text, { color: theme.primary, children: cmd }) }), _jsx(Box, { children: _jsx(Text, { color: theme.dim, children: desc }) })] }, cmd)))] }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Box, { children: _jsx(Text, { bold: true, color: theme.accent, children: "Global Options" }) }), _jsxs(Box, { children: [_jsx(Box, { width: 22, paddingLeft: 2, children: _jsx(Text, { color: theme.primary, children: "--global, -g" }) }), _jsx(Box, { children: _jsx(Text, { color: theme.dim, children: "Target global scope" }) })] }), _jsxs(Box, { children: [_jsx(Box, { width: 22, paddingLeft: 2, children: _jsx(Text, { color: theme.primary, children: "--project, -p" }) }), _jsx(Box, { children: _jsx(Text, { color: theme.dim, children: "Target project scope" }) })] }), _jsxs(Box, { children: [_jsx(Box, { width: 22, paddingLeft: 2, children: _jsx(Text, { color: theme.primary, children: "--github" }) }), _jsx(Box, { children: _jsx(Text, { color: theme.dim, children: "Use GitHub storage for init" }) })] }), _jsxs(Box, { children: [_jsx(Box, { width: 22, paddingLeft: 2, children: _jsx(Text, { color: theme.primary, children: "--local" }) }), _jsx(Box, { children: _jsx(Text, { color: theme.dim, children: "Use local storage for init" }) })] })] })] }));
38
+ };
39
+ export async function helpCommand() {
40
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
41
+ const { printHelpText } = await import('../cli/help-text.js');
42
+ printHelpText();
43
+ return;
44
+ }
45
+ const { waitUntilExit } = render(_jsx(HelpOutput, {}));
46
+ await waitUntilExit();
47
+ }
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { AssetType } from '../types/index.js';
3
+ import { DiscoveredImportAsset, TypeImportSelection } from '../import/types.js';
4
+ export declare const ImportWizardApp: ({ onBack }: {
5
+ onBack?: () => void;
6
+ }) => import("react/jsx-runtime").JSX.Element | null;
7
+ export declare function useImportPickInput(enabled: boolean, group: DiscoveredImportAsset[], pickCursor: number, setSelections: React.Dispatch<React.SetStateAction<Record<AssetType, TypeImportSelection>>>, activeType: AssetType, setPickCursor: React.Dispatch<React.SetStateAction<number>>): void;
@@ -0,0 +1,374 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useState } from 'react';
3
+ import { Box, Text, useApp, useInput } from 'ink';
4
+ import TextInput from 'ink-text-input';
5
+ import { CustomSelectInput } from '../ui/components/CustomSelect.js';
6
+ import { ScopePrompt } from '../ui/components/ScopePrompt.js';
7
+ import { Header } from '../ui/components/Header.js';
8
+ import { Narrator } from '../ui/components/Narrator.js';
9
+ import { ProgressBar } from '../ui/animations/ProgressBar.js';
10
+ import { theme } from '../ui/theme.js';
11
+ import { assetTypeBadge, ASSET_TYPE_PLURAL } from '../ui/assetDisplay.js';
12
+ import { useResponsiveLayout, MIN_COLUMNS, MIN_ROWS } from '../ui/layout.js';
13
+ import { TooSmallScreen } from '../ui/components/TooSmallScreen.js';
14
+ import { importDiscoveryService } from '../import/discovery.service.js';
15
+ import { applyAutoRenameConflicts, detectImportConflicts, executeImportPlan, isGithubDestinationAvailable, summarizeByType, } from '../import/import.service.js';
16
+ import { ASSET_TAB_ORDER } from '../ui/assetDisplay.js';
17
+ const TYPE_ORDER = ASSET_TAB_ORDER;
18
+ function defaultTypeSelections() {
19
+ return {
20
+ skill: { mode: 'all', selectedIds: new Set() },
21
+ prompt: { mode: 'all', selectedIds: new Set() },
22
+ mcp: { mode: 'all', selectedIds: new Set() },
23
+ };
24
+ }
25
+ function canonicalLabel(status) {
26
+ if (status === 'canonical')
27
+ return 'canonical';
28
+ if (status === 'convertible')
29
+ return 'convertible';
30
+ if (status === 'ambiguous')
31
+ return 'ambiguous';
32
+ return 'unknown';
33
+ }
34
+ function applyTypeSelections(assets, selections) {
35
+ const out = [];
36
+ for (const type of TYPE_ORDER) {
37
+ const group = assets.filter((a) => a.type === type);
38
+ const sel = selections[type];
39
+ if (sel.mode === 'skip' || group.length === 0)
40
+ continue;
41
+ if (sel.mode === 'all') {
42
+ out.push(...group);
43
+ continue;
44
+ }
45
+ out.push(...group.filter((a) => sel.selectedIds.has(a.id)));
46
+ }
47
+ return out;
48
+ }
49
+ export const ImportWizardApp = ({ onBack }) => {
50
+ const { exit } = useApp();
51
+ const handleExit = () => {
52
+ if (onBack)
53
+ onBack();
54
+ else
55
+ exit();
56
+ };
57
+ const { isTooSmall, isCompact, physicalColumns, physicalRows, rows } = useResponsiveLayout();
58
+ const [step, setStep] = useState('source');
59
+ const [adapters, setAdapters] = useState([]);
60
+ const [sourceId, setSourceId] = useState(null);
61
+ const [customPath, setCustomPath] = useState('');
62
+ const [discovered, setDiscovered] = useState([]);
63
+ const [typeSelections, setTypeSelections] = useState(defaultTypeSelections());
64
+ const [typeQueueIndex, setTypeQueueIndex] = useState(0);
65
+ const typesWithAssets = useMemo(() => TYPE_ORDER.filter((t) => discovered.some((d) => d.type === t)), [discovered]);
66
+ const [pickCursor, setPickCursor] = useState(0);
67
+ const [destination, setDestination] = useState('local');
68
+ const [scope, setScope] = useState();
69
+ const [conflicts, setConflicts] = useState([]);
70
+ const [conflictBulkMode, setConflictBulkMode] = useState('ask');
71
+ const [conflictCursor, setConflictCursor] = useState(0);
72
+ const [state, setState] = useState('idle');
73
+ const [message, setMessage] = useState('');
74
+ const [progress, setProgress] = useState(0);
75
+ const [resultSummary, setResultSummary] = useState('');
76
+ const githubReady = isGithubDestinationAvailable();
77
+ const selectedItems = useMemo(() => applyTypeSelections(discovered, typeSelections), [discovered, typeSelections]);
78
+ const counts = useMemo(() => summarizeByType(selectedItems), [selectedItems]);
79
+ const activeType = typesWithAssets[typeQueueIndex] ?? null;
80
+ const activeGroup = activeType ? discovered.filter((a) => a.type === activeType) : [];
81
+ useImportPickInput(step === 'type-select' && activeType !== null && typeSelections[activeType].mode === 'select', activeGroup, pickCursor, setTypeSelections, activeType ?? 'skill', setPickCursor);
82
+ useEffect(() => {
83
+ setAdapters(importDiscoveryService.listAdapters());
84
+ }, []);
85
+ useInput((input, key) => {
86
+ if (input === 'q' || (key.escape && step === 'source')) {
87
+ handleExit();
88
+ }
89
+ else if (key.escape && step !== 'importing') {
90
+ if (step === 'custom-path')
91
+ setStep('source');
92
+ else if (step === 'type-select')
93
+ setStep('results');
94
+ else if (step === 'results')
95
+ setStep('source');
96
+ else if (step === 'destination')
97
+ setStep('results');
98
+ else if (step === 'scope')
99
+ setStep('destination');
100
+ else if (step === 'conflict-bulk')
101
+ setStep('scope');
102
+ else if (step === 'conflict-item')
103
+ setStep('conflict-bulk');
104
+ else if (step === 'confirm')
105
+ setStep(conflicts.length ? 'conflict-bulk' : 'scope');
106
+ }
107
+ });
108
+ async function runScan(id, rootPath) {
109
+ setStep('scanning');
110
+ setState('searching');
111
+ setMessage('Scanning for assets...');
112
+ try {
113
+ const items = await importDiscoveryService.scan(id, rootPath ? { rootPath } : undefined);
114
+ setDiscovered(items);
115
+ setTypeSelections(defaultTypeSelections());
116
+ setTypeQueueIndex(0);
117
+ setStep('results');
118
+ }
119
+ catch (err) {
120
+ setState('error');
121
+ setMessage(err instanceof Error ? err.message : String(err));
122
+ setStep('done');
123
+ }
124
+ }
125
+ async function prepareConflicts(nextScope) {
126
+ const items = applyTypeSelections(discovered, typeSelections);
127
+ const found = await detectImportConflicts(items, nextScope);
128
+ const withRename = applyAutoRenameConflicts(found, 'suffix');
129
+ setConflicts(withRename);
130
+ setScope(nextScope);
131
+ setConflictCursor(0);
132
+ setConflictBulkMode('ask');
133
+ if (withRename.length > 0)
134
+ setStep('conflict-bulk');
135
+ else
136
+ setStep('confirm');
137
+ }
138
+ function advanceTypeQueue() {
139
+ if (typeQueueIndex + 1 < typesWithAssets.length) {
140
+ setTypeQueueIndex((i) => i + 1);
141
+ setPickCursor(0);
142
+ }
143
+ else {
144
+ setStep('destination');
145
+ }
146
+ }
147
+ useEffect(() => {
148
+ if (step !== 'importing' || !scope || !sourceId)
149
+ return;
150
+ async function run() {
151
+ if (!sourceId || !scope)
152
+ return;
153
+ setState('installing');
154
+ setMessage('Importing assets...');
155
+ setProgress(10);
156
+ try {
157
+ const plan = {
158
+ sourceId,
159
+ sourceLabel: adapters.find((a) => a.id === sourceId)?.label ?? sourceId,
160
+ destination,
161
+ scope,
162
+ items: selectedItems,
163
+ conflicts,
164
+ };
165
+ const result = await executeImportPlan(plan);
166
+ setProgress(100);
167
+ setState('success');
168
+ setResultSummary(`Imported ${result.imported} · skipped ${result.skipped} · renamed ${result.renamed} · overwritten ${result.overwritten}`);
169
+ setMessage(`Import complete → ${scope}`);
170
+ setStep('done');
171
+ setTimeout(() => handleExit(), 2000);
172
+ }
173
+ catch (err) {
174
+ setState('error');
175
+ setMessage(err instanceof Error ? err.message : String(err));
176
+ setStep('done');
177
+ }
178
+ }
179
+ run();
180
+ }, [step, scope, sourceId, destination, selectedItems, conflicts, adapters]);
181
+ if (isTooSmall) {
182
+ return (_jsx(TooSmallScreen, { columns: physicalColumns, rows: physicalRows, minColumns: MIN_COLUMNS, minRows: MIN_ROWS }));
183
+ }
184
+ if (step === 'scanning' || step === 'importing' || (step === 'done' && state !== 'idle')) {
185
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Header, { compact: true }), _jsx(Narrator, { state: state, message: message }), step === 'importing' && (_jsx(Box, { marginTop: 1, children: _jsx(ProgressBar, { progress: progress }) })), resultSummary && step === 'done' && (_jsx(Text, { color: theme.dim, children: resultSummary }))] }));
186
+ }
187
+ if (step === 'source') {
188
+ const items = adapters
189
+ .filter((a) => a.available)
190
+ .map((a) => ({ label: a.label, value: a.id }));
191
+ const unavailable = adapters.filter((a) => !a.available);
192
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, height: rows, children: [_jsx(Header, { compact: true }), _jsx(Text, { bold: true, color: theme.accent, children: "Import from another tool" }), _jsx(Text, { color: theme.dim, children: "Choose where to import skills, prompts, and MCPs from" }), _jsx(Box, { marginTop: 1, children: _jsx(CustomSelectInput, { items: items, onSelect: (item) => {
193
+ setSourceId(item.value);
194
+ if (item.value === 'custom-path' || item.value === 'local-folder')
195
+ setStep('custom-path');
196
+ else
197
+ void runScan(item.value);
198
+ } }) }), unavailable.length > 0 && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: theme.dim, children: "Unavailable on this machine:" }), unavailable.map((a) => (_jsxs(Text, { color: theme.dim, wrap: "truncate", children: [a.label, ": ", a.unavailableReason] }, a.id)))] })), !isCompact && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.dim, children: "\u2191\u2193 navigate \u00B7 Enter select \u00B7 Esc/q back" }) }))] }));
199
+ }
200
+ if (step === 'custom-path') {
201
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Header, { compact: true }), _jsx(Text, { bold: true, children: "Folder path" }), _jsxs(Box, { marginTop: 1, flexDirection: "row", children: [_jsx(Text, { color: theme.primary, children: "\u276F " }), _jsx(TextInput, { value: customPath, onChange: setCustomPath, onSubmit: () => {
202
+ if (!sourceId)
203
+ return;
204
+ void runScan(sourceId, customPath.trim() || process.cwd());
205
+ }, placeholder: "./path-to-assets" })] }), _jsx(Text, { color: theme.dim, children: "Enter path \u00B7 Enter submit \u00B7 Esc back" })] }));
206
+ }
207
+ if (step === 'results') {
208
+ const byType = TYPE_ORDER.map((t) => ({
209
+ type: t,
210
+ items: discovered.filter((a) => a.type === t),
211
+ }));
212
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, height: rows, children: [_jsx(Header, { compact: true }), _jsx(Text, { bold: true, children: "Discovered assets" }), _jsxs(Text, { color: theme.dim, children: ["Source: ", adapters.find((a) => a.id === sourceId)?.label ?? sourceId] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [byType.map(({ type, items }) => (_jsxs(Text, { children: [assetTypeBadge(type), " ", ASSET_TYPE_PLURAL[type], ": ", items.length] }, type))), discovered.length === 0 && (_jsx(Text, { color: theme.warning, children: "No recognizable assets found at this source." }))] }), !isCompact && discovered.length > 0 && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [discovered.slice(0, 8).map((item) => (_jsxs(Text, { color: theme.dim, wrap: "truncate", children: [assetTypeBadge(item.type), " ", item.name, " \u2014 ", canonicalLabel(item.canonicalStatus), " \u2014 ", item.originLabel, item.canonicalNote ? ` (${item.canonicalNote})` : ''] }, item.id))), discovered.length > 8 && (_jsxs(Text, { color: theme.dim, children: ["\u2026and ", discovered.length - 8, " more"] }))] })), _jsx(Box, { marginTop: 1, children: _jsx(CustomSelectInput, { items: [
213
+ { label: discovered.length ? 'Configure import selection' : 'Choose another source', value: discovered.length ? 'select' : 'back' },
214
+ ...(discovered.length ? [{ label: 'Import all discovered assets', value: 'all' }] : []),
215
+ ], onSelect: (item) => {
216
+ if (item.value === 'back') {
217
+ setStep('source');
218
+ return;
219
+ }
220
+ if (item.value === 'all') {
221
+ setTypeSelections({
222
+ skill: { mode: 'all', selectedIds: new Set() },
223
+ prompt: { mode: 'all', selectedIds: new Set() },
224
+ mcp: { mode: 'all', selectedIds: new Set() },
225
+ });
226
+ setStep('destination');
227
+ return;
228
+ }
229
+ setStep('type-select');
230
+ setTypeQueueIndex(0);
231
+ setPickCursor(0);
232
+ } }) })] }));
233
+ }
234
+ if (step === 'type-select' && activeType) {
235
+ const group = discovered.filter((a) => a.type === activeType);
236
+ const sel = typeSelections[activeType];
237
+ if (sel.mode === 'select') {
238
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, height: rows, children: [_jsx(Header, { compact: true }), _jsxs(Text, { bold: true, children: ["Select ", ASSET_TYPE_PLURAL[activeType].toLowerCase(), " (", typeQueueIndex + 1, "/", typesWithAssets.length, ")"] }), _jsx(Text, { color: theme.dim, children: "Space toggle \u00B7 Enter done \u00B7 Esc back" }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: group.map((item, idx) => {
239
+ const picked = sel.selectedIds.has(item.id);
240
+ return (_jsxs(Text, { color: idx === pickCursor ? theme.primary : theme.dim, children: [picked ? '◉' : '○', " ", item.name, " \u2014 ", item.originLabel] }, item.id));
241
+ }) }), _jsx(Box, { marginTop: 1, children: _jsx(CustomSelectInput, { items: [{ label: 'Done selecting this type', value: 'done' }], onSelect: () => advanceTypeQueue() }) })] }));
242
+ }
243
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Header, { compact: true }), _jsxs(Text, { bold: true, children: [ASSET_TYPE_PLURAL[activeType], " (", group.length, " found) \u2014 step ", typeQueueIndex + 1, "/", typesWithAssets.length] }), _jsx(Box, { marginTop: 1, children: _jsx(CustomSelectInput, { items: [
244
+ { label: `Import all ${ASSET_TYPE_PLURAL[activeType].toLowerCase()}`, value: 'all' },
245
+ { label: `Select specific ${ASSET_TYPE_PLURAL[activeType].toLowerCase()}`, value: 'select' },
246
+ { label: `Skip ${ASSET_TYPE_PLURAL[activeType].toLowerCase()}`, value: 'skip' },
247
+ ], onSelect: (item) => {
248
+ const mode = item.value;
249
+ setTypeSelections((prev) => ({
250
+ ...prev,
251
+ [activeType]: {
252
+ mode,
253
+ selectedIds: new Set(mode === 'select' ? group.map((g) => g.id) : []),
254
+ },
255
+ }));
256
+ if (mode === 'select') {
257
+ setPickCursor(0);
258
+ return;
259
+ }
260
+ advanceTypeQueue();
261
+ } }) })] }));
262
+ }
263
+ if (step === 'destination') {
264
+ const destItems = [
265
+ { label: 'Local environment', value: 'local' },
266
+ ];
267
+ if (githubReady) {
268
+ destItems.push({ label: 'GitHub-backed environment', value: 'github' });
269
+ }
270
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Header, { compact: true }), _jsx(Text, { bold: true, children: "Destination" }), _jsxs(Text, { color: theme.dim, children: ["Selected: ", selectedItems.length, " assets (", counts.skill, " skills \u00B7 ", counts.prompt, " prompts \u00B7 ", counts.mcp, " MCPs)"] }), !githubReady && (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: theme.warning, children: "GitHub is not configured. Use `aman init --github` or connect GitHub first." }), _jsx(Text, { color: theme.dim, children: "Only Local destination is available." })] })), _jsx(Box, { marginTop: 1, children: _jsx(CustomSelectInput, { items: destItems, onSelect: (item) => {
271
+ setDestination(item.value);
272
+ setStep('scope');
273
+ } }) })] }));
274
+ }
275
+ if (step === 'scope') {
276
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Header, { compact: true }), _jsx(Text, { bold: true, children: "Scope" }), _jsx(Text, { color: theme.dim, children: "Where should imported assets be installed?" }), _jsx(Box, { marginTop: 1, children: _jsx(ScopePrompt, { onSelect: (s) => {
277
+ void prepareConflicts(s);
278
+ } }) })] }));
279
+ }
280
+ if (step === 'conflict-bulk') {
281
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, height: rows, children: [_jsx(Header, { compact: true }), _jsxs(Text, { bold: true, color: theme.warning, children: ["Name conflicts detected (", conflicts.length, ")"] }), _jsx(Text, { color: theme.dim, children: "Existing assets with the same name \u2014 choose how to resolve" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [conflicts.slice(0, isCompact ? 4 : 8).map((c) => (_jsxs(Text, { color: theme.dim, wrap: "truncate", children: [assetTypeBadge(c.asset.type), " ", c.asset.name, " \u2192 conflicts with \"", c.existingLocalName, "\""] }, c.asset.id))), conflicts.length > (isCompact ? 4 : 8) && (_jsxs(Text, { color: theme.dim, children: ["\u2026and ", conflicts.length - (isCompact ? 4 : 8), " more"] }))] }), _jsx(Box, { marginTop: 1, children: _jsx(CustomSelectInput, { items: [
282
+ { label: 'Ask for each conflict', value: 'ask' },
283
+ { label: 'Rename all conflicting items', value: 'rename-all' },
284
+ { label: 'Skip all conflicting items', value: 'skip-all' },
285
+ { label: 'Replace all existing items', value: 'replace-all' },
286
+ ], onSelect: (item) => {
287
+ const mode = item.value;
288
+ setConflictBulkMode(mode);
289
+ if (mode === 'rename-all') {
290
+ setConflicts(applyAutoRenameConflicts(conflicts, 'suffix'));
291
+ setStep('confirm');
292
+ }
293
+ else if (mode === 'skip-all') {
294
+ setConflicts(conflicts.map((c) => ({ ...c, resolution: 'skip' })));
295
+ setStep('confirm');
296
+ }
297
+ else if (mode === 'replace-all') {
298
+ setConflicts(conflicts.map((c) => ({ ...c, resolution: 'overwrite', resolvedName: c.existingLocalName })));
299
+ setStep('confirm');
300
+ }
301
+ else {
302
+ // ask mode — walk through each conflict
303
+ setConflictCursor(0);
304
+ setStep('conflict-item');
305
+ }
306
+ } }) })] }));
307
+ }
308
+ if (step === 'conflict-item' && conflictCursor < conflicts.length) {
309
+ const c = conflicts[conflictCursor];
310
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Header, { compact: true }), _jsxs(Text, { bold: true, color: theme.warning, children: ["Conflict ", conflictCursor + 1, " of ", conflicts.length] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { children: [assetTypeBadge(c.asset.type), " ", _jsx(Text, { bold: true, children: c.asset.name }), " already exists as \"", c.existingLocalName, "\""] }), _jsxs(Text, { color: theme.dim, children: ["Source: ", c.asset.originLabel] })] }), _jsx(Box, { marginTop: 1, children: _jsx(CustomSelectInput, { items: [
311
+ { label: `Rename to "${c.resolvedName}"`, value: 'rename' },
312
+ { label: 'Skip this asset', value: 'skip' },
313
+ { label: 'Replace existing', value: 'replace' },
314
+ ], onSelect: (item) => {
315
+ const updated = [...conflicts];
316
+ if (item.value === 'rename') {
317
+ updated[conflictCursor] = { ...c, resolution: 'rename' };
318
+ }
319
+ else if (item.value === 'skip') {
320
+ updated[conflictCursor] = { ...c, resolution: 'skip' };
321
+ }
322
+ else {
323
+ updated[conflictCursor] = { ...c, resolution: 'overwrite', resolvedName: c.existingLocalName };
324
+ }
325
+ setConflicts(updated);
326
+ if (conflictCursor + 1 < conflicts.length) {
327
+ setConflictCursor(conflictCursor + 1);
328
+ }
329
+ else {
330
+ setStep('confirm');
331
+ }
332
+ } }) })] }));
333
+ }
334
+ if (step === 'confirm') {
335
+ const renames = conflicts.filter((c) => c.resolution === 'rename').length;
336
+ const skips = conflicts.filter((c) => c.resolution === 'skip').length;
337
+ const replaces = conflicts.filter((c) => c.resolution === 'overwrite').length;
338
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Header, { compact: true }), _jsx(Text, { bold: true, children: "Confirm import" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { children: ["Source: ", _jsx(Text, { bold: true, children: adapters.find((a) => a.id === sourceId)?.label })] }), _jsxs(Text, { children: ["Skills: ", _jsx(Text, { bold: true, color: theme.primary, children: counts.skill })] }), _jsxs(Text, { children: ["Prompts: ", _jsx(Text, { bold: true, color: theme.success, children: counts.prompt })] }), _jsxs(Text, { children: ["MCPs: ", _jsx(Text, { bold: true, color: theme.warning, children: counts.mcp })] }), _jsxs(Text, { children: ["Destination: ", destination === 'github' ? 'GitHub environment' : 'Local'] }), _jsxs(Text, { children: ["Scope: ", scope] }), conflicts.length > 0 && (_jsxs(Text, { children: ["Conflicts: ", renames > 0 ? `${renames} rename` : '', skips > 0 ? `${renames > 0 ? ' · ' : ''}${skips} skip` : '', replaces > 0 ? `${renames > 0 || skips > 0 ? ' · ' : ''}${replaces} replace` : ''] }))] }), _jsx(Box, { marginTop: 1, children: _jsx(CustomSelectInput, { items: [
339
+ { label: 'Import now', value: 'go' },
340
+ { label: 'Cancel', value: 'cancel' },
341
+ ], onSelect: (item) => {
342
+ if (item.value === 'cancel') {
343
+ handleExit();
344
+ return;
345
+ }
346
+ setStep('importing');
347
+ } }) })] }));
348
+ }
349
+ return null;
350
+ };
351
+ // Space toggle handler for type-select pick mode
352
+ export function useImportPickInput(enabled, group, pickCursor, setSelections, activeType, setPickCursor) {
353
+ useInput((input, key) => {
354
+ if (!enabled)
355
+ return;
356
+ if (key.upArrow)
357
+ setPickCursor((p) => Math.max(0, p - 1));
358
+ if (key.downArrow)
359
+ setPickCursor((p) => Math.min(group.length - 1, p + 1));
360
+ if (input === ' ') {
361
+ const id = group[pickCursor]?.id;
362
+ if (!id)
363
+ return;
364
+ setSelections((prev) => {
365
+ const next = new Set(prev[activeType].selectedIds);
366
+ if (next.has(id))
367
+ next.delete(id);
368
+ else
369
+ next.add(id);
370
+ return { ...prev, [activeType]: { ...prev[activeType], selectedIds: next } };
371
+ });
372
+ }
373
+ });
374
+ }