@deimoscloud/coreai 0.1.9 → 0.1.11
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 +7 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +7 -0
- 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 -410
- package/src/agents/compiler.ts +0 -424
- 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,386 +0,0 @@
|
|
|
1
|
-
import { AdapterFactory, createAdapterFactory, createAdapterInfo } from './factory.js';
|
|
2
|
-
import { AdapterError } from './types.js';
|
|
3
|
-
import type { CoreAIConfig } from '../config/types.js';
|
|
4
|
-
import type { IssueTrackerAdapter, StateProviderAdapter } from './interfaces.js';
|
|
5
|
-
import type {
|
|
6
|
-
AdapterInfo,
|
|
7
|
-
Issue,
|
|
8
|
-
IssueQuery,
|
|
9
|
-
CreateIssueData,
|
|
10
|
-
UpdateIssueData,
|
|
11
|
-
IssueStatus,
|
|
12
|
-
StateEntry,
|
|
13
|
-
StateOptions,
|
|
14
|
-
} from './types.js';
|
|
15
|
-
|
|
16
|
-
// Mock adapter implementations for testing
|
|
17
|
-
function createMockIssueTrackerAdapter(
|
|
18
|
-
provider: string,
|
|
19
|
-
implementation: 'mcp' | 'native' | 'mock'
|
|
20
|
-
): IssueTrackerAdapter {
|
|
21
|
-
const info: AdapterInfo = {
|
|
22
|
-
type: 'issue_tracker',
|
|
23
|
-
provider,
|
|
24
|
-
implementation,
|
|
25
|
-
connected: false,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
getInfo: () => info,
|
|
30
|
-
isConnected: () => info.connected,
|
|
31
|
-
connect: async () => {
|
|
32
|
-
info.connected = true;
|
|
33
|
-
},
|
|
34
|
-
disconnect: async () => {
|
|
35
|
-
info.connected = false;
|
|
36
|
-
},
|
|
37
|
-
getIssue: async (id: string): Promise<Issue> => ({
|
|
38
|
-
id,
|
|
39
|
-
key: `MOCK-${id}`,
|
|
40
|
-
title: 'Mock Issue',
|
|
41
|
-
status: 'todo',
|
|
42
|
-
}),
|
|
43
|
-
listIssues: async (_query?: IssueQuery): Promise<Issue[]> => [],
|
|
44
|
-
createIssue: async (data: CreateIssueData): Promise<Issue> => ({
|
|
45
|
-
id: '1',
|
|
46
|
-
key: 'MOCK-1',
|
|
47
|
-
title: data.title,
|
|
48
|
-
status: 'todo',
|
|
49
|
-
}),
|
|
50
|
-
updateIssue: async (id: string, data: UpdateIssueData): Promise<Issue> => ({
|
|
51
|
-
id,
|
|
52
|
-
key: `MOCK-${id}`,
|
|
53
|
-
title: data.title ?? 'Updated',
|
|
54
|
-
status: data.status ?? 'todo',
|
|
55
|
-
}),
|
|
56
|
-
transitionIssue: async (id: string, status: IssueStatus): Promise<Issue> => ({
|
|
57
|
-
id,
|
|
58
|
-
key: `MOCK-${id}`,
|
|
59
|
-
title: 'Mock Issue',
|
|
60
|
-
status,
|
|
61
|
-
}),
|
|
62
|
-
addComment: async (): Promise<void> => {
|
|
63
|
-
// No-op for mock
|
|
64
|
-
},
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function createMockStateAdapter(
|
|
69
|
-
provider: string,
|
|
70
|
-
implementation: 'mcp' | 'native' | 'mock'
|
|
71
|
-
): StateProviderAdapter {
|
|
72
|
-
const info: AdapterInfo = {
|
|
73
|
-
type: 'state',
|
|
74
|
-
provider,
|
|
75
|
-
implementation,
|
|
76
|
-
connected: false,
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
const storage = new Map<string, string>();
|
|
80
|
-
|
|
81
|
-
return {
|
|
82
|
-
getInfo: () => info,
|
|
83
|
-
isConnected: () => info.connected,
|
|
84
|
-
connect: async () => {
|
|
85
|
-
info.connected = true;
|
|
86
|
-
},
|
|
87
|
-
disconnect: async () => {
|
|
88
|
-
info.connected = false;
|
|
89
|
-
},
|
|
90
|
-
read: async (path: string): Promise<string> => {
|
|
91
|
-
const content = storage.get(path);
|
|
92
|
-
if (!content) throw new Error('Not found');
|
|
93
|
-
return content;
|
|
94
|
-
},
|
|
95
|
-
write: async (path: string, content: string): Promise<void> => {
|
|
96
|
-
storage.set(path, content);
|
|
97
|
-
},
|
|
98
|
-
exists: async (path: string): Promise<boolean> => storage.has(path),
|
|
99
|
-
list: async (_path: string): Promise<StateEntry[]> => [],
|
|
100
|
-
delete: async (path: string, _options?: StateOptions): Promise<void> => {
|
|
101
|
-
storage.delete(path);
|
|
102
|
-
},
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const mockConfig: CoreAIConfig = {
|
|
107
|
-
version: '1.0',
|
|
108
|
-
project: {
|
|
109
|
-
name: 'test-project',
|
|
110
|
-
},
|
|
111
|
-
integrations: {
|
|
112
|
-
issue_tracker: {
|
|
113
|
-
provider: 'jira',
|
|
114
|
-
config: {
|
|
115
|
-
project_key: 'TEST',
|
|
116
|
-
base_url: 'https://jira.example.com',
|
|
117
|
-
},
|
|
118
|
-
strategy: 'auto',
|
|
119
|
-
},
|
|
120
|
-
git: {
|
|
121
|
-
provider: 'github',
|
|
122
|
-
config: {
|
|
123
|
-
repo: 'org/repo',
|
|
124
|
-
},
|
|
125
|
-
strategy: 'native',
|
|
126
|
-
},
|
|
127
|
-
state: {
|
|
128
|
-
provider: 'local',
|
|
129
|
-
config: {
|
|
130
|
-
base_path: './KnowledgeLibrary',
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
describe('AdapterFactory', () => {
|
|
137
|
-
describe('createAdapterFactory', () => {
|
|
138
|
-
it('should create a factory from config', () => {
|
|
139
|
-
const factory = createAdapterFactory(mockConfig);
|
|
140
|
-
expect(factory).toBeInstanceOf(AdapterFactory);
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
describe('createAdapterInfo', () => {
|
|
145
|
-
it('should create adapter info with defaults', () => {
|
|
146
|
-
const info = createAdapterInfo('issue_tracker', 'jira', 'mcp');
|
|
147
|
-
expect(info).toEqual({
|
|
148
|
-
type: 'issue_tracker',
|
|
149
|
-
provider: 'jira',
|
|
150
|
-
implementation: 'mcp',
|
|
151
|
-
connected: false,
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('should create adapter info with connected state', () => {
|
|
156
|
-
const info = createAdapterInfo('git', 'github', 'native', true);
|
|
157
|
-
expect(info.connected).toBe(true);
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
describe('hasIntegration', () => {
|
|
162
|
-
it('should return true for configured integrations', () => {
|
|
163
|
-
const factory = createAdapterFactory(mockConfig);
|
|
164
|
-
expect(factory.hasIntegration('issue_tracker')).toBe(true);
|
|
165
|
-
expect(factory.hasIntegration('git')).toBe(true);
|
|
166
|
-
expect(factory.hasIntegration('state')).toBe(true);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it('should return false for unconfigured integrations', () => {
|
|
170
|
-
const factory = createAdapterFactory(mockConfig);
|
|
171
|
-
expect(factory.hasIntegration('documentation')).toBe(false);
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it('should return false when no integrations configured', () => {
|
|
175
|
-
const factory = createAdapterFactory({
|
|
176
|
-
version: '1.0',
|
|
177
|
-
project: { name: 'test' },
|
|
178
|
-
});
|
|
179
|
-
expect(factory.hasIntegration('issue_tracker')).toBe(false);
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
describe('getIntegrationInfo', () => {
|
|
184
|
-
it('should return provider and strategy for configured integration', () => {
|
|
185
|
-
const factory = createAdapterFactory(mockConfig);
|
|
186
|
-
const info = factory.getIntegrationInfo('issue_tracker');
|
|
187
|
-
expect(info).toEqual({
|
|
188
|
-
provider: 'jira',
|
|
189
|
-
strategy: 'auto',
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it('should return strategy from config', () => {
|
|
194
|
-
const factory = createAdapterFactory(mockConfig);
|
|
195
|
-
const info = factory.getIntegrationInfo('git');
|
|
196
|
-
expect(info?.strategy).toBe('native');
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
it('should default strategy to auto', () => {
|
|
200
|
-
const factory = createAdapterFactory(mockConfig);
|
|
201
|
-
const info = factory.getIntegrationInfo('state');
|
|
202
|
-
expect(info?.strategy).toBe('auto');
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it('should return null for unconfigured integration', () => {
|
|
206
|
-
const factory = createAdapterFactory(mockConfig);
|
|
207
|
-
expect(factory.getIntegrationInfo('documentation')).toBeNull();
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
describe('registerCreator', () => {
|
|
212
|
-
it('should register and use MCP creator', async () => {
|
|
213
|
-
const factory = createAdapterFactory(mockConfig);
|
|
214
|
-
|
|
215
|
-
factory.registerCreator('issue_tracker', 'mcp', async () =>
|
|
216
|
-
createMockIssueTrackerAdapter('jira', 'mcp')
|
|
217
|
-
);
|
|
218
|
-
|
|
219
|
-
const adapter = await factory.getIssueTracker({ implementation: 'mcp' });
|
|
220
|
-
const info = adapter.getInfo();
|
|
221
|
-
|
|
222
|
-
expect(info.type).toBe('issue_tracker');
|
|
223
|
-
expect(info.provider).toBe('jira');
|
|
224
|
-
expect(info.implementation).toBe('mcp');
|
|
225
|
-
expect(adapter.isConnected()).toBe(true);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it('should register and use native creator', async () => {
|
|
229
|
-
const factory = createAdapterFactory(mockConfig);
|
|
230
|
-
|
|
231
|
-
factory.registerCreator('issue_tracker', 'native', async () =>
|
|
232
|
-
createMockIssueTrackerAdapter('jira', 'native')
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
const adapter = await factory.getIssueTracker({ implementation: 'native' });
|
|
236
|
-
expect(adapter.getInfo().implementation).toBe('native');
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
describe('getAdapter', () => {
|
|
241
|
-
it('should cache adapters', async () => {
|
|
242
|
-
const factory = createAdapterFactory(mockConfig);
|
|
243
|
-
|
|
244
|
-
let callCount = 0;
|
|
245
|
-
factory.registerCreator('issue_tracker', 'mcp', async () => {
|
|
246
|
-
callCount++;
|
|
247
|
-
return createMockIssueTrackerAdapter('jira', 'mcp');
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
const adapter1 = await factory.getIssueTracker();
|
|
251
|
-
const adapter2 = await factory.getIssueTracker();
|
|
252
|
-
|
|
253
|
-
expect(adapter1).toBe(adapter2);
|
|
254
|
-
expect(callCount).toBe(1);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
it('should throw for missing implementation', async () => {
|
|
258
|
-
const factory = createAdapterFactory(mockConfig);
|
|
259
|
-
|
|
260
|
-
await expect(factory.getIssueTracker()).rejects.toThrow(AdapterError);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
it('should select MCP over native in auto mode', async () => {
|
|
264
|
-
const factory = createAdapterFactory(mockConfig);
|
|
265
|
-
|
|
266
|
-
factory.registerCreator('issue_tracker', 'mcp', async () =>
|
|
267
|
-
createMockIssueTrackerAdapter('jira', 'mcp')
|
|
268
|
-
);
|
|
269
|
-
factory.registerCreator('issue_tracker', 'native', async () =>
|
|
270
|
-
createMockIssueTrackerAdapter('jira', 'native')
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
const adapter = await factory.getIssueTracker();
|
|
274
|
-
expect(adapter.getInfo().implementation).toBe('mcp');
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
it('should fall back to native when MCP unavailable', async () => {
|
|
278
|
-
const factory = createAdapterFactory(mockConfig);
|
|
279
|
-
|
|
280
|
-
factory.registerCreator('issue_tracker', 'native', async () =>
|
|
281
|
-
createMockIssueTrackerAdapter('jira', 'native')
|
|
282
|
-
);
|
|
283
|
-
|
|
284
|
-
const adapter = await factory.getIssueTracker();
|
|
285
|
-
expect(adapter.getInfo().implementation).toBe('native');
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
it('should respect strategy override in options', async () => {
|
|
289
|
-
const factory = createAdapterFactory(mockConfig);
|
|
290
|
-
|
|
291
|
-
factory.registerCreator('issue_tracker', 'mcp', async () =>
|
|
292
|
-
createMockIssueTrackerAdapter('jira', 'mcp')
|
|
293
|
-
);
|
|
294
|
-
factory.registerCreator('issue_tracker', 'native', async () =>
|
|
295
|
-
createMockIssueTrackerAdapter('jira', 'native')
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
const adapter = await factory.getIssueTracker({ strategy: 'native' });
|
|
299
|
-
expect(adapter.getInfo().implementation).toBe('native');
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it('should throw when requested strategy is unavailable', async () => {
|
|
303
|
-
const factory = createAdapterFactory(mockConfig);
|
|
304
|
-
|
|
305
|
-
factory.registerCreator('issue_tracker', 'native', async () =>
|
|
306
|
-
createMockIssueTrackerAdapter('jira', 'native')
|
|
307
|
-
);
|
|
308
|
-
|
|
309
|
-
await expect(factory.getIssueTracker({ strategy: 'mcp' })).rejects.toThrow(
|
|
310
|
-
'MCP adapter not available'
|
|
311
|
-
);
|
|
312
|
-
});
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
describe('typed adapter getters', () => {
|
|
316
|
-
it('should get issue tracker adapter', async () => {
|
|
317
|
-
const factory = createAdapterFactory(mockConfig);
|
|
318
|
-
factory.registerCreator('issue_tracker', 'mock', async () =>
|
|
319
|
-
createMockIssueTrackerAdapter('jira', 'mock')
|
|
320
|
-
);
|
|
321
|
-
|
|
322
|
-
const adapter = await factory.getIssueTracker();
|
|
323
|
-
expect(adapter.getInfo().type).toBe('issue_tracker');
|
|
324
|
-
|
|
325
|
-
// Test that interface methods exist
|
|
326
|
-
const issue = await adapter.getIssue('123');
|
|
327
|
-
expect(issue.key).toBe('MOCK-123');
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
it('should get state provider adapter', async () => {
|
|
331
|
-
const factory = createAdapterFactory(mockConfig);
|
|
332
|
-
factory.registerCreator('state', 'mock', async () => createMockStateAdapter('local', 'mock'));
|
|
333
|
-
|
|
334
|
-
const adapter = await factory.getStateProvider();
|
|
335
|
-
expect(adapter.getInfo().type).toBe('state');
|
|
336
|
-
|
|
337
|
-
// Test that interface methods work
|
|
338
|
-
await adapter.write('/test.txt', 'hello');
|
|
339
|
-
const content = await adapter.read('/test.txt');
|
|
340
|
-
expect(content).toBe('hello');
|
|
341
|
-
});
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
describe('disconnectAll', () => {
|
|
345
|
-
it('should disconnect all cached adapters', async () => {
|
|
346
|
-
const factory = createAdapterFactory(mockConfig);
|
|
347
|
-
|
|
348
|
-
factory.registerCreator('issue_tracker', 'mock', async () =>
|
|
349
|
-
createMockIssueTrackerAdapter('jira', 'mock')
|
|
350
|
-
);
|
|
351
|
-
factory.registerCreator('state', 'mock', async () => createMockStateAdapter('local', 'mock'));
|
|
352
|
-
|
|
353
|
-
const issueTracker = await factory.getIssueTracker();
|
|
354
|
-
const stateProvider = await factory.getStateProvider();
|
|
355
|
-
|
|
356
|
-
expect(issueTracker.isConnected()).toBe(true);
|
|
357
|
-
expect(stateProvider.isConnected()).toBe(true);
|
|
358
|
-
|
|
359
|
-
await factory.disconnectAll();
|
|
360
|
-
|
|
361
|
-
expect(issueTracker.isConnected()).toBe(false);
|
|
362
|
-
expect(stateProvider.isConnected()).toBe(false);
|
|
363
|
-
});
|
|
364
|
-
});
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
describe('AdapterError', () => {
|
|
368
|
-
it('should create error with message and code', () => {
|
|
369
|
-
const error = new AdapterError('Something went wrong', 'network_error');
|
|
370
|
-
expect(error.message).toBe('Something went wrong');
|
|
371
|
-
expect(error.code).toBe('network_error');
|
|
372
|
-
expect(error.name).toBe('AdapterError');
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
it('should include adapter info', () => {
|
|
376
|
-
const info = createAdapterInfo('git', 'github', 'native', true);
|
|
377
|
-
const error = new AdapterError('Failed', 'provider_error', info);
|
|
378
|
-
expect(error.adapter).toEqual(info);
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
it('should include cause', () => {
|
|
382
|
-
const cause = new Error('Original error');
|
|
383
|
-
const error = new AdapterError('Wrapped error', 'network_error', undefined, cause);
|
|
384
|
-
expect(error.cause).toBe(cause);
|
|
385
|
-
});
|
|
386
|
-
});
|
package/src/adapters/factory.ts
DELETED
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Adapter Factory
|
|
3
|
-
*
|
|
4
|
-
* Creates and manages adapter instances based on configuration.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { CoreAIConfig, AdapterStrategy } from '../config/types.js';
|
|
8
|
-
import type { AdapterType, AdapterInfo, AdapterImplementation } from './types.js';
|
|
9
|
-
import { AdapterError } from './types.js';
|
|
10
|
-
import type {
|
|
11
|
-
IssueTrackerAdapter,
|
|
12
|
-
GitProviderAdapter,
|
|
13
|
-
DocumentationProviderAdapter,
|
|
14
|
-
StateProviderAdapter,
|
|
15
|
-
Adapter,
|
|
16
|
-
} from './interfaces.js';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Options for creating an adapter
|
|
20
|
-
*/
|
|
21
|
-
export interface AdapterFactoryOptions {
|
|
22
|
-
/**
|
|
23
|
-
* Override the strategy from config
|
|
24
|
-
*/
|
|
25
|
-
strategy?: AdapterStrategy;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Force a specific implementation
|
|
29
|
-
*/
|
|
30
|
-
implementation?: AdapterImplementation;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Registry of adapter creators
|
|
35
|
-
*/
|
|
36
|
-
interface AdapterCreator<T extends Adapter> {
|
|
37
|
-
mcp?: (config: CoreAIConfig) => Promise<T>;
|
|
38
|
-
native?: (config: CoreAIConfig) => Promise<T>;
|
|
39
|
-
mock?: (config: CoreAIConfig) => Promise<T>;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Adapter Factory
|
|
44
|
-
*
|
|
45
|
-
* Creates adapter instances based on configuration and available implementations.
|
|
46
|
-
*/
|
|
47
|
-
export class AdapterFactory {
|
|
48
|
-
private config: CoreAIConfig;
|
|
49
|
-
private adapters = new Map<AdapterType, Adapter>();
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Registry of adapter creators by type
|
|
53
|
-
*/
|
|
54
|
-
private creators: {
|
|
55
|
-
issue_tracker: AdapterCreator<IssueTrackerAdapter>;
|
|
56
|
-
git: AdapterCreator<GitProviderAdapter>;
|
|
57
|
-
documentation: AdapterCreator<DocumentationProviderAdapter>;
|
|
58
|
-
state: AdapterCreator<StateProviderAdapter>;
|
|
59
|
-
} = {
|
|
60
|
-
issue_tracker: {},
|
|
61
|
-
git: {},
|
|
62
|
-
documentation: {},
|
|
63
|
-
state: {},
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
constructor(config: CoreAIConfig) {
|
|
67
|
-
this.config = config;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Register an adapter creator
|
|
72
|
-
*/
|
|
73
|
-
registerCreator<T extends AdapterType>(
|
|
74
|
-
type: T,
|
|
75
|
-
implementation: AdapterImplementation,
|
|
76
|
-
creator: (config: CoreAIConfig) => Promise<Adapter>
|
|
77
|
-
): void {
|
|
78
|
-
const typeCreators = this.creators[type] as AdapterCreator<Adapter>;
|
|
79
|
-
typeCreators[implementation] = creator;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Get an issue tracker adapter
|
|
84
|
-
*/
|
|
85
|
-
async getIssueTracker(options?: AdapterFactoryOptions): Promise<IssueTrackerAdapter> {
|
|
86
|
-
return this.getAdapter('issue_tracker', options) as Promise<IssueTrackerAdapter>;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Get a git provider adapter
|
|
91
|
-
*/
|
|
92
|
-
async getGitProvider(options?: AdapterFactoryOptions): Promise<GitProviderAdapter> {
|
|
93
|
-
return this.getAdapter('git', options) as Promise<GitProviderAdapter>;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Get a documentation provider adapter
|
|
98
|
-
*/
|
|
99
|
-
async getDocumentationProvider(
|
|
100
|
-
options?: AdapterFactoryOptions
|
|
101
|
-
): Promise<DocumentationProviderAdapter> {
|
|
102
|
-
return this.getAdapter('documentation', options) as Promise<DocumentationProviderAdapter>;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Get a state provider adapter
|
|
107
|
-
*/
|
|
108
|
-
async getStateProvider(options?: AdapterFactoryOptions): Promise<StateProviderAdapter> {
|
|
109
|
-
return this.getAdapter('state', options) as Promise<StateProviderAdapter>;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Get an adapter by type
|
|
114
|
-
*/
|
|
115
|
-
async getAdapter(type: AdapterType, options?: AdapterFactoryOptions): Promise<Adapter> {
|
|
116
|
-
// Check if we already have this adapter cached
|
|
117
|
-
const cached = this.adapters.get(type);
|
|
118
|
-
if (cached && cached.isConnected()) {
|
|
119
|
-
return cached;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Determine the strategy
|
|
123
|
-
const strategy = this.getStrategy(type, options);
|
|
124
|
-
|
|
125
|
-
// Get the implementation to use
|
|
126
|
-
const implementation = options?.implementation ?? this.selectImplementation(type, strategy);
|
|
127
|
-
|
|
128
|
-
// Create the adapter
|
|
129
|
-
const adapter = await this.createAdapter(type, implementation);
|
|
130
|
-
|
|
131
|
-
// Cache it
|
|
132
|
-
this.adapters.set(type, adapter);
|
|
133
|
-
|
|
134
|
-
return adapter;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Check if an adapter type is configured
|
|
139
|
-
*/
|
|
140
|
-
hasIntegration(type: AdapterType): boolean {
|
|
141
|
-
const integrations = this.config.integrations;
|
|
142
|
-
if (!integrations) return false;
|
|
143
|
-
|
|
144
|
-
switch (type) {
|
|
145
|
-
case 'issue_tracker':
|
|
146
|
-
return !!integrations.issue_tracker?.provider;
|
|
147
|
-
case 'git':
|
|
148
|
-
return !!integrations.git?.provider;
|
|
149
|
-
case 'documentation':
|
|
150
|
-
return !!integrations.documentation?.provider;
|
|
151
|
-
case 'state':
|
|
152
|
-
return !!integrations.state?.provider;
|
|
153
|
-
default:
|
|
154
|
-
return false;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Get information about a configured integration
|
|
160
|
-
*/
|
|
161
|
-
getIntegrationInfo(type: AdapterType): { provider: string; strategy: AdapterStrategy } | null {
|
|
162
|
-
const integrations = this.config.integrations;
|
|
163
|
-
if (!integrations) return null;
|
|
164
|
-
|
|
165
|
-
let integration;
|
|
166
|
-
switch (type) {
|
|
167
|
-
case 'issue_tracker':
|
|
168
|
-
integration = integrations.issue_tracker;
|
|
169
|
-
break;
|
|
170
|
-
case 'git':
|
|
171
|
-
integration = integrations.git;
|
|
172
|
-
break;
|
|
173
|
-
case 'documentation':
|
|
174
|
-
integration = integrations.documentation;
|
|
175
|
-
break;
|
|
176
|
-
case 'state':
|
|
177
|
-
integration = integrations.state;
|
|
178
|
-
break;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (!integration?.provider) return null;
|
|
182
|
-
|
|
183
|
-
return {
|
|
184
|
-
provider: integration.provider,
|
|
185
|
-
strategy: integration.strategy ?? 'auto',
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Disconnect and clear all cached adapters
|
|
191
|
-
*/
|
|
192
|
-
async disconnectAll(): Promise<void> {
|
|
193
|
-
const disconnects: Promise<void>[] = [];
|
|
194
|
-
|
|
195
|
-
for (const adapter of this.adapters.values()) {
|
|
196
|
-
if (adapter.isConnected()) {
|
|
197
|
-
disconnects.push(adapter.disconnect());
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
await Promise.all(disconnects);
|
|
202
|
-
this.adapters.clear();
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Get the strategy for an adapter type
|
|
207
|
-
*/
|
|
208
|
-
private getStrategy(type: AdapterType, options?: AdapterFactoryOptions): AdapterStrategy {
|
|
209
|
-
if (options?.strategy) {
|
|
210
|
-
return options.strategy;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const info = this.getIntegrationInfo(type);
|
|
214
|
-
return info?.strategy ?? 'auto';
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Select the implementation based on strategy and availability
|
|
219
|
-
*/
|
|
220
|
-
private selectImplementation(
|
|
221
|
-
type: AdapterType,
|
|
222
|
-
strategy: AdapterStrategy
|
|
223
|
-
): AdapterImplementation {
|
|
224
|
-
const creators = this.creators[type];
|
|
225
|
-
|
|
226
|
-
switch (strategy) {
|
|
227
|
-
case 'mcp':
|
|
228
|
-
if (creators.mcp) return 'mcp';
|
|
229
|
-
throw new AdapterError(
|
|
230
|
-
`MCP adapter not available for ${type}`,
|
|
231
|
-
'not_implemented',
|
|
232
|
-
undefined
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
case 'native':
|
|
236
|
-
if (creators.native) return 'native';
|
|
237
|
-
throw new AdapterError(
|
|
238
|
-
`Native adapter not available for ${type}`,
|
|
239
|
-
'not_implemented',
|
|
240
|
-
undefined
|
|
241
|
-
);
|
|
242
|
-
|
|
243
|
-
case 'auto':
|
|
244
|
-
default:
|
|
245
|
-
// Prefer MCP, fall back to native
|
|
246
|
-
if (creators.mcp) return 'mcp';
|
|
247
|
-
if (creators.native) return 'native';
|
|
248
|
-
if (creators.mock) return 'mock';
|
|
249
|
-
|
|
250
|
-
throw new AdapterError(
|
|
251
|
-
`No adapter implementation available for ${type}`,
|
|
252
|
-
'not_implemented',
|
|
253
|
-
undefined
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Create an adapter instance
|
|
260
|
-
*/
|
|
261
|
-
private async createAdapter(
|
|
262
|
-
type: AdapterType,
|
|
263
|
-
implementation: AdapterImplementation
|
|
264
|
-
): Promise<Adapter> {
|
|
265
|
-
const creators = this.creators[type];
|
|
266
|
-
const creator = creators[implementation];
|
|
267
|
-
|
|
268
|
-
if (!creator) {
|
|
269
|
-
throw new AdapterError(
|
|
270
|
-
`No ${implementation} adapter creator registered for ${type}`,
|
|
271
|
-
'not_implemented',
|
|
272
|
-
undefined
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
const adapter = await creator(this.config);
|
|
277
|
-
await adapter.connect();
|
|
278
|
-
|
|
279
|
-
return adapter;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Create an adapter factory from configuration
|
|
285
|
-
*/
|
|
286
|
-
export function createAdapterFactory(config: CoreAIConfig): AdapterFactory {
|
|
287
|
-
return new AdapterFactory(config);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* Create adapter info helper
|
|
292
|
-
*/
|
|
293
|
-
export function createAdapterInfo(
|
|
294
|
-
type: AdapterType,
|
|
295
|
-
provider: string,
|
|
296
|
-
implementation: AdapterImplementation,
|
|
297
|
-
connected = false
|
|
298
|
-
): AdapterInfo {
|
|
299
|
-
return {
|
|
300
|
-
type,
|
|
301
|
-
provider,
|
|
302
|
-
implementation,
|
|
303
|
-
connected,
|
|
304
|
-
};
|
|
305
|
-
}
|