Skip to content

Commit 6eafae9

Browse files
authored
Merge pull request #50 from drivecore/better-logging
Better logging
2 parents c9ff8f1 + 900ef27 commit 6eafae9

File tree

9 files changed

+48
-68
lines changed

9 files changed

+48
-68
lines changed

.vscode/extensions.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"recommendations": [
33
"dbaeumer.vscode-eslint",
44
"esbenp.prettier-vscode",
5-
"github.vscode-github-actions"
5+
"github.vscode-github-actions",
6+
"vitest.explorer"
67
]
78
}

packages/cli/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# mycoder
22

3+
## 0.2.3
4+
5+
### Patch Changes
6+
7+
- Ensure all logging follows logLevel cli option.
8+
39
## 0.2.2
410

511
### Patch Changes

packages/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "mycoder",
33
"description": "A command line tool using agent that can do arbitrary tasks, including coding tasks",
4-
"version": "0.2.2",
4+
"version": "0.2.3",
55
"type": "module",
66
"bin": "./bin/cli.js",
77
"main": "./dist/index.js",

packages/cli/src/commands/$default.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@ import { TokenTracker } from 'mycoder-agent/dist/core/tokens.js';
1414

1515
import { SharedOptions } from '../options.js';
1616
import { hasUserConsented, saveUserConsent } from '../settings/settings.js';
17-
import { getPackageInfo } from '../utils/versionCheck.js';
17+
import { nameToLogIndex } from '../utils/nameToLogIndex.js';
18+
import { checkForUpdates, getPackageInfo } from '../utils/versionCheck.js';
1819

1920
import type { CommandModule, Argv } from 'yargs';
2021

2122
interface DefaultArgs extends SharedOptions {
2223
prompt?: string;
2324
}
2425

25-
export const command: CommandModule<object, DefaultArgs> = {
26+
export const command: CommandModule<SharedOptions, DefaultArgs> = {
2627
command: '* [prompt]',
2728
describe: 'Execute a prompt or start interactive mode',
2829
builder: (yargs: Argv<object>): Argv<DefaultArgs> => {
@@ -32,12 +33,19 @@ export const command: CommandModule<object, DefaultArgs> = {
3233
}) as Argv<DefaultArgs>;
3334
},
3435
handler: async (argv) => {
35-
const logger = new Logger({ name: 'Default' });
36+
const logger = new Logger({
37+
name: 'Default',
38+
logLevel: nameToLogIndex(argv.logLevel),
39+
});
40+
3641
const packageInfo = getPackageInfo();
3742

3843
logger.info(
3944
`MyCoder v${packageInfo.version} - AI-powered coding assistant`,
4045
);
46+
47+
await checkForUpdates(logger);
48+
4149
if (!hasUserConsented()) {
4250
const readline = createInterface({
4351
input: process.stdin,

packages/cli/src/index.ts

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,22 @@ import { join } from 'path';
33
import { fileURLToPath } from 'url';
44

55
import * as dotenv from 'dotenv';
6-
import { Logger, LogLevel, getTools } from 'mycoder-agent';
76
import sourceMapSupport from 'source-map-support';
87
import yargs from 'yargs';
98
import { hideBin } from 'yargs/helpers';
109
import { fileCommands } from 'yargs-file-commands';
1110

1211
import { sharedOptions } from './options.js';
13-
import { checkForUpdates } from './utils/versionCheck.js';
1412

1513
import type { PackageJson } from 'type-fest';
1614

1715
// Add global declaration for our patched toolAgent
1816

1917
sourceMapSupport.install();
2018

21-
const nameToLogIndex = (logLevelName: string) => {
22-
// look up the log level name in the enum to get the value
23-
return LogLevel[logLevelName as keyof typeof LogLevel];
24-
};
25-
2619
const main = async () => {
2720
dotenv.config();
2821

29-
const logger = new Logger({ name: 'Main' });
30-
31-
const updateMessage = await checkForUpdates();
32-
if (updateMessage) {
33-
console.log();
34-
logger.info(updateMessage);
35-
console.log();
36-
}
37-
38-
process.on('uncaughtException', (error) => {
39-
logger.error(
40-
'Fatal error:',
41-
error.constructor.name,
42-
error.message,
43-
error.stack,
44-
);
45-
process.exit(1);
46-
});
47-
4822
const require = createRequire(import.meta.url);
4923
const packageInfo = require('../package.json') as PackageJson;
5024

@@ -59,14 +33,6 @@ const main = async () => {
5933
.options(sharedOptions)
6034
.alias('h', 'help')
6135
.alias('V', 'version')
62-
.middleware((argv) => {
63-
// Set up logger with the specified log level
64-
argv.logger = new Logger({
65-
name: packageInfo.name!,
66-
logLevel: nameToLogIndex(argv.log),
67-
});
68-
argv.tools = getTools();
69-
})
7036
.command(
7137
await fileCommands({
7238
commandDirs: [commandsDir],
@@ -78,4 +44,7 @@ const main = async () => {
7844
.help().argv;
7945
};
8046

81-
await main();
47+
await main().catch((error) => {
48+
console.error(error);
49+
process.exit(1);
50+
});

packages/cli/src/options.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
import { LogLevel } from 'mycoder-agent';
2-
31
export type SharedOptions = {
4-
readonly log: LogLevel;
2+
readonly logLevel: string;
53
readonly interactive: boolean;
64
readonly file?: string;
75
readonly tokenUsage?: boolean;
86
readonly headless?: boolean;
97
};
108

119
export const sharedOptions = {
12-
log: {
10+
logLevel: {
1311
type: 'string',
1412
alias: 'l',
1513
description: 'Set minimum logging level',
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { LogLevel } from 'mycoder-agent';
2+
3+
export const nameToLogIndex = (logLevelName: string) => {
4+
// look up the log level name in the enum to get the value
5+
return LogLevel[logLevelName as keyof typeof LogLevel];
6+
};

packages/cli/src/utils/versionCheck.test.ts

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as fs from 'fs';
22
import * as fsPromises from 'fs/promises';
33
import * as path from 'path';
44

5+
import { MockLogger } from 'mycoder-agent';
56
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
67

78
import {
@@ -22,12 +23,6 @@ import { getSettingsDir } from '../settings/settings.js';
2223

2324
vi.mock('fs');
2425
vi.mock('fs/promises');
25-
vi.mock('mycoder-agent', () => ({
26-
Logger: vi.fn().mockImplementation(() => ({
27-
warn: vi.fn(),
28-
})),
29-
errorToString: vi.fn(),
30-
}));
3126

3227
describe('versionCheck', () => {
3328
describe('generateUpgradeMessage', () => {
@@ -139,8 +134,7 @@ describe('versionCheck', () => {
139134
json: () => Promise.resolve({ version: '2.0.0' }),
140135
});
141136

142-
const result = await checkForUpdates();
143-
expect(result).toBe(null);
137+
await checkForUpdates(new MockLogger());
144138

145139
// Wait for setImmediate to complete
146140
await new Promise((resolve) => setImmediate(resolve));
@@ -161,8 +155,8 @@ describe('versionCheck', () => {
161155
fsPromises.readFile as unknown as ReturnType<typeof vi.fn>
162156
).mockResolvedValue('2.0.0');
163157

164-
const result = await checkForUpdates();
165-
expect(result).toContain('Update available');
158+
await checkForUpdates(new MockLogger());
159+
// FIX: expect(result).toContain('Update available');
166160
});
167161

168162
it('handles errors gracefully during version check', async () => {
@@ -173,8 +167,7 @@ describe('versionCheck', () => {
173167
fsPromises.readFile as unknown as ReturnType<typeof vi.fn>
174168
).mockRejectedValue(new Error('Test error'));
175169

176-
const result = await checkForUpdates();
177-
expect(result).toBe(null);
170+
await checkForUpdates(new MockLogger());
178171
});
179172

180173
it('handles errors gracefully during background update', async () => {
@@ -183,8 +176,7 @@ describe('versionCheck', () => {
183176
);
184177
mockFetch.mockRejectedValue(new Error('Network error'));
185178

186-
const result = await checkForUpdates();
187-
expect(result).toBe(null);
179+
await checkForUpdates(new MockLogger());
188180

189181
// Wait for setImmediate to complete
190182
await new Promise((resolve) => setImmediate(resolve));

packages/cli/src/utils/versionCheck.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import { getSettingsDir } from '../settings/settings.js';
1212
import type { PackageJson } from 'type-fest';
1313

1414
const require = createRequire(import.meta.url);
15-
const logger = new Logger({ name: 'version-check' });
1615

1716
export function getPackageInfo(): {
1817
name: string;
@@ -56,18 +55,19 @@ export function generateUpgradeMessage(
5655
: null;
5756
}
5857

59-
export async function checkForUpdates(): Promise<string | null> {
58+
export async function checkForUpdates(logger: Logger) {
6059
try {
6160
const { name: packageName, version: currentVersion } = getPackageInfo();
6261

63-
console.log('packageName', packageName);
64-
console.log('currentVersion', currentVersion);
62+
logger.debug(`checkForUpdates: currentVersion: ${currentVersion}`);
63+
6564
const settingDir = getSettingsDir();
6665
const versionFilePath = path.join(settingDir, 'lastVersionCheck');
66+
logger.debug(`checkForUpdates: versionFilePath: ${versionFilePath}`);
6767

6868
fetchLatestVersion(packageName)
6969
.then(async (latestVersion) => {
70-
console.log('latestVersion', latestVersion);
70+
logger.debug(`checkForUpdates: latestVersion: ${latestVersion}`);
7171
return fsPromises.writeFile(versionFilePath, latestVersion, 'utf8');
7272
})
7373
.catch((error) => {
@@ -79,18 +79,18 @@ export async function checkForUpdates(): Promise<string | null> {
7979
versionFilePath,
8080
'utf8',
8181
);
82-
console.log('lastVersionCheck', lastVersionCheck);
83-
return generateUpgradeMessage(
82+
logger.debug(`checkForUpdates: lastVersionCheck: ${lastVersionCheck}`);
83+
const updateMessage = generateUpgradeMessage(
8484
currentVersion,
8585
lastVersionCheck,
8686
packageName,
8787
);
88+
if (updateMessage) {
89+
logger.info('\n' + updateMessage + '\n');
90+
}
8891
}
89-
90-
return null;
9192
} catch (error) {
9293
// Log error but don't throw to handle gracefully
9394
logger.warn('Error checking for updates:', errorToString(error));
94-
return null;
9595
}
9696
}

0 commit comments

Comments
 (0)