inai-react-components 0.1.7 → 1.2.1

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 (62) hide show
  1. package/README.md +80 -0
  2. package/dist/commands/add.d.ts +38 -5
  3. package/dist/commands/add.d.ts.map +1 -1
  4. package/dist/commands/add.js +391 -80
  5. package/dist/commands/diff.d.ts +6 -0
  6. package/dist/commands/diff.d.ts.map +1 -1
  7. package/dist/commands/diff.js +92 -20
  8. package/dist/commands/init.d.ts +6 -3
  9. package/dist/commands/init.d.ts.map +1 -1
  10. package/dist/commands/init.js +33 -36
  11. package/dist/commands/mcp.d.ts +123 -0
  12. package/dist/commands/mcp.d.ts.map +1 -0
  13. package/dist/commands/mcp.js +289 -0
  14. package/dist/commands/migrate.d.ts +41 -0
  15. package/dist/commands/migrate.d.ts.map +1 -0
  16. package/dist/commands/migrate.js +139 -0
  17. package/dist/commands/registries.d.ts +46 -0
  18. package/dist/commands/registries.d.ts.map +1 -0
  19. package/dist/commands/registries.js +152 -0
  20. package/dist/commands/remove.d.ts +11 -0
  21. package/dist/commands/remove.d.ts.map +1 -0
  22. package/dist/commands/remove.js +170 -0
  23. package/dist/commands/schema.d.ts +16 -0
  24. package/dist/commands/schema.d.ts.map +1 -0
  25. package/dist/commands/schema.js +32 -0
  26. package/dist/commands/status.d.ts +32 -3
  27. package/dist/commands/status.d.ts.map +1 -1
  28. package/dist/commands/status.js +148 -25
  29. package/dist/commands/theme.d.ts.map +1 -1
  30. package/dist/commands/theme.js +3 -37
  31. package/dist/commands/update.d.ts +18 -1
  32. package/dist/commands/update.d.ts.map +1 -1
  33. package/dist/commands/update.js +195 -5
  34. package/dist/index.js +76 -5
  35. package/dist/schemas/registry-config.schema.json +62 -0
  36. package/dist/schemas/registry-item.schema.json +63 -0
  37. package/dist/schemas/registry.schema.json +15 -0
  38. package/dist/types/registry.d.ts +50 -0
  39. package/dist/types/registry.d.ts.map +1 -0
  40. package/dist/types/registry.js +10 -0
  41. package/dist/utils/auto-install.d.ts +11 -0
  42. package/dist/utils/auto-install.d.ts.map +1 -0
  43. package/dist/utils/auto-install.js +29 -0
  44. package/dist/utils/framework-detect.d.ts +15 -0
  45. package/dist/utils/framework-detect.d.ts.map +1 -0
  46. package/dist/utils/framework-detect.js +90 -0
  47. package/dist/utils/fuzzy-search.d.ts +16 -0
  48. package/dist/utils/fuzzy-search.d.ts.map +1 -0
  49. package/dist/utils/fuzzy-search.js +67 -0
  50. package/dist/utils/registry-config.d.ts +27 -0
  51. package/dist/utils/registry-config.d.ts.map +1 -0
  52. package/dist/utils/registry-config.js +94 -0
  53. package/dist/utils/registry-resolver.d.ts +26 -0
  54. package/dist/utils/registry-resolver.d.ts.map +1 -1
  55. package/dist/utils/registry-resolver.js +134 -10
  56. package/dist/utils/snapshot.d.ts +20 -0
  57. package/dist/utils/snapshot.d.ts.map +1 -0
  58. package/dist/utils/snapshot.js +32 -0
  59. package/dist/utils/themes.d.ts +17 -0
  60. package/dist/utils/themes.d.ts.map +1 -0
  61. package/dist/utils/themes.js +49 -0
  62. package/package.json +9 -3
@@ -2,33 +2,80 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import chalk from "chalk";
4
4
  import ora from "ora";
5
+ import { diffLines } from "diff";
5
6
  import { readComponentsJson, readRegistryJson, } from "./status.js";
6
7
  import { resolveRegistryDir } from "../utils/registry-resolver.js";
8
+ const CONTEXT_LINES = 2;
9
+ /**
10
+ * Render a unified-style colored diff between two strings using a real
11
+ * LCS-based algorithm (`diffLines` from the `diff` package). Lines that
12
+ * changed are shown in red/green; unchanged lines are only shown as dim
13
+ * context within `CONTEXT_LINES` of a change.
14
+ */
7
15
  export function computeDiff(localContent, registryContent) {
8
- const localLines = localContent.split("\n");
9
- const registryLines = registryContent.split("\n");
16
+ // `diffLines` reports hunks: each has `value` (the text), and flags
17
+ // `added` (present only in the second arg) or `removed` (present only in
18
+ // the first arg). Neither flag means unchanged.
19
+ // We pass (registryContent, localContent) so that "added" means the
20
+ // local file added a line vs the registry (green +), and "removed" means
21
+ // the line was removed from the registry in the local file (red -).
22
+ const hunks = diffLines(registryContent, localContent);
23
+ const hasChanges = hunks.some((h) => h.added || h.removed);
24
+ if (!hasChanges) {
25
+ return chalk.green("No differences found. Component is up to date.");
26
+ }
10
27
  const output = [];
11
- const maxLen = Math.max(localLines.length, registryLines.length);
12
- let hasChanges = false;
13
- for (let i = 0; i < maxLen; i++) {
14
- const localLine = localLines[i];
15
- const registryLine = registryLines[i];
16
- if (localLine === registryLine) {
17
- output.push(chalk.dim(` ${localLine ?? ""}`));
28
+ for (let i = 0; i < hunks.length; i++) {
29
+ const hunk = hunks[i];
30
+ const lines = hunk.value.replace(/\n$/, "").split("\n");
31
+ if (hunk.added) {
32
+ for (const line of lines) {
33
+ output.push(chalk.green(`+ ${line}`));
34
+ }
35
+ }
36
+ else if (hunk.removed) {
37
+ for (const line of lines) {
38
+ output.push(chalk.red(`- ${line}`));
39
+ }
18
40
  }
19
41
  else {
20
- hasChanges = true;
21
- if (registryLine !== undefined) {
22
- output.push(chalk.red(`- ${registryLine}`));
42
+ // Unchanged hunk — keep only CONTEXT_LINES around neighboring changes.
43
+ const prevChanged = i > 0 && (hunks[i - 1].added || hunks[i - 1].removed);
44
+ const nextChanged = i < hunks.length - 1 && (hunks[i + 1].added || hunks[i + 1].removed);
45
+ if (!prevChanged && !nextChanged) {
46
+ continue;
47
+ }
48
+ if (prevChanged && nextChanged && lines.length > CONTEXT_LINES * 2) {
49
+ // Show trailing context from previous change, a separator, then
50
+ // leading context for next change.
51
+ for (let j = 0; j < CONTEXT_LINES; j++) {
52
+ output.push(chalk.dim(` ${lines[j]}`));
53
+ }
54
+ output.push(chalk.dim(" ..."));
55
+ for (let j = lines.length - CONTEXT_LINES; j < lines.length; j++) {
56
+ output.push(chalk.dim(` ${lines[j]}`));
57
+ }
23
58
  }
24
- if (localLine !== undefined) {
25
- output.push(chalk.green(`+ ${localLine}`));
59
+ else if (prevChanged) {
60
+ const end = Math.min(lines.length, CONTEXT_LINES);
61
+ for (let j = 0; j < end; j++) {
62
+ output.push(chalk.dim(` ${lines[j]}`));
63
+ }
64
+ if (lines.length > CONTEXT_LINES) {
65
+ output.push(chalk.dim(" ..."));
66
+ }
67
+ }
68
+ else if (nextChanged) {
69
+ const start = Math.max(0, lines.length - CONTEXT_LINES);
70
+ if (start > 0) {
71
+ output.push(chalk.dim(" ..."));
72
+ }
73
+ for (let j = start; j < lines.length; j++) {
74
+ output.push(chalk.dim(` ${lines[j]}`));
75
+ }
26
76
  }
27
77
  }
28
78
  }
29
- if (!hasChanges) {
30
- return chalk.green("No differences found. Component is up to date.");
31
- }
32
79
  return output.join("\n");
33
80
  }
34
81
  export function findComponentInRegistry(registryPath, componentName) {
@@ -42,6 +89,29 @@ export function findComponentInRegistry(registryPath, componentName) {
42
89
  ];
43
90
  return allItems.find((c) => c.name === componentName) ?? null;
44
91
  }
92
+ /**
93
+ * Map a registry component to the alias slot that should hold its local copy.
94
+ * Fixes the earlier bug where `diff` always assumed `aliases.components`.
95
+ */
96
+ function getLocalAliasDir(component, componentsJson) {
97
+ const type = component.type.toLowerCase();
98
+ if (type === "block") {
99
+ return componentsJson.aliases.blocks.replace(/^@\//, "src/");
100
+ }
101
+ if (type === "template") {
102
+ // ComponentsJsonFile doesn't officially type `aliases.templates`, but
103
+ // it may be present in user config — fall back to blocks/templates.
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
+ const templatesAlias = componentsJson.aliases.templates;
106
+ if (templatesAlias) {
107
+ return templatesAlias.replace(/^@\//, "src/");
108
+ }
109
+ const blocksDir = componentsJson.aliases.blocks.replace(/^@\//, "src/");
110
+ const parent = path.dirname(blocksDir);
111
+ return path.join(parent, "templates");
112
+ }
113
+ return componentsJson.aliases.components.replace(/^@\//, "src/");
114
+ }
45
115
  export async function runDiff(componentName, rootDir) {
46
116
  const componentsJson = readComponentsJson(rootDir);
47
117
  if (!componentsJson) {
@@ -57,11 +127,14 @@ export async function runDiff(componentName, rootDir) {
57
127
  return chalk.yellow(`Component "${componentName}" has no files in the registry.`);
58
128
  }
59
129
  const results = [];
130
+ const localComponentDir = getLocalAliasDir(registryComponent, componentsJson);
131
+ const isMultiFile = registryComponent.type === "block" || registryComponent.type === "template";
60
132
  for (const filePath of registryComponent.files) {
61
133
  const registryFilePath = path.join(registryDir, filePath);
62
- const localComponentDir = componentsJson.aliases.components.replace(/^@\//, "src/");
63
134
  const fileName = path.basename(filePath);
64
- const localFilePath = path.join(rootDir, localComponentDir, fileName);
135
+ const localFilePath = isMultiFile
136
+ ? path.join(rootDir, localComponentDir, componentName, fileName)
137
+ : path.join(rootDir, localComponentDir, fileName);
65
138
  results.push(chalk.bold(`\nDiff for ${fileName}:`));
66
139
  results.push(chalk.dim("─".repeat(60)));
67
140
  if (!fs.existsSync(registryFilePath)) {
@@ -71,7 +144,6 @@ export async function runDiff(componentName, rootDir) {
71
144
  const registryContent = fs.readFileSync(registryFilePath, "utf-8");
72
145
  if (!fs.existsSync(localFilePath)) {
73
146
  results.push(chalk.yellow(`Local file not found at ${localComponentDir}/${fileName}. Component may not be installed.`));
74
- // Show what registry has as all additions
75
147
  const lines = registryContent.split("\n");
76
148
  for (const line of lines) {
77
149
  results.push(chalk.green(`+ ${line}`));
@@ -1,5 +1,5 @@
1
- declare const AVAILABLE_THEMES: readonly ["inai", "monday", "linear", "notion", "vercel", "anthropic", "shadcn-default", "shadcn-blue", "shadcn-green", "shadcn-orange", "shadcn-red", "shadcn-rose", "shadcn-violet", "shadcn-yellow", "shadcn-amber", "shadcn-lime", "shadcn-emerald", "shadcn-teal", "shadcn-cyan", "shadcn-sky", "shadcn-indigo", "shadcn-purple", "shadcn-fuchsia", "shadcn-pink"];
2
- type Theme = (typeof AVAILABLE_THEMES)[number];
1
+ import { type Framework } from "../utils/framework-detect.js";
2
+ type Theme = string;
3
3
  declare const FONT_PRESETS: readonly [{
4
4
  readonly name: "outfit";
5
5
  readonly label: "Outfit";
@@ -227,11 +227,14 @@ export interface InitConfig {
227
227
  tanstackQuery: boolean;
228
228
  tanstackForm: boolean;
229
229
  tanstackTable: boolean;
230
+ framework?: Framework;
231
+ cssEntryPoint?: string;
230
232
  }
231
233
  export interface ComponentsJson {
232
234
  $schema: string;
233
235
  registrySource?: string;
234
236
  style: string;
237
+ framework?: Framework;
235
238
  tailwind: {
236
239
  config: string;
237
240
  css: string;
@@ -254,7 +257,7 @@ export interface ComponentsJson {
254
257
  table: boolean;
255
258
  };
256
259
  }
257
- export declare function promptInitConfig(registryDir?: string): Promise<InitConfig | null>;
260
+ export declare function promptInitConfig(registryDir?: string, framework?: Framework): Promise<InitConfig | null>;
258
261
  export declare function buildComponentsJson(config: InitConfig, repoUrl?: string): ComponentsJson;
259
262
  export declare function getCnTemplate(): string;
260
263
  export declare function getLocalTailwindCssTemplate(theme: Theme, fontBody: FontPreset, fontHeading: FontPreset, radius: number): string;
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -4,32 +4,9 @@ import chalk from "chalk";
4
4
  import ora from "ora";
5
5
  import prompts from "prompts";
6
6
  import { cloneRegistry, getCacheDir } from "../utils/registry-resolver.js";
7
- const AVAILABLE_THEMES = [
8
- "inai",
9
- "monday",
10
- "linear",
11
- "notion",
12
- "vercel",
13
- "anthropic",
14
- "shadcn-default",
15
- "shadcn-blue",
16
- "shadcn-green",
17
- "shadcn-orange",
18
- "shadcn-red",
19
- "shadcn-rose",
20
- "shadcn-violet",
21
- "shadcn-yellow",
22
- "shadcn-amber",
23
- "shadcn-lime",
24
- "shadcn-emerald",
25
- "shadcn-teal",
26
- "shadcn-cyan",
27
- "shadcn-sky",
28
- "shadcn-indigo",
29
- "shadcn-purple",
30
- "shadcn-fuchsia",
31
- "shadcn-pink",
32
- ];
7
+ import { THEME_NAMES } from "../utils/themes.js";
8
+ import { detectFramework, frameworkLabel, getCssEntryPoint, } from "../utils/framework-detect.js";
9
+ const AVAILABLE_THEMES = THEME_NAMES;
33
10
  const FONT_PRESETS = [
34
11
  // Sans-serif — geometric & modern
35
12
  { name: "outfit", label: "Outfit", family: "'Outfit', system-ui, sans-serif" },
@@ -111,8 +88,11 @@ function discoverThemes(registryDir) {
111
88
  }
112
89
  return [...AVAILABLE_THEMES];
113
90
  }
114
- export async function promptInitConfig(registryDir) {
91
+ export async function promptInitConfig(registryDir, framework) {
115
92
  const themes = discoverThemes(registryDir);
93
+ const defaultCssEntry = framework
94
+ ? getCssEntryPoint(framework)
95
+ : "src/index.css";
116
96
  const response = await prompts([
117
97
  {
118
98
  type: "text",
@@ -198,15 +178,19 @@ export async function promptInitConfig(registryDir) {
198
178
  if (!response.componentPath) {
199
179
  return null;
200
180
  }
201
- return response;
181
+ const config = response;
182
+ config.framework = framework;
183
+ config.cssEntryPoint = defaultCssEntry;
184
+ return config;
202
185
  }
203
186
  export function buildComponentsJson(config, repoUrl) {
204
187
  const json = {
205
188
  $schema: "https://inai-ui.dev/schema.json",
206
189
  style: "default",
190
+ framework: config.framework,
207
191
  tailwind: {
208
192
  config: "tailwind.config.ts",
209
- css: "src/index.css",
193
+ css: config.cssEntryPoint ?? "src/index.css",
210
194
  },
211
195
  aliases: {
212
196
  components: config.importAlias,
@@ -248,7 +232,8 @@ function getFontFamily(font) {
248
232
  }
249
233
  export function getLocalTailwindCssTemplate(theme, fontBody, fontHeading, radius) {
250
234
  return `@import "tailwindcss";
251
- @import "./styles/tokens/index.css";
235
+ @import "./styles/tokens/primitives/colors.css";
236
+ @import "./styles/tokens/base.css";
252
237
  @import "./styles/tokens/themes/${theme}.css";
253
238
  @import "./styles/tokens/presets/typography.css";
254
239
  @import "./styles/tokens/presets/animations.css";
@@ -318,13 +303,23 @@ function copyTokensToProject(registryDir, targetDir, theme) {
318
303
  return copied;
319
304
  fs.mkdirSync(tokensDest, { recursive: true });
320
305
  // Copy base files
321
- for (const file of ["base.css", "index.css"]) {
306
+ for (const file of ["base.css"]) {
322
307
  const src = path.join(tokensSrc, file);
323
308
  if (fs.existsSync(src)) {
324
309
  fs.copyFileSync(src, path.join(tokensDest, file));
325
310
  copied.push(`src/styles/tokens/${file}`);
326
311
  }
327
312
  }
313
+ // Copy primitives (color scales referenced by all themes)
314
+ const primitivesSrc = path.join(tokensSrc, "primitives");
315
+ const primitivesDest = path.join(tokensDest, "primitives");
316
+ if (fs.existsSync(primitivesSrc)) {
317
+ const primitiveCopied = copyDirRecursive(primitivesSrc, primitivesDest);
318
+ for (const file of primitiveCopied) {
319
+ const rel = path.relative(targetDir, file);
320
+ copied.push(rel);
321
+ }
322
+ }
328
323
  // Copy selected theme (normalized so it applies without data-theme attribute)
329
324
  const themesSrc = path.join(tokensSrc, "themes");
330
325
  const themesDest = path.join(tokensDest, "themes");
@@ -373,9 +368,9 @@ export async function runInit(config, targetDir, repoUrl) {
373
368
  fs.writeFileSync(cnPath, getCnTemplate());
374
369
  filesCreated.push("src/lib/cn.ts");
375
370
  // 4. Copy tokens and create CSS
376
- const cssDir = path.join(targetDir, "src");
377
- fs.mkdirSync(cssDir, { recursive: true });
378
- const cssPath = path.join(cssDir, "index.css");
371
+ const cssRelPath = config.cssEntryPoint ?? "src/index.css";
372
+ const cssPath = path.join(targetDir, cssRelPath);
373
+ fs.mkdirSync(path.dirname(cssPath), { recursive: true });
379
374
  if (repoUrl) {
380
375
  // Remote mode: copy tokens from cached registry
381
376
  const registryDir = getCacheDir();
@@ -387,11 +382,13 @@ export async function runInit(config, targetDir, repoUrl) {
387
382
  // Local mode: reference @company/tokens package
388
383
  fs.writeFileSync(cssPath, getLegacyTailwindCssTemplate(config.theme, config.fontBody, config.fontHeading, config.radius));
389
384
  }
390
- filesCreated.push("src/index.css");
385
+ filesCreated.push(cssRelPath);
391
386
  return { success: true, filesCreated };
392
387
  }
393
388
  export async function initCommand(repoUrl) {
394
389
  console.log(chalk.bold("\nInAI UI - Project Initialization\n"));
390
+ const detectedFramework = detectFramework(process.cwd());
391
+ console.log(chalk.dim(`Detected framework: ${frameworkLabel(detectedFramework)}`));
395
392
  if (repoUrl) {
396
393
  const spinner = ora("Cloning component registry...").start();
397
394
  try {
@@ -407,7 +404,7 @@ export async function initCommand(repoUrl) {
407
404
  }
408
405
  }
409
406
  const registryDir = repoUrl ? getCacheDir() : undefined;
410
- const config = await promptInitConfig(registryDir);
407
+ const config = await promptInitConfig(registryDir, detectedFramework);
411
408
  if (!config) {
412
409
  console.log(chalk.yellow("\nInitialization cancelled."));
413
410
  process.exit(0);
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Print the JSON config fragment that users must drop into their Claude
3
+ * Desktop or Cursor `mcpServers` block. Invoked from `inai-ui mcp init`.
4
+ */
5
+ export declare function printMcpConfig(): void;
6
+ export interface ToolTextResult {
7
+ content: Array<{
8
+ type: "text";
9
+ text: string;
10
+ }>;
11
+ isError?: boolean;
12
+ }
13
+ export declare function handleListComponents(args: {
14
+ category?: string;
15
+ } | undefined, cwd: string): Promise<ToolTextResult>;
16
+ export declare function handleViewComponent(args: {
17
+ name?: string;
18
+ } | undefined, cwd: string): Promise<ToolTextResult>;
19
+ export declare function handleAddComponent(args: {
20
+ name?: string;
21
+ force?: boolean;
22
+ } | undefined, cwd: string): Promise<ToolTextResult>;
23
+ export declare function handleDiffComponent(args: {
24
+ name?: string;
25
+ } | undefined, cwd: string): Promise<ToolTextResult>;
26
+ export declare function handleUpdateComponent(args: {
27
+ name?: string;
28
+ } | undefined, cwd: string): Promise<ToolTextResult>;
29
+ export declare function handleListThemes(): Promise<ToolTextResult>;
30
+ export declare function handleStatus(args: {
31
+ json?: boolean;
32
+ } | undefined, cwd: string): Promise<ToolTextResult>;
33
+ export declare const MCP_TOOLS: readonly [{
34
+ readonly name: "list_components";
35
+ readonly description: "List all available components, blocks and templates in the InAI UI registry.";
36
+ readonly inputSchema: {
37
+ readonly type: "object";
38
+ readonly properties: {
39
+ readonly category: {
40
+ readonly type: "string";
41
+ readonly description: "Optional type filter (e.g. 'component', 'form', 'block').";
42
+ };
43
+ };
44
+ };
45
+ }, {
46
+ readonly name: "view_component";
47
+ readonly description: "View the source code of a component from the registry.";
48
+ readonly inputSchema: {
49
+ readonly type: "object";
50
+ readonly properties: {
51
+ readonly name: {
52
+ readonly type: "string";
53
+ readonly description: "Component name";
54
+ };
55
+ };
56
+ readonly required: readonly ["name"];
57
+ };
58
+ }, {
59
+ readonly name: "add_component";
60
+ readonly description: "Install a component (and its transitive registry dependencies) into the current project.";
61
+ readonly inputSchema: {
62
+ readonly type: "object";
63
+ readonly properties: {
64
+ readonly name: {
65
+ readonly type: "string";
66
+ readonly description: "Component name";
67
+ };
68
+ readonly force: {
69
+ readonly type: "boolean";
70
+ readonly description: "Overwrite existing files without prompting.";
71
+ };
72
+ };
73
+ readonly required: readonly ["name"];
74
+ };
75
+ }, {
76
+ readonly name: "diff_component";
77
+ readonly description: "Show a unified diff between the locally-installed component and the registry version.";
78
+ readonly inputSchema: {
79
+ readonly type: "object";
80
+ readonly properties: {
81
+ readonly name: {
82
+ readonly type: "string";
83
+ readonly description: "Component name";
84
+ };
85
+ };
86
+ readonly required: readonly ["name"];
87
+ };
88
+ }, {
89
+ readonly name: "update_component";
90
+ readonly description: "Update an installed component to the latest registry version using a 3-way merge against the snapshot captured at install time. Emits conflict markers when local and registry edits overlap.";
91
+ readonly inputSchema: {
92
+ readonly type: "object";
93
+ readonly properties: {
94
+ readonly name: {
95
+ readonly type: "string";
96
+ readonly description: "Component name";
97
+ };
98
+ };
99
+ readonly required: readonly ["name"];
100
+ };
101
+ }, {
102
+ readonly name: "list_themes";
103
+ readonly description: "List the available InAI UI themes with their categories and descriptions.";
104
+ readonly inputSchema: {
105
+ readonly type: "object";
106
+ readonly properties: {};
107
+ };
108
+ }, {
109
+ readonly name: "project_status";
110
+ readonly description: "Return the InAI UI project status (HEALTHY / DRIFT / OUTDATED / MISSING per component).";
111
+ readonly inputSchema: {
112
+ readonly type: "object";
113
+ readonly properties: {
114
+ readonly json: {
115
+ readonly type: "boolean";
116
+ readonly description: "Return JSON payload (default true).";
117
+ };
118
+ };
119
+ };
120
+ }];
121
+ export declare function runMcp(cwd?: string): Promise<void>;
122
+ export declare function mcpCommand(subcommand?: "init"): Promise<void>;
123
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAgCA;;;GAGG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAErC;AAID,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AASD,wBAAsB,oBAAoB,CACxC,IAAI,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EACvC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CAKzB;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EACnC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CA8BzB;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,EACpD,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CAkBzB;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EACnC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CAmCzB;AAED,wBAAsB,qBAAqB,CACzC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EACnC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CAgBzB;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,cAAc,CAAC,CAEhE;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,EACpC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,CAAC,CAGzB;AAID,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoFZ,CAAC;AAEX,wBAAsB,MAAM,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiEvE;AAED,wBAAsB,UAAU,CAC9B,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAMf"}