@fractary/faber-cli 1.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.
@@ -0,0 +1,330 @@
1
+ /**
2
+ * Logs subcommand - Log management
3
+ *
4
+ * Provides capture, write, search, list, archive operations via LogManager SDK.
5
+ */
6
+ import { Command } from 'commander';
7
+ import chalk from 'chalk';
8
+ import { LogManager } from '@fractary/faber';
9
+ import { parseOptionalInteger, parseValidInteger, parsePositiveInteger } from '../../utils/validation.js';
10
+ /**
11
+ * Create the logs command tree
12
+ */
13
+ export function createLogsCommand() {
14
+ const logs = new Command('logs')
15
+ .description('Log management');
16
+ logs.addCommand(createLogsCaptureCommand());
17
+ logs.addCommand(createLogsStopCommand());
18
+ logs.addCommand(createLogsWriteCommand());
19
+ logs.addCommand(createLogsReadCommand());
20
+ logs.addCommand(createLogsSearchCommand());
21
+ logs.addCommand(createLogsListCommand());
22
+ logs.addCommand(createLogsArchiveCommand());
23
+ logs.addCommand(createLogsDeleteCommand());
24
+ return logs;
25
+ }
26
+ function createLogsCaptureCommand() {
27
+ return new Command('capture')
28
+ .description('Start session capture')
29
+ .argument('<issue_number>', 'Issue number to associate with session')
30
+ .option('--model <model>', 'Model being used')
31
+ .option('--json', 'Output as JSON')
32
+ .action(async (issueNumber, options) => {
33
+ try {
34
+ const logManager = new LogManager();
35
+ const result = await logManager.startCapture({
36
+ issueNumber: parseValidInteger(issueNumber, 'issue number'),
37
+ model: options.model,
38
+ });
39
+ if (options.json) {
40
+ console.log(JSON.stringify({ status: 'success', data: result }, null, 2));
41
+ }
42
+ else {
43
+ console.log(chalk.green(`✓ Started session capture for issue #${issueNumber}`));
44
+ console.log(chalk.gray(` Session ID: ${result.sessionId}`));
45
+ }
46
+ }
47
+ catch (error) {
48
+ handleLogsError(error, options);
49
+ }
50
+ });
51
+ }
52
+ function createLogsStopCommand() {
53
+ return new Command('stop')
54
+ .description('Stop session capture')
55
+ .option('--json', 'Output as JSON')
56
+ .action(async (options) => {
57
+ try {
58
+ const logManager = new LogManager();
59
+ const result = await logManager.stopCapture();
60
+ if (options.json) {
61
+ console.log(JSON.stringify({ status: 'success', data: result }, null, 2));
62
+ }
63
+ else {
64
+ console.log(chalk.green('✓ Stopped session capture'));
65
+ if (result?.logPath) {
66
+ console.log(chalk.gray(` Log saved to: ${result.logPath}`));
67
+ }
68
+ }
69
+ }
70
+ catch (error) {
71
+ handleLogsError(error, options);
72
+ }
73
+ });
74
+ }
75
+ function createLogsWriteCommand() {
76
+ return new Command('write')
77
+ .description('Write a typed log entry')
78
+ .requiredOption('--type <type>', 'Log type: session|build|deployment|debug|test|audit|operational')
79
+ .requiredOption('--title <title>', 'Log entry title')
80
+ .requiredOption('--content <text>', 'Log content')
81
+ .option('--issue <number>', 'Associated issue number')
82
+ .option('--json', 'Output as JSON')
83
+ .action(async (options) => {
84
+ try {
85
+ const logManager = new LogManager();
86
+ const result = logManager.writeLog({
87
+ type: options.type,
88
+ title: options.title,
89
+ content: options.content,
90
+ issueNumber: parseOptionalInteger(options.issue, 'issue number'),
91
+ });
92
+ if (options.json) {
93
+ console.log(JSON.stringify({ status: 'success', data: result }, null, 2));
94
+ }
95
+ else {
96
+ console.log(chalk.green(`✓ Created ${options.type} log: ${options.title}`));
97
+ console.log(chalk.gray(` ID: ${result.id}`));
98
+ console.log(chalk.gray(` Path: ${result.path}`));
99
+ }
100
+ }
101
+ catch (error) {
102
+ handleLogsError(error, options);
103
+ }
104
+ });
105
+ }
106
+ function createLogsReadCommand() {
107
+ return new Command('read')
108
+ .description('Read a log entry by ID or path')
109
+ .argument('<id>', 'Log ID or path')
110
+ .option('--json', 'Output as JSON')
111
+ .action(async (id, options) => {
112
+ try {
113
+ const logManager = new LogManager();
114
+ const log = logManager.readLog(id);
115
+ if (!log) {
116
+ if (options.json) {
117
+ console.error(JSON.stringify({
118
+ status: 'error',
119
+ error: { code: 'LOG_NOT_FOUND', message: `Log not found: ${id}` },
120
+ }));
121
+ }
122
+ else {
123
+ console.error(chalk.red(`Log not found: ${id}`));
124
+ }
125
+ process.exit(5);
126
+ }
127
+ if (options.json) {
128
+ console.log(JSON.stringify({ status: 'success', data: log }, null, 2));
129
+ }
130
+ else {
131
+ console.log(chalk.bold(`[${log.type}] ${log.title}`));
132
+ console.log(chalk.gray(`ID: ${log.id}`));
133
+ console.log(chalk.gray(`Date: ${log.metadata.date}`));
134
+ console.log(chalk.gray(`Path: ${log.path}`));
135
+ console.log('\n' + log.content);
136
+ }
137
+ }
138
+ catch (error) {
139
+ handleLogsError(error, options);
140
+ }
141
+ });
142
+ }
143
+ function createLogsSearchCommand() {
144
+ return new Command('search')
145
+ .description('Search logs')
146
+ .requiredOption('--query <text>', 'Search query')
147
+ .option('--type <type>', 'Filter by log type')
148
+ .option('--issue <number>', 'Filter by issue number')
149
+ .option('--regex', 'Use regex search')
150
+ .option('--json', 'Output as JSON')
151
+ .action(async (options) => {
152
+ try {
153
+ const logManager = new LogManager();
154
+ const results = logManager.searchLogs({
155
+ query: options.query,
156
+ type: options.type,
157
+ issueNumber: parseOptionalInteger(options.issue, 'issue number'),
158
+ regex: options.regex,
159
+ });
160
+ if (options.json) {
161
+ console.log(JSON.stringify({ status: 'success', data: results }, null, 2));
162
+ }
163
+ else {
164
+ if (results.length === 0) {
165
+ console.log(chalk.yellow('No logs found'));
166
+ }
167
+ else {
168
+ results.forEach((result) => {
169
+ console.log(chalk.bold(`[${result.log.type}] ${result.log.title}`));
170
+ console.log(chalk.gray(` ${result.log.path}`));
171
+ if (result.snippets && result.snippets.length > 0) {
172
+ result.snippets.forEach((snippet) => {
173
+ console.log(chalk.gray(` ...${snippet}...`));
174
+ });
175
+ }
176
+ console.log('');
177
+ });
178
+ }
179
+ }
180
+ }
181
+ catch (error) {
182
+ handleLogsError(error, options);
183
+ }
184
+ });
185
+ }
186
+ function createLogsListCommand() {
187
+ return new Command('list')
188
+ .description('List logs')
189
+ .option('--type <type>', 'Filter by log type')
190
+ .option('--status <status>', 'Filter by status (active, archived)', 'active')
191
+ .option('--issue <number>', 'Filter by issue number')
192
+ .option('--limit <n>', 'Max results', '50')
193
+ .option('--json', 'Output as JSON')
194
+ .action(async (options) => {
195
+ try {
196
+ const logManager = new LogManager();
197
+ const logs = logManager.listLogs({
198
+ type: options.type,
199
+ status: options.status,
200
+ issueNumber: parseOptionalInteger(options.issue, 'issue number'),
201
+ limit: parsePositiveInteger(options.limit, 'limit'),
202
+ });
203
+ if (options.json) {
204
+ console.log(JSON.stringify({ status: 'success', data: logs }, null, 2));
205
+ }
206
+ else {
207
+ if (logs.length === 0) {
208
+ console.log(chalk.yellow('No logs found'));
209
+ }
210
+ else {
211
+ logs.forEach((log) => {
212
+ const typeColor = getTypeColor(log.type);
213
+ console.log(`${typeColor(`[${log.type}]`)} ${log.title} (${log.metadata.date})`);
214
+ });
215
+ }
216
+ }
217
+ }
218
+ catch (error) {
219
+ handleLogsError(error, options);
220
+ }
221
+ });
222
+ }
223
+ function createLogsArchiveCommand() {
224
+ return new Command('archive')
225
+ .description('Archive old logs')
226
+ .option('--max-age <days>', 'Archive logs older than N days', '30')
227
+ .option('--compress', 'Compress archived logs')
228
+ .option('--json', 'Output as JSON')
229
+ .action(async (options) => {
230
+ try {
231
+ const logManager = new LogManager();
232
+ const result = logManager.archiveLogs({
233
+ maxAgeDays: parsePositiveInteger(options.maxAge, 'max age (days)'),
234
+ compress: options.compress,
235
+ });
236
+ if (options.json) {
237
+ console.log(JSON.stringify({ status: 'success', data: result }, null, 2));
238
+ }
239
+ else {
240
+ if (result.archived.length === 0 && result.deleted.length === 0) {
241
+ console.log(chalk.yellow('No logs to archive'));
242
+ }
243
+ else {
244
+ if (result.archived.length > 0) {
245
+ console.log(chalk.green(`✓ Archived ${result.archived.length} log(s)`));
246
+ result.archived.forEach((log) => {
247
+ console.log(chalk.gray(` - ${log}`));
248
+ });
249
+ }
250
+ if (result.deleted.length > 0) {
251
+ console.log(chalk.green(`✓ Deleted ${result.deleted.length} log(s)`));
252
+ result.deleted.forEach((log) => {
253
+ console.log(chalk.gray(` - ${log}`));
254
+ });
255
+ }
256
+ if (result.errors.length > 0) {
257
+ console.log(chalk.yellow(`\nErrors (${result.errors.length}):`));
258
+ result.errors.forEach((err) => {
259
+ console.log(chalk.red(` - ${err}`));
260
+ });
261
+ }
262
+ }
263
+ }
264
+ }
265
+ catch (error) {
266
+ handleLogsError(error, options);
267
+ }
268
+ });
269
+ }
270
+ function createLogsDeleteCommand() {
271
+ return new Command('delete')
272
+ .description('Delete a log entry')
273
+ .argument('<id>', 'Log ID or path')
274
+ .option('--json', 'Output as JSON')
275
+ .action(async (id, options) => {
276
+ try {
277
+ const logManager = new LogManager();
278
+ const deleted = logManager.deleteLog(id);
279
+ if (options.json) {
280
+ console.log(JSON.stringify({ status: 'success', data: { deleted } }, null, 2));
281
+ }
282
+ else {
283
+ if (deleted) {
284
+ console.log(chalk.green(`✓ Deleted log: ${id}`));
285
+ }
286
+ else {
287
+ console.log(chalk.yellow(`Log not found: ${id}`));
288
+ }
289
+ }
290
+ }
291
+ catch (error) {
292
+ handleLogsError(error, options);
293
+ }
294
+ });
295
+ }
296
+ // Helper functions
297
+ function getTypeColor(type) {
298
+ switch (type) {
299
+ case 'session':
300
+ return chalk.blue;
301
+ case 'build':
302
+ return chalk.cyan;
303
+ case 'deployment':
304
+ return chalk.magenta;
305
+ case 'debug':
306
+ return chalk.yellow;
307
+ case 'test':
308
+ return chalk.green;
309
+ case 'audit':
310
+ return chalk.red;
311
+ case 'operational':
312
+ return chalk.gray;
313
+ default:
314
+ return chalk.white;
315
+ }
316
+ }
317
+ // Error handling
318
+ function handleLogsError(error, options) {
319
+ const message = error instanceof Error ? error.message : String(error);
320
+ if (options.json) {
321
+ console.error(JSON.stringify({
322
+ status: 'error',
323
+ error: { code: 'LOGS_ERROR', message },
324
+ }));
325
+ }
326
+ else {
327
+ console.error(chalk.red('Error:'), message);
328
+ }
329
+ process.exit(1);
330
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Repo subcommand - Repository operations
3
+ *
4
+ * Provides branch, commit, pr, tag, and worktree operations via @fractary/faber RepoManager.
5
+ */
6
+ import { Command } from 'commander';
7
+ /**
8
+ * Create the repo command tree
9
+ */
10
+ export declare function createRepoCommand(): Command;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/repo/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAoD3C"}