cli4ai 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +275 -0
- package/package.json +49 -0
- package/src/bin.ts +120 -0
- package/src/cli.ts +256 -0
- package/src/commands/add.ts +530 -0
- package/src/commands/browse.ts +449 -0
- package/src/commands/config.ts +126 -0
- package/src/commands/info.ts +102 -0
- package/src/commands/init.test.ts +163 -0
- package/src/commands/init.ts +560 -0
- package/src/commands/list.ts +89 -0
- package/src/commands/mcp-config.ts +59 -0
- package/src/commands/remove.ts +72 -0
- package/src/commands/routines.ts +393 -0
- package/src/commands/run.ts +45 -0
- package/src/commands/search.ts +148 -0
- package/src/commands/secrets.ts +273 -0
- package/src/commands/start.ts +40 -0
- package/src/commands/update.ts +218 -0
- package/src/core/config.test.ts +188 -0
- package/src/core/config.ts +649 -0
- package/src/core/execute.ts +507 -0
- package/src/core/link.test.ts +238 -0
- package/src/core/link.ts +190 -0
- package/src/core/lockfile.test.ts +337 -0
- package/src/core/lockfile.ts +308 -0
- package/src/core/manifest.test.ts +327 -0
- package/src/core/manifest.ts +319 -0
- package/src/core/routine-engine.test.ts +139 -0
- package/src/core/routine-engine.ts +725 -0
- package/src/core/routines.ts +111 -0
- package/src/core/secrets.test.ts +79 -0
- package/src/core/secrets.ts +430 -0
- package/src/lib/cli.ts +234 -0
- package/src/mcp/adapter.test.ts +132 -0
- package/src/mcp/adapter.ts +123 -0
- package/src/mcp/config-gen.test.ts +214 -0
- package/src/mcp/config-gen.ts +106 -0
- package/src/mcp/server.ts +363 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for init command
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
|
|
6
|
+
import { mkdtempSync, rmSync, existsSync, readFileSync } from 'fs';
|
|
7
|
+
import { join } from 'path';
|
|
8
|
+
import { tmpdir } from 'os';
|
|
9
|
+
import { initCommand } from './init.js';
|
|
10
|
+
|
|
11
|
+
describe('init command', () => {
|
|
12
|
+
let tempDir: string;
|
|
13
|
+
let originalCwd: string;
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
tempDir = mkdtempSync(join(tmpdir(), 'cli4ai-init-test-'));
|
|
17
|
+
originalCwd = process.cwd();
|
|
18
|
+
process.chdir(tempDir);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
process.chdir(originalCwd);
|
|
23
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('with name argument (creates subdirectory)', () => {
|
|
27
|
+
test('creates cli4ai.json in subdirectory', async () => {
|
|
28
|
+
await initCommand('test-tool', {});
|
|
29
|
+
|
|
30
|
+
expect(existsSync(join(tempDir, 'test-tool', 'cli4ai.json'))).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('creates run.ts entry file in subdirectory', async () => {
|
|
34
|
+
await initCommand('test-tool', {});
|
|
35
|
+
|
|
36
|
+
expect(existsSync(join(tempDir, 'test-tool', 'run.ts'))).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('creates README.md and package.json', async () => {
|
|
40
|
+
await initCommand('test-tool', {});
|
|
41
|
+
|
|
42
|
+
expect(existsSync(join(tempDir, 'test-tool', 'README.md'))).toBe(true);
|
|
43
|
+
expect(existsSync(join(tempDir, 'test-tool', 'package.json'))).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('creates the subdirectory', async () => {
|
|
47
|
+
await initCommand('new-project', {});
|
|
48
|
+
|
|
49
|
+
expect(existsSync(join(tempDir, 'new-project'))).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('without name argument (uses current directory)', () => {
|
|
54
|
+
test('creates cli4ai.json in current directory', async () => {
|
|
55
|
+
await initCommand(undefined, {});
|
|
56
|
+
|
|
57
|
+
expect(existsSync(join(tempDir, 'cli4ai.json'))).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('creates run.ts entry file', async () => {
|
|
61
|
+
await initCommand(undefined, {});
|
|
62
|
+
|
|
63
|
+
expect(existsSync(join(tempDir, 'run.ts'))).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('uses directory name as package name', async () => {
|
|
67
|
+
await initCommand(undefined, {});
|
|
68
|
+
|
|
69
|
+
const manifest = JSON.parse(readFileSync(join(tempDir, 'cli4ai.json'), 'utf-8'));
|
|
70
|
+
// Name is normalized from the temp dir name
|
|
71
|
+
expect(manifest.name).toBeDefined();
|
|
72
|
+
expect(typeof manifest.name).toBe('string');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe('manifest content', () => {
|
|
77
|
+
test('manifest has correct name', async () => {
|
|
78
|
+
await initCommand('my-cool-tool', {});
|
|
79
|
+
|
|
80
|
+
const manifest = JSON.parse(readFileSync(join(tempDir, 'my-cool-tool', 'cli4ai.json'), 'utf-8'));
|
|
81
|
+
expect(manifest.name).toBe('my-cool-tool');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('manifest has default version', async () => {
|
|
85
|
+
await initCommand('tool', {});
|
|
86
|
+
|
|
87
|
+
const manifest = JSON.parse(readFileSync(join(tempDir, 'tool', 'cli4ai.json'), 'utf-8'));
|
|
88
|
+
expect(manifest.version).toBe('1.0.0');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('manifest has default runtime bun', async () => {
|
|
92
|
+
await initCommand('tool', {});
|
|
93
|
+
|
|
94
|
+
const manifest = JSON.parse(readFileSync(join(tempDir, 'tool', 'cli4ai.json'), 'utf-8'));
|
|
95
|
+
expect(manifest.runtime).toBe('bun');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test('manifest has entry pointing to run.ts', async () => {
|
|
99
|
+
await initCommand('tool', {});
|
|
100
|
+
|
|
101
|
+
const manifest = JSON.parse(readFileSync(join(tempDir, 'tool', 'cli4ai.json'), 'utf-8'));
|
|
102
|
+
expect(manifest.entry).toBe('run.ts');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test('manifest has hello command defined', async () => {
|
|
106
|
+
await initCommand('tool', {});
|
|
107
|
+
|
|
108
|
+
const manifest = JSON.parse(readFileSync(join(tempDir, 'tool', 'cli4ai.json'), 'utf-8'));
|
|
109
|
+
expect(manifest.commands?.hello).toBeDefined();
|
|
110
|
+
expect(manifest.commands?.hello?.description).toBe('Say hello');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test('manifest includes dependencies for bun runtime', async () => {
|
|
114
|
+
await initCommand('tool', {});
|
|
115
|
+
|
|
116
|
+
const manifest = JSON.parse(readFileSync(join(tempDir, 'tool', 'cli4ai.json'), 'utf-8'));
|
|
117
|
+
expect(manifest.dependencies).toBeDefined();
|
|
118
|
+
expect(manifest.dependencies['@cli4ai/lib']).toBeDefined();
|
|
119
|
+
expect(manifest.dependencies['commander']).toBeDefined();
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('entry file content', () => {
|
|
124
|
+
test('run.ts starts with shebang', async () => {
|
|
125
|
+
await initCommand('tool', {});
|
|
126
|
+
|
|
127
|
+
const content = readFileSync(join(tempDir, 'tool', 'run.ts'), 'utf-8');
|
|
128
|
+
expect(content.startsWith('#!/usr/bin/env bun')).toBe(true);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test('run.ts has hello command', async () => {
|
|
132
|
+
await initCommand('tool', {});
|
|
133
|
+
|
|
134
|
+
const content = readFileSync(join(tempDir, 'tool', 'run.ts'), 'utf-8');
|
|
135
|
+
expect(content).toContain('hello');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test('run.ts uses cli4ai SDK helpers', async () => {
|
|
139
|
+
await initCommand('tool', {});
|
|
140
|
+
|
|
141
|
+
const content = readFileSync(join(tempDir, 'tool', 'run.ts'), 'utf-8');
|
|
142
|
+
expect(content).toContain("@cli4ai/lib/cli.ts");
|
|
143
|
+
expect(content).toContain('output(');
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe('runtime option', () => {
|
|
148
|
+
test('respects runtime option', async () => {
|
|
149
|
+
await initCommand('tool', { runtime: 'node' });
|
|
150
|
+
|
|
151
|
+
const manifest = JSON.parse(readFileSync(join(tempDir, 'tool', 'cli4ai.json'), 'utf-8'));
|
|
152
|
+
expect(manifest.runtime).toBe('node');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test('node runtime uses run.mjs entry', async () => {
|
|
156
|
+
await initCommand('tool', { runtime: 'node' });
|
|
157
|
+
|
|
158
|
+
const manifest = JSON.parse(readFileSync(join(tempDir, 'tool', 'cli4ai.json'), 'utf-8'));
|
|
159
|
+
expect(manifest.entry).toBe('run.mjs');
|
|
160
|
+
expect(existsSync(join(tempDir, 'tool', 'run.mjs'))).toBe(true);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
});
|