@deimoscloud/coreai 0.1.8 → 0.1.10
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/dist/cli/index.js +5 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
- package/.prettierrc +0 -9
- package/AGENT_SPEC.md +0 -347
- package/ARCHITECTURE.md +0 -547
- package/DRAFT_PRD.md +0 -1440
- package/IMPLEMENTATION_PLAN.md +0 -256
- package/PRODUCT.md +0 -473
- package/WORKFLOWS.md +0 -295
- package/commands/core/check-inbox.md +0 -34
- package/commands/core/delegate.md +0 -30
- package/commands/core/git-commit.md +0 -144
- package/commands/core/pr-create.md +0 -193
- package/commands/core/review.md +0 -56
- package/commands/core/sprint-status.md +0 -65
- package/commands/optional/docs-update.md +0 -200
- package/commands/optional/jira-create.md +0 -200
- package/commands/optional/jira-transition.md +0 -184
- package/commands/optional/worktree-cleanup.md +0 -167
- package/commands/optional/worktree-setup.md +0 -110
- package/eslint.config.js +0 -29
- package/jest.config.js +0 -22
- package/knowledge-library/README.md +0 -118
- package/knowledge-library/android-engineer/context/current.txt +0 -42
- package/knowledge-library/android-engineer/control/decisions.txt +0 -9
- package/knowledge-library/android-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/android-engineer/control/objectives.txt +0 -26
- package/knowledge-library/android-engineer/history/.gitkeep +0 -0
- package/knowledge-library/android-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/android-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/android-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/architecture.txt +0 -61
- package/knowledge-library/backend-engineer/context/current.txt +0 -42
- package/knowledge-library/backend-engineer/control/decisions.txt +0 -9
- package/knowledge-library/backend-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/backend-engineer/control/objectives.txt +0 -26
- package/knowledge-library/backend-engineer/history/.gitkeep +0 -0
- package/knowledge-library/backend-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/backend-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/backend-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/context.txt +0 -52
- package/knowledge-library/devops-engineer/context/current.txt +0 -42
- package/knowledge-library/devops-engineer/control/decisions.txt +0 -9
- package/knowledge-library/devops-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/devops-engineer/control/objectives.txt +0 -26
- package/knowledge-library/devops-engineer/history/.gitkeep +0 -0
- package/knowledge-library/devops-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/devops-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/devops-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/context/current.txt +0 -40
- package/knowledge-library/engineering-manager/control/decisions.txt +0 -9
- package/knowledge-library/engineering-manager/control/objectives.txt +0 -27
- package/knowledge-library/engineering-manager/history/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/outbox/.gitkeep +0 -0
- package/knowledge-library/engineering-manager/tech/.gitkeep +0 -0
- package/knowledge-library/prd.txt +0 -81
- package/knowledge-library/product-manager/context/current.txt +0 -42
- package/knowledge-library/product-manager/control/decisions.txt +0 -9
- package/knowledge-library/product-manager/control/dependencies.txt +0 -19
- package/knowledge-library/product-manager/control/objectives.txt +0 -26
- package/knowledge-library/product-manager/history/.gitkeep +0 -0
- package/knowledge-library/product-manager/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/product-manager/outbox/.gitkeep +0 -0
- package/knowledge-library/product-manager/tech/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/context/current.txt +0 -42
- package/knowledge-library/qa-engineer/control/decisions.txt +0 -9
- package/knowledge-library/qa-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/qa-engineer/control/objectives.txt +0 -26
- package/knowledge-library/qa-engineer/history/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/qa-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/security-engineer/context/current.txt +0 -42
- package/knowledge-library/security-engineer/control/decisions.txt +0 -9
- package/knowledge-library/security-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/security-engineer/control/objectives.txt +0 -26
- package/knowledge-library/security-engineer/history/.gitkeep +0 -0
- package/knowledge-library/security-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/security-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/security-engineer/tech/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/context/current.txt +0 -42
- package/knowledge-library/solutions-architect/control/decisions.txt +0 -9
- package/knowledge-library/solutions-architect/control/dependencies.txt +0 -19
- package/knowledge-library/solutions-architect/control/objectives.txt +0 -26
- package/knowledge-library/solutions-architect/history/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/outbox/.gitkeep +0 -0
- package/knowledge-library/solutions-architect/tech/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/context/current.txt +0 -42
- package/knowledge-library/wearos-engineer/control/decisions.txt +0 -9
- package/knowledge-library/wearos-engineer/control/dependencies.txt +0 -19
- package/knowledge-library/wearos-engineer/control/objectives.txt +0 -26
- package/knowledge-library/wearos-engineer/history/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/inbox/processed/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/outbox/.gitkeep +0 -0
- package/knowledge-library/wearos-engineer/tech/.gitkeep +0 -0
- package/scripts/add-agent.sh +0 -323
- package/scripts/install.sh +0 -354
- package/src/adapters/factory.test.ts +0 -386
- package/src/adapters/factory.ts +0 -305
- package/src/adapters/index.ts +0 -113
- package/src/adapters/interfaces.ts +0 -268
- package/src/adapters/mcp/client.test.ts +0 -130
- package/src/adapters/mcp/client.ts +0 -451
- package/src/adapters/mcp/discovery.test.ts +0 -315
- package/src/adapters/mcp/discovery.ts +0 -340
- package/src/adapters/mcp/index.ts +0 -66
- package/src/adapters/mcp/mapper.test.ts +0 -218
- package/src/adapters/mcp/mapper.ts +0 -536
- package/src/adapters/mcp/registry.test.ts +0 -433
- package/src/adapters/mcp/registry.ts +0 -550
- package/src/adapters/mcp/types.ts +0 -258
- package/src/adapters/native/filesystem.test.ts +0 -350
- package/src/adapters/native/filesystem.ts +0 -393
- package/src/adapters/native/github.test.ts +0 -173
- package/src/adapters/native/github.ts +0 -627
- package/src/adapters/native/index.ts +0 -22
- package/src/adapters/native/selector.test.ts +0 -224
- package/src/adapters/native/selector.ts +0 -150
- package/src/adapters/types.ts +0 -270
- package/src/agents/compiler.test.ts +0 -399
- package/src/agents/compiler.ts +0 -422
- package/src/agents/index.ts +0 -37
- package/src/agents/loader.test.ts +0 -319
- package/src/agents/loader.ts +0 -143
- package/src/agents/resolver.test.ts +0 -282
- package/src/agents/resolver.ts +0 -262
- package/src/agents/types.ts +0 -97
- package/src/cache/index.ts +0 -38
- package/src/cache/interfaces.ts +0 -283
- package/src/cache/manager.test.ts +0 -266
- package/src/cache/manager.ts +0 -388
- package/src/cache/provider.test.ts +0 -485
- package/src/cache/provider.ts +0 -745
- package/src/cache/types.test.ts +0 -192
- package/src/cache/types.ts +0 -313
- package/src/cli/commands/build.test.ts +0 -248
- package/src/cli/commands/build.ts +0 -284
- package/src/cli/commands/cache.test.ts +0 -221
- package/src/cli/commands/cache.ts +0 -229
- package/src/cli/commands/index.ts +0 -63
- package/src/cli/commands/init.test.ts +0 -173
- package/src/cli/commands/init.ts +0 -296
- package/src/cli/commands/skills.test.ts +0 -272
- package/src/cli/commands/skills.ts +0 -348
- package/src/cli/commands/status.test.ts +0 -392
- package/src/cli/commands/status.ts +0 -332
- package/src/cli/commands/sync.test.ts +0 -213
- package/src/cli/commands/sync.ts +0 -251
- package/src/cli/commands/validate.test.ts +0 -216
- package/src/cli/commands/validate.ts +0 -340
- package/src/cli/index.test.ts +0 -190
- package/src/cli/index.ts +0 -493
- package/src/commands/context.test.ts +0 -163
- package/src/commands/context.ts +0 -111
- package/src/commands/index.ts +0 -56
- package/src/commands/loader.test.ts +0 -273
- package/src/commands/loader.ts +0 -355
- package/src/commands/registry.test.ts +0 -384
- package/src/commands/registry.ts +0 -248
- package/src/commands/runner.test.ts +0 -297
- package/src/commands/runner.ts +0 -222
- package/src/commands/types.ts +0 -361
- package/src/config/index.ts +0 -19
- package/src/config/loader.test.ts +0 -262
- package/src/config/loader.ts +0 -188
- package/src/config/types.ts +0 -154
- package/src/context/index.ts +0 -14
- package/src/context/loader.test.ts +0 -334
- package/src/context/loader.ts +0 -357
- package/src/index.test.ts +0 -13
- package/src/index.ts +0 -268
- package/src/knowledge-library/index.ts +0 -44
- package/src/knowledge-library/manager.test.ts +0 -536
- package/src/knowledge-library/manager.ts +0 -804
- package/src/knowledge-library/types.ts +0 -432
- package/src/skills/generator.test.ts +0 -602
- package/src/skills/generator.ts +0 -491
- package/src/skills/index.ts +0 -27
- package/src/skills/templates.ts +0 -520
- package/src/skills/types.ts +0 -251
- package/templates/completion-report.md +0 -72
- package/templates/feedback.md +0 -56
- package/templates/project-files/CLAUDE.md.template +0 -109
- package/templates/project-files/coreai.json.example +0 -47
- package/templates/project-files/mcp.json.template +0 -20
- package/templates/review-complete.md +0 -64
- package/templates/review-request.md +0 -67
- package/templates/task-assignment.md +0 -51
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -26
- package/tsup.config.ts +0 -23
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cache Commands Tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { promises as fs } from 'fs';
|
|
6
|
-
import { join } from 'path';
|
|
7
|
-
import { tmpdir } from 'os';
|
|
8
|
-
import { FileCacheProvider } from '../../cache/provider.js';
|
|
9
|
-
import {
|
|
10
|
-
cacheStatus,
|
|
11
|
-
cacheClear,
|
|
12
|
-
cacheClearExpired,
|
|
13
|
-
formatCacheStatus,
|
|
14
|
-
formatBytes,
|
|
15
|
-
} from './cache.js';
|
|
16
|
-
|
|
17
|
-
describe('Cache Commands', () => {
|
|
18
|
-
let testDir: string;
|
|
19
|
-
|
|
20
|
-
beforeEach(async () => {
|
|
21
|
-
testDir = join(tmpdir(), `cache-cmd-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
22
|
-
await fs.mkdir(testDir, { recursive: true });
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
afterEach(async () => {
|
|
26
|
-
try {
|
|
27
|
-
await fs.rm(testDir, { recursive: true, force: true });
|
|
28
|
-
} catch {
|
|
29
|
-
// Ignore cleanup errors
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
describe('cacheStatus', () => {
|
|
34
|
-
it('should return initialized for new directory', async () => {
|
|
35
|
-
// Cache auto-initializes when called
|
|
36
|
-
const result = await cacheStatus({ cachePath: join(testDir, 'new-cache') });
|
|
37
|
-
|
|
38
|
-
expect(result.initialized).toBe(true);
|
|
39
|
-
expect(result.stats).not.toBeNull();
|
|
40
|
-
expect(result.entries).toHaveLength(0);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should return status for initialized cache', async () => {
|
|
44
|
-
// Initialize cache with some entries
|
|
45
|
-
const provider = new FileCacheProvider({ basePath: testDir });
|
|
46
|
-
await provider.initialize();
|
|
47
|
-
await provider.set('test-key', 'test content', {
|
|
48
|
-
source: 'github',
|
|
49
|
-
sourceUrl: 'https://github.com/test',
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const result = await cacheStatus({ cachePath: testDir });
|
|
53
|
-
|
|
54
|
-
expect(result.initialized).toBe(true);
|
|
55
|
-
expect(result.stats).not.toBeNull();
|
|
56
|
-
expect(result.stats?.totalEntries).toBe(1);
|
|
57
|
-
expect(result.entries).toHaveLength(1);
|
|
58
|
-
expect(result.entries[0].key).toBe('test-key');
|
|
59
|
-
expect(result.entries[0].source).toBe('github');
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should include entry status', async () => {
|
|
63
|
-
const provider = new FileCacheProvider({ basePath: testDir });
|
|
64
|
-
await provider.initialize();
|
|
65
|
-
await provider.set(
|
|
66
|
-
'valid-entry',
|
|
67
|
-
'content',
|
|
68
|
-
{ source: 'local', sourceUrl: '' },
|
|
69
|
-
{ ttl: 3600 }
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
const result = await cacheStatus({ cachePath: testDir });
|
|
73
|
-
|
|
74
|
-
expect(result.entries[0].status).toBe('valid');
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
describe('cacheClear', () => {
|
|
79
|
-
it('should clear all cache entries', async () => {
|
|
80
|
-
const provider = new FileCacheProvider({ basePath: testDir });
|
|
81
|
-
await provider.initialize();
|
|
82
|
-
await provider.set('key1', 'content1', { source: 'local', sourceUrl: '' });
|
|
83
|
-
await provider.set('key2', 'content2', { source: 'local', sourceUrl: '' });
|
|
84
|
-
|
|
85
|
-
const result = await cacheClear({ cachePath: testDir });
|
|
86
|
-
|
|
87
|
-
expect(result.success).toBe(true);
|
|
88
|
-
expect(result.cleared).toBe(2);
|
|
89
|
-
|
|
90
|
-
// Verify cache is empty
|
|
91
|
-
const status = await cacheStatus({ cachePath: testDir });
|
|
92
|
-
expect(status.entries).toHaveLength(0);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('should handle empty cache', async () => {
|
|
96
|
-
const provider = new FileCacheProvider({ basePath: testDir });
|
|
97
|
-
await provider.initialize();
|
|
98
|
-
|
|
99
|
-
const result = await cacheClear({ cachePath: testDir });
|
|
100
|
-
|
|
101
|
-
expect(result.success).toBe(true);
|
|
102
|
-
expect(result.cleared).toBe(0);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('should handle uninitialized cache directory', async () => {
|
|
106
|
-
const result = await cacheClear({ cachePath: join(testDir, 'new-cache') });
|
|
107
|
-
|
|
108
|
-
expect(result.success).toBe(true);
|
|
109
|
-
expect(result.cleared).toBe(0);
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
describe('cacheClearExpired', () => {
|
|
114
|
-
it('should only clear expired entries', async () => {
|
|
115
|
-
const provider = new FileCacheProvider({ basePath: testDir });
|
|
116
|
-
await provider.initialize();
|
|
117
|
-
|
|
118
|
-
// Add a valid entry
|
|
119
|
-
await provider.set('valid', 'content', { source: 'local', sourceUrl: '' }, { ttl: 3600 });
|
|
120
|
-
|
|
121
|
-
// Add an "expired" entry by manipulating the metadata
|
|
122
|
-
await provider.set('expired', 'content', { source: 'local', sourceUrl: '' }, { ttl: 1 });
|
|
123
|
-
|
|
124
|
-
// Wait for expiration
|
|
125
|
-
await new Promise((resolve) => setTimeout(resolve, 1100));
|
|
126
|
-
|
|
127
|
-
const result = await cacheClearExpired({ cachePath: testDir });
|
|
128
|
-
|
|
129
|
-
expect(result.success).toBe(true);
|
|
130
|
-
expect(result.cleared).toBe(1);
|
|
131
|
-
|
|
132
|
-
// Valid entry should still exist
|
|
133
|
-
const status = await cacheStatus({ cachePath: testDir });
|
|
134
|
-
expect(status.entries.map((e) => e.key)).toContain('valid');
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
describe('formatBytes', () => {
|
|
139
|
-
it('should format bytes correctly', () => {
|
|
140
|
-
expect(formatBytes(0)).toBe('0 B');
|
|
141
|
-
expect(formatBytes(100)).toBe('100 B');
|
|
142
|
-
expect(formatBytes(1024)).toBe('1 KB');
|
|
143
|
-
expect(formatBytes(1536)).toBe('1.5 KB');
|
|
144
|
-
expect(formatBytes(1048576)).toBe('1 MB');
|
|
145
|
-
expect(formatBytes(1073741824)).toBe('1 GB');
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
describe('formatCacheStatus', () => {
|
|
150
|
-
it('should format uninitialized cache', () => {
|
|
151
|
-
const result = formatCacheStatus({
|
|
152
|
-
initialized: false,
|
|
153
|
-
path: '/test/cache',
|
|
154
|
-
stats: null,
|
|
155
|
-
entries: [],
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
expect(result).toContain('Not initialized');
|
|
159
|
-
expect(result).toContain('/test/cache');
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it('should format initialized cache with entries', () => {
|
|
163
|
-
const result = formatCacheStatus({
|
|
164
|
-
initialized: true,
|
|
165
|
-
path: '/test/cache',
|
|
166
|
-
stats: {
|
|
167
|
-
totalEntries: 2,
|
|
168
|
-
totalSize: 1024,
|
|
169
|
-
validEntries: 1,
|
|
170
|
-
staleEntries: 1,
|
|
171
|
-
expiredEntries: 0,
|
|
172
|
-
bySource: { github: 2, confluence: 0, notion: 0, local: 0, custom: 0 },
|
|
173
|
-
newestEntry: '2024-01-01T00:00:00Z',
|
|
174
|
-
},
|
|
175
|
-
entries: [
|
|
176
|
-
{
|
|
177
|
-
key: 'entry1',
|
|
178
|
-
source: 'github',
|
|
179
|
-
status: 'valid',
|
|
180
|
-
size: 512,
|
|
181
|
-
cachedAt: '2024-01-01T00:00:00Z',
|
|
182
|
-
expiresAt: '2024-01-02T00:00:00Z',
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
key: 'entry2',
|
|
186
|
-
source: 'github',
|
|
187
|
-
status: 'stale',
|
|
188
|
-
size: 512,
|
|
189
|
-
cachedAt: '2024-01-01T00:00:00Z',
|
|
190
|
-
expiresAt: '2024-01-02T00:00:00Z',
|
|
191
|
-
},
|
|
192
|
-
],
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
expect(result).toContain('Initialized');
|
|
196
|
-
expect(result).toContain('Entries: 2');
|
|
197
|
-
expect(result).toContain('1 KB');
|
|
198
|
-
expect(result).toContain('github');
|
|
199
|
-
expect(result).toContain('entry1');
|
|
200
|
-
expect(result).toContain('entry2');
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('should format empty cache', () => {
|
|
204
|
-
const result = formatCacheStatus({
|
|
205
|
-
initialized: true,
|
|
206
|
-
path: '/test/cache',
|
|
207
|
-
stats: {
|
|
208
|
-
totalEntries: 0,
|
|
209
|
-
totalSize: 0,
|
|
210
|
-
validEntries: 0,
|
|
211
|
-
staleEntries: 0,
|
|
212
|
-
expiredEntries: 0,
|
|
213
|
-
bySource: { github: 0, confluence: 0, notion: 0, local: 0, custom: 0 },
|
|
214
|
-
},
|
|
215
|
-
entries: [],
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
expect(result).toContain('No entries in cache');
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
});
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cache Commands
|
|
3
|
-
*
|
|
4
|
-
* Commands for managing the local cache.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { join } from 'path';
|
|
8
|
-
import { FileCacheProvider, CACHE_PATHS, type CacheStats } from '../../cache/index.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Options for cache commands
|
|
12
|
-
*/
|
|
13
|
-
export interface CacheCommandOptions {
|
|
14
|
-
/**
|
|
15
|
-
* Project root directory
|
|
16
|
-
*/
|
|
17
|
-
projectRoot?: string;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Custom cache path (overrides default)
|
|
21
|
-
*/
|
|
22
|
-
cachePath?: string;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Output format
|
|
26
|
-
*/
|
|
27
|
-
format?: 'text' | 'json';
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Result of cache status command
|
|
32
|
-
*/
|
|
33
|
-
export interface CacheStatusResult {
|
|
34
|
-
initialized: boolean;
|
|
35
|
-
path: string;
|
|
36
|
-
stats: CacheStats | null;
|
|
37
|
-
entries: {
|
|
38
|
-
key: string;
|
|
39
|
-
source: string;
|
|
40
|
-
status: string;
|
|
41
|
-
size: number;
|
|
42
|
-
cachedAt: string;
|
|
43
|
-
expiresAt: string;
|
|
44
|
-
}[];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Result of cache clear command
|
|
49
|
-
*/
|
|
50
|
-
export interface CacheClearResult {
|
|
51
|
-
cleared: number;
|
|
52
|
-
success: boolean;
|
|
53
|
-
error?: string;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Get the cache path for a project
|
|
58
|
-
*/
|
|
59
|
-
function getCachePath(options: CacheCommandOptions): string {
|
|
60
|
-
if (options.cachePath) {
|
|
61
|
-
return options.cachePath;
|
|
62
|
-
}
|
|
63
|
-
const root = options.projectRoot ?? process.cwd();
|
|
64
|
-
return join(root, CACHE_PATHS.ROOT);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Get cache status
|
|
69
|
-
*/
|
|
70
|
-
export async function cacheStatus(options: CacheCommandOptions = {}): Promise<CacheStatusResult> {
|
|
71
|
-
const cachePath = getCachePath(options);
|
|
72
|
-
|
|
73
|
-
const provider = new FileCacheProvider({ basePath: cachePath });
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
await provider.initialize();
|
|
77
|
-
} catch {
|
|
78
|
-
return {
|
|
79
|
-
initialized: false,
|
|
80
|
-
path: cachePath,
|
|
81
|
-
stats: null,
|
|
82
|
-
entries: [],
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const stats = await provider.getStats();
|
|
87
|
-
const metadataList = await provider.list();
|
|
88
|
-
|
|
89
|
-
const entries = await Promise.all(
|
|
90
|
-
metadataList.map(async (metadata) => {
|
|
91
|
-
const status = await provider.getStatus(metadata.key);
|
|
92
|
-
return {
|
|
93
|
-
key: metadata.key,
|
|
94
|
-
source: metadata.source,
|
|
95
|
-
status: status ?? 'unknown',
|
|
96
|
-
size: metadata.size,
|
|
97
|
-
cachedAt: metadata.cachedAt,
|
|
98
|
-
expiresAt: metadata.expiresAt,
|
|
99
|
-
};
|
|
100
|
-
})
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
initialized: true,
|
|
105
|
-
path: cachePath,
|
|
106
|
-
stats,
|
|
107
|
-
entries,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Clear all cache entries
|
|
113
|
-
*/
|
|
114
|
-
export async function cacheClear(options: CacheCommandOptions = {}): Promise<CacheClearResult> {
|
|
115
|
-
const cachePath = getCachePath(options);
|
|
116
|
-
|
|
117
|
-
const provider = new FileCacheProvider({ basePath: cachePath });
|
|
118
|
-
|
|
119
|
-
try {
|
|
120
|
-
await provider.initialize();
|
|
121
|
-
const cleared = await provider.clear();
|
|
122
|
-
return { cleared, success: true };
|
|
123
|
-
} catch (error) {
|
|
124
|
-
return {
|
|
125
|
-
cleared: 0,
|
|
126
|
-
success: false,
|
|
127
|
-
error: error instanceof Error ? error.message : String(error),
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Clear expired cache entries
|
|
134
|
-
*/
|
|
135
|
-
export async function cacheClearExpired(
|
|
136
|
-
options: CacheCommandOptions = {}
|
|
137
|
-
): Promise<CacheClearResult> {
|
|
138
|
-
const cachePath = getCachePath(options);
|
|
139
|
-
|
|
140
|
-
const provider = new FileCacheProvider({ basePath: cachePath });
|
|
141
|
-
|
|
142
|
-
try {
|
|
143
|
-
await provider.initialize();
|
|
144
|
-
const cleared = await provider.clearExpired();
|
|
145
|
-
return { cleared, success: true };
|
|
146
|
-
} catch (error) {
|
|
147
|
-
return {
|
|
148
|
-
cleared: 0,
|
|
149
|
-
success: false,
|
|
150
|
-
error: error instanceof Error ? error.message : String(error),
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Format bytes to human-readable string
|
|
157
|
-
*/
|
|
158
|
-
export function formatBytes(bytes: number): string {
|
|
159
|
-
if (bytes === 0) return '0 B';
|
|
160
|
-
const k = 1024;
|
|
161
|
-
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
162
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
163
|
-
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Format cache status for terminal output
|
|
168
|
-
*/
|
|
169
|
-
export function formatCacheStatus(result: CacheStatusResult): string {
|
|
170
|
-
const lines: string[] = [];
|
|
171
|
-
|
|
172
|
-
lines.push('Cache Status');
|
|
173
|
-
lines.push('============');
|
|
174
|
-
lines.push('');
|
|
175
|
-
|
|
176
|
-
if (!result.initialized) {
|
|
177
|
-
lines.push(`Path: ${result.path}`);
|
|
178
|
-
lines.push('Status: Not initialized (no cache found)');
|
|
179
|
-
return lines.join('\n');
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
lines.push(`Path: ${result.path}`);
|
|
183
|
-
lines.push('Status: Initialized');
|
|
184
|
-
lines.push('');
|
|
185
|
-
|
|
186
|
-
if (result.stats) {
|
|
187
|
-
lines.push('Statistics:');
|
|
188
|
-
lines.push(` Entries: ${result.stats.totalEntries}`);
|
|
189
|
-
lines.push(` Total size: ${formatBytes(result.stats.totalSize)}`);
|
|
190
|
-
lines.push(
|
|
191
|
-
` Valid: ${result.stats.validEntries}, Stale: ${result.stats.staleEntries}, Expired: ${result.stats.expiredEntries}`
|
|
192
|
-
);
|
|
193
|
-
if (result.stats.newestEntry) {
|
|
194
|
-
lines.push(` Last updated: ${result.stats.newestEntry}`);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (result.entries.length > 0) {
|
|
199
|
-
lines.push('');
|
|
200
|
-
lines.push('Entries:');
|
|
201
|
-
lines.push('');
|
|
202
|
-
|
|
203
|
-
// Group by source
|
|
204
|
-
const bySource = new Map<string, typeof result.entries>();
|
|
205
|
-
for (const entry of result.entries) {
|
|
206
|
-
const source = entry.source;
|
|
207
|
-
if (!bySource.has(source)) {
|
|
208
|
-
bySource.set(source, []);
|
|
209
|
-
}
|
|
210
|
-
const entries = bySource.get(source);
|
|
211
|
-
if (entries) {
|
|
212
|
-
entries.push(entry);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
for (const [source, entries] of bySource) {
|
|
217
|
-
lines.push(` ${source}:`);
|
|
218
|
-
for (const entry of entries) {
|
|
219
|
-
const statusIcon = entry.status === 'valid' ? '✓' : entry.status === 'stale' ? '○' : '✗';
|
|
220
|
-
lines.push(` ${statusIcon} ${entry.key} (${formatBytes(entry.size)})`);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
} else {
|
|
224
|
-
lines.push('');
|
|
225
|
-
lines.push('No entries in cache.');
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
return lines.join('\n');
|
|
229
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI Commands
|
|
3
|
-
*
|
|
4
|
-
* Command implementations for the CoreAI CLI.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
// Cache commands
|
|
8
|
-
export {
|
|
9
|
-
cacheStatus,
|
|
10
|
-
cacheClear,
|
|
11
|
-
cacheClearExpired,
|
|
12
|
-
formatCacheStatus,
|
|
13
|
-
formatBytes,
|
|
14
|
-
type CacheCommandOptions,
|
|
15
|
-
type CacheStatusResult,
|
|
16
|
-
type CacheClearResult,
|
|
17
|
-
} from './cache.js';
|
|
18
|
-
|
|
19
|
-
// Sync commands
|
|
20
|
-
export { sync, formatSyncResult, type SyncCommandOptions, type SyncCommandResult } from './sync.js';
|
|
21
|
-
|
|
22
|
-
// Init command
|
|
23
|
-
export { init, formatInitResult, type InitCommandOptions, type InitCommandResult } from './init.js';
|
|
24
|
-
|
|
25
|
-
// Build command
|
|
26
|
-
export {
|
|
27
|
-
build,
|
|
28
|
-
formatBuildResult,
|
|
29
|
-
type BuildCommandOptions,
|
|
30
|
-
type BuildCommandResult,
|
|
31
|
-
} from './build.js';
|
|
32
|
-
|
|
33
|
-
// Validate command
|
|
34
|
-
export {
|
|
35
|
-
validate,
|
|
36
|
-
formatValidateResult,
|
|
37
|
-
type ValidateCommandOptions,
|
|
38
|
-
type ValidateCommandResult,
|
|
39
|
-
type ValidationIssue,
|
|
40
|
-
} from './validate.js';
|
|
41
|
-
|
|
42
|
-
// Skills commands
|
|
43
|
-
export {
|
|
44
|
-
skillsGenerate,
|
|
45
|
-
formatSkillsGenerateResult,
|
|
46
|
-
skillsList,
|
|
47
|
-
formatSkillsListResult,
|
|
48
|
-
type SkillsGenerateOptions,
|
|
49
|
-
type SkillsGenerateResult,
|
|
50
|
-
type SkillsListOptions,
|
|
51
|
-
type SkillsListResult,
|
|
52
|
-
type SkillInfo,
|
|
53
|
-
} from './skills.js';
|
|
54
|
-
|
|
55
|
-
// Status command
|
|
56
|
-
export {
|
|
57
|
-
status,
|
|
58
|
-
formatStatusResult,
|
|
59
|
-
formatStatusSummary,
|
|
60
|
-
type StatusCommandOptions,
|
|
61
|
-
type StatusCommandResult,
|
|
62
|
-
type AgentStatus,
|
|
63
|
-
} from './status.js';
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Init Command Tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { promises as fs } from 'fs';
|
|
6
|
-
import { join } from 'path';
|
|
7
|
-
import { tmpdir } from 'os';
|
|
8
|
-
import { init, formatInitResult } from './init.js';
|
|
9
|
-
|
|
10
|
-
describe('Init Command', () => {
|
|
11
|
-
let testDir: string;
|
|
12
|
-
|
|
13
|
-
beforeEach(async () => {
|
|
14
|
-
testDir = join(tmpdir(), `init-cmd-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
15
|
-
await fs.mkdir(testDir, { recursive: true });
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
afterEach(async () => {
|
|
19
|
-
try {
|
|
20
|
-
await fs.rm(testDir, { recursive: true, force: true });
|
|
21
|
-
} catch {
|
|
22
|
-
// Ignore cleanup errors
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
describe('init', () => {
|
|
27
|
-
it('should create config file with defaults', async () => {
|
|
28
|
-
const result = init({
|
|
29
|
-
projectRoot: testDir,
|
|
30
|
-
name: 'test-project',
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
expect(result.success).toBe(true);
|
|
34
|
-
expect(result.configPath).toBe(join(testDir, 'coreai.config.yaml'));
|
|
35
|
-
|
|
36
|
-
// Verify file exists
|
|
37
|
-
const configPath = result.configPath ?? '';
|
|
38
|
-
const content = await fs.readFile(configPath, 'utf-8');
|
|
39
|
-
expect(content).toContain('name: "test-project"');
|
|
40
|
-
expect(content).toContain('type: software');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should create directory structure', async () => {
|
|
44
|
-
const result = init({
|
|
45
|
-
projectRoot: testDir,
|
|
46
|
-
name: 'test-project',
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
expect(result.success).toBe(true);
|
|
50
|
-
expect(result.createdDirs).toBeDefined();
|
|
51
|
-
expect(result.createdDirs?.length).toBeGreaterThan(0);
|
|
52
|
-
|
|
53
|
-
// Verify directories exist
|
|
54
|
-
const coreaiDir = join(testDir, 'coreai', 'agents');
|
|
55
|
-
const stat = await fs.stat(coreaiDir);
|
|
56
|
-
expect(stat.isDirectory()).toBe(true);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('should skip directory creation when skipDirs is true', async () => {
|
|
60
|
-
const result = init({
|
|
61
|
-
projectRoot: testDir,
|
|
62
|
-
name: 'test-project',
|
|
63
|
-
skipDirs: true,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
expect(result.success).toBe(true);
|
|
67
|
-
expect(result.createdDirs).toEqual([]);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('should fail if config already exists without force', async () => {
|
|
71
|
-
// Create existing config
|
|
72
|
-
await fs.writeFile(join(testDir, 'coreai.config.yaml'), 'version: "1.0"');
|
|
73
|
-
|
|
74
|
-
const result = init({
|
|
75
|
-
projectRoot: testDir,
|
|
76
|
-
name: 'test-project',
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
expect(result.success).toBe(false);
|
|
80
|
-
expect(result.error).toContain('already exists');
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('should overwrite config with force option', async () => {
|
|
84
|
-
// Create existing config
|
|
85
|
-
await fs.writeFile(join(testDir, 'coreai.config.yaml'), 'version: "1.0"');
|
|
86
|
-
|
|
87
|
-
const result = init({
|
|
88
|
-
projectRoot: testDir,
|
|
89
|
-
name: 'new-project',
|
|
90
|
-
force: true,
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
expect(result.success).toBe(true);
|
|
94
|
-
|
|
95
|
-
const configPath2 = result.configPath ?? '';
|
|
96
|
-
const content = await fs.readFile(configPath2, 'utf-8');
|
|
97
|
-
expect(content).toContain('name: "new-project"');
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('should use custom project type', async () => {
|
|
101
|
-
const result = init({
|
|
102
|
-
projectRoot: testDir,
|
|
103
|
-
name: 'mobile-app',
|
|
104
|
-
type: 'mobile',
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
expect(result.success).toBe(true);
|
|
108
|
-
|
|
109
|
-
const configPath3 = result.configPath ?? '';
|
|
110
|
-
const content = await fs.readFile(configPath3, 'utf-8');
|
|
111
|
-
expect(content).toContain('type: mobile');
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('should detect project name from directory', async () => {
|
|
115
|
-
const result = init({
|
|
116
|
-
projectRoot: testDir,
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
expect(result.success).toBe(true);
|
|
120
|
-
|
|
121
|
-
// Should use directory name as project name
|
|
122
|
-
const configPath4 = result.configPath ?? '';
|
|
123
|
-
const content = await fs.readFile(configPath4, 'utf-8');
|
|
124
|
-
expect(content).toContain('name:');
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
describe('formatInitResult', () => {
|
|
129
|
-
it('should format success result', () => {
|
|
130
|
-
const result = {
|
|
131
|
-
success: true,
|
|
132
|
-
configPath: '/path/to/coreai.config.yaml',
|
|
133
|
-
createdDirs: ['/path/to/coreai/agents'],
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
const output = formatInitResult(result);
|
|
137
|
-
|
|
138
|
-
expect(output).toContain('initialized successfully');
|
|
139
|
-
expect(output).toContain('coreai.config.yaml');
|
|
140
|
-
expect(output).toContain('Next steps');
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('should format error result', () => {
|
|
144
|
-
const result = {
|
|
145
|
-
success: false,
|
|
146
|
-
error: 'Config already exists',
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const output = formatInitResult(result);
|
|
150
|
-
|
|
151
|
-
expect(output).toContain('Error');
|
|
152
|
-
expect(output).toContain('Config already exists');
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('should show detected git info', () => {
|
|
156
|
-
const result = {
|
|
157
|
-
success: true,
|
|
158
|
-
configPath: '/path/to/config.yaml',
|
|
159
|
-
createdDirs: [],
|
|
160
|
-
gitInfo: {
|
|
161
|
-
provider: 'github' as const,
|
|
162
|
-
owner: 'test-owner',
|
|
163
|
-
repo: 'test-repo',
|
|
164
|
-
},
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const output = formatInitResult(result);
|
|
168
|
-
|
|
169
|
-
expect(output).toContain('github');
|
|
170
|
-
expect(output).toContain('test-owner/test-repo');
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
});
|