@agentuity/cli 0.1.34 → 0.1.36

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 (114) hide show
  1. package/bin/cli.ts +110 -6
  2. package/dist/cmd/ai/index.d.ts.map +1 -1
  3. package/dist/cmd/ai/index.js +0 -6
  4. package/dist/cmd/ai/index.js.map +1 -1
  5. package/dist/cmd/ai/opencode/uninstall.js +1 -1
  6. package/dist/cmd/ai/opencode/uninstall.js.map +1 -1
  7. package/dist/cmd/build/vite/bun-dev-server.d.ts +6 -0
  8. package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
  9. package/dist/cmd/build/vite/bun-dev-server.js +100 -33
  10. package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
  11. package/dist/cmd/cloud/apikey/create.d.ts.map +1 -1
  12. package/dist/cmd/cloud/apikey/create.js +1 -1
  13. package/dist/cmd/cloud/apikey/create.js.map +1 -1
  14. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  15. package/dist/cmd/cloud/deploy.js +4 -1
  16. package/dist/cmd/cloud/deploy.js.map +1 -1
  17. package/dist/cmd/cloud/env/delete.d.ts.map +1 -1
  18. package/dist/cmd/cloud/env/delete.js +100 -45
  19. package/dist/cmd/cloud/env/delete.js.map +1 -1
  20. package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
  21. package/dist/cmd/cloud/env/pull.js +1 -1
  22. package/dist/cmd/cloud/env/pull.js.map +1 -1
  23. package/dist/cmd/cloud/machine/delete.js +1 -1
  24. package/dist/cmd/cloud/machine/delete.js.map +1 -1
  25. package/dist/cmd/dev/index.d.ts.map +1 -1
  26. package/dist/cmd/dev/index.js +58 -10
  27. package/dist/cmd/dev/index.js.map +1 -1
  28. package/dist/cmd/index.d.ts.map +1 -1
  29. package/dist/cmd/index.js +1 -0
  30. package/dist/cmd/index.js.map +1 -1
  31. package/dist/cmd/support/index.d.ts +2 -0
  32. package/dist/cmd/support/index.d.ts.map +1 -0
  33. package/dist/cmd/support/index.js +11 -0
  34. package/dist/cmd/support/index.js.map +1 -0
  35. package/dist/cmd/support/logs/index.d.ts +3 -0
  36. package/dist/cmd/support/logs/index.d.ts.map +1 -0
  37. package/dist/cmd/support/logs/index.js +9 -0
  38. package/dist/cmd/support/logs/index.js.map +1 -0
  39. package/dist/cmd/support/logs/path.d.ts +3 -0
  40. package/dist/cmd/support/logs/path.d.ts.map +1 -0
  41. package/dist/cmd/support/logs/path.js +52 -0
  42. package/dist/cmd/support/logs/path.js.map +1 -0
  43. package/dist/cmd/support/logs/show.d.ts +3 -0
  44. package/dist/cmd/support/logs/show.d.ts.map +1 -0
  45. package/dist/cmd/support/logs/show.js +121 -0
  46. package/dist/cmd/support/logs/show.js.map +1 -0
  47. package/dist/cmd/support/report.d.ts +3 -0
  48. package/dist/cmd/support/report.d.ts.map +1 -0
  49. package/dist/cmd/support/report.js +299 -0
  50. package/dist/cmd/support/report.js.map +1 -0
  51. package/dist/cmd/support/system.d.ts +3 -0
  52. package/dist/cmd/support/system.d.ts.map +1 -0
  53. package/dist/cmd/support/system.js +120 -0
  54. package/dist/cmd/support/system.js.map +1 -0
  55. package/dist/cmd/version/index.d.ts.map +1 -1
  56. package/dist/cmd/version/index.js +1 -0
  57. package/dist/cmd/version/index.js.map +1 -1
  58. package/dist/composite-logger.d.ts +35 -0
  59. package/dist/composite-logger.d.ts.map +1 -0
  60. package/dist/composite-logger.js +78 -0
  61. package/dist/composite-logger.js.map +1 -0
  62. package/dist/index.d.ts +2 -0
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +2 -0
  65. package/dist/index.js.map +1 -1
  66. package/dist/internal-logger.d.ts +77 -0
  67. package/dist/internal-logger.d.ts.map +1 -0
  68. package/dist/internal-logger.js +363 -0
  69. package/dist/internal-logger.js.map +1 -0
  70. package/dist/types.d.ts +6 -0
  71. package/dist/types.d.ts.map +1 -1
  72. package/dist/types.js.map +1 -1
  73. package/package.json +6 -6
  74. package/src/cmd/ai/index.ts +0 -6
  75. package/src/cmd/ai/opencode/uninstall.ts +1 -1
  76. package/src/cmd/build/vite/bun-dev-server.ts +113 -36
  77. package/src/cmd/cloud/apikey/create.ts +3 -1
  78. package/src/cmd/cloud/deploy.ts +4 -1
  79. package/src/cmd/cloud/env/delete.ts +100 -45
  80. package/src/cmd/cloud/env/pull.ts +1 -6
  81. package/src/cmd/cloud/machine/delete.ts +1 -1
  82. package/src/cmd/dev/index.ts +59 -11
  83. package/src/cmd/index.ts +1 -0
  84. package/src/cmd/support/index.ts +11 -0
  85. package/src/cmd/support/logs/index.ts +9 -0
  86. package/src/cmd/support/logs/path.ts +56 -0
  87. package/src/cmd/support/logs/show.ts +144 -0
  88. package/src/cmd/support/report.ts +364 -0
  89. package/src/cmd/support/system.ts +130 -0
  90. package/src/cmd/version/index.ts +1 -0
  91. package/src/composite-logger.ts +86 -0
  92. package/src/index.ts +7 -0
  93. package/src/internal-logger.ts +435 -0
  94. package/src/types.ts +6 -0
  95. package/dist/cmd/ai/skills/generate.d.ts +0 -3
  96. package/dist/cmd/ai/skills/generate.d.ts.map +0 -1
  97. package/dist/cmd/ai/skills/generate.js +0 -65
  98. package/dist/cmd/ai/skills/generate.js.map +0 -1
  99. package/dist/cmd/ai/skills/generator.d.ts +0 -4
  100. package/dist/cmd/ai/skills/generator.d.ts.map +0 -1
  101. package/dist/cmd/ai/skills/generator.js +0 -410
  102. package/dist/cmd/ai/skills/generator.js.map +0 -1
  103. package/dist/cmd/ai/skills/index.d.ts +0 -4
  104. package/dist/cmd/ai/skills/index.d.ts.map +0 -1
  105. package/dist/cmd/ai/skills/index.js +0 -21
  106. package/dist/cmd/ai/skills/index.js.map +0 -1
  107. package/dist/cmd/dev/skills.d.ts +0 -10
  108. package/dist/cmd/dev/skills.d.ts.map +0 -1
  109. package/dist/cmd/dev/skills.js +0 -57
  110. package/dist/cmd/dev/skills.js.map +0 -1
  111. package/src/cmd/ai/skills/generate.ts +0 -75
  112. package/src/cmd/ai/skills/generator.ts +0 -527
  113. package/src/cmd/ai/skills/index.ts +0 -23
  114. package/src/cmd/dev/skills.ts +0 -82
@@ -11,6 +11,7 @@ export const command = createCommand({
11
11
  name: 'version',
12
12
  description: 'Display version information',
13
13
  skipUpgradeCheck: true,
14
+ skipInternalLogging: true,
14
15
  tags: ['read-only', 'fast'],
15
16
  examples: [
16
17
  { command: getCommand('version'), description: 'Show the CLI semantic version' },
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Composite Logger
3
+ *
4
+ * Combines multiple loggers to write to all of them simultaneously.
5
+ * Used to send logs to both the console (respecting user log level)
6
+ * and the internal trace logger (always at trace level for debugging).
7
+ */
8
+
9
+ import type { Logger } from '@agentuity/core';
10
+
11
+ /**
12
+ * A logger that delegates to multiple child loggers
13
+ */
14
+ export class CompositeLogger implements Logger {
15
+ constructor(private loggers: Logger[]) {}
16
+
17
+ trace(message: unknown, ...args: unknown[]): void {
18
+ for (const logger of this.loggers) {
19
+ logger.trace(message, ...args);
20
+ }
21
+ }
22
+
23
+ debug(message: unknown, ...args: unknown[]): void {
24
+ for (const logger of this.loggers) {
25
+ logger.debug(message, ...args);
26
+ }
27
+ }
28
+
29
+ info(message: unknown, ...args: unknown[]): void {
30
+ for (const logger of this.loggers) {
31
+ logger.info(message, ...args);
32
+ }
33
+ }
34
+
35
+ warn(message: unknown, ...args: unknown[]): void {
36
+ for (const logger of this.loggers) {
37
+ logger.warn(message, ...args);
38
+ }
39
+ }
40
+
41
+ error(message: unknown, ...args: unknown[]): void {
42
+ for (const logger of this.loggers) {
43
+ logger.error(message, ...args);
44
+ }
45
+ }
46
+
47
+ fatal(message: unknown, ...args: unknown[]): never {
48
+ // Call fatal on all loggers, but only the first one will exit
49
+ for (const logger of this.loggers) {
50
+ try {
51
+ logger.fatal(message, ...args);
52
+ } catch {
53
+ // Ignore - the logger will exit the process
54
+ }
55
+ }
56
+ // Fallback exit if none of the loggers exit
57
+ process.exit(1);
58
+ }
59
+
60
+ child(opts: Record<string, unknown>): Logger {
61
+ // Create child loggers for all delegates
62
+ const childLoggers = this.loggers.map((logger) => logger.child(opts));
63
+ return new CompositeLogger(childLoggers);
64
+ }
65
+
66
+ /**
67
+ * Add a logger to the composite
68
+ */
69
+ addLogger(logger: Logger): void {
70
+ this.loggers.push(logger);
71
+ }
72
+
73
+ /**
74
+ * Get all loggers in the composite
75
+ */
76
+ getLoggers(): Logger[] {
77
+ return [...this.loggers];
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Create a composite logger from multiple loggers
83
+ */
84
+ export function createCompositeLogger(...loggers: Logger[]): CompositeLogger {
85
+ return new CompositeLogger(loggers);
86
+ }
package/src/index.ts CHANGED
@@ -17,6 +17,13 @@ export {
17
17
  type StructuredError,
18
18
  } from './errors';
19
19
  export { wrapLogger, CLILogger } from './cli-logger';
20
+ export {
21
+ InternalLogger,
22
+ createInternalLogger,
23
+ getLatestLogSession,
24
+ getLogsDirPath,
25
+ } from './internal-logger';
26
+ export { CompositeLogger, createCompositeLogger } from './composite-logger';
20
27
  export {
21
28
  isJSONMode,
22
29
  isQuietMode,
@@ -0,0 +1,435 @@
1
+ /**
2
+ * Internal Logger for CLI command tracing
3
+ *
4
+ * This logger captures all CLI execution details for debugging purposes.
5
+ * It maintains two files per command execution:
6
+ * 1. session.json - Command metadata, environment, and system info
7
+ * 2. logs.jsonl - JSON Lines format log entries
8
+ *
9
+ * The logger automatically cleans up old logs, keeping only the most recent execution.
10
+ */
11
+
12
+ import {
13
+ appendFileSync,
14
+ existsSync,
15
+ mkdirSync,
16
+ readdirSync,
17
+ rmSync,
18
+ writeFileSync,
19
+ readFileSync,
20
+ } from 'node:fs';
21
+ import { join, resolve } from 'node:path';
22
+ import { homedir, platform, arch, cpus, totalmem } from 'node:os';
23
+ import type { Logger, LogLevel } from '@agentuity/core';
24
+ import { randomUUID } from 'node:crypto';
25
+
26
+ // Sensitive environment variable patterns to mask
27
+ const SENSITIVE_ENV_PATTERNS = [
28
+ /KEY/i, // Any env var with KEY in the name
29
+ /SECRET/i,
30
+ /TOKEN/i,
31
+ /PASSWORD/i,
32
+ /^AWS_/i,
33
+ /^GCP_/i,
34
+ /^AZURE_/i,
35
+ /^CLOUDFLARE_/i,
36
+ /^DATABASE_URL$/i,
37
+ /^DB_/i,
38
+ /^QUILL_/i, // Code signing keys
39
+ /^MACOS_/i, // macOS signing keys
40
+ /_P12$/i, // Certificate files
41
+ /BEARER/i,
42
+ /CREDENTIALS?/i,
43
+ /AUTH/i,
44
+ ];
45
+
46
+ interface SessionMetadata {
47
+ sessionId: string;
48
+ command: string;
49
+ args: string[];
50
+ timestamp: string;
51
+ cli: {
52
+ version: string;
53
+ name: string;
54
+ };
55
+ system: {
56
+ platform: string;
57
+ arch: string;
58
+ cpus: number;
59
+ memory: number;
60
+ bunPath: string;
61
+ bunVersion: string;
62
+ };
63
+ environment: Record<string, string>;
64
+ cwd: string;
65
+ userId?: string;
66
+ projectId?: string;
67
+ orgId?: string;
68
+ }
69
+
70
+ interface LogEntry {
71
+ timestamp: string;
72
+ level: LogLevel;
73
+ message: string;
74
+ context?: Record<string, unknown>;
75
+ }
76
+
77
+ /**
78
+ * Mask sensitive values in environment variables
79
+ */
80
+ function maskEnvironment(): Record<string, string> {
81
+ const masked: Record<string, string> = {};
82
+ for (const [key, value] of Object.entries(process.env)) {
83
+ if (!value) continue;
84
+
85
+ // Check if this env var matches sensitive patterns
86
+ const isSensitive = SENSITIVE_ENV_PATTERNS.some((pattern) => pattern.test(key));
87
+
88
+ if (isSensitive) {
89
+ // Show only first and last 4 chars for keys/tokens, or just mask completely
90
+ if (value.length > 12) {
91
+ masked[key] = `${value.slice(0, 4)}...${value.slice(-4)}`;
92
+ } else {
93
+ masked[key] = '***MASKED***';
94
+ }
95
+ } else {
96
+ masked[key] = value;
97
+ }
98
+ }
99
+ return masked;
100
+ }
101
+
102
+ /**
103
+ * Get the logs directory path
104
+ */
105
+ function getLogsDir(): string {
106
+ return join(homedir(), '.config', 'agentuity', 'logs');
107
+ }
108
+
109
+ /**
110
+ * Clean up old log directories, keeping only the most recent one
111
+ */
112
+ function cleanupOldLogs(currentSessionId: string): void {
113
+ // Skip cleanup when inheriting a parent's session ID to avoid
114
+ // deleting the parent's session directory (race condition).
115
+ // This applies to forked deploy processes and any subprocess
116
+ // that inherits AGENTUITY_INTERNAL_SESSION_ID.
117
+ if (process.env.AGENTUITY_INTERNAL_SESSION_ID) {
118
+ return;
119
+ }
120
+
121
+ const logsDir = getLogsDir();
122
+ if (!existsSync(logsDir)) {
123
+ return;
124
+ }
125
+
126
+ try {
127
+ const entries = readdirSync(logsDir, { withFileTypes: true });
128
+ const dirs = entries
129
+ .filter((e) => e.isDirectory())
130
+ .map((e) => e.name)
131
+ .filter((name) => name !== currentSessionId);
132
+
133
+ // Remove all directories except the current one
134
+ for (const dir of dirs) {
135
+ const dirPath = join(logsDir, dir);
136
+ try {
137
+ rmSync(dirPath, { recursive: true, force: true });
138
+ } catch (err) {
139
+ // Ignore errors during cleanup
140
+ console.debug(`Failed to remove old log directory ${dir}: ${err}`);
141
+ }
142
+ }
143
+ } catch (err) {
144
+ // Ignore errors during cleanup
145
+ console.debug(`Failed to cleanup old logs: ${err}`);
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Internal logger for capturing all CLI command execution details
151
+ */
152
+ export class InternalLogger implements Logger {
153
+ private sessionId: string;
154
+ private sessionDir: string;
155
+ private sessionFile: string;
156
+ private logsFile: string;
157
+ private initialized = false;
158
+ private disabled = false;
159
+
160
+ constructor(
161
+ private cliVersion: string,
162
+ private cliName: string
163
+ ) {
164
+ // When a parent session ID is set in the environment, use it to ensure
165
+ // all CLI invocations (parent and any subprocesses) write to the same log file.
166
+ // This prevents race conditions where child processes delete parent's logs.
167
+ const parentSessionId = process.env.AGENTUITY_INTERNAL_SESSION_ID;
168
+ if (parentSessionId) {
169
+ this.sessionId = parentSessionId;
170
+ } else {
171
+ this.sessionId = randomUUID();
172
+ }
173
+ this.sessionDir = join(getLogsDir(), this.sessionId);
174
+ this.sessionFile = join(this.sessionDir, 'session.json');
175
+ this.logsFile = join(this.sessionDir, 'logs.jsonl');
176
+ }
177
+
178
+ /**
179
+ * Initialize the internal logger with command metadata
180
+ * @param command - The command being executed
181
+ * @param args - Command line arguments
182
+ * @param userId - Optional user ID (set later via setUserId if not provided)
183
+ * @param projectDir - Optional project directory from --dir flag (defaults to process.cwd())
184
+ */
185
+ init(command: string, args: string[], userId?: string, projectDir?: string): void {
186
+ if (this.disabled) return;
187
+
188
+ try {
189
+ // Create logs directory (may already exist if we're a child process)
190
+ mkdirSync(this.sessionDir, { recursive: true, mode: 0o700 });
191
+
192
+ // Clean up old logs (keep only this session)
193
+ // This is skipped for child processes to avoid deleting parent's session
194
+ cleanupOldLogs(this.sessionId);
195
+
196
+ // When inheriting a parent's session ID, skip session.json creation
197
+ // (parent already created it) but enable logging
198
+ if (process.env.AGENTUITY_INTERNAL_SESSION_ID) {
199
+ this.initialized = true;
200
+ return;
201
+ }
202
+
203
+ // Determine project directory: use provided projectDir, or fall back to cwd
204
+ let workingDir = projectDir || process.cwd();
205
+
206
+ // Handle home directory expansion (~/path -> /home/user/path)
207
+ if (workingDir.startsWith('~/')) {
208
+ workingDir = join(homedir(), workingDir.slice(2));
209
+ }
210
+
211
+ // Resolve to absolute path
212
+ workingDir = resolve(workingDir);
213
+
214
+ // Check for agentuity.json in the determined directory
215
+ let projectId: string | undefined;
216
+ let orgId: string | undefined;
217
+
218
+ try {
219
+ const agentuityJsonPath = join(workingDir, 'agentuity.json');
220
+ if (existsSync(agentuityJsonPath)) {
221
+ const agentuityJson = JSON.parse(readFileSync(agentuityJsonPath, 'utf-8'));
222
+ projectId = agentuityJson.projectId;
223
+ orgId = agentuityJson.orgId;
224
+ }
225
+ } catch {
226
+ // Ignore errors reading agentuity.json
227
+ }
228
+
229
+ // Use workingDir as cwd in session metadata
230
+ const cwd = workingDir;
231
+
232
+ // Gather session metadata
233
+ const sessionMetadata: SessionMetadata = {
234
+ sessionId: this.sessionId,
235
+ command,
236
+ args,
237
+ timestamp: new Date().toISOString(),
238
+ cli: {
239
+ version: this.cliVersion,
240
+ name: this.cliName,
241
+ },
242
+ system: {
243
+ platform: platform(),
244
+ arch: arch(),
245
+ cpus: cpus().length,
246
+ memory: totalmem(),
247
+ bunPath: process.execPath || '',
248
+ bunVersion: Bun.version || process.version,
249
+ },
250
+ environment: maskEnvironment(),
251
+ cwd,
252
+ ...(userId && { userId }),
253
+ ...(projectId && { projectId }),
254
+ ...(orgId && { orgId }),
255
+ };
256
+
257
+ // Write session metadata
258
+ writeFileSync(this.sessionFile, JSON.stringify(sessionMetadata, null, 2));
259
+ this.initialized = true;
260
+ } catch (err) {
261
+ // If we fail to initialize, disable the logger
262
+ console.debug(`Failed to initialize internal logger: ${err}`);
263
+ this.disabled = true;
264
+ }
265
+ }
266
+
267
+ /**
268
+ * Write a log entry to the logs file
269
+ */
270
+ private writeLog(level: LogLevel, message: unknown, args: unknown[]): void {
271
+ if (!this.initialized || this.disabled) return;
272
+
273
+ try {
274
+ // Format the message
275
+ let formattedMessage: string;
276
+ if (typeof message === 'string') {
277
+ // Simple sprintf-style formatting for %s and %d
278
+ formattedMessage = message;
279
+ let argIndex = 0;
280
+ formattedMessage = formattedMessage.replace(/%[sd]/g, () => {
281
+ if (argIndex < args.length) {
282
+ return String(args[argIndex++]);
283
+ }
284
+ return '';
285
+ });
286
+ // Append any remaining args
287
+ if (argIndex < args.length) {
288
+ formattedMessage += ' ' + args.slice(argIndex).map(String).join(' ');
289
+ }
290
+ } else {
291
+ formattedMessage = [message, ...args].map(String).join(' ');
292
+ }
293
+
294
+ // Strip ANSI color codes since this is going to JSON
295
+ if (typeof Bun !== 'undefined' && typeof Bun.stripANSI === 'function') {
296
+ formattedMessage = Bun.stripANSI(formattedMessage);
297
+ }
298
+
299
+ // Extract context from args (look for objects)
300
+ const context: Record<string, unknown> = {};
301
+ for (const arg of args) {
302
+ if (arg && typeof arg === 'object' && !Array.isArray(arg)) {
303
+ Object.assign(context, arg);
304
+ }
305
+ }
306
+
307
+ const entry: LogEntry = {
308
+ timestamp: new Date().toISOString(),
309
+ level,
310
+ message: formattedMessage,
311
+ ...(Object.keys(context).length > 0 && { context }),
312
+ };
313
+
314
+ appendFileSync(this.logsFile, JSON.stringify(entry) + '\n');
315
+ } catch (err) {
316
+ // If write fails, disable the logger to prevent repeated errors
317
+ console.debug(`Failed to write log entry: ${err}`);
318
+ this.disabled = true;
319
+ }
320
+ }
321
+
322
+ trace(message: unknown, ...args: unknown[]): void {
323
+ this.writeLog('trace', message, args);
324
+ }
325
+
326
+ debug(message: unknown, ...args: unknown[]): void {
327
+ this.writeLog('debug', message, args);
328
+ }
329
+
330
+ info(message: unknown, ...args: unknown[]): void {
331
+ this.writeLog('info', message, args);
332
+ }
333
+
334
+ warn(message: unknown, ...args: unknown[]): void {
335
+ this.writeLog('warn', message, args);
336
+ }
337
+
338
+ error(message: unknown, ...args: unknown[]): void {
339
+ this.writeLog('error', message, args);
340
+ }
341
+
342
+ fatal(message: unknown, ...args: unknown[]): never {
343
+ this.writeLog('error', message, args);
344
+ process.exit(1);
345
+ }
346
+
347
+ child(_opts: Record<string, unknown>): Logger {
348
+ // Return the same logger - we don't need separate child loggers for internal logging
349
+ return this;
350
+ }
351
+
352
+ /**
353
+ * Get the session ID for this logger
354
+ */
355
+ getSessionId(): string {
356
+ return this.sessionId;
357
+ }
358
+
359
+ /**
360
+ * Get the session directory path
361
+ */
362
+ getSessionDir(): string {
363
+ return this.sessionDir;
364
+ }
365
+
366
+ /**
367
+ * Check if the logger is disabled
368
+ */
369
+ isDisabled(): boolean {
370
+ return this.disabled;
371
+ }
372
+
373
+ /**
374
+ * Update the session with user ID after authentication
375
+ */
376
+ setUserId(userId: string): void {
377
+ if (!this.initialized || this.disabled) return;
378
+
379
+ try {
380
+ // Read existing session data
381
+ const existingData = JSON.parse(readFileSync(this.sessionFile, 'utf-8'));
382
+ existingData.userId = userId;
383
+ // Write updated session data
384
+ writeFileSync(this.sessionFile, JSON.stringify(existingData, null, 2));
385
+ } catch (err) {
386
+ // Ignore errors - this is a best-effort update
387
+ console.debug(`Failed to update userId in session: ${err}`);
388
+ }
389
+ }
390
+
391
+ /**
392
+ * Disable the internal logger (prevents init and logging)
393
+ */
394
+ disable(): void {
395
+ this.disabled = true;
396
+ }
397
+ }
398
+
399
+ /**
400
+ * Create a new internal logger instance
401
+ */
402
+ export function createInternalLogger(cliVersion: string, cliName: string): InternalLogger {
403
+ return new InternalLogger(cliVersion, cliName);
404
+ }
405
+
406
+ /**
407
+ * Get the latest log session directory (if any)
408
+ */
409
+ export function getLatestLogSession(): string | null {
410
+ const logsDir = getLogsDir();
411
+ if (!existsSync(logsDir)) {
412
+ return null;
413
+ }
414
+
415
+ try {
416
+ const entries = readdirSync(logsDir, { withFileTypes: true });
417
+ const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
418
+
419
+ if (dirs.length === 0) {
420
+ return null;
421
+ }
422
+
423
+ // Return the first directory (should be the only one due to cleanup)
424
+ return join(logsDir, dirs[0]);
425
+ } catch {
426
+ return null;
427
+ }
428
+ }
429
+
430
+ /**
431
+ * Get the logs directory path (exported for external use)
432
+ */
433
+ export function getLogsDirPath(): string {
434
+ return getLogsDir();
435
+ }
package/src/types.ts CHANGED
@@ -457,6 +457,7 @@ export function createSubcommand<
457
457
  banner?: true;
458
458
  aliases?: string[];
459
459
  toplevel?: boolean;
460
+ skipInternalLogging?: boolean;
460
461
  requires?: R;
461
462
  optional?: O;
462
463
  examples?: CommandExample[];
@@ -503,6 +504,7 @@ export function createCommand<
503
504
  executable?: boolean;
504
505
  skipUpgradeCheck?: boolean;
505
506
  passThroughArgs?: boolean;
507
+ skipInternalLogging?: boolean;
506
508
  requires?: R;
507
509
  optional?: O;
508
510
  examples?: CommandExample[];
@@ -545,6 +547,7 @@ type CommandDefBase =
545
547
  skipUpgradeCheck?: boolean;
546
548
  passThroughArgs?: boolean;
547
549
  skipSkill?: boolean;
550
+ skipInternalLogging?: boolean;
548
551
  examples?: CommandExample[];
549
552
  idempotent?: boolean;
550
553
  prerequisites?: string[];
@@ -564,6 +567,7 @@ type CommandDefBase =
564
567
  skipUpgradeCheck?: boolean;
565
568
  passThroughArgs?: boolean;
566
569
  skipSkill?: boolean;
570
+ skipInternalLogging?: boolean;
567
571
  examples?: CommandExample[];
568
572
  idempotent?: boolean;
569
573
  prerequisites?: string[];
@@ -583,6 +587,7 @@ type SubcommandDefBase =
583
587
  toplevel?: boolean;
584
588
  banner?: boolean;
585
589
  skipSkill?: boolean;
590
+ skipInternalLogging?: boolean;
586
591
  examples?: CommandExample[];
587
592
  idempotent?: boolean;
588
593
  prerequisites?: string[];
@@ -600,6 +605,7 @@ type SubcommandDefBase =
600
605
  toplevel?: boolean;
601
606
  banner?: boolean;
602
607
  skipSkill?: boolean;
608
+ skipInternalLogging?: boolean;
603
609
  examples?: CommandExample[];
604
610
  idempotent?: boolean;
605
611
  prerequisites?: string[];
@@ -1,3 +0,0 @@
1
- export declare const generateSubcommand: import("../../..").SubcommandDefinition;
2
- export default generateSubcommand;
3
- //# sourceMappingURL=generate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../../src/cmd/ai/skills/generate.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,kBAAkB,yCA0D7B,CAAC;AAEH,eAAe,kBAAkB,CAAC"}
@@ -1,65 +0,0 @@
1
- import { z } from 'zod';
2
- import { createSubcommand } from '../../../types';
3
- import { getCommand } from '../../../command-prefix';
4
- import { ErrorCode } from '../../../errors';
5
- import * as tui from '../../../tui';
6
- import * as path from 'node:path';
7
- import { generateSkills, collectSkillsForPreview } from './generator';
8
- const OptionsSchema = z.object({
9
- output: z.string().describe('Output directory for generated skills'),
10
- includeHidden: z.boolean().default(false).describe('Include hidden commands'),
11
- });
12
- export const generateSubcommand = createSubcommand({
13
- name: 'generate',
14
- description: 'Generate Agent Skills from CLI schema',
15
- tags: ['fast'],
16
- idempotent: true,
17
- examples: [
18
- {
19
- command: getCommand('ai skills generate --output ./skills'),
20
- description: 'Generate skills to a directory',
21
- },
22
- {
23
- command: getCommand('--dry-run ai skills generate --output ./skills'),
24
- description: 'Preview without writing files',
25
- },
26
- {
27
- command: getCommand('ai skills generate --output ./skills --include-hidden'),
28
- description: 'Include hidden commands',
29
- },
30
- ],
31
- schema: {
32
- options: OptionsSchema,
33
- },
34
- async handler(ctx) {
35
- const { logger, opts, options } = ctx;
36
- const { output, includeHidden } = opts;
37
- const dryRun = options.dryRun === true;
38
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
- const schema = global.__CLI_SCHEMA__;
40
- if (!schema) {
41
- return logger.fatal('Schema not available. This is a CLI bug.', ErrorCode.INTERNAL_ERROR);
42
- }
43
- const baseDir = path.join(output, 'skills', 'agentuity', 'cli');
44
- if (dryRun) {
45
- const skills = collectSkillsForPreview(schema, output, includeHidden);
46
- if (skills.length === 0) {
47
- logger.warn('No skills to generate');
48
- return;
49
- }
50
- tui.info(`Would generate ${skills.length} skills:`);
51
- for (const skillPath of skills) {
52
- console.log(tui.muted(` ${skillPath}`));
53
- }
54
- return;
55
- }
56
- const created = await generateSkills(schema, output, includeHidden);
57
- if (created === 0) {
58
- logger.warn('No skills to generate');
59
- return;
60
- }
61
- tui.success(`Generated ${created} skills to ${baseDir}`);
62
- },
63
- });
64
- export default generateSubcommand;
65
- //# sourceMappingURL=generate.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../../src/cmd/ai/skills/generate.ts"],"names":[],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- import type { CLISchema } from '../../../schema-generator';
2
- export declare function collectSkillsForPreview(schema: CLISchema, outputDir: string, includeHidden: boolean): string[];
3
- export declare function generateSkills(schema: CLISchema, outputDir: string, includeHidden: boolean): Promise<number>;
4
- //# sourceMappingURL=generator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../../../src/cmd/ai/skills/generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,SAAS,EAIT,MAAM,2BAA2B,CAAC;AAienC,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,OAAO,GACpB,MAAM,EAAE,CAGV;AAED,wBAAsB,cAAc,CACnC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,OAAO,GACpB,OAAO,CAAC,MAAM,CAAC,CA2BjB"}