@agile-vibe-coding/avc 0.1.1 → 0.3.1

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 (239) hide show
  1. package/cli/agent-loader.js +21 -0
  2. package/cli/agents/agent-selector.md +152 -0
  3. package/cli/agents/architecture-recommender.md +418 -0
  4. package/cli/agents/code-implementer.md +117 -0
  5. package/cli/agents/code-validator.md +80 -0
  6. package/cli/agents/context-reviewer-epic.md +101 -0
  7. package/cli/agents/context-reviewer-story.md +92 -0
  8. package/cli/agents/context-writer-epic.md +145 -0
  9. package/cli/agents/context-writer-story.md +111 -0
  10. package/cli/agents/database-deep-dive.md +470 -0
  11. package/cli/agents/database-recommender.md +634 -0
  12. package/cli/agents/doc-distributor.md +176 -0
  13. package/cli/agents/doc-writer-epic.md +42 -0
  14. package/cli/agents/doc-writer-story.md +43 -0
  15. package/cli/agents/documentation-updater.md +203 -0
  16. package/cli/agents/duplicate-detector.md +110 -0
  17. package/cli/agents/epic-story-decomposer.md +559 -0
  18. package/cli/agents/feature-context-generator.md +91 -0
  19. package/cli/agents/gap-checker-epic.md +52 -0
  20. package/cli/agents/impact-checker-story.md +51 -0
  21. package/cli/agents/migration-guide-generator.md +305 -0
  22. package/cli/agents/mission-scope-generator.md +143 -0
  23. package/cli/agents/mission-scope-validator.md +146 -0
  24. package/cli/agents/project-context-extractor.md +122 -0
  25. package/cli/agents/project-documentation-creator.json +226 -0
  26. package/cli/agents/project-documentation-creator.md +595 -0
  27. package/cli/agents/question-prefiller.md +269 -0
  28. package/cli/agents/refiner-epic.md +39 -0
  29. package/cli/agents/refiner-story.md +42 -0
  30. package/cli/agents/scaffolding-generator.md +99 -0
  31. package/cli/agents/seed-validator.md +71 -0
  32. package/cli/agents/story-doc-enricher.md +133 -0
  33. package/cli/agents/story-scope-reviewer.md +147 -0
  34. package/cli/agents/story-splitter.md +83 -0
  35. package/cli/agents/suggestion-business-analyst.md +88 -0
  36. package/cli/agents/suggestion-deployment-architect.md +263 -0
  37. package/cli/agents/suggestion-product-manager.md +129 -0
  38. package/cli/agents/suggestion-security-specialist.md +156 -0
  39. package/cli/agents/suggestion-technical-architect.md +269 -0
  40. package/cli/agents/suggestion-ux-researcher.md +93 -0
  41. package/cli/agents/task-subtask-decomposer.md +188 -0
  42. package/cli/agents/validator-documentation.json +183 -0
  43. package/cli/agents/validator-documentation.md +455 -0
  44. package/cli/agents/validator-selector.md +211 -0
  45. package/cli/ansi-colors.js +21 -0
  46. package/cli/api-reference-tool.js +368 -0
  47. package/cli/build-docs.js +29 -8
  48. package/cli/ceremony-history.js +369 -0
  49. package/cli/checks/catalog.json +76 -0
  50. package/cli/checks/code/quality.json +26 -0
  51. package/cli/checks/code/testing.json +14 -0
  52. package/cli/checks/code/traceability.json +26 -0
  53. package/cli/checks/cross-refs/epic.json +171 -0
  54. package/cli/checks/cross-refs/story.json +149 -0
  55. package/cli/checks/epic/api.json +114 -0
  56. package/cli/checks/epic/backend.json +126 -0
  57. package/cli/checks/epic/cloud.json +126 -0
  58. package/cli/checks/epic/data.json +102 -0
  59. package/cli/checks/epic/database.json +114 -0
  60. package/cli/checks/epic/developer.json +182 -0
  61. package/cli/checks/epic/devops.json +174 -0
  62. package/cli/checks/epic/frontend.json +162 -0
  63. package/cli/checks/epic/mobile.json +102 -0
  64. package/cli/checks/epic/qa.json +90 -0
  65. package/cli/checks/epic/security.json +184 -0
  66. package/cli/checks/epic/solution-architect.json +192 -0
  67. package/cli/checks/epic/test-architect.json +90 -0
  68. package/cli/checks/epic/ui.json +102 -0
  69. package/cli/checks/epic/ux.json +90 -0
  70. package/cli/checks/fixes/epic-fix-template.md +10 -0
  71. package/cli/checks/fixes/story-fix-template.md +10 -0
  72. package/cli/checks/story/api.json +186 -0
  73. package/cli/checks/story/backend.json +102 -0
  74. package/cli/checks/story/cloud.json +102 -0
  75. package/cli/checks/story/data.json +210 -0
  76. package/cli/checks/story/database.json +102 -0
  77. package/cli/checks/story/developer.json +168 -0
  78. package/cli/checks/story/devops.json +102 -0
  79. package/cli/checks/story/frontend.json +174 -0
  80. package/cli/checks/story/mobile.json +102 -0
  81. package/cli/checks/story/qa.json +210 -0
  82. package/cli/checks/story/security.json +198 -0
  83. package/cli/checks/story/solution-architect.json +230 -0
  84. package/cli/checks/story/test-architect.json +210 -0
  85. package/cli/checks/story/ui.json +102 -0
  86. package/cli/checks/story/ux.json +102 -0
  87. package/cli/coding-order.js +401 -0
  88. package/cli/command-logger.js +49 -12
  89. package/cli/components/static-output.js +63 -0
  90. package/cli/console-output-manager.js +94 -0
  91. package/cli/dependency-checker.js +72 -0
  92. package/cli/docs-sync.js +306 -0
  93. package/cli/epic-story-validator.js +659 -0
  94. package/cli/evaluation-prompts.js +1008 -0
  95. package/cli/execution-context.js +195 -0
  96. package/cli/generate-summary-table.js +340 -0
  97. package/cli/init-model-config.js +704 -0
  98. package/cli/init.js +1737 -278
  99. package/cli/kanban-server-manager.js +227 -0
  100. package/cli/llm-claude.js +150 -1
  101. package/cli/llm-gemini.js +109 -0
  102. package/cli/llm-local.js +493 -0
  103. package/cli/llm-mock.js +233 -0
  104. package/cli/llm-openai.js +454 -0
  105. package/cli/llm-provider.js +379 -3
  106. package/cli/llm-token-limits.js +211 -0
  107. package/cli/llm-verifier.js +662 -0
  108. package/cli/llm-xiaomi.js +143 -0
  109. package/cli/message-constants.js +49 -0
  110. package/cli/message-manager.js +334 -0
  111. package/cli/message-types.js +96 -0
  112. package/cli/messaging-api.js +291 -0
  113. package/cli/micro-check-fixer.js +335 -0
  114. package/cli/micro-check-runner.js +449 -0
  115. package/cli/micro-check-scorer.js +148 -0
  116. package/cli/micro-check-validator.js +538 -0
  117. package/cli/model-pricing.js +192 -0
  118. package/cli/model-query-engine.js +468 -0
  119. package/cli/model-recommendation-analyzer.js +495 -0
  120. package/cli/model-selector.js +270 -0
  121. package/cli/output-buffer.js +107 -0
  122. package/cli/process-manager.js +73 -2
  123. package/cli/prompt-logger.js +57 -0
  124. package/cli/repl-ink.js +4625 -1094
  125. package/cli/repl-old.js +3 -4
  126. package/cli/seed-processor.js +962 -0
  127. package/cli/sprint-planning-processor.js +4162 -0
  128. package/cli/template-processor.js +2149 -105
  129. package/cli/templates/project.md +25 -8
  130. package/cli/templates/vitepress-config.mts.template +5 -4
  131. package/cli/token-tracker.js +547 -0
  132. package/cli/tools/generate-story-validators.js +317 -0
  133. package/cli/tools/generate-validators.js +669 -0
  134. package/cli/update-checker.js +19 -17
  135. package/cli/update-notifier.js +4 -4
  136. package/cli/validation-router.js +667 -0
  137. package/cli/verification-tracker.js +563 -0
  138. package/cli/worktree-runner.js +654 -0
  139. package/kanban/README.md +386 -0
  140. package/kanban/client/README.md +205 -0
  141. package/kanban/client/components.json +20 -0
  142. package/kanban/client/dist/assets/index-D_KC5EQT.css +1 -0
  143. package/kanban/client/dist/assets/index-DjY5zqW7.js +351 -0
  144. package/kanban/client/dist/index.html +16 -0
  145. package/kanban/client/dist/vite.svg +1 -0
  146. package/kanban/client/index.html +15 -0
  147. package/kanban/client/package-lock.json +9442 -0
  148. package/kanban/client/package.json +44 -0
  149. package/kanban/client/postcss.config.js +6 -0
  150. package/kanban/client/public/vite.svg +1 -0
  151. package/kanban/client/src/App.jsx +651 -0
  152. package/kanban/client/src/components/ProjectFileEditorPopup.jsx +117 -0
  153. package/kanban/client/src/components/ceremony/AskArchPopup.jsx +420 -0
  154. package/kanban/client/src/components/ceremony/AskModelPopup.jsx +629 -0
  155. package/kanban/client/src/components/ceremony/CeremonyWorkflowModal.jsx +1133 -0
  156. package/kanban/client/src/components/ceremony/EpicStorySelectionModal.jsx +254 -0
  157. package/kanban/client/src/components/ceremony/ProviderSwitcherButton.jsx +290 -0
  158. package/kanban/client/src/components/ceremony/SponsorCallModal.jsx +686 -0
  159. package/kanban/client/src/components/ceremony/SprintPlanningModal.jsx +838 -0
  160. package/kanban/client/src/components/ceremony/steps/ArchitectureStep.jsx +150 -0
  161. package/kanban/client/src/components/ceremony/steps/CompleteStep.jsx +136 -0
  162. package/kanban/client/src/components/ceremony/steps/DatabaseStep.jsx +202 -0
  163. package/kanban/client/src/components/ceremony/steps/DeploymentStep.jsx +123 -0
  164. package/kanban/client/src/components/ceremony/steps/MissionStep.jsx +106 -0
  165. package/kanban/client/src/components/ceremony/steps/ReviewAnswersStep.jsx +329 -0
  166. package/kanban/client/src/components/ceremony/steps/RunningStep.jsx +249 -0
  167. package/kanban/client/src/components/kanban/CardDetailModal.jsx +646 -0
  168. package/kanban/client/src/components/kanban/EpicSection.jsx +146 -0
  169. package/kanban/client/src/components/kanban/FilterToolbar.jsx +222 -0
  170. package/kanban/client/src/components/kanban/GroupingSelector.jsx +63 -0
  171. package/kanban/client/src/components/kanban/KanbanBoard.jsx +211 -0
  172. package/kanban/client/src/components/kanban/KanbanCard.jsx +147 -0
  173. package/kanban/client/src/components/kanban/KanbanColumn.jsx +90 -0
  174. package/kanban/client/src/components/kanban/RefineWorkItemPopup.jsx +784 -0
  175. package/kanban/client/src/components/kanban/RunButton.jsx +162 -0
  176. package/kanban/client/src/components/kanban/SeedButton.jsx +176 -0
  177. package/kanban/client/src/components/layout/LoadingScreen.jsx +82 -0
  178. package/kanban/client/src/components/process/ProcessMonitorBar.jsx +80 -0
  179. package/kanban/client/src/components/settings/AgentEditorPopup.jsx +171 -0
  180. package/kanban/client/src/components/settings/AgentsTab.jsx +381 -0
  181. package/kanban/client/src/components/settings/ApiKeysTab.jsx +142 -0
  182. package/kanban/client/src/components/settings/CeremonyModelsTab.jsx +105 -0
  183. package/kanban/client/src/components/settings/CheckEditorPopup.jsx +507 -0
  184. package/kanban/client/src/components/settings/CostThresholdsTab.jsx +95 -0
  185. package/kanban/client/src/components/settings/ModelPricingTab.jsx +269 -0
  186. package/kanban/client/src/components/settings/OpenAIAuthSection.jsx +412 -0
  187. package/kanban/client/src/components/settings/ServersTab.jsx +121 -0
  188. package/kanban/client/src/components/settings/SettingsModal.jsx +84 -0
  189. package/kanban/client/src/components/stats/CostModal.jsx +384 -0
  190. package/kanban/client/src/components/ui/badge.jsx +27 -0
  191. package/kanban/client/src/components/ui/dialog.jsx +121 -0
  192. package/kanban/client/src/components/ui/tabs.jsx +85 -0
  193. package/kanban/client/src/hooks/__tests__/useGrouping.test.js +232 -0
  194. package/kanban/client/src/hooks/useGrouping.js +177 -0
  195. package/kanban/client/src/hooks/useWebSocket.js +120 -0
  196. package/kanban/client/src/lib/__tests__/api.test.js +196 -0
  197. package/kanban/client/src/lib/__tests__/status-grouping.test.js +94 -0
  198. package/kanban/client/src/lib/api.js +515 -0
  199. package/kanban/client/src/lib/status-grouping.js +154 -0
  200. package/kanban/client/src/lib/utils.js +11 -0
  201. package/kanban/client/src/main.jsx +10 -0
  202. package/kanban/client/src/store/__tests__/kanbanStore.test.js +164 -0
  203. package/kanban/client/src/store/ceremonyStore.js +172 -0
  204. package/kanban/client/src/store/filterStore.js +201 -0
  205. package/kanban/client/src/store/kanbanStore.js +123 -0
  206. package/kanban/client/src/store/processStore.js +65 -0
  207. package/kanban/client/src/store/sprintPlanningStore.js +33 -0
  208. package/kanban/client/src/styles/globals.css +59 -0
  209. package/kanban/client/tailwind.config.js +77 -0
  210. package/kanban/client/vite.config.js +28 -0
  211. package/kanban/client/vitest.config.js +28 -0
  212. package/kanban/dev-start.sh +47 -0
  213. package/kanban/package.json +12 -0
  214. package/kanban/server/index.js +537 -0
  215. package/kanban/server/routes/ceremony.js +454 -0
  216. package/kanban/server/routes/costs.js +163 -0
  217. package/kanban/server/routes/openai-oauth.js +366 -0
  218. package/kanban/server/routes/processes.js +50 -0
  219. package/kanban/server/routes/settings.js +736 -0
  220. package/kanban/server/routes/websocket.js +281 -0
  221. package/kanban/server/routes/work-items.js +487 -0
  222. package/kanban/server/services/CeremonyService.js +1441 -0
  223. package/kanban/server/services/FileSystemScanner.js +95 -0
  224. package/kanban/server/services/FileWatcher.js +144 -0
  225. package/kanban/server/services/HierarchyBuilder.js +196 -0
  226. package/kanban/server/services/ProcessRegistry.js +122 -0
  227. package/kanban/server/services/TaskRunnerService.js +261 -0
  228. package/kanban/server/services/WorkItemReader.js +123 -0
  229. package/kanban/server/services/WorkItemRefineService.js +510 -0
  230. package/kanban/server/start.js +49 -0
  231. package/kanban/server/utils/kanban-logger.js +132 -0
  232. package/kanban/server/utils/markdown.js +91 -0
  233. package/kanban/server/utils/status-grouping.js +107 -0
  234. package/kanban/server/workers/run-task-worker.js +121 -0
  235. package/kanban/server/workers/seed-worker.js +94 -0
  236. package/kanban/server/workers/sponsor-call-worker.js +92 -0
  237. package/kanban/server/workers/sprint-planning-worker.js +212 -0
  238. package/package.json +19 -7
  239. package/cli/agents/documentation.md +0 -302
@@ -0,0 +1,143 @@
1
+ /**
2
+ * llm-xiaomi.js — Xiaomi MiMo LLM provider.
3
+ *
4
+ * Uses the OpenAI-compatible API at https://api.xiaomimimo.com/v1.
5
+ * Supports: mimo-v2-flash, mimo-v2-pro, mimo-v2-omni.
6
+ *
7
+ * Requires XIAOMI_API_KEY environment variable.
8
+ */
9
+
10
+ import OpenAI from 'openai';
11
+ import { LLMProvider } from './llm-provider.js';
12
+
13
+ const XIAOMI_BASE_URL = 'https://api.xiaomimimo.com/v1';
14
+
15
+ function cleanResponse(text) {
16
+ if (!text) return '';
17
+ // Strip markdown code fences
18
+ return text.replace(/^```(?:json)?\s*\n?/i, '').replace(/\n?```\s*$/i, '').trim();
19
+ }
20
+
21
+ function extractJSON(text) {
22
+ // Try to find JSON object or array in the response
23
+ const jsonMatch = text.match(/(\{[\s\S]*\}|\[[\s\S]*\])/);
24
+ return jsonMatch ? jsonMatch[1] : text;
25
+ }
26
+
27
+ export class XiaomiProvider extends LLMProvider {
28
+ constructor(model) {
29
+ super('xiaomi', model || 'mimo-v2-flash');
30
+ }
31
+
32
+ _createClient() {
33
+ const apiKey = process.env.XIAOMI_API_KEY;
34
+ if (!apiKey) {
35
+ throw new Error('XIAOMI_API_KEY not set. Add it to your .env file. Get a key at https://platform.xiaomimimo.com/#/console/api-keys');
36
+ }
37
+ return new OpenAI({
38
+ apiKey,
39
+ baseURL: XIAOMI_BASE_URL,
40
+ timeout: 10 * 60_000, // 10 min
41
+ maxRetries: 0,
42
+ });
43
+ }
44
+
45
+ async _callProvider(prompt, maxTokens, systemInstructions) {
46
+ if (!this._client) this._client = this._createClient();
47
+
48
+ const messages = [];
49
+ if (systemInstructions) {
50
+ messages.push({ role: 'system', content: systemInstructions });
51
+ }
52
+ messages.push({ role: 'user', content: prompt });
53
+
54
+ const response = await this._client.chat.completions.create({
55
+ model: this.model,
56
+ messages,
57
+ max_tokens: maxTokens,
58
+ });
59
+
60
+ const usage = response.usage;
61
+ this._trackTokens(usage, { prompt, agentInstructions: systemInstructions, response: response.choices?.[0]?.message?.content });
62
+
63
+ return response.choices?.[0]?.message?.content || '';
64
+ }
65
+
66
+ async generateJSON(prompt, agentInstructions = null, cachedContext = null) {
67
+ if (!this._client) this._client = this._createClient();
68
+
69
+ const JSON_SYSTEM = 'You are a helpful assistant that always returns valid JSON. Your response must be a valid JSON object or array, nothing else. Do not include any thinking, reasoning, or explanation — only the JSON.';
70
+ const systemParts = [JSON_SYSTEM];
71
+ if (agentInstructions) systemParts.push(agentInstructions);
72
+ if (cachedContext) systemParts.push(`---\n\n${cachedContext}`);
73
+
74
+ const messages = [
75
+ { role: 'system', content: systemParts.join('\n\n') },
76
+ { role: 'user', content: prompt },
77
+ ];
78
+
79
+ const _t0 = Date.now();
80
+ const response = await this._withRetry(
81
+ () => this._client.chat.completions.create({
82
+ model: this.model,
83
+ messages,
84
+ response_format: { type: 'json_object' },
85
+ }),
86
+ 'JSON generation (Xiaomi)'
87
+ );
88
+
89
+ const content = response.choices?.[0]?.message?.content || '';
90
+ this._trackTokens(response.usage, {
91
+ prompt,
92
+ agentInstructions: agentInstructions ?? null,
93
+ response: content,
94
+ elapsed: Date.now() - _t0,
95
+ });
96
+
97
+ const jsonStr = extractJSON(cleanResponse(content));
98
+ try {
99
+ return JSON.parse(jsonStr);
100
+ } catch (firstError) {
101
+ // Try jsonrepair as fallback
102
+ try {
103
+ const { jsonrepair } = await import('jsonrepair');
104
+ return JSON.parse(jsonrepair(jsonStr));
105
+ } catch {
106
+ throw new Error(`Failed to parse JSON from Xiaomi (${this.model}): ${firstError.message}\n\nResponse:\n${content.slice(0, 500)}`);
107
+ }
108
+ }
109
+ }
110
+
111
+ async generateText(prompt, agentInstructions = null, cachedContext = null) {
112
+ if (!this._client) this._client = this._createClient();
113
+
114
+ const systemParts = [];
115
+ if (agentInstructions) systemParts.push(agentInstructions);
116
+ if (cachedContext) systemParts.push(cachedContext);
117
+
118
+ const messages = [];
119
+ if (systemParts.length > 0) {
120
+ messages.push({ role: 'system', content: systemParts.join('\n\n') });
121
+ }
122
+ messages.push({ role: 'user', content: prompt });
123
+
124
+ const _t0 = Date.now();
125
+ const response = await this._withRetry(
126
+ () => this._client.chat.completions.create({
127
+ model: this.model,
128
+ messages,
129
+ }),
130
+ 'Text generation (Xiaomi)'
131
+ );
132
+
133
+ const content = response.choices?.[0]?.message?.content || '';
134
+ this._trackTokens(response.usage, {
135
+ prompt,
136
+ agentInstructions: agentInstructions ?? null,
137
+ response: content,
138
+ elapsed: Date.now() - _t0,
139
+ });
140
+
141
+ return content;
142
+ }
143
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Message Constants - Reusable message definitions
3
+ *
4
+ * Centralized message strings to prevent duplication and ensure consistency.
5
+ * Use these constants instead of hardcoded strings throughout the codebase.
6
+ */
7
+
8
+ /**
9
+ * Common error messages
10
+ */
11
+ export const MESSAGES = {
12
+ /**
13
+ * Project not initialized error
14
+ */
15
+ PROJECT_NOT_INITIALIZED: {
16
+ error: 'Project not initialized',
17
+ help: 'Please run /init first to create the project structure.'
18
+ },
19
+
20
+ /**
21
+ * Ceremony headers with titles and documentation URLs
22
+ */
23
+ CEREMONY_HEADERS: {
24
+ 'sponsor-call': { title: 'Sponsor Call Ceremony' },
25
+ 'sprint-planning': { title: 'Sprint Planning Ceremony' },
26
+ 'seed': { title: 'Seed Ceremony' },
27
+ }
28
+ };
29
+
30
+ /**
31
+ * Helper function to get full "project not initialized" error message
32
+ * @returns {string} Complete error message with help text
33
+ */
34
+ export function getProjectNotInitializedMessage() {
35
+ return `${MESSAGES.PROJECT_NOT_INITIALIZED.error}\n\n${MESSAGES.PROJECT_NOT_INITIALIZED.help}`;
36
+ }
37
+
38
+ /**
39
+ * Helper function to get ceremony header
40
+ * @param {string} ceremonyName - Name of ceremony ('sponsor-call', 'sprint-planning', 'seed')
41
+ * @returns {object} Object with title and url properties
42
+ */
43
+ export function getCeremonyHeader(ceremonyName) {
44
+ const header = MESSAGES.CEREMONY_HEADERS[ceremonyName];
45
+ if (!header) {
46
+ throw new Error(`Unknown ceremony: ${ceremonyName}`);
47
+ }
48
+ return header;
49
+ }
@@ -0,0 +1,334 @@
1
+ /**
2
+ * MessageManager - Centralized message handling system
3
+ *
4
+ * Singleton that manages all console output through execution contexts.
5
+ * Prevents ghost messages by tracking command lifecycle and cancelling
6
+ * messages from previous runs.
7
+ */
8
+
9
+ import { MessageType } from './message-types.js';
10
+ import { ExecutionContext } from './execution-context.js';
11
+ import { outputBuffer } from './output-buffer.js';
12
+
13
+ /**
14
+ * MessageManager singleton class
15
+ */
16
+ class MessageManager {
17
+ constructor() {
18
+ if (MessageManager.instance) {
19
+ return MessageManager.instance;
20
+ }
21
+
22
+ this.currentContext = null;
23
+ this.contextHistory = [];
24
+ this.maxHistorySize = 10;
25
+ this.executingMessageCallback = null;
26
+ this.executingSubstepCallback = null;
27
+
28
+ MessageManager.instance = this;
29
+ }
30
+
31
+ /**
32
+ * Set executing message callback (from React state setter)
33
+ * @param {Function} callback - setExecutingMessage function
34
+ */
35
+ setExecutingMessageCallback(callback) {
36
+ this.executingMessageCallback = callback;
37
+ }
38
+
39
+ /**
40
+ * Set executing substep callback (from React state setter)
41
+ * @param {Function} callback - setExecutingSubstep function
42
+ */
43
+ setExecutingSubstepCallback(callback) {
44
+ this.executingSubstepCallback = callback;
45
+ }
46
+
47
+ /**
48
+ * Start a new execution context for a command
49
+ * @param {string} commandName - Name of the command
50
+ * @returns {ExecutionContext} New execution context
51
+ */
52
+ startExecution(commandName) {
53
+ // Cancel previous context if active
54
+ if (this.currentContext && this.currentContext.isActive()) {
55
+ this.currentContext.cancel();
56
+ }
57
+
58
+ // Create new context
59
+ this.currentContext = new ExecutionContext(commandName);
60
+
61
+ // Add to history
62
+ this.contextHistory.push(this.currentContext);
63
+ if (this.contextHistory.length > this.maxHistorySize) {
64
+ this.contextHistory.shift();
65
+ }
66
+
67
+ // Insert visual separator between commands in the Static output
68
+ outputBuffer.clear();
69
+
70
+ return this.currentContext;
71
+ }
72
+
73
+ /**
74
+ * End the current execution context
75
+ */
76
+ endExecution() {
77
+ if (this.currentContext) {
78
+ this.currentContext.complete();
79
+ this.currentContext = null;
80
+ }
81
+
82
+ // Clear progress indicators
83
+ if (this.executingMessageCallback) {
84
+ this.executingMessageCallback('');
85
+ }
86
+ if (this.executingSubstepCallback) {
87
+ this.executingSubstepCallback('');
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Cancel the current execution context
93
+ */
94
+ cancelExecution() {
95
+ if (this.currentContext) {
96
+ this.currentContext.cancel();
97
+ this.currentContext = null;
98
+ }
99
+
100
+ // Clear progress indicators
101
+ if (this.executingMessageCallback) {
102
+ this.executingMessageCallback('');
103
+ }
104
+ if (this.executingSubstepCallback) {
105
+ this.executingSubstepCallback('');
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Get current execution context
111
+ * @returns {ExecutionContext|null} Current context or null
112
+ */
113
+ getCurrentContext() {
114
+ return this.currentContext;
115
+ }
116
+
117
+ /**
118
+ * Send a message through the current context
119
+ * @param {string} type - MessageType
120
+ * @param {string} content - Message content
121
+ * @param {Object} options - Additional options
122
+ */
123
+ send(type, content, options = {}) {
124
+ // Validate message type
125
+ if (!Object.values(MessageType).includes(type)) {
126
+ console.error(`Invalid message type: ${type}`);
127
+ return;
128
+ }
129
+
130
+ // Ignore if no active context
131
+ if (!this.currentContext || !this.currentContext.isActive()) {
132
+ return;
133
+ }
134
+
135
+ // Handle different message types
136
+ switch (type) {
137
+ case MessageType.COMMAND_START:
138
+ this._handleCommandStart(content);
139
+ break;
140
+
141
+ case MessageType.CEREMONY_HEADER:
142
+ this._handleCeremonyHeader(content);
143
+ break;
144
+
145
+ case MessageType.PROGRESS:
146
+ this._handleProgress(content);
147
+ break;
148
+
149
+ case MessageType.SUBSTEP:
150
+ this._handleSubstep(content);
151
+ break;
152
+
153
+ case MessageType.USER_OUTPUT:
154
+ this._handleUserOutput(content);
155
+ break;
156
+
157
+ case MessageType.ERROR:
158
+ this._handleError(content);
159
+ break;
160
+
161
+ case MessageType.WARNING:
162
+ this._handleWarning(content);
163
+ break;
164
+
165
+ case MessageType.SUCCESS:
166
+ this._handleSuccess(content);
167
+ break;
168
+
169
+ case MessageType.INFO:
170
+ this._handleInfo(content);
171
+ break;
172
+
173
+ case MessageType.DEBUG:
174
+ this._handleDebug(content, options);
175
+ break;
176
+
177
+ default:
178
+ this._handleUserOutput(content);
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Handle COMMAND_START message
184
+ * @private
185
+ */
186
+ _handleCommandStart(content) {
187
+ // Clear output buffer (already done in startExecution)
188
+ // This is a marker message type, no output needed
189
+ }
190
+
191
+ /**
192
+ * Handle CEREMONY_HEADER message
193
+ * @private
194
+ */
195
+ _handleCeremonyHeader(content) {
196
+ outputBuffer.append(content);
197
+ }
198
+
199
+ /**
200
+ * Handle PROGRESS message
201
+ * @private
202
+ */
203
+ _handleProgress(content) {
204
+ if (this.currentContext) {
205
+ this.currentContext.setExecutingMessage(content);
206
+ }
207
+ if (this.executingMessageCallback) {
208
+ this.executingMessageCallback(content);
209
+ }
210
+ }
211
+
212
+ /**
213
+ * Handle SUBSTEP message
214
+ * @private
215
+ */
216
+ _handleSubstep(content) {
217
+ if (this.currentContext) {
218
+ this.currentContext.setExecutingSubstep(content);
219
+ }
220
+ if (this.executingSubstepCallback) {
221
+ this.executingSubstepCallback(content);
222
+ }
223
+ }
224
+
225
+ /**
226
+ * Handle USER_OUTPUT message
227
+ * @private
228
+ */
229
+ _handleUserOutput(content) {
230
+ // Empty string means "blank line" — outputBuffer ignores falsy values,
231
+ // so convert '' to '\n' to produce the intended visual gap.
232
+ outputBuffer.append(content === '' ? '\n' : content);
233
+ }
234
+
235
+ /**
236
+ * Handle ERROR message
237
+ * @private
238
+ */
239
+ _handleError(content) {
240
+ outputBuffer.append(`ERROR: ${content}`, 'ERROR');
241
+ }
242
+
243
+ /**
244
+ * Handle WARNING message
245
+ * @private
246
+ */
247
+ _handleWarning(content) {
248
+ outputBuffer.append(`WARNING: ${content}`, 'WARNING');
249
+ }
250
+
251
+ /**
252
+ * Handle SUCCESS message
253
+ * @private
254
+ */
255
+ _handleSuccess(content) {
256
+ outputBuffer.append(`SUCCESS: ${content}`, 'SUCCESS');
257
+ }
258
+
259
+ /**
260
+ * Handle INFO message
261
+ * @private
262
+ */
263
+ _handleInfo(content) {
264
+ outputBuffer.append(`INFO: ${content}`, 'INFO');
265
+ }
266
+
267
+ /**
268
+ * Handle DEBUG message
269
+ * @private
270
+ */
271
+ _handleDebug(content, options = {}) {
272
+ // Debug messages only go to console.log, not main output
273
+ const timestamp = new Date().toISOString();
274
+ if (options.data) {
275
+ console.log(`[DEBUG][${timestamp}] ${content}`, JSON.stringify(options.data, null, 2));
276
+ } else {
277
+ console.log(`[DEBUG][${timestamp}] ${content}`);
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Clear progress indicators
283
+ */
284
+ clearProgress() {
285
+ if (this.currentContext) {
286
+ this.currentContext.clearExecutingMessage();
287
+ this.currentContext.clearExecutingSubstep();
288
+ }
289
+ if (this.executingMessageCallback) {
290
+ this.executingMessageCallback('');
291
+ }
292
+ if (this.executingSubstepCallback) {
293
+ this.executingSubstepCallback('');
294
+ }
295
+ }
296
+
297
+ /**
298
+ * Get execution context history
299
+ * @returns {Array} Array of execution contexts
300
+ */
301
+ getHistory() {
302
+ return [...this.contextHistory];
303
+ }
304
+
305
+ /**
306
+ * Get manager state for debugging
307
+ * @returns {Object} Manager state
308
+ */
309
+ toJSON() {
310
+ return {
311
+ hasCurrentContext: !!this.currentContext,
312
+ currentContext: this.currentContext ? this.currentContext.toJSON() : null,
313
+ historySize: this.contextHistory.length,
314
+ hasCallbacks: {
315
+ executingMessage: !!this.executingMessageCallback,
316
+ executingSubstep: !!this.executingSubstepCallback
317
+ }
318
+ };
319
+ }
320
+
321
+ /**
322
+ * Reset manager (for testing)
323
+ */
324
+ reset() {
325
+ if (this.currentContext) {
326
+ this.currentContext.cancel();
327
+ }
328
+ this.currentContext = null;
329
+ this.contextHistory = [];
330
+ }
331
+ }
332
+
333
+ // Export singleton instance
334
+ export const messageManager = new MessageManager();
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Message Types for MessageManager
3
+ *
4
+ * Defines different types of messages that can be sent through the messaging system.
5
+ * Each type can be handled differently (formatting, logging, display).
6
+ */
7
+
8
+ export const MessageType = {
9
+ /**
10
+ * Command start - marks the beginning of a command execution
11
+ * Typically clears the output buffer
12
+ */
13
+ COMMAND_START: 'COMMAND_START',
14
+
15
+ /**
16
+ * Ceremony header - displays ceremony title and documentation URL
17
+ * Format: šŸŽÆ Title\nšŸ“– URL
18
+ */
19
+ CEREMONY_HEADER: 'CEREMONY_HEADER',
20
+
21
+ /**
22
+ * Progress indicator - shows ongoing operation status
23
+ * These go to executingMessage state, not main output
24
+ */
25
+ PROGRESS: 'PROGRESS',
26
+
27
+ /**
28
+ * Substep progress - shows detailed progress within an operation
29
+ * These go to executingSubstep state, not main output
30
+ */
31
+ SUBSTEP: 'SUBSTEP',
32
+
33
+ /**
34
+ * User output - main content shown to user
35
+ * Standard output messages
36
+ */
37
+ USER_OUTPUT: 'USER_OUTPUT',
38
+
39
+ /**
40
+ * Error message - displays errors to user
41
+ * Automatically formatted with ERROR: prefix in red bold
42
+ */
43
+ ERROR: 'ERROR',
44
+
45
+ /**
46
+ * Warning message - displays warnings to user
47
+ * Automatically formatted with WARNING: prefix in yellow bold
48
+ */
49
+ WARNING: 'WARNING',
50
+
51
+ /**
52
+ * Success message - displays success confirmation
53
+ * Automatically formatted with SUCCESS: prefix in green bold
54
+ */
55
+ SUCCESS: 'SUCCESS',
56
+
57
+ /**
58
+ * Debug message - development/troubleshooting info
59
+ * Not shown in main output, only console.log
60
+ */
61
+ DEBUG: 'DEBUG',
62
+
63
+ /**
64
+ * Info message - informational content
65
+ * Automatically formatted with INFO: prefix in cyan
66
+ */
67
+ INFO: 'INFO'
68
+ };
69
+
70
+ /**
71
+ * Check if a message type is valid
72
+ * @param {string} type - Message type to validate
73
+ * @returns {boolean} True if valid
74
+ */
75
+ export function isValidMessageType(type) {
76
+ return Object.values(MessageType).includes(type);
77
+ }
78
+
79
+ /**
80
+ * Get default formatting for a message type
81
+ * @param {string} type - Message type
82
+ * @returns {object} Format configuration with prefix, color, and bold flag
83
+ */
84
+ export function getMessageFormat(type) {
85
+ const formats = {
86
+ [MessageType.ERROR]: { prefix: 'ERROR: ', color: 'red', bold: true },
87
+ [MessageType.WARNING]: { prefix: 'WARNING: ', color: 'yellow', bold: true },
88
+ [MessageType.SUCCESS]: { prefix: 'SUCCESS: ', color: 'green', bold: true },
89
+ [MessageType.INFO]: { prefix: 'INFO: ', color: 'cyan', bold: false },
90
+ [MessageType.CEREMONY_HEADER]: { prefix: '', color: 'cyan', bold: true },
91
+ [MessageType.USER_OUTPUT]: { prefix: '', color: 'white', bold: false },
92
+ [MessageType.DEBUG]: { prefix: '[DEBUG] ', color: 'gray', bold: false }
93
+ };
94
+
95
+ return formats[type] || { prefix: '', color: 'white', bold: false };
96
+ }