ekairos-cli 0.1.0 → 0.1.2
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/README.md +55 -55
- package/dist/index.js +46 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
# Ekairos CLI
|
|
2
|
-
|
|
3
|
-
The official CLI for managing Ekairos UI components and agents.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Interactive UI**: Built with Ink (React for CLI).
|
|
8
|
-
- **Auto-Configuration**: Automatically configures `components.json` for the Ekairos registry.
|
|
9
|
-
- **Component Management**: Detects installed components and offers bulk updates.
|
|
10
|
-
- **Seamless Integration**: Wraps `shadcn` CLI to ensure consistent installations.
|
|
11
|
-
- **Async/Session Mode**: Designed for AI agents and automation.
|
|
12
|
-
|
|
13
|
-
## Usage
|
|
14
|
-
|
|
15
|
-
Run the CLI in your project root:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npx ekairos@latest
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
### AI / Automation Mode
|
|
22
|
-
|
|
23
|
-
For automated interactions, use the `--async` flag. The CLI will output JSON state and exit, allowing you to resume the session with inputs.
|
|
24
|
-
|
|
25
|
-
1. **Start Session**:
|
|
26
|
-
```bash
|
|
27
|
-
npx ekairos --async
|
|
28
|
-
```
|
|
29
|
-
Output:
|
|
30
|
-
```json
|
|
31
|
-
{
|
|
32
|
-
"sessionId": "uuid...",
|
|
33
|
-
"step": "MENU",
|
|
34
|
-
"inputSchema": { ... }
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
2. **Continue Session**:
|
|
39
|
-
```bash
|
|
40
|
-
npx ekairos --session <uuid> --input '{"action": "update-all"}'
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Development
|
|
44
|
-
|
|
45
|
-
To run locally against a local registry:
|
|
46
|
-
|
|
47
|
-
1. Start the registry server (`packages/registry`).
|
|
48
|
-
2. Build the CLI:
|
|
49
|
-
```bash
|
|
50
|
-
pnpm --filter ekairos build
|
|
51
|
-
```
|
|
52
|
-
3. Run with override:
|
|
53
|
-
```bash
|
|
54
|
-
EKAIROS_REGISTRY_URL="http://localhost:3001" node packages/cli/dist/index.mjs
|
|
55
|
-
```
|
|
1
|
+
# Ekairos CLI
|
|
2
|
+
|
|
3
|
+
The official CLI for managing Ekairos UI components and agents.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Interactive UI**: Built with Ink (React for CLI).
|
|
8
|
+
- **Auto-Configuration**: Automatically configures `components.json` for the Ekairos registry.
|
|
9
|
+
- **Component Management**: Detects installed components and offers bulk updates.
|
|
10
|
+
- **Seamless Integration**: Wraps `shadcn` CLI to ensure consistent installations.
|
|
11
|
+
- **Async/Session Mode**: Designed for AI agents and automation.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Run the CLI in your project root:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx ekairos@latest
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### AI / Automation Mode
|
|
22
|
+
|
|
23
|
+
For automated interactions, use the `--async` flag. The CLI will output JSON state and exit, allowing you to resume the session with inputs.
|
|
24
|
+
|
|
25
|
+
1. **Start Session**:
|
|
26
|
+
```bash
|
|
27
|
+
npx ekairos --async
|
|
28
|
+
```
|
|
29
|
+
Output:
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"sessionId": "uuid...",
|
|
33
|
+
"step": "MENU",
|
|
34
|
+
"inputSchema": { ... }
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
2. **Continue Session**:
|
|
39
|
+
```bash
|
|
40
|
+
npx ekairos --session <uuid> --input '{"action": "update-all"}'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Development
|
|
44
|
+
|
|
45
|
+
To run locally against a local registry:
|
|
46
|
+
|
|
47
|
+
1. Start the registry server (`packages/registry`).
|
|
48
|
+
2. Build the CLI:
|
|
49
|
+
```bash
|
|
50
|
+
pnpm --filter ekairos build
|
|
51
|
+
```
|
|
52
|
+
3. Run with override:
|
|
53
|
+
```bash
|
|
54
|
+
EKAIROS_REGISTRY_URL="http://localhost:3001" node packages/cli/dist/index.mjs
|
|
55
|
+
```
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import { useState, useEffect } from "react";
|
|
|
9
9
|
import { Box, Text, useApp } from "ink";
|
|
10
10
|
import Spinner from "ink-spinner";
|
|
11
11
|
import SelectInput from "ink-select-input";
|
|
12
|
+
import { createRequire } from "module";
|
|
12
13
|
|
|
13
14
|
// src/lib/shadcn.ts
|
|
14
15
|
import fs from "fs-extra";
|
|
@@ -20,7 +21,7 @@ var getRegistryUrl = () => {
|
|
|
20
21
|
if (process.env.EKAIROS_REGISTRY_URL) {
|
|
21
22
|
return process.env.EKAIROS_REGISTRY_URL;
|
|
22
23
|
}
|
|
23
|
-
return "https://registry.ekairos.dev";
|
|
24
|
+
return "https://registry.ekairos.dev/";
|
|
24
25
|
};
|
|
25
26
|
var REGISTRY_ALIAS = "@ekairos";
|
|
26
27
|
|
|
@@ -35,9 +36,15 @@ async function ensureEkairosRegistry() {
|
|
|
35
36
|
if (!config.registries) {
|
|
36
37
|
config.registries = {};
|
|
37
38
|
}
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
|
|
39
|
+
const rawRegistryUrl = getRegistryUrl();
|
|
40
|
+
const sanitizedUrl = rawRegistryUrl.trim().replace(/\s+/g, "");
|
|
41
|
+
let registryConfigUrl;
|
|
42
|
+
if (sanitizedUrl.includes("{name}")) {
|
|
43
|
+
registryConfigUrl = sanitizedUrl;
|
|
44
|
+
} else {
|
|
45
|
+
const baseUrl = sanitizedUrl.replace(/\/registry\.json$/i, "").replace(/\/+$/, "");
|
|
46
|
+
registryConfigUrl = `${baseUrl}/{name}.json`;
|
|
47
|
+
}
|
|
41
48
|
if (config.registries[REGISTRY_ALIAS] !== registryConfigUrl) {
|
|
42
49
|
config.registries[REGISTRY_ALIAS] = registryConfigUrl;
|
|
43
50
|
await fs.writeJson(configPath, config, { spaces: 2 });
|
|
@@ -55,7 +62,7 @@ async function getInstalledComponents() {
|
|
|
55
62
|
const files = await fs.readdir(fullPath, { recursive: true });
|
|
56
63
|
const detected = [];
|
|
57
64
|
const fileList = Array.isArray(files) ? files : [];
|
|
58
|
-
if (await fs.pathExists(path.join(fullPath, "agent"))) detected.push("
|
|
65
|
+
if (await fs.pathExists(path.join(fullPath, "agent"))) detected.push("agent");
|
|
59
66
|
return detected;
|
|
60
67
|
}
|
|
61
68
|
}
|
|
@@ -84,6 +91,8 @@ async function initShadcn() {
|
|
|
84
91
|
|
|
85
92
|
// src/app.tsx
|
|
86
93
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
94
|
+
var require2 = createRequire(import.meta.url);
|
|
95
|
+
var { version: CLI_VERSION = "dev" } = require2("../package.json");
|
|
87
96
|
var REGISTRY_URL = getRegistryUrl();
|
|
88
97
|
function App() {
|
|
89
98
|
const { exit } = useApp();
|
|
@@ -132,12 +141,12 @@ function App() {
|
|
|
132
141
|
} else if (item.value === "update-all" || item.value === "install-essentials") {
|
|
133
142
|
setState((s) => ({ ...s, step: "installing", message: "Running shadcn..." }));
|
|
134
143
|
try {
|
|
135
|
-
const componentsToInstall = item.value === "update-all" ? state.installedComponents : ["@ekairos/
|
|
144
|
+
const componentsToInstall = item.value === "update-all" ? state.installedComponents : ["@ekairos/agent"];
|
|
136
145
|
const targets = [...new Set(componentsToInstall)].map(
|
|
137
146
|
(c) => c.startsWith("@ekairos/") ? c : `@ekairos/${c}`
|
|
138
147
|
);
|
|
139
148
|
if (targets.length === 0) {
|
|
140
|
-
targets.push("@ekairos/
|
|
149
|
+
targets.push("@ekairos/agent");
|
|
141
150
|
}
|
|
142
151
|
for (const component of targets) {
|
|
143
152
|
setState((s) => ({ ...s, message: `Installing ${component}...` }));
|
|
@@ -163,10 +172,13 @@ function App() {
|
|
|
163
172
|
{ label: "Exit", value: "exit" }
|
|
164
173
|
];
|
|
165
174
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, children: [
|
|
166
|
-
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
|
|
167
|
-
/* @__PURE__ */
|
|
175
|
+
/* @__PURE__ */ jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [
|
|
176
|
+
/* @__PURE__ */ jsxs(Text, { bold: true, color: "cyan", children: [
|
|
177
|
+
"Ekairos CLI v",
|
|
178
|
+
CLI_VERSION
|
|
179
|
+
] }),
|
|
168
180
|
/* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
169
|
-
"
|
|
181
|
+
"using registry: ",
|
|
170
182
|
REGISTRY_URL
|
|
171
183
|
] })
|
|
172
184
|
] }),
|
|
@@ -281,11 +293,11 @@ async function processAsyncStep(state, input) {
|
|
|
281
293
|
if (input.action === "update-all" || input.action === "install-essentials") {
|
|
282
294
|
state.step = "INSTALLING";
|
|
283
295
|
await saveSession(state);
|
|
284
|
-
const componentsToInstall = input.action === "update-all" ? state.installedComponents : ["@ekairos/
|
|
296
|
+
const componentsToInstall = input.action === "update-all" ? state.installedComponents : ["@ekairos/agent"];
|
|
285
297
|
let targets = [...new Set(componentsToInstall)].map(
|
|
286
298
|
(c) => c.startsWith("@ekairos/") ? c : `@ekairos/${c}`
|
|
287
299
|
);
|
|
288
|
-
if (targets.length === 0) targets.push("@ekairos/
|
|
300
|
+
if (targets.length === 0) targets.push("@ekairos/agent");
|
|
289
301
|
for (const component of targets) {
|
|
290
302
|
await installComponent(component);
|
|
291
303
|
}
|
|
@@ -309,6 +321,7 @@ async function processAsyncStep(state, input) {
|
|
|
309
321
|
|
|
310
322
|
// src/index.tsx
|
|
311
323
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
324
|
+
var VALID_ACTIONS = /* @__PURE__ */ new Set(["init-shadcn", "update-all", "install-essentials", "exit"]);
|
|
312
325
|
var cli = meow(
|
|
313
326
|
`
|
|
314
327
|
Usage
|
|
@@ -318,6 +331,7 @@ var cli = meow(
|
|
|
318
331
|
--async Run in async/session mode
|
|
319
332
|
--session Session ID for continuing an async session
|
|
320
333
|
--input JSON input for the session step
|
|
334
|
+
--action Convenience flag for async actions (update-all, install-essentials, init-shadcn, exit)
|
|
321
335
|
|
|
322
336
|
Examples
|
|
323
337
|
$ ekairos --async
|
|
@@ -334,6 +348,9 @@ var cli = meow(
|
|
|
334
348
|
},
|
|
335
349
|
input: {
|
|
336
350
|
type: "string"
|
|
351
|
+
},
|
|
352
|
+
action: {
|
|
353
|
+
type: "string"
|
|
337
354
|
}
|
|
338
355
|
}
|
|
339
356
|
}
|
|
@@ -343,13 +360,29 @@ async function run() {
|
|
|
343
360
|
try {
|
|
344
361
|
let state;
|
|
345
362
|
let input = null;
|
|
363
|
+
const tryParseActionString = (value) => {
|
|
364
|
+
if (!value) return null;
|
|
365
|
+
const trimmed = value.trim();
|
|
366
|
+
return VALID_ACTIONS.has(trimmed) ? { action: trimmed } : null;
|
|
367
|
+
};
|
|
346
368
|
if (cli.flags.input) {
|
|
347
369
|
try {
|
|
348
370
|
input = JSON.parse(cli.flags.input);
|
|
349
371
|
} catch (e) {
|
|
350
|
-
|
|
372
|
+
input = tryParseActionString(cli.flags.input);
|
|
373
|
+
if (!input) {
|
|
374
|
+
console.error(JSON.stringify({ error: "Invalid JSON input" }));
|
|
375
|
+
process.exit(1);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (!input && cli.flags.action) {
|
|
380
|
+
const parsed = tryParseActionString(cli.flags.action);
|
|
381
|
+
if (!parsed) {
|
|
382
|
+
console.error(JSON.stringify({ error: "Invalid action value" }));
|
|
351
383
|
process.exit(1);
|
|
352
384
|
}
|
|
385
|
+
input = parsed;
|
|
353
386
|
}
|
|
354
387
|
if (cli.flags.session) {
|
|
355
388
|
state = await loadSession(cli.flags.session);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.tsx","../src/app.tsx","../src/lib/shadcn.ts","../src/lib/config.ts","../src/lib/session.ts"],"sourcesContent":["import React from 'react';\r\nimport { render } from 'ink';\r\nimport meow from 'meow';\r\nimport App from './app.js';\r\nimport { createSession, loadSession, processAsyncStep } from './lib/session.js';\r\n\r\nconst cli = meow(\r\n\t`\r\n\tUsage\r\n\t $ ekairos\r\n\r\n\tOptions\r\n\t\t--async Run in async/session mode\r\n\t\t--session Session ID for continuing an async session\r\n\t\t--input JSON input for the session step\r\n\r\n\tExamples\r\n\t $ ekairos --async\r\n\t $ ekairos --session <uuid> --input '{\"action\": \"update-all\"}'\r\n`,\r\n\t{\r\n\t\timportMeta: import.meta,\r\n\t\tflags: {\r\n\t\t\tasync: {\r\n\t\t\t\ttype: 'boolean',\r\n\t\t\t},\r\n\t\t\tsession: {\r\n\t\t\t\ttype: 'string',\r\n\t\t\t},\r\n\t\t\tinput: {\r\n\t\t\t\ttype: 'string',\r\n\t\t\t}\r\n\t\t},\r\n\t},\r\n);\r\n\r\nasync function run() {\r\n\tif (cli.flags.async || cli.flags.session) {\r\n\t\ttry {\r\n\t\t\tlet state;\r\n\t\t\tlet input = null;\r\n\r\n\t\t\tif (cli.flags.input) {\r\n\t\t\t\ttry {\r\n\t\t\t\t\tinput = JSON.parse(cli.flags.input);\r\n\t\t\t\t} catch (e) {\r\n\t\t\t\t\tconsole.error(JSON.stringify({ error: 'Invalid JSON input' }));\r\n\t\t\t\t\tprocess.exit(1);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (cli.flags.session) {\r\n\t\t\t\tstate = await loadSession(cli.flags.session);\r\n\t\t\t\tif (!state) {\r\n\t\t\t\t\tconsole.error(JSON.stringify({ error: 'Session not found or expired' }));\r\n\t\t\t\t\tprocess.exit(1);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t// New session\r\n\t\t\t\tstate = await createSession();\r\n\t\t\t}\r\n\r\n\t\t\tconst response = await processAsyncStep(state!, input);\r\n\t\t\tconsole.log(JSON.stringify(response, null, 2));\r\n\t\t\tprocess.exit(0);\r\n\r\n\t\t} catch (error) {\r\n\t\t\tconsole.error(JSON.stringify({ error: error instanceof Error ? error.message : 'Unknown error' }));\r\n\t\t\tprocess.exit(1);\r\n\t\t}\r\n\t} else {\r\n\t\t// Interactive Mode\r\n\t\trender(<App />);\r\n\t}\r\n}\r\n\r\nrun();\r\n","import React, { useState, useEffect } from 'react';\r\nimport { Box, Text, useApp } from 'ink';\r\nimport Spinner from 'ink-spinner';\r\nimport SelectInput from 'ink-select-input';\r\nimport { checkShadcnConfig, ensureEkairosRegistry, getInstalledComponents, installComponent, initShadcn } from './lib/shadcn.js';\r\nimport { getRegistryUrl } from './lib/config.js';\r\n\r\nconst REGISTRY_URL = getRegistryUrl();\r\n\r\ntype Step = 'check-config' | 'init-shadcn' | 'check-installed' | 'prompt-action' | 'installing' | 'success' | 'error';\r\n\r\ninterface AppState {\r\n step: Step;\r\n message: string;\r\n installedComponents: string[];\r\n error?: string;\r\n}\r\n\r\nexport default function App() {\r\n const { exit } = useApp();\r\n const [state, setState] = useState<AppState>({\r\n step: 'check-config',\r\n message: 'Checking configuration...',\r\n installedComponents: []\r\n });\r\n\r\n useEffect(() => {\r\n const init = async () => {\r\n try {\r\n // 1. Check Shadcn Config\r\n const hasConfig = await checkShadcnConfig();\r\n if (!hasConfig) {\r\n // Prompt for init\r\n setState(s => ({ ...s, step: 'init-shadcn', message: 'components.json not found.' }));\r\n return;\r\n }\r\n\r\n await runScan();\r\n\r\n } catch (err) {\r\n setState(s => ({ ...s, step: 'error', error: err instanceof Error ? err.message : 'Unknown error' }));\r\n }\r\n };\r\n\r\n if (state.step === 'check-config') {\r\n init();\r\n }\r\n }, [state.step]); // Dependency on step to retry after init\r\n\r\n const runScan = async () => {\r\n // 2. Ensure Registry Config\r\n await ensureEkairosRegistry();\r\n\r\n // 3. Check Installed Components\r\n setState(s => ({ ...s, step: 'check-installed', message: 'Scanning installed components...' }));\r\n const installed = await getInstalledComponents();\r\n \r\n setState({\r\n step: 'prompt-action',\r\n message: installed.length > 0 \r\n ? `Found ${installed.length} Ekairos components.` \r\n : 'No Ekairos components found.',\r\n installedComponents: installed,\r\n error: undefined\r\n });\r\n };\r\n\r\n const handleSelect = async (item: { value: string }) => {\r\n if (item.value === 'init-shadcn') {\r\n try {\r\n setState(s => ({ ...s, message: 'Initializing shadcn...' }));\r\n await initShadcn();\r\n // After init, check again\r\n setState(s => ({ ...s, step: 'check-config' }));\r\n } catch (err) {\r\n setState(s => ({ ...s, step: 'error', error: 'Failed to initialize shadcn.' }));\r\n }\r\n } else if (item.value === 'update-all' || item.value === 'install-essentials') {\r\n\r\n setState(s => ({ ...s, step: 'installing', message: 'Running shadcn...' }));\r\n \r\n try {\r\n const componentsToInstall = item.value === 'update-all' \r\n ? state.installedComponents \r\n : ['@ekairos/ekairos-agent-Agent']; // Default bundle\r\n\r\n // Dedup and ensure prefix\r\n const targets = [...new Set(componentsToInstall)].map(c => \r\n c.startsWith('@ekairos/') ? c : `@ekairos/${c}`\r\n );\r\n\r\n if (targets.length === 0) {\r\n // Fallback if update-all called but nothing detected, force agent\r\n targets.push('@ekairos/ekairos-agent-Agent');\r\n }\r\n\r\n for (const component of targets) {\r\n setState(s => ({ ...s, message: `Installing ${component}...` }));\r\n await installComponent(component);\r\n }\r\n\r\n setState(s => ({ ...s, step: 'success', message: 'All operations completed successfully!' }));\r\n setTimeout(() => exit(), 2000);\r\n\r\n } catch (err) {\r\n setState(s => ({ ...s, step: 'error', error: err instanceof Error ? err.message : 'Installation failed' }));\r\n }\r\n } else if (item.value === 'exit') {\r\n exit();\r\n }\r\n };\r\n\r\n const options = state.step === 'init-shadcn'\r\n ? [\r\n { label: 'Initialize shadcn project', value: 'init-shadcn' },\r\n { label: 'Exit', value: 'exit' }\r\n ]\r\n : state.installedComponents.length > 0\r\n ? [\r\n { label: 'Update all components', value: 'update-all' },\r\n { label: 'Exit', value: 'exit' }\r\n ]\r\n : [\r\n { label: 'Install Ekairos Essentials (Agent)', value: 'install-essentials' },\r\n { label: 'Exit', value: 'exit' }\r\n ];\r\n\r\n return (\r\n <Box flexDirection=\"column\" padding={1}>\r\n <Box marginBottom={1}>\r\n <Text bold color=\"cyan\">Ekairos CLI</Text>\r\n <Text color=\"gray\"> using registry: {REGISTRY_URL}</Text>\r\n </Box>\r\n\r\n {(state.step === 'check-config' || state.step === 'check-installed' || state.step === 'installing') && (\r\n <Box>\r\n <Text color=\"green\"><Spinner type=\"dots\" /> </Text>\r\n <Text>{state.message}</Text>\r\n </Box>\r\n )}\r\n\r\n {(state.step === 'prompt-action' || state.step === 'init-shadcn') && (\r\n <Box flexDirection=\"column\">\r\n <Text marginBottom={1}>{state.message}</Text>\r\n <Text>What would you like to do?</Text>\r\n <SelectInput items={options} onSelect={handleSelect} />\r\n </Box>\r\n )}\r\n\r\n {state.step === 'success' && (\r\n <Box>\r\n <Text color=\"green\">✔ {state.message}</Text>\r\n </Box>\r\n )}\r\n\r\n {state.step === 'error' && (\r\n <Box>\r\n <Text color=\"red\">✖ Error: {state.error}</Text>\r\n </Box>\r\n )}\r\n </Box>\r\n );\r\n}\r\n\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport { execa } from 'execa';\r\nimport { REGISTRY_ALIAS, getRegistryUrl } from './config.js';\r\n\r\n// Check if components.json exists in CWD\r\nexport async function checkShadcnConfig(): Promise<boolean> {\r\n return fs.pathExists(path.join(process.cwd(), 'components.json'));\r\n}\r\n\r\n// Ensure @ekairos registry is configured in components.json\r\nexport async function ensureEkairosRegistry() {\r\n const configPath = path.join(process.cwd(), 'components.json');\r\n if (!await fs.pathExists(configPath)) return;\r\n\r\n const config = await fs.readJson(configPath);\r\n \r\n // We check if registries is configured\r\n if (!config.registries) {\r\n config.registries = {};\r\n }\r\n\r\n const registryUrl = getRegistryUrl();\r\n // Ensure URL pattern supports namespaces\r\n // If registryUrl ends with /registry.json, strip it to get base\r\n const baseUrl = registryUrl.replace(/\\/registry\\.json$/, '');\r\n const registryConfigUrl = `${baseUrl}/{name}.json`;\r\n\r\n // Update configuration if needed\r\n if (config.registries[REGISTRY_ALIAS] !== registryConfigUrl) {\r\n config.registries[REGISTRY_ALIAS] = registryConfigUrl;\r\n await fs.writeJson(configPath, config, { spaces: 2 });\r\n }\r\n}\r\n\r\n// Scan components to see what is installed\r\nexport async function getInstalledComponents(): Promise<string[]> {\r\n // Logic: Check src/components/ekairos folder? \r\n // Or check components.json aliases? \r\n // A simple robust way is checking the filesystem based on the alias.\r\n \r\n // Assuming default alias @/components\r\n // We can read components.json to find the resolved path for \"components\" alias if needed,\r\n // but searching for \"src/components/ekairos\" is a safe 80/20 bet for this project structure.\r\n \r\n const possiblePaths = [\r\n 'src/components/ekairos',\r\n 'components/ekairos',\r\n 'lib/components/ekairos'\r\n ];\r\n\r\n for (const p of possiblePaths) {\r\n const fullPath = path.join(process.cwd(), p);\r\n if (await fs.pathExists(fullPath)) {\r\n // Read directories/files in there\r\n // This is a heuristic. A file Agent.tsx means ekairos-agent-Agent is likely installed\r\n // Ideally we track this in a manifest, but we don't have one yet.\r\n // So we will just return detected component names based on files.\r\n \r\n // For simplicity in v1, we just return found files as a proxy for \"Agent\"\r\n const files = await fs.readdir(fullPath, { recursive: true });\r\n \r\n // If we find 'agent/Agent.tsx', we assume 'ekairos-agent-Agent'\r\n // This mapping is tricky without a manifest. \r\n // FOR NOW: We will return a generic list if any are found, or empty.\r\n // The prompt will effectively just list 'ekairos-agent-Agent' if detected.\r\n \r\n const detected = [];\r\n const fileList = Array.isArray(files) ? files : []; // readdir recursive returns string[] in node 20+? wait fs-extra might differ.\r\n \r\n // fs-extra readdir is standard. recursive not supported in older node with string, but let's assume standard recursive or walk.\r\n // Let's stick to checking specific known folders for v1.\r\n \r\n if (await fs.pathExists(path.join(fullPath, 'agent'))) detected.push('ekairos-agent-Agent');\r\n // Add more detections here as registry grows\r\n \r\n return detected;\r\n }\r\n }\r\n \r\n return [];\r\n}\r\n\r\nexport async function installComponent(componentName: string) {\r\n // Run shadcn add\r\n // npx --yes shadcn@latest add @ekairos/name -y --overwrite\r\n \r\n // Ensure component has prefix if it's a known component without one\r\n // But for now, we assume input is correct or handled by caller.\r\n // However, if we are using namespaces, we should prefer the namespaced format.\r\n \r\n let target = componentName;\r\n if (!target.startsWith('@') && !target.startsWith('http')) {\r\n target = `${REGISTRY_ALIAS}/${componentName}`;\r\n }\r\n\r\n await execa('npx', [\r\n '--yes',\r\n 'shadcn@latest', \r\n 'add', \r\n target, \r\n '-y', \r\n '--overwrite'\r\n ], {\r\n stdio: 'inherit' // Let the user see shadcn output\r\n });\r\n}\r\n\r\nexport async function initShadcn() {\r\n await execa('npx', ['--yes', 'shadcn@latest', 'init'], { stdio: 'inherit' });\r\n}\r\n\r\n","export const getRegistryUrl = () => {\r\n // Allow override for local testing\r\n if (process.env.EKAIROS_REGISTRY_URL) {\r\n return process.env.EKAIROS_REGISTRY_URL;\r\n }\r\n // Default production URL\r\n return \"https://registry.ekairos.dev\";\r\n};\r\n\r\nexport const REGISTRY_ALIAS = \"@ekairos\";\r\n\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport { checkShadcnConfig, ensureEkairosRegistry, getInstalledComponents, initShadcn, installComponent } from './shadcn.js';\r\n\r\nexport interface SessionState {\r\n sessionId: string;\r\n step: 'INIT' | 'MENU' | 'INSTALLING' | 'SUCCESS' | 'ERROR';\r\n installedComponents: string[];\r\n message?: string;\r\n error?: string;\r\n}\r\n\r\nconst TMP_DIR = path.join(os.tmpdir(), 'ekairos-cli-sessions');\r\n\r\nexport async function createSession(): Promise<SessionState> {\r\n const sessionId = crypto.randomUUID();\r\n const state: SessionState = {\r\n sessionId,\r\n step: 'INIT',\r\n installedComponents: []\r\n };\r\n await saveSession(state);\r\n return state;\r\n}\r\n\r\nexport async function loadSession(sessionId: string): Promise<SessionState | null> {\r\n const filePath = path.join(TMP_DIR, `${sessionId}.json`);\r\n if (!await fs.pathExists(filePath)) return null;\r\n return fs.readJson(filePath);\r\n}\r\n\r\nexport async function saveSession(state: SessionState) {\r\n await fs.ensureDir(TMP_DIR);\r\n const filePath = path.join(TMP_DIR, `${state.sessionId}.json`);\r\n await fs.writeJson(filePath, state, { spaces: 2 });\r\n}\r\n\r\nexport async function deleteSession(sessionId: string) {\r\n const filePath = path.join(TMP_DIR, `${sessionId}.json`);\r\n await fs.remove(filePath);\r\n}\r\n\r\nexport interface AsyncResponse {\r\n sessionId: string;\r\n step: string;\r\n message?: string;\r\n error?: string;\r\n inputSchema?: object;\r\n context?: any;\r\n}\r\n\r\nexport async function processAsyncStep(state: SessionState, input: any): Promise<AsyncResponse> {\r\n // State Machine Logic\r\n \r\n // 1. INIT -> Check Config -> MENU or ERROR_CONFIG\r\n if (state.step === 'INIT') {\r\n const hasConfig = await checkShadcnConfig();\r\n if (!hasConfig) {\r\n state.step = 'ERROR'; \r\n // We treat config missing as a special state that allows input, but let's map it to MENU-like behavior\r\n // Or we can just handle it here.\r\n // Let's define a sub-step or just reuse steps.\r\n // Simplified: If no config, we return a state waiting for 'init' action.\r\n state.error = 'components.json not found';\r\n state.message = 'Configuration missing. Action required.';\r\n \r\n await saveSession(state);\r\n return {\r\n sessionId: state.sessionId,\r\n step: 'CONFIG_MISSING', // Custom step name for the output\r\n message: state.message,\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n action: { type: 'string', enum: ['init-shadcn', 'exit'] }\r\n },\r\n required: ['action']\r\n }\r\n };\r\n }\r\n\r\n // If config exists, ensure registry and scan\r\n await ensureEkairosRegistry();\r\n state.installedComponents = await getInstalledComponents();\r\n state.step = 'MENU';\r\n state.message = `Found ${state.installedComponents.length} components.`;\r\n \r\n await saveSession(state);\r\n return {\r\n sessionId: state.sessionId,\r\n step: 'MENU',\r\n message: state.message,\r\n context: { installedComponents: state.installedComponents },\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n action: { type: 'string', enum: ['update-all', 'install-essentials', 'exit'] }\r\n },\r\n required: ['action']\r\n }\r\n };\r\n }\r\n\r\n // 2. Handle Inputs based on current step\r\n if (input && input.action === 'exit') {\r\n await deleteSession(state.sessionId);\r\n return {\r\n sessionId: state.sessionId,\r\n step: 'TERMINATED',\r\n message: 'Session ended by user.'\r\n };\r\n }\r\n\r\n // Handle CONFIG_MISSING logic (simulated via state check)\r\n // If we are in a state where config was missing, we expect 'init-shadcn'\r\n // But since we persisted 'ERROR' step, let's check if input handles it.\r\n // To make it clean, let's rely on input action primarily if valid.\r\n\r\n if (input && input.action === 'init-shadcn') {\r\n await initShadcn();\r\n // Reset to INIT to re-check\r\n state.step = 'INIT';\r\n state.error = undefined;\r\n // Recursively call process to advance\r\n return processAsyncStep(state, null);\r\n }\r\n\r\n if (state.step === 'MENU' && input) {\r\n if (input.action === 'update-all' || input.action === 'install-essentials') {\r\n state.step = 'INSTALLING';\r\n await saveSession(state);\r\n \r\n // Perform installation\r\n const componentsToInstall = input.action === 'update-all' \r\n ? state.installedComponents \r\n : ['@ekairos/ekairos-agent-Agent'];\r\n\r\n let targets = [...new Set(componentsToInstall)].map(c => \r\n c.startsWith('@ekairos/') ? c : `@ekairos/${c}`\r\n );\r\n\r\n if (targets.length === 0) targets.push('@ekairos/ekairos-agent-Agent');\r\n\r\n for (const component of targets) {\r\n await installComponent(component);\r\n }\r\n\r\n state.step = 'SUCCESS';\r\n state.message = 'Operations completed successfully.';\r\n await deleteSession(state.sessionId); // Done\r\n\r\n return {\r\n sessionId: state.sessionId,\r\n step: 'SUCCESS',\r\n message: state.message\r\n };\r\n }\r\n }\r\n \r\n // Default fallback if state didn't advance or input invalid\r\n return {\r\n sessionId: state.sessionId,\r\n step: state.step,\r\n message: state.message,\r\n error: 'Invalid state or input for current step.'\r\n };\r\n}\r\n\r\n"],"mappings":"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","names":["fs","path","path","fs","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx","../src/app.tsx","../src/lib/shadcn.ts","../src/lib/config.ts","../src/lib/session.ts"],"sourcesContent":["import React from 'react';\nimport { render } from 'ink';\nimport meow from 'meow';\nimport App from './app.js';\nimport { createSession, loadSession, processAsyncStep } from './lib/session.js';\n\nconst VALID_ACTIONS = new Set(['init-shadcn', 'update-all', 'install-essentials', 'exit']);\n\nconst cli = meow(\n\t`\n\tUsage\n\t $ ekairos\n\n\tOptions\n\t\t--async Run in async/session mode\n\t\t--session Session ID for continuing an async session\n\t\t--input JSON input for the session step\n\t\t--action Convenience flag for async actions (update-all, install-essentials, init-shadcn, exit)\n\n\tExamples\n\t $ ekairos --async\n\t $ ekairos --session <uuid> --input '{\"action\": \"update-all\"}'\n`,\n\t{\n\t\timportMeta: import.meta,\n\t\tflags: {\n\t\t\tasync: {\n\t\t\t\ttype: 'boolean',\n\t\t\t},\n\t\t\tsession: {\n\t\t\t\ttype: 'string',\n\t\t\t},\n\t\t\tinput: {\n\t\t\t\ttype: 'string',\n\t\t\t},\n\t\t\taction: {\n\t\t\t\ttype: 'string',\n\t\t\t}\n\t\t},\n\t},\n);\n\nasync function run() {\n\tif (cli.flags.async || cli.flags.session) {\n\t\ttry {\n\t\t\tlet state;\n\t\t\tlet input = null;\n\n\t\t\tconst tryParseActionString = (value: string | undefined) => {\n\t\t\t\tif (!value) return null;\n\t\t\t\tconst trimmed = value.trim();\n\t\t\t\treturn VALID_ACTIONS.has(trimmed) ? { action: trimmed } : null;\n\t\t\t};\n\n\t\t\tif (cli.flags.input) {\n\t\t\t\ttry {\n\t\t\t\t\tinput = JSON.parse(cli.flags.input);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tinput = tryParseActionString(cli.flags.input);\n\t\t\t\t\tif (!input) {\n\t\t\t\t\t\tconsole.error(JSON.stringify({ error: 'Invalid JSON input' }));\n\t\t\t\t\t\tprocess.exit(1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!input && cli.flags.action) {\n\t\t\t\tconst parsed = tryParseActionString(cli.flags.action);\n\t\t\t\tif (!parsed) {\n\t\t\t\t\tconsole.error(JSON.stringify({ error: 'Invalid action value' }));\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t\tinput = parsed;\n\t\t\t}\n\n\t\t\tif (cli.flags.session) {\n\t\t\t\tstate = await loadSession(cli.flags.session);\n\t\t\t\tif (!state) {\n\t\t\t\t\tconsole.error(JSON.stringify({ error: 'Session not found or expired' }));\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// New session\n\t\t\t\tstate = await createSession();\n\t\t\t}\n\n\t\t\tconst response = await processAsyncStep(state!, input);\n\t\t\tconsole.log(JSON.stringify(response, null, 2));\n\t\t\tprocess.exit(0);\n\n\t\t} catch (error) {\n\t\t\tconsole.error(JSON.stringify({ error: error instanceof Error ? error.message : 'Unknown error' }));\n\t\t\tprocess.exit(1);\n\t\t}\n\t} else {\n\t\t// Interactive Mode\n\t\trender(<App />);\n\t}\n}\n\nrun();\n","import React, { useState, useEffect } from 'react';\nimport { Box, Text, useApp } from 'ink';\nimport Spinner from 'ink-spinner';\nimport SelectInput from 'ink-select-input';\nimport { createRequire } from 'module';\nimport { checkShadcnConfig, ensureEkairosRegistry, getInstalledComponents, installComponent, initShadcn } from './lib/shadcn.js';\nimport { getRegistryUrl } from './lib/config.js';\n\nconst require = createRequire(import.meta.url);\nconst { version: CLI_VERSION = 'dev' } = require('../package.json') as { version?: string };\n\nconst REGISTRY_URL = getRegistryUrl();\n\ntype Step = 'check-config' | 'init-shadcn' | 'check-installed' | 'prompt-action' | 'installing' | 'success' | 'error';\n\ninterface AppState {\n step: Step;\n message: string;\n installedComponents: string[];\n error?: string;\n}\n\nexport default function App() {\n const { exit } = useApp();\n const [state, setState] = useState<AppState>({\n step: 'check-config',\n message: 'Checking configuration...',\n installedComponents: []\n });\n\n useEffect(() => {\n const init = async () => {\n try {\n // 1. Check Shadcn Config\n const hasConfig = await checkShadcnConfig();\n if (!hasConfig) {\n // Prompt for init\n setState(s => ({ ...s, step: 'init-shadcn', message: 'components.json not found.' }));\n return;\n }\n\n await runScan();\n\n } catch (err) {\n setState(s => ({ ...s, step: 'error', error: err instanceof Error ? err.message : 'Unknown error' }));\n }\n };\n\n if (state.step === 'check-config') {\n init();\n }\n }, [state.step]); // Dependency on step to retry after init\n\n const runScan = async () => {\n // 2. Ensure Registry Config\n await ensureEkairosRegistry();\n\n // 3. Check Installed Components\n setState(s => ({ ...s, step: 'check-installed', message: 'Scanning installed components...' }));\n const installed = await getInstalledComponents();\n \n setState({\n step: 'prompt-action',\n message: installed.length > 0 \n ? `Found ${installed.length} Ekairos components.` \n : 'No Ekairos components found.',\n installedComponents: installed,\n error: undefined\n });\n };\n\n const handleSelect = async (item: { value: string }) => {\n if (item.value === 'init-shadcn') {\n try {\n setState(s => ({ ...s, message: 'Initializing shadcn...' }));\n await initShadcn();\n // After init, check again\n setState(s => ({ ...s, step: 'check-config' }));\n } catch (err) {\n setState(s => ({ ...s, step: 'error', error: 'Failed to initialize shadcn.' }));\n }\n } else if (item.value === 'update-all' || item.value === 'install-essentials') {\n\n setState(s => ({ ...s, step: 'installing', message: 'Running shadcn...' }));\n \n try {\n const componentsToInstall = item.value === 'update-all' \n ? state.installedComponents \n : ['@ekairos/agent']; // Default bundle\n\n // Dedup and ensure prefix\n const targets = [...new Set(componentsToInstall)].map(c => \n c.startsWith('@ekairos/') ? c : `@ekairos/${c}`\n );\n\n if (targets.length === 0) {\n // Fallback if update-all called but nothing detected, force agent\n targets.push('@ekairos/agent');\n }\n\n for (const component of targets) {\n setState(s => ({ ...s, message: `Installing ${component}...` }));\n await installComponent(component);\n }\n\n setState(s => ({ ...s, step: 'success', message: 'All operations completed successfully!' }));\n setTimeout(() => exit(), 2000);\n\n } catch (err) {\n setState(s => ({ ...s, step: 'error', error: err instanceof Error ? err.message : 'Installation failed' }));\n }\n } else if (item.value === 'exit') {\n exit();\n }\n };\n\n const options = state.step === 'init-shadcn'\n ? [\n { label: 'Initialize shadcn project', value: 'init-shadcn' },\n { label: 'Exit', value: 'exit' }\n ]\n : state.installedComponents.length > 0\n ? [\n { label: 'Update all components', value: 'update-all' },\n { label: 'Exit', value: 'exit' }\n ]\n : [\n { label: 'Install Ekairos Essentials (Agent)', value: 'install-essentials' },\n { label: 'Exit', value: 'exit' }\n ];\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Box marginBottom={1} flexDirection=\"column\">\n <Text bold color=\"cyan\">Ekairos CLI v{CLI_VERSION}</Text>\n <Text color=\"gray\">using registry: {REGISTRY_URL}</Text>\n </Box>\n\n {(state.step === 'check-config' || state.step === 'check-installed' || state.step === 'installing') && (\n <Box>\n <Text color=\"green\"><Spinner type=\"dots\" /> </Text>\n <Text>{state.message}</Text>\n </Box>\n )}\n\n {(state.step === 'prompt-action' || state.step === 'init-shadcn') && (\n <Box flexDirection=\"column\">\n <Text marginBottom={1}>{state.message}</Text>\n <Text>What would you like to do?</Text>\n <SelectInput items={options} onSelect={handleSelect} />\n </Box>\n )}\n\n {state.step === 'success' && (\n <Box>\n <Text color=\"green\">✔ {state.message}</Text>\n </Box>\n )}\n\n {state.step === 'error' && (\n <Box>\n <Text color=\"red\">✖ Error: {state.error}</Text>\n </Box>\n )}\n </Box>\n );\n}\n\n","import fs from 'fs-extra';\nimport path from 'path';\nimport { execa } from 'execa';\nimport { REGISTRY_ALIAS, getRegistryUrl } from './config.js';\n\n// Check if components.json exists in CWD\nexport async function checkShadcnConfig(): Promise<boolean> {\n return fs.pathExists(path.join(process.cwd(), 'components.json'));\n}\n\n// Ensure @ekairos registry is configured in components.json\nexport async function ensureEkairosRegistry() {\n const configPath = path.join(process.cwd(), 'components.json');\n if (!await fs.pathExists(configPath)) return;\n\n const config = await fs.readJson(configPath);\n \n if (!config.registries) {\n config.registries = {};\n }\n\n const rawRegistryUrl = getRegistryUrl();\n const sanitizedUrl = rawRegistryUrl.trim().replace(/\\s+/g, '');\n\n let registryConfigUrl: string;\n if (sanitizedUrl.includes('{name}')) {\n registryConfigUrl = sanitizedUrl;\n } else {\n const baseUrl = sanitizedUrl\n .replace(/\\/registry\\.json$/i, '')\n .replace(/\\/+$/, '');\n registryConfigUrl = `${baseUrl}/{name}.json`;\n }\n\n if (config.registries[REGISTRY_ALIAS] !== registryConfigUrl) {\n config.registries[REGISTRY_ALIAS] = registryConfigUrl;\n await fs.writeJson(configPath, config, { spaces: 2 });\n }\n}\n\n// Scan components to see what is installed\nexport async function getInstalledComponents(): Promise<string[]> {\n // Logic: Check src/components/ekairos folder? \n // Or check components.json aliases? \n // A simple robust way is checking the filesystem based on the alias.\n \n // Assuming default alias @/components\n // We can read components.json to find the resolved path for \"components\" alias if needed,\n // but searching for \"src/components/ekairos\" is a safe 80/20 bet for this project structure.\n \n const possiblePaths = [\n 'src/components/ekairos',\n 'components/ekairos',\n 'lib/components/ekairos'\n ];\n\n for (const p of possiblePaths) {\n const fullPath = path.join(process.cwd(), p);\n if (await fs.pathExists(fullPath)) {\n // Read directories/files in there\n // This is a heuristic. A folder \"agent\" means the main Ekairos Agent is likely installed\n // Ideally we track this in a manifest, but we don't have one yet.\n // So we will just return detected component names based on files.\n \n // For simplicity in v1, we just return found files as a proxy for \"Agent\"\n const files = await fs.readdir(fullPath, { recursive: true });\n \n // If we find 'agent', we assume 'agent' as the installed Ekairos bundle\n // This mapping is tricky without a manifest. \n // FOR NOW: We will return a generic list if any are found, or empty.\n // The prompt will effectively just list 'agent' if detected.\n \n const detected = [];\n const fileList = Array.isArray(files) ? files : []; // readdir recursive returns string[] in node 20+? wait fs-extra might differ.\n \n // fs-extra readdir is standard. recursive not supported in older node with string, but let's assume standard recursive or walk.\n // Let's stick to checking specific known folders for v1.\n \n if (await fs.pathExists(path.join(fullPath, 'agent'))) detected.push('agent');\n // Add more detections here as registry grows\n \n return detected;\n }\n }\n \n return [];\n}\n\nexport async function installComponent(componentName: string) {\n // Run shadcn add\n // npx --yes shadcn@latest add @ekairos/name -y --overwrite\n \n // Ensure component has prefix if it's a known component without one\n // But for now, we assume input is correct or handled by caller.\n // However, if we are using namespaces, we should prefer the namespaced format.\n \n let target = componentName;\n if (!target.startsWith('@') && !target.startsWith('http')) {\n target = `${REGISTRY_ALIAS}/${componentName}`;\n }\n\n await execa('npx', [\n '--yes',\n 'shadcn@latest', \n 'add', \n target, \n '-y', \n '--overwrite'\n ], {\n stdio: 'inherit' // Let the user see shadcn output\n });\n}\n\nexport async function initShadcn() {\n await execa('npx', ['--yes', 'shadcn@latest', 'init'], { stdio: 'inherit' });\n}\n\n","export const getRegistryUrl = () => {\r\n // Allow override for local testing / staging\r\n if (process.env.EKAIROS_REGISTRY_URL) {\r\n return process.env.EKAIROS_REGISTRY_URL;\r\n }\r\n // Default production URL (canonical base)\r\n return \"https://registry.ekairos.dev/\";\r\n};\r\n\r\nexport const REGISTRY_ALIAS = \"@ekairos\";\r\n\r\n\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport { checkShadcnConfig, ensureEkairosRegistry, getInstalledComponents, initShadcn, installComponent } from './shadcn.js';\r\n\r\nexport interface SessionState {\r\n sessionId: string;\r\n step: 'INIT' | 'MENU' | 'INSTALLING' | 'SUCCESS' | 'ERROR';\r\n installedComponents: string[];\r\n message?: string;\r\n error?: string;\r\n}\r\n\r\nconst TMP_DIR = path.join(os.tmpdir(), 'ekairos-cli-sessions');\r\n\r\nexport async function createSession(): Promise<SessionState> {\r\n const sessionId = crypto.randomUUID();\r\n const state: SessionState = {\r\n sessionId,\r\n step: 'INIT',\r\n installedComponents: []\r\n };\r\n await saveSession(state);\r\n return state;\r\n}\r\n\r\nexport async function loadSession(sessionId: string): Promise<SessionState | null> {\r\n const filePath = path.join(TMP_DIR, `${sessionId}.json`);\r\n if (!await fs.pathExists(filePath)) return null;\r\n return fs.readJson(filePath);\r\n}\r\n\r\nexport async function saveSession(state: SessionState) {\r\n await fs.ensureDir(TMP_DIR);\r\n const filePath = path.join(TMP_DIR, `${state.sessionId}.json`);\r\n await fs.writeJson(filePath, state, { spaces: 2 });\r\n}\r\n\r\nexport async function deleteSession(sessionId: string) {\r\n const filePath = path.join(TMP_DIR, `${sessionId}.json`);\r\n await fs.remove(filePath);\r\n}\r\n\r\nexport interface AsyncResponse {\r\n sessionId: string;\r\n step: string;\r\n message?: string;\r\n error?: string;\r\n inputSchema?: object;\r\n context?: any;\r\n}\r\n\r\nexport async function processAsyncStep(state: SessionState, input: any): Promise<AsyncResponse> {\r\n // State Machine Logic\r\n \r\n // 1. INIT -> Check Config -> MENU or ERROR_CONFIG\r\n if (state.step === 'INIT') {\r\n const hasConfig = await checkShadcnConfig();\r\n if (!hasConfig) {\r\n state.step = 'ERROR'; \r\n // We treat config missing as a special state that allows input, but let's map it to MENU-like behavior\r\n // Or we can just handle it here.\r\n // Let's define a sub-step or just reuse steps.\r\n // Simplified: If no config, we return a state waiting for 'init' action.\r\n state.error = 'components.json not found';\r\n state.message = 'Configuration missing. Action required.';\r\n \r\n await saveSession(state);\r\n return {\r\n sessionId: state.sessionId,\r\n step: 'CONFIG_MISSING', // Custom step name for the output\r\n message: state.message,\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n action: { type: 'string', enum: ['init-shadcn', 'exit'] }\r\n },\r\n required: ['action']\r\n }\r\n };\r\n }\r\n\r\n // If config exists, ensure registry and scan\r\n await ensureEkairosRegistry();\r\n state.installedComponents = await getInstalledComponents();\r\n state.step = 'MENU';\r\n state.message = `Found ${state.installedComponents.length} components.`;\r\n \r\n await saveSession(state);\r\n return {\r\n sessionId: state.sessionId,\r\n step: 'MENU',\r\n message: state.message,\r\n context: { installedComponents: state.installedComponents },\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n action: { type: 'string', enum: ['update-all', 'install-essentials', 'exit'] }\r\n },\r\n required: ['action']\r\n }\r\n };\r\n }\r\n\r\n // 2. Handle Inputs based on current step\r\n if (input && input.action === 'exit') {\r\n await deleteSession(state.sessionId);\r\n return {\r\n sessionId: state.sessionId,\r\n step: 'TERMINATED',\r\n message: 'Session ended by user.'\r\n };\r\n }\r\n\r\n // Handle CONFIG_MISSING logic (simulated via state check)\r\n // If we are in a state where config was missing, we expect 'init-shadcn'\r\n // But since we persisted 'ERROR' step, let's check if input handles it.\r\n // To make it clean, let's rely on input action primarily if valid.\r\n\r\n if (input && input.action === 'init-shadcn') {\r\n await initShadcn();\r\n // Reset to INIT to re-check\r\n state.step = 'INIT';\r\n state.error = undefined;\r\n // Recursively call process to advance\r\n return processAsyncStep(state, null);\r\n }\r\n\r\n if (state.step === 'MENU' && input) {\r\n if (input.action === 'update-all' || input.action === 'install-essentials') {\r\n state.step = 'INSTALLING';\r\n await saveSession(state);\r\n \r\n // Perform installation\r\n const componentsToInstall = input.action === 'update-all' \r\n ? state.installedComponents \r\n : ['@ekairos/agent'];\r\n\r\n let targets = [...new Set(componentsToInstall)].map(c => \r\n c.startsWith('@ekairos/') ? c : `@ekairos/${c}`\r\n );\r\n\r\n if (targets.length === 0) targets.push('@ekairos/agent');\r\n\r\n for (const component of targets) {\r\n await installComponent(component);\r\n }\r\n\r\n state.step = 'SUCCESS';\r\n state.message = 'Operations completed successfully.';\r\n await deleteSession(state.sessionId); // Done\r\n\r\n return {\r\n sessionId: state.sessionId,\r\n step: 'SUCCESS',\r\n message: state.message\r\n };\r\n }\r\n }\r\n \r\n // Default fallback if state didn't advance or input invalid\r\n return {\r\n sessionId: state.sessionId,\r\n step: state.step,\r\n message: state.message,\r\n error: 'Invalid state or input for current step.'\r\n };\r\n}\r\n\r\n\r\n"],"mappings":"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","names":["require","fs","path","path","fs","jsx"]}
|