@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.
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +1 -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 -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,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
|
-
});
|