s9n-devops-agent 1.7.3 → 2.0.0
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/README.md +126 -454
- package/README.v1.md +529 -0
- package/bin/cs-devops-agent +31 -13
- package/docs/FILE_COORDINATION_GUIDE.md +481 -0
- package/docs/MULTI_AGENT_WORKFLOWS.md +692 -0
- package/docs/V2_FINAL_SUMMARY.md +526 -0
- package/docs/V2_QUICK_REFERENCE.md +447 -0
- package/docs/V2_STATUS_REPORT.md +324 -0
- package/package.json +1 -1
- package/src/help-system.js +475 -0
- package/src/instruction-formatter.js +346 -0
- package/src/setup-cs-devops-agent.js +91 -55
- package/src/tutorial-mode.js +550 -0
- package/src/ui-utils.js +509 -0
- package/start-devops-session.sh +71 -31
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ============================================================================
|
|
5
|
+
* INSTRUCTION FORMATTER - Beautiful AI Assistant Instructions for v2.0
|
|
6
|
+
* ============================================================================
|
|
7
|
+
*
|
|
8
|
+
* Generates clear, structured, visually appealing instructions for AI
|
|
9
|
+
* assistants working in DevOps Agent sessions.
|
|
10
|
+
*
|
|
11
|
+
* Features:
|
|
12
|
+
* - Numbered steps with clear hierarchy
|
|
13
|
+
* - Visual separators and formatting
|
|
14
|
+
* - Context-aware content
|
|
15
|
+
* - Copy-paste ready format
|
|
16
|
+
* - Critical information highlighted
|
|
17
|
+
*
|
|
18
|
+
* ============================================================================
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { colors, status, box } from './ui-utils.js';
|
|
22
|
+
import path from 'path';
|
|
23
|
+
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// INSTRUCTION TEMPLATES
|
|
26
|
+
// ============================================================================
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Format complete instructions for an AI assistant
|
|
30
|
+
*
|
|
31
|
+
* @param {Object} session - Session configuration
|
|
32
|
+
* @param {string} session.id - Session ID
|
|
33
|
+
* @param {string} session.task - Task name
|
|
34
|
+
* @param {string} session.agent - Agent type (claude, cursor, etc.)
|
|
35
|
+
* @param {string} session.worktreePath - Full path to worktree
|
|
36
|
+
* @param {string} session.houseRulesPath - Path to house rules file
|
|
37
|
+
* @param {Array<string>} session.declaredFiles - Optional pre-declared files
|
|
38
|
+
* @param {Object} options - Formatting options
|
|
39
|
+
* @returns {string} Formatted instructions
|
|
40
|
+
*/
|
|
41
|
+
export function formatInstructions(session, options = {}) {
|
|
42
|
+
const lines = [];
|
|
43
|
+
|
|
44
|
+
// Header
|
|
45
|
+
lines.push('');
|
|
46
|
+
lines.push(box.doubleTopLeft + box.doubleHorizontal.repeat(68) + box.doubleTopRight);
|
|
47
|
+
lines.push(box.doubleVertical + ` ${status.robot} Instructions for Your AI Assistant`.padEnd(69) + box.doubleVertical);
|
|
48
|
+
lines.push(box.doubleBottomLeft + box.doubleHorizontal.repeat(68) + box.doubleBottomRight);
|
|
49
|
+
lines.push('');
|
|
50
|
+
|
|
51
|
+
// Intro
|
|
52
|
+
lines.push(`${colors.bright}Copy this ENTIRE message to ${session.agent}:${colors.reset}`);
|
|
53
|
+
lines.push('');
|
|
54
|
+
lines.push('━'.repeat(70));
|
|
55
|
+
lines.push(`${status.rocket} ${colors.bright}DevOps Session Configuration${colors.reset}`);
|
|
56
|
+
lines.push('');
|
|
57
|
+
|
|
58
|
+
// Session Info
|
|
59
|
+
lines.push(`Session ID: ${colors.cyan}${session.id}${colors.reset}`);
|
|
60
|
+
lines.push(`Task: ${colors.bright}${session.task}${colors.reset}`);
|
|
61
|
+
lines.push(`Working Directory: ${colors.dim}${session.worktreePath}${colors.reset}`);
|
|
62
|
+
lines.push('');
|
|
63
|
+
|
|
64
|
+
// Critical First Step - House Rules
|
|
65
|
+
lines.push(`${colors.bright}${status.point} STEP 1: Read the house rules${colors.reset} ${colors.red}(CRITICAL - Do this first!)${colors.reset}`);
|
|
66
|
+
lines.push(` ${colors.green}cat "${session.houseRulesPath}"${colors.reset}`);
|
|
67
|
+
lines.push('');
|
|
68
|
+
lines.push(` ${colors.dim}House rules contain:${colors.reset}`);
|
|
69
|
+
lines.push(` ${colors.dim}• Project conventions and coding standards${colors.reset}`);
|
|
70
|
+
lines.push(` ${colors.dim}• Testing requirements${colors.reset}`);
|
|
71
|
+
lines.push(` ${colors.dim}• Commit message format${colors.reset}`);
|
|
72
|
+
lines.push(` ${colors.dim}• File coordination protocols${colors.reset}`);
|
|
73
|
+
lines.push('');
|
|
74
|
+
|
|
75
|
+
// Step 2 - Switch Directory
|
|
76
|
+
lines.push(`${colors.bright}${status.point} STEP 2: Switch to your workspace${colors.reset}`);
|
|
77
|
+
lines.push(` ${colors.green}cd "${session.worktreePath}"${colors.reset}`);
|
|
78
|
+
lines.push('');
|
|
79
|
+
lines.push(` ${colors.dim}This is your isolated workspace. All your work happens here.${colors.reset}`);
|
|
80
|
+
lines.push('');
|
|
81
|
+
|
|
82
|
+
// Step 3 - File Coordination
|
|
83
|
+
lines.push(`${colors.bright}${status.point} STEP 3: Declare files before editing${colors.reset} ${colors.yellow}(MANDATORY)${colors.reset}`);
|
|
84
|
+
lines.push(` ${colors.dim}Before touching ANY file, declare it in:${colors.reset}`);
|
|
85
|
+
lines.push(` ${colors.cyan}.file-coordination/active-edits/${session.agent}-${session.id}.json${colors.reset}`);
|
|
86
|
+
lines.push('');
|
|
87
|
+
lines.push(` ${colors.dim}Example declaration:${colors.reset}`);
|
|
88
|
+
lines.push(` {`);
|
|
89
|
+
lines.push(` "agent": "${session.agent}",`);
|
|
90
|
+
lines.push(` "session": "${session.id}",`);
|
|
91
|
+
lines.push(` "files": ["src/auth/login.js", "src/auth/token.js"],`);
|
|
92
|
+
lines.push(` "operation": "edit",`);
|
|
93
|
+
lines.push(` "reason": "${session.task}",`);
|
|
94
|
+
lines.push(` "declaredAt": "${new Date().toISOString()}"`);
|
|
95
|
+
lines.push(` }`);
|
|
96
|
+
lines.push('');
|
|
97
|
+
lines.push(` ${colors.yellow}${status.warning} Why this matters:${colors.reset}`);
|
|
98
|
+
lines.push(` ${colors.dim}• Prevents conflicts with other AI agents${colors.reset}`);
|
|
99
|
+
lines.push(` ${colors.dim}• System alerts if files are already locked${colors.reset}`);
|
|
100
|
+
lines.push(` ${colors.dim}• Ensures coordinated multi-agent workflows${colors.reset}`);
|
|
101
|
+
lines.push('');
|
|
102
|
+
|
|
103
|
+
// Step 4 - Making Changes
|
|
104
|
+
lines.push(`${colors.bright}${status.point} STEP 4: Make your changes${colors.reset}`);
|
|
105
|
+
lines.push(` ${colors.dim}Edit the files you declared. Follow house rules for:${colors.reset}`);
|
|
106
|
+
lines.push(` ${colors.dim}• Code style and formatting${colors.reset}`);
|
|
107
|
+
lines.push(` ${colors.dim}• Testing requirements${colors.reset}`);
|
|
108
|
+
lines.push(` ${colors.dim}• Documentation standards${colors.reset}`);
|
|
109
|
+
lines.push('');
|
|
110
|
+
|
|
111
|
+
// Step 5 - Commit Messages
|
|
112
|
+
lines.push(`${colors.bright}${status.point} STEP 5: Write commit messages${colors.reset}`);
|
|
113
|
+
lines.push(` ${colors.dim}After each logical change, write commit message to:${colors.reset}`);
|
|
114
|
+
lines.push(` ${colors.cyan}.devops-commit-${session.id}.msg${colors.reset}`);
|
|
115
|
+
lines.push('');
|
|
116
|
+
lines.push(` ${colors.dim}DevOps Agent will automatically:${colors.reset}`);
|
|
117
|
+
lines.push(` ${colors.dim}• Stage all changes${colors.reset}`);
|
|
118
|
+
lines.push(` ${colors.dim}• Commit with your message${colors.reset}`);
|
|
119
|
+
lines.push(` ${colors.dim}• Push to GitHub${colors.reset}`);
|
|
120
|
+
lines.push(` ${colors.dim}• Clear the message file${colors.reset}`);
|
|
121
|
+
lines.push('');
|
|
122
|
+
lines.push(` ${colors.green}${status.checkmark} Commit Message Format:${colors.reset}`);
|
|
123
|
+
lines.push(` ${colors.dim}type(scope): subject line (max 72 chars)${colors.reset}`);
|
|
124
|
+
lines.push(` ${colors.dim}${colors.reset}`);
|
|
125
|
+
lines.push(` ${colors.dim}- Bullet point 1: Specific change made${colors.reset}`);
|
|
126
|
+
lines.push(` ${colors.dim}- Bullet point 2: Another change${colors.reset}`);
|
|
127
|
+
lines.push('');
|
|
128
|
+
|
|
129
|
+
// File Coordination Rules
|
|
130
|
+
lines.push('');
|
|
131
|
+
lines.push(`${status.lock} ${colors.bright}File Coordination Protocol:${colors.reset}`);
|
|
132
|
+
lines.push('');
|
|
133
|
+
lines.push(` ${colors.red}${status.error} DO NOT edit files without declaring them first${colors.reset}`);
|
|
134
|
+
lines.push(` ${colors.green}${status.checkmark} Always check .file-coordination/active-edits/ for conflicts${colors.reset}`);
|
|
135
|
+
lines.push(` ${colors.green}${status.checkmark} If another agent locked a file, ask user for guidance${colors.reset}`);
|
|
136
|
+
lines.push(` ${colors.green}${status.checkmark} Release files by deleting your declaration when done${colors.reset}`);
|
|
137
|
+
lines.push('');
|
|
138
|
+
|
|
139
|
+
// Testing Reminder
|
|
140
|
+
if (options.testCommand) {
|
|
141
|
+
lines.push(`${status.checkmark} ${colors.bright}Testing:${colors.reset}`);
|
|
142
|
+
lines.push(` ${colors.dim}Run tests before closing session:${colors.reset}`);
|
|
143
|
+
lines.push(` ${colors.green}${options.testCommand}${colors.reset}`);
|
|
144
|
+
lines.push('');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Docker Reminder
|
|
148
|
+
if (options.dockerEnabled) {
|
|
149
|
+
lines.push(`${status.checkmark} ${colors.bright}Docker:${colors.reset}`);
|
|
150
|
+
lines.push(` ${colors.dim}Containers will auto-restart after each push${colors.reset}`);
|
|
151
|
+
lines.push('');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Footer
|
|
155
|
+
lines.push('━'.repeat(70));
|
|
156
|
+
lines.push('');
|
|
157
|
+
lines.push(`${status.checkmark} ${colors.green}DevOps Agent is now monitoring this session...${colors.reset}`);
|
|
158
|
+
lines.push(` ${colors.dim}Press Ctrl+C to stop monitoring${colors.reset}`);
|
|
159
|
+
lines.push(` ${colors.dim}To close session: ${colors.cyan}s9n-devops-agent close ${session.id}${colors.reset}`);
|
|
160
|
+
lines.push('');
|
|
161
|
+
lines.push(`${colors.dim}💡 Tip: Keep this terminal open. Open a new terminal for other work.${colors.reset}`);
|
|
162
|
+
lines.push('');
|
|
163
|
+
|
|
164
|
+
return lines.join('\n');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Format condensed instructions (for experienced users)
|
|
169
|
+
*/
|
|
170
|
+
export function formatCondensedInstructions(session) {
|
|
171
|
+
const lines = [];
|
|
172
|
+
|
|
173
|
+
lines.push('');
|
|
174
|
+
lines.push(`${status.robot} ${colors.bright}DevOps Session: ${session.id}${colors.reset}`);
|
|
175
|
+
lines.push('');
|
|
176
|
+
lines.push(`${status.point} Read house rules: ${colors.green}cat "${session.houseRulesPath}"${colors.reset}`);
|
|
177
|
+
lines.push(`${status.point} Switch workspace: ${colors.green}cd "${session.worktreePath}"${colors.reset}`);
|
|
178
|
+
lines.push(`${status.point} Declare files: ${colors.cyan}.file-coordination/active-edits/${session.agent}-${session.id}.json${colors.reset}`);
|
|
179
|
+
lines.push(`${status.point} Write commits: ${colors.cyan}.devops-commit-${session.id}.msg${colors.reset}`);
|
|
180
|
+
lines.push('');
|
|
181
|
+
lines.push(`${colors.dim}Full instructions: s9n-devops-agent instructions ${session.id}${colors.reset}`);
|
|
182
|
+
lines.push('');
|
|
183
|
+
|
|
184
|
+
return lines.join('\n');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Format instructions for resuming an existing session
|
|
189
|
+
*/
|
|
190
|
+
export function formatResumeInstructions(session) {
|
|
191
|
+
const lines = [];
|
|
192
|
+
|
|
193
|
+
lines.push('');
|
|
194
|
+
lines.push(`${status.robot} ${colors.bright}Resuming Session: ${session.id}${colors.reset}`);
|
|
195
|
+
lines.push('');
|
|
196
|
+
lines.push(`Task: ${colors.cyan}${session.task}${colors.reset}`);
|
|
197
|
+
lines.push(`Status: ${colors.yellow}Paused${colors.reset} → ${colors.green}Active${colors.reset}`);
|
|
198
|
+
lines.push('');
|
|
199
|
+
lines.push(`${status.point} ${colors.bright}Switch to workspace:${colors.reset}`);
|
|
200
|
+
lines.push(` ${colors.green}cd "${session.worktreePath}"${colors.reset}`);
|
|
201
|
+
lines.push('');
|
|
202
|
+
lines.push(`${status.point} ${colors.bright}Check your file locks:${colors.reset}`);
|
|
203
|
+
lines.push(` ${colors.green}cat .file-coordination/active-edits/${session.agent}-${session.id}.json${colors.reset}`);
|
|
204
|
+
lines.push('');
|
|
205
|
+
lines.push(`${status.point} ${colors.bright}Continue where you left off${colors.reset}`);
|
|
206
|
+
lines.push(` ${colors.dim}Your previous changes are preserved${colors.reset}`);
|
|
207
|
+
lines.push(` ${colors.dim}File locks are still active${colors.reset}`);
|
|
208
|
+
lines.push('');
|
|
209
|
+
lines.push(`${colors.dim}Write commits to: ${colors.cyan}.devops-commit-${session.id}.msg${colors.reset}`);
|
|
210
|
+
lines.push('');
|
|
211
|
+
|
|
212
|
+
return lines.join('\n');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Format multi-agent coordination message
|
|
217
|
+
*/
|
|
218
|
+
export function formatMultiAgentWarning(conflictingSession) {
|
|
219
|
+
const lines = [];
|
|
220
|
+
|
|
221
|
+
lines.push('');
|
|
222
|
+
lines.push(colors.yellow + '⚠'.repeat(70) + colors.reset);
|
|
223
|
+
lines.push(`${colors.yellow}${colors.bright} MULTI-AGENT COORDINATION ALERT${colors.reset}`);
|
|
224
|
+
lines.push(colors.yellow + '⚠'.repeat(70) + colors.reset);
|
|
225
|
+
lines.push('');
|
|
226
|
+
lines.push(`${colors.bright}Another agent is working on related files:${colors.reset}`);
|
|
227
|
+
lines.push('');
|
|
228
|
+
lines.push(` Session: ${colors.cyan}${conflictingSession.id}${colors.reset}`);
|
|
229
|
+
lines.push(` Agent: ${colors.cyan}${conflictingSession.agent}${colors.reset}`);
|
|
230
|
+
lines.push(` Task: ${conflictingSession.task}`);
|
|
231
|
+
lines.push(` Files locked: ${conflictingSession.lockedFiles.join(', ')}`);
|
|
232
|
+
lines.push('');
|
|
233
|
+
lines.push(`${colors.yellow}${status.warning} Recommended actions:${colors.reset}`);
|
|
234
|
+
lines.push('');
|
|
235
|
+
lines.push(` 1. ${colors.bright}Coordinate with user${colors.reset}`);
|
|
236
|
+
lines.push(` Ask which session should proceed first`);
|
|
237
|
+
lines.push('');
|
|
238
|
+
lines.push(` 2. ${colors.bright}Work on different files${colors.reset}`);
|
|
239
|
+
lines.push(` Choose non-conflicting files for now`);
|
|
240
|
+
lines.push('');
|
|
241
|
+
lines.push(` 3. ${colors.bright}Wait for other session to complete${colors.reset}`);
|
|
242
|
+
lines.push(` Files will be available after session closes`);
|
|
243
|
+
lines.push('');
|
|
244
|
+
lines.push(colors.yellow + '⚠'.repeat(70) + colors.reset);
|
|
245
|
+
lines.push('');
|
|
246
|
+
|
|
247
|
+
return lines.join('\n');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Format closing instructions
|
|
252
|
+
*/
|
|
253
|
+
export function formatClosingInstructions(session) {
|
|
254
|
+
const lines = [];
|
|
255
|
+
|
|
256
|
+
lines.push('');
|
|
257
|
+
lines.push(`${status.checkmark} ${colors.bright}Ready to close session ${session.id}?${colors.reset}`);
|
|
258
|
+
lines.push('');
|
|
259
|
+
lines.push(`${colors.bright}What will happen:${colors.reset}`);
|
|
260
|
+
lines.push('');
|
|
261
|
+
lines.push(` ${status.point} ${colors.cyan}Commit any pending changes${colors.reset}`);
|
|
262
|
+
lines.push(` Ensures all work is saved`);
|
|
263
|
+
lines.push('');
|
|
264
|
+
lines.push(` ${status.point} ${colors.cyan}Merge to daily branch${colors.reset}`);
|
|
265
|
+
lines.push(` Integrates with today's work`);
|
|
266
|
+
lines.push('');
|
|
267
|
+
lines.push(` ${status.point} ${colors.cyan}Merge to main branch${colors.reset}`);
|
|
268
|
+
lines.push(` Makes changes available to team`);
|
|
269
|
+
lines.push('');
|
|
270
|
+
lines.push(` ${status.point} ${colors.cyan}Release file locks${colors.reset}`);
|
|
271
|
+
lines.push(` Files available for other agents`);
|
|
272
|
+
lines.push('');
|
|
273
|
+
lines.push(` ${status.point} ${colors.cyan}Clean up worktree${colors.reset}`);
|
|
274
|
+
lines.push(` Removes session directory`);
|
|
275
|
+
lines.push('');
|
|
276
|
+
lines.push(`${colors.bright}Command:${colors.reset}`);
|
|
277
|
+
lines.push(` ${colors.green}s9n-devops-agent close ${session.id}${colors.reset}`);
|
|
278
|
+
lines.push('');
|
|
279
|
+
|
|
280
|
+
return lines.join('\n');
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Format quick reference card
|
|
285
|
+
*/
|
|
286
|
+
export function formatQuickReference(session) {
|
|
287
|
+
const lines = [];
|
|
288
|
+
|
|
289
|
+
lines.push('');
|
|
290
|
+
lines.push(box.topLeft + box.horizontal.repeat(68) + box.topRight);
|
|
291
|
+
lines.push(box.vertical + ` ${colors.bright}Quick Reference - Session ${session.id}${colors.reset}`.padEnd(70) + box.vertical);
|
|
292
|
+
lines.push(box.leftT + box.horizontal.repeat(68) + box.rightT);
|
|
293
|
+
lines.push(box.vertical + ` ${colors.cyan}Essential Commands${colors.reset}`.padEnd(90) + box.vertical);
|
|
294
|
+
lines.push(box.vertical + ' '.repeat(70) + box.vertical);
|
|
295
|
+
lines.push(box.vertical + ` Switch workspace: cd "${session.worktreePath}"`.padEnd(90) + box.vertical);
|
|
296
|
+
lines.push(box.vertical + ` Declare files: .file-coordination/active-edits/${session.agent}-${session.id}.json`.padEnd(140) + box.vertical);
|
|
297
|
+
lines.push(box.vertical + ` Write commit: .devops-commit-${session.id}.msg`.padEnd(98) + box.vertical);
|
|
298
|
+
lines.push(box.vertical + ` Close session: s9n-devops-agent close ${session.id}`.padEnd(100) + box.vertical);
|
|
299
|
+
lines.push(box.bottomLeft + box.horizontal.repeat(68) + box.bottomRight);
|
|
300
|
+
lines.push('');
|
|
301
|
+
|
|
302
|
+
return lines.join('\n');
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// ============================================================================
|
|
306
|
+
// HELPER FUNCTIONS
|
|
307
|
+
// ============================================================================
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Create session object from parameters
|
|
311
|
+
*/
|
|
312
|
+
export function createSession(id, task, agent, worktreePath, projectRoot) {
|
|
313
|
+
return {
|
|
314
|
+
id,
|
|
315
|
+
task,
|
|
316
|
+
agent,
|
|
317
|
+
worktreePath,
|
|
318
|
+
houseRulesPath: path.join(projectRoot, 'docs', 'houserules.md'),
|
|
319
|
+
declaredFiles: [],
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Get appropriate agent name display
|
|
325
|
+
*/
|
|
326
|
+
export function getAgentDisplayName(agentType) {
|
|
327
|
+
const names = {
|
|
328
|
+
claude: 'Claude',
|
|
329
|
+
cursor: 'Cursor',
|
|
330
|
+
copilot: 'GitHub Copilot',
|
|
331
|
+
cline: 'Cline',
|
|
332
|
+
other: 'AI Assistant',
|
|
333
|
+
};
|
|
334
|
+
return names[agentType] || agentType;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export default {
|
|
338
|
+
formatInstructions,
|
|
339
|
+
formatCondensedInstructions,
|
|
340
|
+
formatResumeInstructions,
|
|
341
|
+
formatMultiAgentWarning,
|
|
342
|
+
formatClosingInstructions,
|
|
343
|
+
formatQuickReference,
|
|
344
|
+
createSession,
|
|
345
|
+
getAgentDisplayName,
|
|
346
|
+
};
|
|
@@ -2,48 +2,59 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* ============================================================================
|
|
5
|
-
* DEVOPS-AGENT
|
|
5
|
+
* DEVOPS-AGENT SETUP WIZARD (v2.0)
|
|
6
6
|
* ============================================================================
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* 1. Prompts for developer's 3-letter initials
|
|
10
|
-
* 2. Configures branch prefix (e.g., dev_sdd_ becomes dev_abc_)
|
|
11
|
-
* 3. Installs required npm packages
|
|
12
|
-
* 4. Creates/updates VS Code settings and tasks
|
|
13
|
-
* 5. Sets up commit message files
|
|
14
|
-
* 6. Creates a personalized run script
|
|
8
|
+
* Enhanced setup experience with explanations and auto-detection.
|
|
15
9
|
*
|
|
16
|
-
*
|
|
10
|
+
* What this does:
|
|
11
|
+
* - Configures your developer environment
|
|
12
|
+
* - Sets up git automation
|
|
13
|
+
* - Creates VS Code integration
|
|
14
|
+
* - Installs required dependencies
|
|
15
|
+
*
|
|
16
|
+
* Why it matters:
|
|
17
|
+
* - One-time setup for smooth development
|
|
18
|
+
* - Personalized configuration
|
|
19
|
+
* - Ready-to-use AI agent integration
|
|
20
|
+
*
|
|
21
|
+
* Usage: s9n-devops-agent setup
|
|
17
22
|
* ============================================================================
|
|
18
23
|
*/
|
|
19
24
|
|
|
20
25
|
import fs from 'fs';
|
|
21
26
|
import path from 'path';
|
|
22
27
|
import { execSync } from 'child_process';
|
|
23
|
-
import readline from 'readline';
|
|
24
28
|
import { fileURLToPath } from 'url';
|
|
25
29
|
import { dirname } from 'path';
|
|
30
|
+
import {
|
|
31
|
+
colors,
|
|
32
|
+
status,
|
|
33
|
+
showWelcome,
|
|
34
|
+
sectionTitle,
|
|
35
|
+
explain,
|
|
36
|
+
tip,
|
|
37
|
+
warn,
|
|
38
|
+
info,
|
|
39
|
+
success,
|
|
40
|
+
error as errorMsg,
|
|
41
|
+
confirm,
|
|
42
|
+
prompt as uiPrompt,
|
|
43
|
+
progressStep,
|
|
44
|
+
drawSection
|
|
45
|
+
} from './ui-utils.js';
|
|
26
46
|
|
|
27
47
|
const __filename = fileURLToPath(import.meta.url);
|
|
28
48
|
const __dirname = dirname(__filename);
|
|
29
49
|
|
|
30
|
-
//
|
|
31
|
-
const colors = {
|
|
32
|
-
reset: '\x1b[0m',
|
|
33
|
-
bright: '\x1b[1m',
|
|
34
|
-
green: '\x1b[32m',
|
|
35
|
-
yellow: '\x1b[33m',
|
|
36
|
-
blue: '\x1b[36m',
|
|
37
|
-
red: '\x1b[31m',
|
|
38
|
-
};
|
|
39
|
-
|
|
50
|
+
// Backward compatibility log functions
|
|
40
51
|
const log = {
|
|
41
|
-
info: (msg) =>
|
|
42
|
-
success: (msg) =>
|
|
43
|
-
warn: (msg) =>
|
|
44
|
-
error: (msg) =>
|
|
45
|
-
header: (
|
|
46
|
-
title: (msg) =>
|
|
52
|
+
info: (msg) => info(msg),
|
|
53
|
+
success: (msg) => success(msg),
|
|
54
|
+
warn: (msg) => warn(msg),
|
|
55
|
+
error: (msg) => errorMsg(msg),
|
|
56
|
+
header: () => console.log('\n' + '━'.repeat(70) + '\n'),
|
|
57
|
+
title: (msg) => sectionTitle(msg),
|
|
47
58
|
};
|
|
48
59
|
|
|
49
60
|
// ============================================================================
|
|
@@ -65,18 +76,11 @@ function findProjectRoot() {
|
|
|
65
76
|
return process.cwd();
|
|
66
77
|
}
|
|
67
78
|
|
|
79
|
+
// Use UI utilities prompt with fallback
|
|
68
80
|
async function prompt(question) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
return new Promise((resolve) => {
|
|
75
|
-
rl.question(question, (answer) => {
|
|
76
|
-
rl.close();
|
|
77
|
-
resolve(answer);
|
|
78
|
-
});
|
|
79
|
-
});
|
|
81
|
+
// Strip ANSI codes and clean question for display
|
|
82
|
+
const cleanQuestion = question.replace(/\x1b\[[0-9;]*m/g, '').trim();
|
|
83
|
+
return await uiPrompt(cleanQuestion);
|
|
80
84
|
}
|
|
81
85
|
|
|
82
86
|
function validateInitials(initials) {
|
|
@@ -917,12 +921,24 @@ function cleanupDevOpsAgentFiles(projectRoot) {
|
|
|
917
921
|
|
|
918
922
|
async function main() {
|
|
919
923
|
console.clear();
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
console.log(
|
|
924
|
-
|
|
925
|
-
|
|
924
|
+
|
|
925
|
+
// Show welcome
|
|
926
|
+
showWelcome('DevOps Agent Setup Wizard');
|
|
927
|
+
console.log();
|
|
928
|
+
|
|
929
|
+
explain(`
|
|
930
|
+
Welcome to the DevOps Agent setup! This wizard will configure everything
|
|
931
|
+
you need to start working with AI assistants on your project.
|
|
932
|
+
|
|
933
|
+
${colors.bright}What we'll set up:${colors.reset}
|
|
934
|
+
${status.checkmark} Your personal developer configuration
|
|
935
|
+
${status.checkmark} Git automation and branch management
|
|
936
|
+
${status.checkmark} VS Code integration and shortcuts
|
|
937
|
+
${status.checkmark} Required npm dependencies
|
|
938
|
+
|
|
939
|
+
${colors.dim}This takes about 2 minutes.${colors.reset}
|
|
940
|
+
`);
|
|
941
|
+
console.log();
|
|
926
942
|
|
|
927
943
|
// Find project root
|
|
928
944
|
const projectRoot = findProjectRoot();
|
|
@@ -937,31 +953,51 @@ async function main() {
|
|
|
937
953
|
}
|
|
938
954
|
|
|
939
955
|
// Get developer initials
|
|
956
|
+
console.log();
|
|
957
|
+
sectionTitle('Developer Identification');
|
|
958
|
+
explain(`
|
|
959
|
+
${colors.bright}What:${colors.reset} Your 3-letter initials (e.g., abc, xyz)
|
|
960
|
+
${colors.bright}Why:${colors.reset} Identifies your branches and configuration
|
|
961
|
+
${colors.bright}How:${colors.reset} Creates branches like dev_abc_2025-10-31
|
|
962
|
+
`);
|
|
963
|
+
|
|
940
964
|
let initials = null;
|
|
941
965
|
while (!initials) {
|
|
942
|
-
const input = await prompt('
|
|
966
|
+
const input = await prompt('Enter your 3-letter initials');
|
|
943
967
|
initials = validateInitials(input);
|
|
944
968
|
|
|
945
969
|
if (!initials) {
|
|
946
|
-
|
|
970
|
+
errorMsg('Please enter exactly 3 letters (a-z)');
|
|
971
|
+
tip('Examples: abc, xyz, jdoe');
|
|
947
972
|
}
|
|
948
973
|
}
|
|
949
974
|
|
|
950
|
-
|
|
975
|
+
success(`Using initials: ${colors.cyan}${initials.toUpperCase()}${colors.reset}`);
|
|
976
|
+
tip(`Your branches will be named: ${colors.cyan}dev_${initials}_YYYY-MM-DD${colors.reset}`);
|
|
977
|
+
console.log();
|
|
951
978
|
|
|
952
979
|
// Confirm before proceeding
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
980
|
+
drawSection('Configuration Summary', [
|
|
981
|
+
`${status.folder} Branch prefix: ${colors.cyan}dev_${initials}_${colors.reset}`,
|
|
982
|
+
`${status.branch} Daily branches: ${colors.cyan}dev_${initials}_YYYY-MM-DD${colors.reset}`,
|
|
983
|
+
`${status.checkmark} VS Code settings and tasks`,
|
|
984
|
+
`${status.checkmark} NPM packages and scripts`,
|
|
985
|
+
`${status.checkmark} Commit message files`,
|
|
986
|
+
`${status.checkmark} House rules for AI agents`
|
|
987
|
+
]);
|
|
988
|
+
console.log();
|
|
989
|
+
|
|
990
|
+
const proceed = await confirm('Ready to configure DevOps Agent?', true);
|
|
991
|
+
|
|
992
|
+
if (!proceed) {
|
|
993
|
+
warn('Setup cancelled');
|
|
962
994
|
process.exit(0);
|
|
963
995
|
}
|
|
964
996
|
|
|
997
|
+
console.log();
|
|
998
|
+
info('Starting configuration...');
|
|
999
|
+
console.log();
|
|
1000
|
+
|
|
965
1001
|
try {
|
|
966
1002
|
// Run setup steps
|
|
967
1003
|
const packageJson = await setupNpmPackages(projectRoot);
|