@deimoscloud/coreai 0.1.9 → 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.
Files changed (196) hide show
  1. package/dist/cli/index.js +1 -1
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/package.json +6 -1
  6. package/.prettierrc +0 -9
  7. package/AGENT_SPEC.md +0 -347
  8. package/ARCHITECTURE.md +0 -547
  9. package/DRAFT_PRD.md +0 -1440
  10. package/IMPLEMENTATION_PLAN.md +0 -256
  11. package/PRODUCT.md +0 -473
  12. package/WORKFLOWS.md +0 -295
  13. package/commands/core/check-inbox.md +0 -34
  14. package/commands/core/delegate.md +0 -30
  15. package/commands/core/git-commit.md +0 -144
  16. package/commands/core/pr-create.md +0 -193
  17. package/commands/core/review.md +0 -56
  18. package/commands/core/sprint-status.md +0 -65
  19. package/commands/optional/docs-update.md +0 -200
  20. package/commands/optional/jira-create.md +0 -200
  21. package/commands/optional/jira-transition.md +0 -184
  22. package/commands/optional/worktree-cleanup.md +0 -167
  23. package/commands/optional/worktree-setup.md +0 -110
  24. package/eslint.config.js +0 -29
  25. package/jest.config.js +0 -22
  26. package/knowledge-library/README.md +0 -118
  27. package/knowledge-library/android-engineer/context/current.txt +0 -42
  28. package/knowledge-library/android-engineer/control/decisions.txt +0 -9
  29. package/knowledge-library/android-engineer/control/dependencies.txt +0 -19
  30. package/knowledge-library/android-engineer/control/objectives.txt +0 -26
  31. package/knowledge-library/android-engineer/history/.gitkeep +0 -0
  32. package/knowledge-library/android-engineer/inbox/processed/.gitkeep +0 -0
  33. package/knowledge-library/android-engineer/outbox/.gitkeep +0 -0
  34. package/knowledge-library/android-engineer/tech/.gitkeep +0 -0
  35. package/knowledge-library/architecture.txt +0 -61
  36. package/knowledge-library/backend-engineer/context/current.txt +0 -42
  37. package/knowledge-library/backend-engineer/control/decisions.txt +0 -9
  38. package/knowledge-library/backend-engineer/control/dependencies.txt +0 -19
  39. package/knowledge-library/backend-engineer/control/objectives.txt +0 -26
  40. package/knowledge-library/backend-engineer/history/.gitkeep +0 -0
  41. package/knowledge-library/backend-engineer/inbox/processed/.gitkeep +0 -0
  42. package/knowledge-library/backend-engineer/outbox/.gitkeep +0 -0
  43. package/knowledge-library/backend-engineer/tech/.gitkeep +0 -0
  44. package/knowledge-library/context.txt +0 -52
  45. package/knowledge-library/devops-engineer/context/current.txt +0 -42
  46. package/knowledge-library/devops-engineer/control/decisions.txt +0 -9
  47. package/knowledge-library/devops-engineer/control/dependencies.txt +0 -19
  48. package/knowledge-library/devops-engineer/control/objectives.txt +0 -26
  49. package/knowledge-library/devops-engineer/history/.gitkeep +0 -0
  50. package/knowledge-library/devops-engineer/inbox/processed/.gitkeep +0 -0
  51. package/knowledge-library/devops-engineer/outbox/.gitkeep +0 -0
  52. package/knowledge-library/devops-engineer/tech/.gitkeep +0 -0
  53. package/knowledge-library/engineering-manager/context/current.txt +0 -40
  54. package/knowledge-library/engineering-manager/control/decisions.txt +0 -9
  55. package/knowledge-library/engineering-manager/control/objectives.txt +0 -27
  56. package/knowledge-library/engineering-manager/history/.gitkeep +0 -0
  57. package/knowledge-library/engineering-manager/inbox/processed/.gitkeep +0 -0
  58. package/knowledge-library/engineering-manager/outbox/.gitkeep +0 -0
  59. package/knowledge-library/engineering-manager/tech/.gitkeep +0 -0
  60. package/knowledge-library/prd.txt +0 -81
  61. package/knowledge-library/product-manager/context/current.txt +0 -42
  62. package/knowledge-library/product-manager/control/decisions.txt +0 -9
  63. package/knowledge-library/product-manager/control/dependencies.txt +0 -19
  64. package/knowledge-library/product-manager/control/objectives.txt +0 -26
  65. package/knowledge-library/product-manager/history/.gitkeep +0 -0
  66. package/knowledge-library/product-manager/inbox/processed/.gitkeep +0 -0
  67. package/knowledge-library/product-manager/outbox/.gitkeep +0 -0
  68. package/knowledge-library/product-manager/tech/.gitkeep +0 -0
  69. package/knowledge-library/qa-engineer/context/current.txt +0 -42
  70. package/knowledge-library/qa-engineer/control/decisions.txt +0 -9
  71. package/knowledge-library/qa-engineer/control/dependencies.txt +0 -19
  72. package/knowledge-library/qa-engineer/control/objectives.txt +0 -26
  73. package/knowledge-library/qa-engineer/history/.gitkeep +0 -0
  74. package/knowledge-library/qa-engineer/inbox/processed/.gitkeep +0 -0
  75. package/knowledge-library/qa-engineer/outbox/.gitkeep +0 -0
  76. package/knowledge-library/qa-engineer/tech/.gitkeep +0 -0
  77. package/knowledge-library/security-engineer/context/current.txt +0 -42
  78. package/knowledge-library/security-engineer/control/decisions.txt +0 -9
  79. package/knowledge-library/security-engineer/control/dependencies.txt +0 -19
  80. package/knowledge-library/security-engineer/control/objectives.txt +0 -26
  81. package/knowledge-library/security-engineer/history/.gitkeep +0 -0
  82. package/knowledge-library/security-engineer/inbox/processed/.gitkeep +0 -0
  83. package/knowledge-library/security-engineer/outbox/.gitkeep +0 -0
  84. package/knowledge-library/security-engineer/tech/.gitkeep +0 -0
  85. package/knowledge-library/solutions-architect/context/current.txt +0 -42
  86. package/knowledge-library/solutions-architect/control/decisions.txt +0 -9
  87. package/knowledge-library/solutions-architect/control/dependencies.txt +0 -19
  88. package/knowledge-library/solutions-architect/control/objectives.txt +0 -26
  89. package/knowledge-library/solutions-architect/history/.gitkeep +0 -0
  90. package/knowledge-library/solutions-architect/inbox/processed/.gitkeep +0 -0
  91. package/knowledge-library/solutions-architect/outbox/.gitkeep +0 -0
  92. package/knowledge-library/solutions-architect/tech/.gitkeep +0 -0
  93. package/knowledge-library/wearos-engineer/context/current.txt +0 -42
  94. package/knowledge-library/wearos-engineer/control/decisions.txt +0 -9
  95. package/knowledge-library/wearos-engineer/control/dependencies.txt +0 -19
  96. package/knowledge-library/wearos-engineer/control/objectives.txt +0 -26
  97. package/knowledge-library/wearos-engineer/history/.gitkeep +0 -0
  98. package/knowledge-library/wearos-engineer/inbox/processed/.gitkeep +0 -0
  99. package/knowledge-library/wearos-engineer/outbox/.gitkeep +0 -0
  100. package/knowledge-library/wearos-engineer/tech/.gitkeep +0 -0
  101. package/scripts/add-agent.sh +0 -323
  102. package/scripts/install.sh +0 -354
  103. package/src/adapters/factory.test.ts +0 -386
  104. package/src/adapters/factory.ts +0 -305
  105. package/src/adapters/index.ts +0 -113
  106. package/src/adapters/interfaces.ts +0 -268
  107. package/src/adapters/mcp/client.test.ts +0 -130
  108. package/src/adapters/mcp/client.ts +0 -451
  109. package/src/adapters/mcp/discovery.test.ts +0 -315
  110. package/src/adapters/mcp/discovery.ts +0 -340
  111. package/src/adapters/mcp/index.ts +0 -66
  112. package/src/adapters/mcp/mapper.test.ts +0 -218
  113. package/src/adapters/mcp/mapper.ts +0 -536
  114. package/src/adapters/mcp/registry.test.ts +0 -433
  115. package/src/adapters/mcp/registry.ts +0 -550
  116. package/src/adapters/mcp/types.ts +0 -258
  117. package/src/adapters/native/filesystem.test.ts +0 -350
  118. package/src/adapters/native/filesystem.ts +0 -393
  119. package/src/adapters/native/github.test.ts +0 -173
  120. package/src/adapters/native/github.ts +0 -627
  121. package/src/adapters/native/index.ts +0 -22
  122. package/src/adapters/native/selector.test.ts +0 -224
  123. package/src/adapters/native/selector.ts +0 -150
  124. package/src/adapters/types.ts +0 -270
  125. package/src/agents/compiler.test.ts +0 -410
  126. package/src/agents/compiler.ts +0 -424
  127. package/src/agents/index.ts +0 -37
  128. package/src/agents/loader.test.ts +0 -319
  129. package/src/agents/loader.ts +0 -143
  130. package/src/agents/resolver.test.ts +0 -282
  131. package/src/agents/resolver.ts +0 -262
  132. package/src/agents/types.ts +0 -97
  133. package/src/cache/index.ts +0 -38
  134. package/src/cache/interfaces.ts +0 -283
  135. package/src/cache/manager.test.ts +0 -266
  136. package/src/cache/manager.ts +0 -388
  137. package/src/cache/provider.test.ts +0 -485
  138. package/src/cache/provider.ts +0 -745
  139. package/src/cache/types.test.ts +0 -192
  140. package/src/cache/types.ts +0 -313
  141. package/src/cli/commands/build.test.ts +0 -248
  142. package/src/cli/commands/build.ts +0 -284
  143. package/src/cli/commands/cache.test.ts +0 -221
  144. package/src/cli/commands/cache.ts +0 -229
  145. package/src/cli/commands/index.ts +0 -63
  146. package/src/cli/commands/init.test.ts +0 -173
  147. package/src/cli/commands/init.ts +0 -296
  148. package/src/cli/commands/skills.test.ts +0 -272
  149. package/src/cli/commands/skills.ts +0 -348
  150. package/src/cli/commands/status.test.ts +0 -392
  151. package/src/cli/commands/status.ts +0 -332
  152. package/src/cli/commands/sync.test.ts +0 -213
  153. package/src/cli/commands/sync.ts +0 -251
  154. package/src/cli/commands/validate.test.ts +0 -216
  155. package/src/cli/commands/validate.ts +0 -340
  156. package/src/cli/index.test.ts +0 -190
  157. package/src/cli/index.ts +0 -493
  158. package/src/commands/context.test.ts +0 -163
  159. package/src/commands/context.ts +0 -111
  160. package/src/commands/index.ts +0 -56
  161. package/src/commands/loader.test.ts +0 -273
  162. package/src/commands/loader.ts +0 -355
  163. package/src/commands/registry.test.ts +0 -384
  164. package/src/commands/registry.ts +0 -248
  165. package/src/commands/runner.test.ts +0 -297
  166. package/src/commands/runner.ts +0 -222
  167. package/src/commands/types.ts +0 -361
  168. package/src/config/index.ts +0 -19
  169. package/src/config/loader.test.ts +0 -262
  170. package/src/config/loader.ts +0 -188
  171. package/src/config/types.ts +0 -154
  172. package/src/context/index.ts +0 -14
  173. package/src/context/loader.test.ts +0 -334
  174. package/src/context/loader.ts +0 -357
  175. package/src/index.test.ts +0 -13
  176. package/src/index.ts +0 -268
  177. package/src/knowledge-library/index.ts +0 -44
  178. package/src/knowledge-library/manager.test.ts +0 -536
  179. package/src/knowledge-library/manager.ts +0 -804
  180. package/src/knowledge-library/types.ts +0 -432
  181. package/src/skills/generator.test.ts +0 -602
  182. package/src/skills/generator.ts +0 -491
  183. package/src/skills/index.ts +0 -27
  184. package/src/skills/templates.ts +0 -520
  185. package/src/skills/types.ts +0 -251
  186. package/templates/completion-report.md +0 -72
  187. package/templates/feedback.md +0 -56
  188. package/templates/project-files/CLAUDE.md.template +0 -109
  189. package/templates/project-files/coreai.json.example +0 -47
  190. package/templates/project-files/mcp.json.template +0 -20
  191. package/templates/review-complete.md +0 -64
  192. package/templates/review-request.md +0 -67
  193. package/templates/task-assignment.md +0 -51
  194. package/tsconfig.build.json +0 -4
  195. package/tsconfig.json +0 -26
  196. package/tsup.config.ts +0 -23
@@ -1,332 +0,0 @@
1
- /**
2
- * Status Command
3
- *
4
- * Shows agent states and pending messages.
5
- */
6
-
7
- import { configExists, loadConfig, ConfigError } from '../../config/loader.js';
8
- import type { ResolvedCoreAIConfig } from '../../config/types.js';
9
- import {
10
- getKnowledgeLibraryState,
11
- getAgentKnowledgeState,
12
- initKnowledgeLibrary,
13
- type KnowledgeLibraryState,
14
- } from '../../knowledge-library/index.js';
15
-
16
- /**
17
- * Options for status command
18
- */
19
- export interface StatusCommandOptions {
20
- /**
21
- * Project root directory
22
- */
23
- projectRoot?: string;
24
-
25
- /**
26
- * Show status for specific agent only
27
- */
28
- agent?: string;
29
-
30
- /**
31
- * Show detailed status including message subjects
32
- */
33
- detailed?: boolean;
34
-
35
- /**
36
- * Initialize KnowledgeLibrary if not exists
37
- */
38
- init?: boolean;
39
- }
40
-
41
- /**
42
- * Agent status info
43
- */
44
- export interface AgentStatus {
45
- /**
46
- * Agent name/role
47
- */
48
- name: string;
49
-
50
- /**
51
- * Whether the agent's KnowledgeLibrary is initialized
52
- */
53
- initialized: boolean;
54
-
55
- /**
56
- * Current status (e.g., "idle", "working")
57
- */
58
- status?: string;
59
-
60
- /**
61
- * Current task
62
- */
63
- currentTask?: string;
64
-
65
- /**
66
- * Current ticket
67
- */
68
- currentTicket?: string;
69
-
70
- /**
71
- * Number of pending inbox messages
72
- */
73
- pendingMessages: number;
74
-
75
- /**
76
- * Last activity timestamp
77
- */
78
- lastActivity?: Date;
79
-
80
- /**
81
- * Message details (if detailed mode)
82
- */
83
- messageDetails?: {
84
- type: string;
85
- from: string;
86
- subject: string;
87
- date?: Date;
88
- }[];
89
- }
90
-
91
- /**
92
- * Result of status command
93
- */
94
- export interface StatusCommandResult {
95
- success: boolean;
96
- knowledgeLibrary?: KnowledgeLibraryState;
97
- agents: AgentStatus[];
98
- error?: string;
99
- warnings?: string[];
100
- }
101
-
102
- /**
103
- * Get status of agents and KnowledgeLibrary
104
- */
105
- export function status(options: StatusCommandOptions = {}): StatusCommandResult {
106
- const projectRoot = options.projectRoot ?? process.cwd();
107
- const warnings: string[] = [];
108
-
109
- // Load config if available to get team agents
110
- let config: ResolvedCoreAIConfig | undefined;
111
- let configuredAgents: string[] = [];
112
-
113
- if (configExists(projectRoot)) {
114
- try {
115
- config = loadConfig(projectRoot);
116
- if (config.team?.agents) {
117
- configuredAgents = config.team.agents;
118
- }
119
- } catch (error) {
120
- if (error instanceof ConfigError) {
121
- warnings.push(`Configuration error: ${error.message}`);
122
- } else {
123
- warnings.push(
124
- `Failed to load config: ${error instanceof Error ? error.message : String(error)}`
125
- );
126
- }
127
- }
128
- } else {
129
- warnings.push('No configuration file found.');
130
- }
131
-
132
- // Get KnowledgeLibrary state
133
- let klState = getKnowledgeLibraryState({ projectRoot });
134
-
135
- // Initialize if requested and doesn't exist
136
- if (!klState && options.init) {
137
- const initResult = initKnowledgeLibrary({ projectRoot, createDefaults: true });
138
- if (initResult.success) {
139
- klState = getKnowledgeLibraryState({ projectRoot });
140
- } else {
141
- return {
142
- success: false,
143
- agents: [],
144
- error: `Failed to initialize KnowledgeLibrary: ${initResult.error}`,
145
- warnings: warnings.length > 0 ? warnings : undefined,
146
- };
147
- }
148
- }
149
-
150
- if (!klState) {
151
- return {
152
- success: true,
153
- agents: [],
154
- warnings: [
155
- ...warnings,
156
- 'KnowledgeLibrary not initialized. Run `coreai status --init` to create it.',
157
- ],
158
- };
159
- }
160
-
161
- // Determine which agents to show status for
162
- let agentsToCheck: string[];
163
- if (options.agent) {
164
- agentsToCheck = [options.agent];
165
- } else {
166
- // Combine configured agents and discovered agents
167
- agentsToCheck = [...new Set([...configuredAgents, ...klState.agents])];
168
- }
169
-
170
- // Get status for each agent
171
- const agentStatuses: AgentStatus[] = [];
172
-
173
- for (const agentName of agentsToCheck) {
174
- const agentState = getAgentKnowledgeState(agentName, { projectRoot });
175
-
176
- const agentStatus: AgentStatus = {
177
- name: agentName,
178
- initialized: agentState.initialized,
179
- pendingMessages: agentState.pendingMessages.length,
180
- };
181
-
182
- if (agentState.context) {
183
- agentStatus.status = agentState.context.status;
184
- agentStatus.currentTask = agentState.context.currentTask;
185
- agentStatus.currentTicket = agentState.context.currentTicket;
186
- agentStatus.lastActivity = agentState.context.lastUpdated;
187
- }
188
-
189
- // Add message details if detailed mode
190
- if (options.detailed && agentState.pendingMessages.length > 0) {
191
- agentStatus.messageDetails = agentState.pendingMessages.map((msg) => ({
192
- type: msg.metadata.type ?? 'unknown',
193
- from: msg.metadata.from ?? 'unknown',
194
- subject: msg.metadata.subject ?? msg.filename,
195
- date: msg.metadata.date,
196
- }));
197
- }
198
-
199
- agentStatuses.push(agentStatus);
200
- }
201
-
202
- // Sort by pending messages (most first), then by name
203
- agentStatuses.sort((a, b) => {
204
- if (b.pendingMessages !== a.pendingMessages) {
205
- return b.pendingMessages - a.pendingMessages;
206
- }
207
- return a.name.localeCompare(b.name);
208
- });
209
-
210
- return {
211
- success: true,
212
- knowledgeLibrary: klState,
213
- agents: agentStatuses,
214
- warnings: warnings.length > 0 ? warnings : undefined,
215
- };
216
- }
217
-
218
- /**
219
- * Format status result for display
220
- */
221
- export function formatStatusResult(result: StatusCommandResult): string {
222
- const lines: string[] = [];
223
-
224
- // Warnings
225
- if (result.warnings && result.warnings.length > 0) {
226
- for (const warning of result.warnings) {
227
- lines.push(`⚠ ${warning}`);
228
- }
229
- lines.push('');
230
- }
231
-
232
- if (!result.success) {
233
- lines.push(`Error: ${result.error}`);
234
- return lines.join('\n');
235
- }
236
-
237
- if (result.agents.length === 0) {
238
- lines.push('No agents found.');
239
- return lines.join('\n');
240
- }
241
-
242
- lines.push('Agent Status\n');
243
-
244
- // Summary table header
245
- const activeAgents = result.agents.filter((a) => a.status === 'working');
246
- const idleAgents = result.agents.filter(
247
- (a) => a.initialized && (!a.status || a.status === 'idle')
248
- );
249
- const uninitializedAgents = result.agents.filter((a) => !a.initialized);
250
- const totalPending = result.agents.reduce((sum, a) => sum + a.pendingMessages, 0);
251
-
252
- lines.push(`Total agents: ${result.agents.length}`);
253
- if (activeAgents.length > 0) {
254
- lines.push(` Active: ${activeAgents.length}`);
255
- }
256
- if (idleAgents.length > 0) {
257
- lines.push(` Idle: ${idleAgents.length}`);
258
- }
259
- if (uninitializedAgents.length > 0) {
260
- lines.push(` Not initialized: ${uninitializedAgents.length}`);
261
- }
262
- if (totalPending > 0) {
263
- lines.push(` Total pending messages: ${totalPending}`);
264
- }
265
- lines.push('');
266
-
267
- // Detailed agent list
268
- for (const agent of result.agents) {
269
- const statusIcon = !agent.initialized ? '○' : agent.pendingMessages > 0 ? '●' : '◎';
270
- const statusText = !agent.initialized ? 'not initialized' : (agent.status ?? 'idle');
271
-
272
- lines.push(`${statusIcon} ${agent.name}`);
273
- lines.push(` Status: ${statusText}`);
274
-
275
- if (agent.currentTask) {
276
- lines.push(` Task: ${agent.currentTask}`);
277
- }
278
-
279
- if (agent.currentTicket) {
280
- lines.push(` Ticket: ${agent.currentTicket}`);
281
- }
282
-
283
- if (agent.pendingMessages > 0) {
284
- lines.push(` Pending messages: ${agent.pendingMessages}`);
285
-
286
- // Show message details if available
287
- if (agent.messageDetails && agent.messageDetails.length > 0) {
288
- for (const msg of agent.messageDetails) {
289
- const dateStr = msg.date ? msg.date.toISOString().slice(0, 16).replace('T', ' ') : '';
290
- lines.push(` - [${msg.type}] from ${msg.from}: ${msg.subject}`);
291
- if (dateStr) {
292
- lines.push(` ${dateStr}`);
293
- }
294
- }
295
- }
296
- }
297
-
298
- if (agent.lastActivity) {
299
- const activityStr = agent.lastActivity.toISOString().slice(0, 16).replace('T', ' ');
300
- lines.push(` Last activity: ${activityStr}`);
301
- }
302
-
303
- lines.push('');
304
- }
305
-
306
- return lines.join('\n');
307
- }
308
-
309
- /**
310
- * Format a compact status summary
311
- */
312
- export function formatStatusSummary(result: StatusCommandResult): string {
313
- if (!result.success) {
314
- return `Error: ${result.error}`;
315
- }
316
-
317
- const activeCount = result.agents.filter((a) => a.status === 'working').length;
318
- const pendingCount = result.agents.reduce((sum, a) => sum + a.pendingMessages, 0);
319
-
320
- const parts: string[] = [];
321
- parts.push(`${result.agents.length} agents`);
322
-
323
- if (activeCount > 0) {
324
- parts.push(`${activeCount} active`);
325
- }
326
-
327
- if (pendingCount > 0) {
328
- parts.push(`${pendingCount} pending messages`);
329
- }
330
-
331
- return parts.join(', ');
332
- }
@@ -1,213 +0,0 @@
1
- /**
2
- * Sync Command 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 { sync, formatSyncResult } from './sync.js';
10
-
11
- describe('Sync Command', () => {
12
- let testDir: string;
13
-
14
- beforeEach(async () => {
15
- testDir = join(tmpdir(), `sync-cmd-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
16
- await fs.mkdir(testDir, { recursive: true });
17
- });
18
-
19
- afterEach(async () => {
20
- try {
21
- await fs.rm(testDir, { recursive: true, force: true });
22
- } catch {
23
- // Ignore cleanup errors
24
- }
25
- });
26
-
27
- describe('sync', () => {
28
- it('should return success for empty cache', async () => {
29
- const provider = new FileCacheProvider({ basePath: testDir });
30
- await provider.initialize();
31
-
32
- const result = await sync({ cachePath: testDir });
33
-
34
- expect(result.success).toBe(true);
35
- expect(result.result).not.toBeNull();
36
- expect(result.result?.added).toBe(0);
37
- expect(result.result?.updated).toBe(0);
38
- expect(result.result?.failed).toBe(0);
39
- });
40
-
41
- it('should attempt to sync cached entries', async () => {
42
- const provider = new FileCacheProvider({ basePath: testDir });
43
- await provider.initialize();
44
- await provider.set('cached-entry', 'content', {
45
- source: 'github',
46
- sourceUrl: 'https://github.com/test/repo',
47
- });
48
-
49
- const result = await sync({
50
- cachePath: testDir,
51
- continueOnError: true,
52
- });
53
-
54
- // Should fail because there's no real fetcher configured
55
- expect(result.sources).toContain('github');
56
- // The placeholder fetcher will fail
57
- expect(result.result?.failed).toBeGreaterThanOrEqual(0);
58
- });
59
-
60
- it('should filter by source', async () => {
61
- const provider = new FileCacheProvider({ basePath: testDir });
62
- await provider.initialize();
63
- await provider.set('github-entry', 'content', {
64
- source: 'github',
65
- sourceUrl: 'https://github.com/test',
66
- });
67
- await provider.set('confluence-entry', 'content', {
68
- source: 'confluence',
69
- sourceUrl: 'https://confluence.test.com/page',
70
- });
71
-
72
- const result = await sync({
73
- cachePath: testDir,
74
- source: 'github',
75
- continueOnError: true,
76
- });
77
-
78
- expect(result.sources).toContain('github');
79
- expect(result.sources).not.toContain('confluence');
80
- });
81
-
82
- it('should handle uninitialized cache', async () => {
83
- const result = await sync({ cachePath: join(testDir, 'new-cache') });
84
-
85
- // Should initialize and return empty result
86
- expect(result.success).toBe(true);
87
- expect(result.result?.added).toBe(0);
88
- });
89
-
90
- it('should call progress callback', async () => {
91
- const provider = new FileCacheProvider({ basePath: testDir });
92
- await provider.initialize();
93
- await provider.set('entry', 'content', {
94
- source: 'github',
95
- sourceUrl: 'https://github.com/test',
96
- });
97
-
98
- const progressCalls: { completed: number; total: number; message: string }[] = [];
99
-
100
- await sync({
101
- cachePath: testDir,
102
- continueOnError: true,
103
- onProgress: (completed, total, message) => {
104
- progressCalls.push({ completed, total, message });
105
- },
106
- });
107
-
108
- expect(progressCalls.length).toBeGreaterThan(0);
109
- expect(progressCalls[0].message).toContain('Starting');
110
- });
111
- });
112
-
113
- describe('formatSyncResult', () => {
114
- it('should format error result', () => {
115
- const result = formatSyncResult({
116
- success: false,
117
- result: null,
118
- error: 'Connection failed',
119
- sources: [],
120
- });
121
-
122
- expect(result).toContain('Error');
123
- expect(result).toContain('Connection failed');
124
- });
125
-
126
- it('should format empty cache result', () => {
127
- const result = formatSyncResult({
128
- success: true,
129
- result: {
130
- added: 0,
131
- updated: 0,
132
- removed: 0,
133
- failed: 0,
134
- errors: [],
135
- duration: 0,
136
- },
137
- sources: [],
138
- });
139
-
140
- expect(result).toContain('empty');
141
- expect(result).toContain('Nothing to sync');
142
- });
143
-
144
- it('should format successful sync', () => {
145
- const result = formatSyncResult({
146
- success: true,
147
- result: {
148
- added: 2,
149
- updated: 3,
150
- removed: 1,
151
- failed: 0,
152
- errors: [],
153
- duration: 1500,
154
- },
155
- sources: ['github', 'confluence'],
156
- });
157
-
158
- expect(result).toContain('Duration: 1500ms');
159
- expect(result).toContain('Added: 2');
160
- expect(result).toContain('Updated: 3');
161
- expect(result).toContain('Removed: 1');
162
- expect(result).toContain('github');
163
- expect(result).toContain('confluence');
164
- });
165
-
166
- it('should format sync with errors', () => {
167
- const result = formatSyncResult({
168
- success: false,
169
- result: {
170
- added: 1,
171
- updated: 0,
172
- removed: 0,
173
- failed: 2,
174
- errors: [
175
- { key: 'entry1', error: 'Network error' },
176
- { key: 'entry2', error: 'Not found' },
177
- ],
178
- duration: 500,
179
- },
180
- sources: ['github'],
181
- });
182
-
183
- expect(result).toContain('Failed: 2');
184
- expect(result).toContain('Errors:');
185
- expect(result).toContain('entry1');
186
- expect(result).toContain('Network error');
187
- expect(result).toContain('entry2');
188
- expect(result).toContain('Not found');
189
- });
190
-
191
- it('should truncate long error lists', () => {
192
- const errors = Array.from({ length: 15 }, (_, i) => ({
193
- key: `entry${i}`,
194
- error: `Error ${i}`,
195
- }));
196
-
197
- const result = formatSyncResult({
198
- success: false,
199
- result: {
200
- added: 0,
201
- updated: 0,
202
- removed: 0,
203
- failed: 15,
204
- errors,
205
- duration: 100,
206
- },
207
- sources: ['github'],
208
- });
209
-
210
- expect(result).toContain('and 5 more errors');
211
- });
212
- });
213
- });