@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.
- package/bin/cli.ts +110 -6
- package/dist/cmd/ai/index.d.ts.map +1 -1
- package/dist/cmd/ai/index.js +0 -6
- package/dist/cmd/ai/index.js.map +1 -1
- package/dist/cmd/ai/opencode/uninstall.js +1 -1
- package/dist/cmd/ai/opencode/uninstall.js.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.d.ts +6 -0
- package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.js +100 -33
- package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
- package/dist/cmd/cloud/apikey/create.d.ts.map +1 -1
- package/dist/cmd/cloud/apikey/create.js +1 -1
- package/dist/cmd/cloud/apikey/create.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +4 -1
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/env/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/env/delete.js +100 -45
- package/dist/cmd/cloud/env/delete.js.map +1 -1
- package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
- package/dist/cmd/cloud/env/pull.js +1 -1
- package/dist/cmd/cloud/env/pull.js.map +1 -1
- package/dist/cmd/cloud/machine/delete.js +1 -1
- package/dist/cmd/cloud/machine/delete.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +58 -10
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/index.d.ts.map +1 -1
- package/dist/cmd/index.js +1 -0
- package/dist/cmd/index.js.map +1 -1
- package/dist/cmd/support/index.d.ts +2 -0
- package/dist/cmd/support/index.d.ts.map +1 -0
- package/dist/cmd/support/index.js +11 -0
- package/dist/cmd/support/index.js.map +1 -0
- package/dist/cmd/support/logs/index.d.ts +3 -0
- package/dist/cmd/support/logs/index.d.ts.map +1 -0
- package/dist/cmd/support/logs/index.js +9 -0
- package/dist/cmd/support/logs/index.js.map +1 -0
- package/dist/cmd/support/logs/path.d.ts +3 -0
- package/dist/cmd/support/logs/path.d.ts.map +1 -0
- package/dist/cmd/support/logs/path.js +52 -0
- package/dist/cmd/support/logs/path.js.map +1 -0
- package/dist/cmd/support/logs/show.d.ts +3 -0
- package/dist/cmd/support/logs/show.d.ts.map +1 -0
- package/dist/cmd/support/logs/show.js +121 -0
- package/dist/cmd/support/logs/show.js.map +1 -0
- package/dist/cmd/support/report.d.ts +3 -0
- package/dist/cmd/support/report.d.ts.map +1 -0
- package/dist/cmd/support/report.js +299 -0
- package/dist/cmd/support/report.js.map +1 -0
- package/dist/cmd/support/system.d.ts +3 -0
- package/dist/cmd/support/system.d.ts.map +1 -0
- package/dist/cmd/support/system.js +120 -0
- package/dist/cmd/support/system.js.map +1 -0
- package/dist/cmd/version/index.d.ts.map +1 -1
- package/dist/cmd/version/index.js +1 -0
- package/dist/cmd/version/index.js.map +1 -1
- package/dist/composite-logger.d.ts +35 -0
- package/dist/composite-logger.d.ts.map +1 -0
- package/dist/composite-logger.js +78 -0
- package/dist/composite-logger.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/internal-logger.d.ts +77 -0
- package/dist/internal-logger.d.ts.map +1 -0
- package/dist/internal-logger.js +363 -0
- package/dist/internal-logger.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -6
- package/src/cmd/ai/index.ts +0 -6
- package/src/cmd/ai/opencode/uninstall.ts +1 -1
- package/src/cmd/build/vite/bun-dev-server.ts +113 -36
- package/src/cmd/cloud/apikey/create.ts +3 -1
- package/src/cmd/cloud/deploy.ts +4 -1
- package/src/cmd/cloud/env/delete.ts +100 -45
- package/src/cmd/cloud/env/pull.ts +1 -6
- package/src/cmd/cloud/machine/delete.ts +1 -1
- package/src/cmd/dev/index.ts +59 -11
- package/src/cmd/index.ts +1 -0
- package/src/cmd/support/index.ts +11 -0
- package/src/cmd/support/logs/index.ts +9 -0
- package/src/cmd/support/logs/path.ts +56 -0
- package/src/cmd/support/logs/show.ts +144 -0
- package/src/cmd/support/report.ts +364 -0
- package/src/cmd/support/system.ts +130 -0
- package/src/cmd/version/index.ts +1 -0
- package/src/composite-logger.ts +86 -0
- package/src/index.ts +7 -0
- package/src/internal-logger.ts +435 -0
- package/src/types.ts +6 -0
- package/dist/cmd/ai/skills/generate.d.ts +0 -3
- package/dist/cmd/ai/skills/generate.d.ts.map +0 -1
- package/dist/cmd/ai/skills/generate.js +0 -65
- package/dist/cmd/ai/skills/generate.js.map +0 -1
- package/dist/cmd/ai/skills/generator.d.ts +0 -4
- package/dist/cmd/ai/skills/generator.d.ts.map +0 -1
- package/dist/cmd/ai/skills/generator.js +0 -410
- package/dist/cmd/ai/skills/generator.js.map +0 -1
- package/dist/cmd/ai/skills/index.d.ts +0 -4
- package/dist/cmd/ai/skills/index.d.ts.map +0 -1
- package/dist/cmd/ai/skills/index.js +0 -21
- package/dist/cmd/ai/skills/index.js.map +0 -1
- package/dist/cmd/dev/skills.d.ts +0 -10
- package/dist/cmd/dev/skills.d.ts.map +0 -1
- package/dist/cmd/dev/skills.js +0 -57
- package/dist/cmd/dev/skills.js.map +0 -1
- package/src/cmd/ai/skills/generate.ts +0 -75
- package/src/cmd/ai/skills/generator.ts +0 -527
- package/src/cmd/ai/skills/index.ts +0 -23
- package/src/cmd/dev/skills.ts +0 -82
package/src/cmd/version/index.ts
CHANGED
|
@@ -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 +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"}
|