@agentuity/cli 0.1.33 → 0.1.35
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 +107 -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/cloud/sandbox/exec.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.js +10 -35
- package/dist/cmd/cloud/sandbox/exec.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 +340 -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/dist/utils/installation-type.d.ts.map +1 -1
- package/dist/utils/installation-type.js +54 -16
- package/dist/utils/installation-type.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/cloud/sandbox/exec.ts +10 -41
- 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 +411 -0
- package/src/types.ts +6 -0
- package/src/utils/installation-type.ts +55 -16
- 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
|
@@ -0,0 +1,411 @@
|
|
|
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
|
+
const logsDir = getLogsDir();
|
|
114
|
+
if (!existsSync(logsDir)) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const entries = readdirSync(logsDir, { withFileTypes: true });
|
|
120
|
+
const dirs = entries
|
|
121
|
+
.filter((e) => e.isDirectory())
|
|
122
|
+
.map((e) => e.name)
|
|
123
|
+
.filter((name) => name !== currentSessionId);
|
|
124
|
+
|
|
125
|
+
// Remove all directories except the current one
|
|
126
|
+
for (const dir of dirs) {
|
|
127
|
+
const dirPath = join(logsDir, dir);
|
|
128
|
+
try {
|
|
129
|
+
rmSync(dirPath, { recursive: true, force: true });
|
|
130
|
+
} catch (err) {
|
|
131
|
+
// Ignore errors during cleanup
|
|
132
|
+
console.debug(`Failed to remove old log directory ${dir}: ${err}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} catch (err) {
|
|
136
|
+
// Ignore errors during cleanup
|
|
137
|
+
console.debug(`Failed to cleanup old logs: ${err}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Internal logger for capturing all CLI command execution details
|
|
143
|
+
*/
|
|
144
|
+
export class InternalLogger implements Logger {
|
|
145
|
+
private sessionId: string;
|
|
146
|
+
private sessionDir: string;
|
|
147
|
+
private sessionFile: string;
|
|
148
|
+
private logsFile: string;
|
|
149
|
+
private initialized = false;
|
|
150
|
+
private disabled = false;
|
|
151
|
+
|
|
152
|
+
constructor(
|
|
153
|
+
private cliVersion: string,
|
|
154
|
+
private cliName: string
|
|
155
|
+
) {
|
|
156
|
+
this.sessionId = randomUUID();
|
|
157
|
+
this.sessionDir = join(getLogsDir(), this.sessionId);
|
|
158
|
+
this.sessionFile = join(this.sessionDir, 'session.json');
|
|
159
|
+
this.logsFile = join(this.sessionDir, 'logs.jsonl');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Initialize the internal logger with command metadata
|
|
164
|
+
* @param command - The command being executed
|
|
165
|
+
* @param args - Command line arguments
|
|
166
|
+
* @param userId - Optional user ID (set later via setUserId if not provided)
|
|
167
|
+
* @param projectDir - Optional project directory from --dir flag (defaults to process.cwd())
|
|
168
|
+
*/
|
|
169
|
+
init(command: string, args: string[], userId?: string, projectDir?: string): void {
|
|
170
|
+
if (this.disabled) return;
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
// Create logs directory
|
|
174
|
+
mkdirSync(this.sessionDir, { recursive: true, mode: 0o700 });
|
|
175
|
+
|
|
176
|
+
// Clean up old logs (keep only this session)
|
|
177
|
+
cleanupOldLogs(this.sessionId);
|
|
178
|
+
|
|
179
|
+
// Determine project directory: use provided projectDir, or fall back to cwd
|
|
180
|
+
let workingDir = projectDir || process.cwd();
|
|
181
|
+
|
|
182
|
+
// Handle home directory expansion (~/path -> /home/user/path)
|
|
183
|
+
if (workingDir.startsWith('~/')) {
|
|
184
|
+
workingDir = join(homedir(), workingDir.slice(2));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Resolve to absolute path
|
|
188
|
+
workingDir = resolve(workingDir);
|
|
189
|
+
|
|
190
|
+
// Check for agentuity.json in the determined directory
|
|
191
|
+
let projectId: string | undefined;
|
|
192
|
+
let orgId: string | undefined;
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
const agentuityJsonPath = join(workingDir, 'agentuity.json');
|
|
196
|
+
if (existsSync(agentuityJsonPath)) {
|
|
197
|
+
const agentuityJson = JSON.parse(readFileSync(agentuityJsonPath, 'utf-8'));
|
|
198
|
+
projectId = agentuityJson.projectId;
|
|
199
|
+
orgId = agentuityJson.orgId;
|
|
200
|
+
}
|
|
201
|
+
} catch {
|
|
202
|
+
// Ignore errors reading agentuity.json
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Use workingDir as cwd in session metadata
|
|
206
|
+
const cwd = workingDir;
|
|
207
|
+
|
|
208
|
+
// Gather session metadata
|
|
209
|
+
const sessionMetadata: SessionMetadata = {
|
|
210
|
+
sessionId: this.sessionId,
|
|
211
|
+
command,
|
|
212
|
+
args,
|
|
213
|
+
timestamp: new Date().toISOString(),
|
|
214
|
+
cli: {
|
|
215
|
+
version: this.cliVersion,
|
|
216
|
+
name: this.cliName,
|
|
217
|
+
},
|
|
218
|
+
system: {
|
|
219
|
+
platform: platform(),
|
|
220
|
+
arch: arch(),
|
|
221
|
+
cpus: cpus().length,
|
|
222
|
+
memory: totalmem(),
|
|
223
|
+
bunPath: process.execPath || '',
|
|
224
|
+
bunVersion: Bun.version || process.version,
|
|
225
|
+
},
|
|
226
|
+
environment: maskEnvironment(),
|
|
227
|
+
cwd,
|
|
228
|
+
...(userId && { userId }),
|
|
229
|
+
...(projectId && { projectId }),
|
|
230
|
+
...(orgId && { orgId }),
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
// Write session metadata
|
|
234
|
+
writeFileSync(this.sessionFile, JSON.stringify(sessionMetadata, null, 2));
|
|
235
|
+
this.initialized = true;
|
|
236
|
+
} catch (err) {
|
|
237
|
+
// If we fail to initialize, disable the logger
|
|
238
|
+
console.debug(`Failed to initialize internal logger: ${err}`);
|
|
239
|
+
this.disabled = true;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Write a log entry to the logs file
|
|
245
|
+
*/
|
|
246
|
+
private writeLog(level: LogLevel, message: unknown, args: unknown[]): void {
|
|
247
|
+
if (!this.initialized || this.disabled) return;
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
// Format the message
|
|
251
|
+
let formattedMessage: string;
|
|
252
|
+
if (typeof message === 'string') {
|
|
253
|
+
// Simple sprintf-style formatting for %s and %d
|
|
254
|
+
formattedMessage = message;
|
|
255
|
+
let argIndex = 0;
|
|
256
|
+
formattedMessage = formattedMessage.replace(/%[sd]/g, () => {
|
|
257
|
+
if (argIndex < args.length) {
|
|
258
|
+
return String(args[argIndex++]);
|
|
259
|
+
}
|
|
260
|
+
return '';
|
|
261
|
+
});
|
|
262
|
+
// Append any remaining args
|
|
263
|
+
if (argIndex < args.length) {
|
|
264
|
+
formattedMessage += ' ' + args.slice(argIndex).map(String).join(' ');
|
|
265
|
+
}
|
|
266
|
+
} else {
|
|
267
|
+
formattedMessage = [message, ...args].map(String).join(' ');
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Strip ANSI color codes since this is going to JSON
|
|
271
|
+
if (typeof Bun !== 'undefined' && typeof Bun.stripANSI === 'function') {
|
|
272
|
+
formattedMessage = Bun.stripANSI(formattedMessage);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Extract context from args (look for objects)
|
|
276
|
+
const context: Record<string, unknown> = {};
|
|
277
|
+
for (const arg of args) {
|
|
278
|
+
if (arg && typeof arg === 'object' && !Array.isArray(arg)) {
|
|
279
|
+
Object.assign(context, arg);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const entry: LogEntry = {
|
|
284
|
+
timestamp: new Date().toISOString(),
|
|
285
|
+
level,
|
|
286
|
+
message: formattedMessage,
|
|
287
|
+
...(Object.keys(context).length > 0 && { context }),
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
appendFileSync(this.logsFile, JSON.stringify(entry) + '\n');
|
|
291
|
+
} catch (err) {
|
|
292
|
+
// If write fails, disable the logger to prevent repeated errors
|
|
293
|
+
console.debug(`Failed to write log entry: ${err}`);
|
|
294
|
+
this.disabled = true;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
trace(message: unknown, ...args: unknown[]): void {
|
|
299
|
+
this.writeLog('trace', message, args);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
debug(message: unknown, ...args: unknown[]): void {
|
|
303
|
+
this.writeLog('debug', message, args);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
info(message: unknown, ...args: unknown[]): void {
|
|
307
|
+
this.writeLog('info', message, args);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
warn(message: unknown, ...args: unknown[]): void {
|
|
311
|
+
this.writeLog('warn', message, args);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
error(message: unknown, ...args: unknown[]): void {
|
|
315
|
+
this.writeLog('error', message, args);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
fatal(message: unknown, ...args: unknown[]): never {
|
|
319
|
+
this.writeLog('error', message, args);
|
|
320
|
+
process.exit(1);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
child(_opts: Record<string, unknown>): Logger {
|
|
324
|
+
// Return the same logger - we don't need separate child loggers for internal logging
|
|
325
|
+
return this;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Get the session ID for this logger
|
|
330
|
+
*/
|
|
331
|
+
getSessionId(): string {
|
|
332
|
+
return this.sessionId;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Get the session directory path
|
|
337
|
+
*/
|
|
338
|
+
getSessionDir(): string {
|
|
339
|
+
return this.sessionDir;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Check if the logger is disabled
|
|
344
|
+
*/
|
|
345
|
+
isDisabled(): boolean {
|
|
346
|
+
return this.disabled;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Update the session with user ID after authentication
|
|
351
|
+
*/
|
|
352
|
+
setUserId(userId: string): void {
|
|
353
|
+
if (!this.initialized || this.disabled) return;
|
|
354
|
+
|
|
355
|
+
try {
|
|
356
|
+
// Read existing session data
|
|
357
|
+
const existingData = JSON.parse(readFileSync(this.sessionFile, 'utf-8'));
|
|
358
|
+
existingData.userId = userId;
|
|
359
|
+
// Write updated session data
|
|
360
|
+
writeFileSync(this.sessionFile, JSON.stringify(existingData, null, 2));
|
|
361
|
+
} catch (err) {
|
|
362
|
+
// Ignore errors - this is a best-effort update
|
|
363
|
+
console.debug(`Failed to update userId in session: ${err}`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Disable the internal logger (prevents init and logging)
|
|
369
|
+
*/
|
|
370
|
+
disable(): void {
|
|
371
|
+
this.disabled = true;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Create a new internal logger instance
|
|
377
|
+
*/
|
|
378
|
+
export function createInternalLogger(cliVersion: string, cliName: string): InternalLogger {
|
|
379
|
+
return new InternalLogger(cliVersion, cliName);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Get the latest log session directory (if any)
|
|
384
|
+
*/
|
|
385
|
+
export function getLatestLogSession(): string | null {
|
|
386
|
+
const logsDir = getLogsDir();
|
|
387
|
+
if (!existsSync(logsDir)) {
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
try {
|
|
392
|
+
const entries = readdirSync(logsDir, { withFileTypes: true });
|
|
393
|
+
const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
394
|
+
|
|
395
|
+
if (dirs.length === 0) {
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Return the first directory (should be the only one due to cleanup)
|
|
400
|
+
return join(logsDir, dirs[0]);
|
|
401
|
+
} catch {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Get the logs directory path (exported for external use)
|
|
408
|
+
*/
|
|
409
|
+
export function getLogsDirPath(): string {
|
|
410
|
+
return getLogsDir();
|
|
411
|
+
}
|
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[];
|
|
@@ -2,10 +2,26 @@
|
|
|
2
2
|
* Detects how the CLI was installed and is being run
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import fs from 'node:fs';
|
|
5
6
|
import os from 'node:os';
|
|
6
7
|
|
|
7
8
|
export type InstallationType = 'global' | 'local' | 'source';
|
|
8
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a path to its real path (following symlinks) and normalize to POSIX separators.
|
|
12
|
+
* Returns the original path if resolution fails.
|
|
13
|
+
*/
|
|
14
|
+
function resolveRealPath(path: string): string {
|
|
15
|
+
if (!path) return '';
|
|
16
|
+
try {
|
|
17
|
+
// fs.realpathSync resolves symlinks (e.g., /tmp -> /private/tmp on macOS)
|
|
18
|
+
return fs.realpathSync(path).replace(/\\/g, '/');
|
|
19
|
+
} catch {
|
|
20
|
+
// If the path doesn't exist or can't be resolved, return normalized original
|
|
21
|
+
return path.replace(/\\/g, '/');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
9
25
|
/**
|
|
10
26
|
* Determines the installation type based on how the CLI is being executed
|
|
11
27
|
*
|
|
@@ -14,34 +30,57 @@ export type InstallationType = 'global' | 'local' | 'source';
|
|
|
14
30
|
* @returns 'source' - Running from source code (development)
|
|
15
31
|
*/
|
|
16
32
|
export function getInstallationType(): InstallationType {
|
|
17
|
-
//
|
|
33
|
+
// Bun.main already returns the resolved real path, just normalize separators
|
|
18
34
|
const mainPath = Bun.main.replace(/\\/g, '/');
|
|
19
|
-
// Bun.argv[1] contains the original invocation path (before symlink resolution)
|
|
20
|
-
const invokedPath = (Bun.argv[1] ?? '').replace(/\\/g, '/');
|
|
21
35
|
|
|
22
|
-
// Get
|
|
23
|
-
//
|
|
24
|
-
const home = os.homedir() ?? process.env.HOME ?? process.env.USERPROFILE ?? '';
|
|
25
|
-
const bunInstall = (process.env.BUN_INSTALL ?? (home ? `${home}/.bun` : '')).replace(/\\/g, '/');
|
|
26
|
-
const globalBinDir = bunInstall ? `${bunInstall}/bin/` : '';
|
|
36
|
+
// Get home directory reliably and resolve symlinks
|
|
37
|
+
// On macOS, os.homedir() returns /Users/xxx which is already real
|
|
38
|
+
const home = resolveRealPath(os.homedir() ?? process.env.HOME ?? process.env.USERPROFILE ?? '');
|
|
27
39
|
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
// Get bun install directory from BUN_INSTALL or default to ~/.bun
|
|
41
|
+
// Resolve symlinks to handle cases like BUN_INSTALL=/tmp/... on macOS where /tmp -> /private/tmp
|
|
42
|
+
const bunInstallRaw = process.env.BUN_INSTALL ?? (home ? `${home}/.bun` : '');
|
|
43
|
+
const bunInstall = resolveRealPath(bunInstallRaw);
|
|
44
|
+
|
|
45
|
+
// GLOBAL DETECTION: Check if running from bun's global install location
|
|
46
|
+
// When installed via `bun add -g`, the CLI lives at ~/.bun/node_modules/@agentuity/cli/
|
|
47
|
+
// or ~/.bun/install/global/node_modules/@agentuity/cli/
|
|
48
|
+
if (bunInstall) {
|
|
49
|
+
// Check for ~/.bun/node_modules/@agentuity/cli/ (common bun global layout)
|
|
50
|
+
if (mainPath.startsWith(`${bunInstall}/node_modules/@agentuity/cli/`)) {
|
|
51
|
+
return 'global';
|
|
52
|
+
}
|
|
53
|
+
// Check for ~/.bun/install/global/node_modules/@agentuity/cli/ (alternative layout)
|
|
54
|
+
if (mainPath.startsWith(`${bunInstall}/install/global/`)) {
|
|
55
|
+
return 'global';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// GLOBAL DETECTION: Check for legacy ~/.agentuity/ installation
|
|
60
|
+
// The install.sh script may install to ~/.agentuity/node_modules/@agentuity/cli/
|
|
61
|
+
// or create a shim at ~/.agentuity/bin/agentuity
|
|
62
|
+
if (home) {
|
|
63
|
+
const agentuityDir = resolveRealPath(`${home}/.agentuity`);
|
|
64
|
+
if (mainPath.startsWith(`${agentuityDir}/`)) {
|
|
65
|
+
return 'global';
|
|
66
|
+
}
|
|
32
67
|
}
|
|
33
68
|
|
|
34
|
-
//
|
|
35
|
-
|
|
69
|
+
// GLOBAL DETECTION: Fallback check for any path containing /.bun/ before node_modules
|
|
70
|
+
// This catches edge cases where BUN_INSTALL might not match the actual path
|
|
71
|
+
if (mainPath.includes('/.bun/') && mainPath.includes('/node_modules/@agentuity/cli/')) {
|
|
36
72
|
return 'global';
|
|
37
73
|
}
|
|
38
74
|
|
|
39
|
-
//
|
|
75
|
+
// LOCAL DETECTION: Running from a project's node_modules
|
|
76
|
+
// This is when someone runs `bunx agentuity` or has it as a project dependency
|
|
77
|
+
// At this point, we've ruled out global installs, so any node_modules path is local
|
|
40
78
|
if (mainPath.includes('/node_modules/@agentuity/cli/')) {
|
|
41
79
|
return 'local';
|
|
42
80
|
}
|
|
43
81
|
|
|
44
|
-
//
|
|
82
|
+
// SOURCE DETECTION: Running from source code (development)
|
|
83
|
+
// This is when running directly from the monorepo: packages/cli/bin/cli.ts
|
|
45
84
|
return 'source';
|
|
46
85
|
}
|
|
47
86
|
|
|
@@ -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"}
|