@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.
Files changed (196) hide show
  1. package/dist/cli/index.js +7 -0
  2. package/dist/cli/index.js.map +1 -1
  3. package/dist/index.js +7 -0
  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,804 +0,0 @@
1
- /**
2
- * KnowledgeLibrary Manager
3
- *
4
- * Manages the KnowledgeLibrary directory structure and agent state.
5
- */
6
-
7
- import {
8
- existsSync,
9
- mkdirSync,
10
- writeFileSync,
11
- readFileSync,
12
- readdirSync,
13
- renameSync,
14
- statSync,
15
- } from 'fs';
16
- import { join, basename } from 'path';
17
- import type {
18
- AgentDirectories,
19
- AgentKnowledgeState,
20
- InitKnowledgeLibraryOptions,
21
- InitKnowledgeLibraryResult,
22
- KnowledgeLibraryState,
23
- Message,
24
- MessageMetadata,
25
- ReadMessagesOptions,
26
- WriteMessageOptions,
27
- AgentContext,
28
- } from './types.js';
29
-
30
- /**
31
- * Default KnowledgeLibrary base path
32
- */
33
- export const DEFAULT_KNOWLEDGE_LIBRARY_PATH = 'KnowledgeLibrary';
34
-
35
- /**
36
- * Standard files in a KnowledgeLibrary
37
- */
38
- export const STANDARD_FILES = {
39
- context: 'context.txt',
40
- architecture: 'architecture.txt',
41
- prd: 'prd.txt',
42
- } as const;
43
-
44
- /**
45
- * Standard directories for each agent
46
- */
47
- export const AGENT_DIRECTORIES = [
48
- 'inbox',
49
- 'inbox/processed',
50
- 'outbox',
51
- 'context',
52
- 'control',
53
- 'history',
54
- 'tech',
55
- ] as const;
56
-
57
- /**
58
- * Standard files in an agent's control directory
59
- */
60
- export const CONTROL_FILES = {
61
- objectives: 'objectives.txt',
62
- decisions: 'decisions.txt',
63
- dependencies: 'dependencies.txt',
64
- } as const;
65
-
66
- /**
67
- * Get the path to an agent's directories
68
- */
69
- export function getAgentDirectories(basePath: string, agentName: string): AgentDirectories {
70
- const root = join(basePath, agentName);
71
- return {
72
- root,
73
- inbox: join(root, 'inbox'),
74
- inboxProcessed: join(root, 'inbox', 'processed'),
75
- outbox: join(root, 'outbox'),
76
- context: join(root, 'context'),
77
- control: join(root, 'control'),
78
- history: join(root, 'history'),
79
- tech: join(root, 'tech'),
80
- };
81
- }
82
-
83
- /**
84
- * Initialize the KnowledgeLibrary base structure
85
- */
86
- export function initKnowledgeLibrary(
87
- options: InitKnowledgeLibraryOptions = {}
88
- ): InitKnowledgeLibraryResult {
89
- const projectRoot = options.projectRoot ?? process.cwd();
90
- const basePath = join(projectRoot, options.basePath ?? DEFAULT_KNOWLEDGE_LIBRARY_PATH);
91
- const createDefaults = options.createDefaults ?? true;
92
-
93
- const createdDirs: string[] = [];
94
- const createdFiles: string[] = [];
95
-
96
- try {
97
- // Create base directory
98
- if (!existsSync(basePath)) {
99
- mkdirSync(basePath, { recursive: true });
100
- createdDirs.push(basePath);
101
- }
102
-
103
- // Create default global files if requested
104
- if (createDefaults) {
105
- // context.txt
106
- const contextPath = join(basePath, STANDARD_FILES.context);
107
- if (!existsSync(contextPath)) {
108
- writeFileSync(
109
- contextPath,
110
- `# Project Context
111
-
112
- ## Current Sprint
113
- - Sprint: [Sprint name/number]
114
- - Goals: [Sprint goals]
115
- - Deadline: [Sprint deadline]
116
-
117
- ## Priorities
118
- 1. [Priority 1]
119
- 2. [Priority 2]
120
- 3. [Priority 3]
121
-
122
- ## Notes
123
- [Project-wide notes and context]
124
- `,
125
- 'utf-8'
126
- );
127
- createdFiles.push(contextPath);
128
- }
129
-
130
- // architecture.txt
131
- const architecturePath = join(basePath, STANDARD_FILES.architecture);
132
- if (!existsSync(architecturePath)) {
133
- writeFileSync(
134
- architecturePath,
135
- `# Architecture Notes
136
-
137
- ## Technical Decisions
138
- [Record major technical decisions here]
139
-
140
- ## System Overview
141
- [High-level system architecture]
142
-
143
- ## Key Components
144
- [Important system components]
145
- `,
146
- 'utf-8'
147
- );
148
- createdFiles.push(architecturePath);
149
- }
150
-
151
- // prd.txt
152
- const prdPath = join(basePath, STANDARD_FILES.prd);
153
- if (!existsSync(prdPath)) {
154
- writeFileSync(
155
- prdPath,
156
- `# Product Requirements Document
157
-
158
- ## Overview
159
- [Product overview]
160
-
161
- ## Goals
162
- [Product goals]
163
-
164
- ## Features
165
- [Feature list]
166
-
167
- ## Requirements
168
- [Detailed requirements]
169
- `,
170
- 'utf-8'
171
- );
172
- createdFiles.push(prdPath);
173
- }
174
- }
175
-
176
- return {
177
- success: true,
178
- createdDirs,
179
- createdFiles,
180
- };
181
- } catch (error) {
182
- return {
183
- success: false,
184
- createdDirs,
185
- createdFiles,
186
- error: error instanceof Error ? error.message : String(error),
187
- };
188
- }
189
- }
190
-
191
- /**
192
- * Initialize an agent's KnowledgeLibrary directories
193
- */
194
- export function initAgentKnowledgeLibrary(
195
- agentName: string,
196
- options: InitKnowledgeLibraryOptions = {}
197
- ): InitKnowledgeLibraryResult {
198
- const projectRoot = options.projectRoot ?? process.cwd();
199
- const basePath = join(projectRoot, options.basePath ?? DEFAULT_KNOWLEDGE_LIBRARY_PATH);
200
- const createDefaults = options.createDefaults ?? true;
201
-
202
- const createdDirs: string[] = [];
203
- const createdFiles: string[] = [];
204
-
205
- try {
206
- // Ensure base KnowledgeLibrary exists
207
- if (!existsSync(basePath)) {
208
- const baseResult = initKnowledgeLibrary(options);
209
- if (!baseResult.success) {
210
- return baseResult;
211
- }
212
- createdDirs.push(...baseResult.createdDirs);
213
- createdFiles.push(...baseResult.createdFiles);
214
- }
215
-
216
- // Get agent directories
217
- const dirs = getAgentDirectories(basePath, agentName);
218
-
219
- // Create all agent directories
220
- for (const dir of AGENT_DIRECTORIES) {
221
- const dirPath = join(dirs.root, dir);
222
- if (!existsSync(dirPath)) {
223
- mkdirSync(dirPath, { recursive: true });
224
- createdDirs.push(dirPath);
225
- }
226
- }
227
-
228
- // Create default files if requested
229
- if (createDefaults) {
230
- // context/current.txt
231
- const currentContextPath = join(dirs.context, 'current.txt');
232
- if (!existsSync(currentContextPath)) {
233
- writeFileSync(
234
- currentContextPath,
235
- `# ${agentName} Current Context
236
-
237
- ## Status
238
- - State: idle
239
- - Current Task: None
240
- - Last Updated: ${new Date().toISOString()}
241
-
242
- ## Notes
243
- [Agent-specific context notes]
244
- `,
245
- 'utf-8'
246
- );
247
- createdFiles.push(currentContextPath);
248
- }
249
-
250
- // control/objectives.txt
251
- const objectivesPath = join(dirs.control, CONTROL_FILES.objectives);
252
- if (!existsSync(objectivesPath)) {
253
- writeFileSync(
254
- objectivesPath,
255
- `# ${agentName} Objectives
256
-
257
- ## Current Objectives
258
- [None]
259
-
260
- ## Success Criteria
261
- [Define success criteria for objectives]
262
- `,
263
- 'utf-8'
264
- );
265
- createdFiles.push(objectivesPath);
266
- }
267
-
268
- // control/decisions.txt
269
- const decisionsPath = join(dirs.control, CONTROL_FILES.decisions);
270
- if (!existsSync(decisionsPath)) {
271
- writeFileSync(
272
- decisionsPath,
273
- `# ${agentName} Decision Log
274
-
275
- ## Decisions
276
- [Record important decisions here]
277
-
278
- Format:
279
- - Date: YYYY-MM-DD
280
- - Decision: [What was decided]
281
- - Reasoning: [Why]
282
- - Related: [Ticket or task reference]
283
- `,
284
- 'utf-8'
285
- );
286
- createdFiles.push(decisionsPath);
287
- }
288
-
289
- // control/dependencies.txt
290
- const dependenciesPath = join(dirs.control, CONTROL_FILES.dependencies);
291
- if (!existsSync(dependenciesPath)) {
292
- writeFileSync(
293
- dependenciesPath,
294
- `# ${agentName} Dependencies
295
-
296
- ## Blocked By
297
- [Tasks/agents blocking this agent]
298
-
299
- ## Blocking
300
- [Tasks/agents this agent is blocking]
301
-
302
- Last Updated: ${new Date().toISOString()}
303
- `,
304
- 'utf-8'
305
- );
306
- createdFiles.push(dependenciesPath);
307
- }
308
- }
309
-
310
- return {
311
- success: true,
312
- createdDirs,
313
- createdFiles,
314
- };
315
- } catch (error) {
316
- return {
317
- success: false,
318
- createdDirs,
319
- createdFiles,
320
- error: error instanceof Error ? error.message : String(error),
321
- };
322
- }
323
- }
324
-
325
- /**
326
- * Check if a KnowledgeLibrary exists for an agent
327
- */
328
- export function agentKnowledgeLibraryExists(
329
- agentName: string,
330
- options: { projectRoot?: string; basePath?: string } = {}
331
- ): boolean {
332
- const projectRoot = options.projectRoot ?? process.cwd();
333
- const basePath = join(projectRoot, options.basePath ?? DEFAULT_KNOWLEDGE_LIBRARY_PATH);
334
- const agentRoot = join(basePath, agentName);
335
-
336
- return existsSync(agentRoot) && existsSync(join(agentRoot, 'inbox'));
337
- }
338
-
339
- /**
340
- * Get the KnowledgeLibrary state for an agent
341
- */
342
- export function getAgentKnowledgeState(
343
- agentName: string,
344
- options: { projectRoot?: string; basePath?: string } = {}
345
- ): AgentKnowledgeState {
346
- const projectRoot = options.projectRoot ?? process.cwd();
347
- const basePath = join(projectRoot, options.basePath ?? DEFAULT_KNOWLEDGE_LIBRARY_PATH);
348
- const dirs = getAgentDirectories(basePath, agentName);
349
-
350
- const initialized = agentKnowledgeLibraryExists(agentName, options);
351
-
352
- // Get pending messages
353
- const pendingMessages = initialized ? readInboxMessages(agentName, options) : [];
354
-
355
- // Get context
356
- let context: AgentContext | undefined;
357
- const currentContextPath = join(dirs.context, 'current.txt');
358
- if (existsSync(currentContextPath)) {
359
- const content = readFileSync(currentContextPath, 'utf-8');
360
- context = parseContextFile(content);
361
- }
362
-
363
- const state: AgentKnowledgeState = {
364
- agentName,
365
- directories: dirs,
366
- pendingMessages,
367
- initialized,
368
- };
369
-
370
- if (context) {
371
- state.context = context;
372
- }
373
-
374
- return state;
375
- }
376
-
377
- /**
378
- * Parse a context file into AgentContext
379
- */
380
- function parseContextFile(content: string): AgentContext {
381
- const context: AgentContext = {
382
- lastUpdated: new Date(),
383
- };
384
-
385
- // Simple parsing - look for key patterns
386
- const statusMatch = content.match(/State:\s*(.+)/i);
387
- if (statusMatch && statusMatch[1]) {
388
- context.status = statusMatch[1].trim();
389
- }
390
-
391
- const taskMatch = content.match(/Current Task:\s*(.+)/i);
392
- if (taskMatch && taskMatch[1] && taskMatch[1].trim() !== 'None') {
393
- context.currentTask = taskMatch[1].trim();
394
- }
395
-
396
- const ticketMatch = content.match(/Current Ticket:\s*([A-Z]+-\d+)/i);
397
- if (ticketMatch && ticketMatch[1]) {
398
- context.currentTicket = ticketMatch[1];
399
- }
400
-
401
- const updatedMatch = content.match(/Last Updated:\s*(.+)/i);
402
- if (updatedMatch) {
403
- const dateStr = updatedMatch[1]?.trim();
404
- if (dateStr) {
405
- const parsed = new Date(dateStr);
406
- if (!isNaN(parsed.getTime())) {
407
- context.lastUpdated = parsed;
408
- }
409
- }
410
- }
411
-
412
- return context;
413
- }
414
-
415
- /**
416
- * Generate a message filename
417
- */
418
- export function generateMessageFilename(from: string, subject: string): string {
419
- const now = new Date();
420
- const timestamp = now.toISOString().replace(/[-:T]/g, '').slice(0, 12); // YYYYMMDDHHMM
421
- const sanitizedSubject = subject
422
- .toLowerCase()
423
- .replace(/[^a-z0-9]+/g, '-')
424
- .slice(0, 30);
425
- return `${timestamp}-${from}-${sanitizedSubject}.md`;
426
- }
427
-
428
- /**
429
- * Parse message frontmatter
430
- */
431
- function parseMessageFrontmatter(content: string): {
432
- metadata: Partial<MessageMetadata>;
433
- body: string;
434
- } {
435
- const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
436
-
437
- if (!match) {
438
- return { metadata: {}, body: content };
439
- }
440
-
441
- const frontmatter = match[1] ?? '';
442
- const body = match[2] ?? '';
443
- const metadata: Partial<MessageMetadata> = {};
444
-
445
- for (const line of frontmatter.split(/\r?\n/)) {
446
- const colonIndex = line.indexOf(':');
447
- if (colonIndex === -1) continue;
448
-
449
- const key = line.slice(0, colonIndex).trim();
450
- const value = line.slice(colonIndex + 1).trim();
451
-
452
- switch (key) {
453
- case 'type':
454
- metadata.type = value as MessageMetadata['type'];
455
- break;
456
- case 'from':
457
- metadata.from = value;
458
- break;
459
- case 'to':
460
- metadata.to = value;
461
- break;
462
- case 'date':
463
- metadata.date = new Date(value);
464
- break;
465
- case 'ticket':
466
- metadata.ticket = value;
467
- break;
468
- case 'priority':
469
- if (value === 'P0' || value === 'P1' || value === 'P2' || value === 'P3') {
470
- metadata.priority = value;
471
- }
472
- break;
473
- case 'subject':
474
- metadata.subject = value;
475
- break;
476
- }
477
- }
478
-
479
- return { metadata, body };
480
- }
481
-
482
- /**
483
- * Read inbox messages for an agent
484
- */
485
- export function readInboxMessages(
486
- agentName: string,
487
- options: { projectRoot?: string; basePath?: string } & ReadMessagesOptions = {}
488
- ): Message[] {
489
- const projectRoot = options.projectRoot ?? process.cwd();
490
- const basePath = join(projectRoot, options.basePath ?? DEFAULT_KNOWLEDGE_LIBRARY_PATH);
491
- const dirs = getAgentDirectories(basePath, agentName);
492
-
493
- const messages: Message[] = [];
494
-
495
- // Read inbox
496
- if (existsSync(dirs.inbox)) {
497
- const files = readdirSync(dirs.inbox).filter(
498
- (f) => f.endsWith('.md') && statSync(join(dirs.inbox, f)).isFile()
499
- );
500
-
501
- for (const file of files) {
502
- const filePath = join(dirs.inbox, file);
503
- const rawContent = readFileSync(filePath, 'utf-8');
504
- const { metadata, body } = parseMessageFrontmatter(rawContent);
505
-
506
- // Apply filters
507
- if (options.type && metadata.type !== options.type) continue;
508
- if (options.from && metadata.from !== options.from) continue;
509
- if (options.priority && metadata.priority !== options.priority) continue;
510
-
511
- messages.push({
512
- filename: file,
513
- path: filePath,
514
- metadata: metadata as MessageMetadata,
515
- rawContent,
516
- body,
517
- });
518
- }
519
- }
520
-
521
- // Include processed if requested
522
- if (options.includeProcessed && existsSync(dirs.inboxProcessed)) {
523
- const files = readdirSync(dirs.inboxProcessed).filter(
524
- (f) => f.endsWith('.md') && statSync(join(dirs.inboxProcessed, f)).isFile()
525
- );
526
-
527
- for (const file of files) {
528
- const filePath = join(dirs.inboxProcessed, file);
529
- const rawContent = readFileSync(filePath, 'utf-8');
530
- const { metadata, body } = parseMessageFrontmatter(rawContent);
531
-
532
- // Apply filters
533
- if (options.type && metadata.type !== options.type) continue;
534
- if (options.from && metadata.from !== options.from) continue;
535
- if (options.priority && metadata.priority !== options.priority) continue;
536
-
537
- messages.push({
538
- filename: file,
539
- path: filePath,
540
- metadata: metadata as MessageMetadata,
541
- rawContent,
542
- body,
543
- });
544
- }
545
- }
546
-
547
- // Sort by date (newest first)
548
- messages.sort((a, b) => {
549
- const dateA = a.metadata.date?.getTime() ?? 0;
550
- const dateB = b.metadata.date?.getTime() ?? 0;
551
- return dateB - dateA;
552
- });
553
-
554
- // Apply limit
555
- if (options.limit && messages.length > options.limit) {
556
- return messages.slice(0, options.limit);
557
- }
558
-
559
- return messages;
560
- }
561
-
562
- /**
563
- * Write a message to an agent's inbox
564
- */
565
- export function writeInboxMessage(
566
- options: WriteMessageOptions & { projectRoot?: string; basePath?: string }
567
- ): { success: boolean; path?: string; error?: string } {
568
- const projectRoot = options.projectRoot ?? process.cwd();
569
- const basePath = join(projectRoot, options.basePath ?? DEFAULT_KNOWLEDGE_LIBRARY_PATH);
570
- const dirs = getAgentDirectories(basePath, options.to);
571
-
572
- try {
573
- // Ensure agent inbox exists
574
- if (!existsSync(dirs.inbox)) {
575
- mkdirSync(dirs.inbox, { recursive: true });
576
- }
577
-
578
- // Generate filename
579
- const filename = generateMessageFilename(options.from, options.subject);
580
- const filePath = join(dirs.inbox, filename);
581
-
582
- // Format message
583
- const now = new Date();
584
- const content = formatMessage(options, now);
585
-
586
- // Write file
587
- writeFileSync(filePath, content, 'utf-8');
588
-
589
- // Also copy to sender's outbox
590
- const senderDirs = getAgentDirectories(basePath, options.from);
591
- if (existsSync(senderDirs.outbox)) {
592
- writeFileSync(join(senderDirs.outbox, filename), content, 'utf-8');
593
- }
594
-
595
- return { success: true, path: filePath };
596
- } catch (error) {
597
- return {
598
- success: false,
599
- error: error instanceof Error ? error.message : String(error),
600
- };
601
- }
602
- }
603
-
604
- /**
605
- * Format a message with frontmatter
606
- */
607
- function formatMessage(options: WriteMessageOptions, date: Date): string {
608
- let frontmatter = `---
609
- type: ${options.type}
610
- from: ${options.from}
611
- to: ${options.to}
612
- date: ${date.toISOString().slice(0, 16).replace('T', ' ')}`;
613
-
614
- if (options.ticket) {
615
- frontmatter += `\nticket: ${options.ticket}`;
616
- }
617
-
618
- if (options.priority) {
619
- frontmatter += `\npriority: ${options.priority}`;
620
- }
621
-
622
- frontmatter += `\nsubject: ${options.subject}`;
623
-
624
- frontmatter += `\n---
625
-
626
- ## ${options.subject}
627
-
628
- ${options.body}`;
629
-
630
- return frontmatter;
631
- }
632
-
633
- /**
634
- * Mark a message as processed (move to processed folder)
635
- */
636
- export function markMessageProcessed(
637
- agentName: string,
638
- messageFilename: string,
639
- options: { projectRoot?: string; basePath?: string } = {}
640
- ): { success: boolean; error?: string } {
641
- const projectRoot = options.projectRoot ?? process.cwd();
642
- const basePath = join(projectRoot, options.basePath ?? DEFAULT_KNOWLEDGE_LIBRARY_PATH);
643
- const dirs = getAgentDirectories(basePath, agentName);
644
-
645
- const sourcePath = join(dirs.inbox, messageFilename);
646
- const destPath = join(dirs.inboxProcessed, messageFilename);
647
-
648
- try {
649
- if (!existsSync(sourcePath)) {
650
- return { success: false, error: `Message not found: ${messageFilename}` };
651
- }
652
-
653
- if (!existsSync(dirs.inboxProcessed)) {
654
- mkdirSync(dirs.inboxProcessed, { recursive: true });
655
- }
656
-
657
- renameSync(sourcePath, destPath);
658
- return { success: true };
659
- } catch (error) {
660
- return {
661
- success: false,
662
- error: error instanceof Error ? error.message : String(error),
663
- };
664
- }
665
- }
666
-
667
- /**
668
- * Get global KnowledgeLibrary state
669
- */
670
- export function getKnowledgeLibraryState(
671
- options: { projectRoot?: string; basePath?: string } = {}
672
- ): KnowledgeLibraryState | null {
673
- const projectRoot = options.projectRoot ?? process.cwd();
674
- const basePath = join(projectRoot, options.basePath ?? DEFAULT_KNOWLEDGE_LIBRARY_PATH);
675
-
676
- if (!existsSync(basePath)) {
677
- return null;
678
- }
679
-
680
- // Get list of agents
681
- const agents: string[] = [];
682
- const entries = readdirSync(basePath);
683
- for (const entry of entries) {
684
- const entryPath = join(basePath, entry);
685
- if (statSync(entryPath).isDirectory() && existsSync(join(entryPath, 'inbox'))) {
686
- agents.push(entry);
687
- }
688
- }
689
-
690
- return {
691
- basePath,
692
- contextPath: join(basePath, STANDARD_FILES.context),
693
- architecturePath: join(basePath, STANDARD_FILES.architecture),
694
- prdPath: join(basePath, STANDARD_FILES.prd),
695
- agents,
696
- };
697
- }
698
-
699
- /**
700
- * Update agent context
701
- */
702
- export function updateAgentContext(
703
- agentName: string,
704
- context: Partial<AgentContext>,
705
- options: { projectRoot?: string; basePath?: string } = {}
706
- ): { success: boolean; error?: string } {
707
- const projectRoot = options.projectRoot ?? process.cwd();
708
- const basePath = join(projectRoot, options.basePath ?? DEFAULT_KNOWLEDGE_LIBRARY_PATH);
709
- const dirs = getAgentDirectories(basePath, agentName);
710
- const contextPath = join(dirs.context, 'current.txt');
711
-
712
- try {
713
- const now = new Date();
714
- const content = `# ${agentName} Current Context
715
-
716
- ## Status
717
- - State: ${context.status ?? 'idle'}
718
- - Current Task: ${context.currentTask ?? 'None'}
719
- ${context.currentTicket ? `- Current Ticket: ${context.currentTicket}` : ''}- Last Updated: ${now.toISOString()}
720
-
721
- ## Notes
722
- ${context.notes ?? '[Agent-specific context notes]'}
723
- `;
724
-
725
- if (!existsSync(dirs.context)) {
726
- mkdirSync(dirs.context, { recursive: true });
727
- }
728
-
729
- writeFileSync(contextPath, content, 'utf-8');
730
- return { success: true };
731
- } catch (error) {
732
- return {
733
- success: false,
734
- error: error instanceof Error ? error.message : String(error),
735
- };
736
- }
737
- }
738
-
739
- /**
740
- * Format KnowledgeLibrary state for display
741
- */
742
- export function formatKnowledgeLibraryState(state: KnowledgeLibraryState | null): string {
743
- if (!state) {
744
- return 'KnowledgeLibrary not initialized.';
745
- }
746
-
747
- const lines: string[] = [];
748
- lines.push(`KnowledgeLibrary: ${state.basePath}\n`);
749
-
750
- lines.push('Global files:');
751
- lines.push(` - ${basename(state.contextPath)}`);
752
- lines.push(` - ${basename(state.architecturePath)}`);
753
- lines.push(` - ${basename(state.prdPath)}`);
754
- lines.push('');
755
-
756
- if (state.agents.length > 0) {
757
- lines.push(`Agents (${state.agents.length}):`);
758
- for (const agent of state.agents) {
759
- lines.push(` - ${agent}`);
760
- }
761
- } else {
762
- lines.push('No agents initialized.');
763
- }
764
-
765
- return lines.join('\n');
766
- }
767
-
768
- /**
769
- * Format agent knowledge state for display
770
- */
771
- export function formatAgentKnowledgeState(state: AgentKnowledgeState): string {
772
- const lines: string[] = [];
773
-
774
- lines.push(`Agent: ${state.agentName}`);
775
- lines.push(`Status: ${state.initialized ? 'Initialized' : 'Not initialized'}`);
776
- lines.push('');
777
-
778
- if (state.context) {
779
- lines.push('Context:');
780
- lines.push(` State: ${state.context.status ?? 'unknown'}`);
781
- if (state.context.currentTask) {
782
- lines.push(` Current Task: ${state.context.currentTask}`);
783
- }
784
- if (state.context.currentTicket) {
785
- lines.push(` Current Ticket: ${state.context.currentTicket}`);
786
- }
787
- lines.push(` Last Updated: ${state.context.lastUpdated.toISOString()}`);
788
- lines.push('');
789
- }
790
-
791
- if (state.pendingMessages.length > 0) {
792
- lines.push(`Pending Messages (${state.pendingMessages.length}):`);
793
- for (const msg of state.pendingMessages) {
794
- const type = msg.metadata.type ?? 'unknown';
795
- const from = msg.metadata.from ?? 'unknown';
796
- const subject = msg.metadata.subject ?? msg.filename;
797
- lines.push(` - [${type}] from ${from}: ${subject}`);
798
- }
799
- } else {
800
- lines.push('No pending messages.');
801
- }
802
-
803
- return lines.join('\n');
804
- }