Skip to content

Commit cba629c

Browse files
authored
Linting (#79)
1 parent 4102b50 commit cba629c

8 files changed

Lines changed: 93 additions & 42 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ jobs:
2626
- name: Install dependencies
2727
run: bun install --frozen-lockfile
2828

29+
- name: Run lint
30+
run: bun run lint
31+
2932
- name: Run typecheck
3033
run: bun run typecheck
3134

biome.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,24 @@
99
"linter": {
1010
"enabled": true,
1111
"rules": {
12-
"recommended": true
12+
"recommended": true,
13+
"suspicious": {
14+
"noExplicitAny": "warn"
15+
}
1316
}
1417
},
18+
"overrides": [
19+
{
20+
"includes": ["**/*.test.ts", "**/*.test.tsx"],
21+
"linter": {
22+
"rules": {
23+
"suspicious": {
24+
"noExplicitAny": "off"
25+
}
26+
}
27+
}
28+
}
29+
],
1530
"formatter": {
1631
"enabled": true,
1732
"formatWithErrors": false,

src/cli/config-io.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,9 +297,9 @@ export function detectCurrentConfig(): DetectedConfig {
297297
// Try to detect from lite config
298298
const { config: liteConfig } = parseConfig(getLiteConfig());
299299
if (liteConfig && typeof liteConfig === 'object') {
300-
const configObj = liteConfig as Record<string, any>;
300+
const configObj = liteConfig as Record<string, unknown>;
301301
const presetName = configObj.preset as string;
302-
const presets = configObj.presets as Record<string, any>;
302+
const presets = configObj.presets as Record<string, unknown>;
303303
const agents = presets?.[presetName] as
304304
| Record<string, { model?: string }>
305305
| undefined;
@@ -313,7 +313,8 @@ export function detectCurrentConfig(): DetectedConfig {
313313
}
314314

315315
if (configObj.tmux && typeof configObj.tmux === 'object') {
316-
result.hasTmux = configObj.tmux.enabled === true;
316+
const tmuxConfig = configObj.tmux as { enabled?: boolean };
317+
result.hasTmux = tmuxConfig.enabled === true;
317318
}
318319
}
319320

src/cli/install.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ function formatConfigSummary(config: InstallConfig): string {
122122
function printAgentModels(config: InstallConfig): void {
123123
const liteConfig = generateLiteConfig(config);
124124
const presetName = (liteConfig.preset as string) || 'unknown';
125-
const presets = liteConfig.presets as Record<string, any>;
125+
const presets = liteConfig.presets as Record<string, unknown>;
126126
const agents = presets?.[presetName] as Record<
127127
string,
128128
{ model: string; skills: string[] }

src/index.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ import {
2121
lsp_rename,
2222
SkillMcpManager,
2323
} from './tools';
24+
import { parseList } from './tools/skill/builtin';
2425
import { startTmuxCheck } from './utils';
2526
import { log } from './utils/logger';
26-
import { parseList } from './tools/skill/builtin';
2727

2828
const OhMyOpenCodeLite: Plugin = async (ctx) => {
2929
const config = loadPluginConfig(ctx.directory);
@@ -103,7 +103,7 @@ const OhMyOpenCodeLite: Plugin = async (ctx) => {
103103
} else {
104104
Object.assign(opencodeConfig.agent, agents);
105105
}
106-
const configAgent = opencodeConfig.agent as Record<string, any>;
106+
const configAgent = opencodeConfig.agent as Record<string, unknown>;
107107

108108
// Merge MCP configs
109109
const configMcp = opencodeConfig.mcp as
@@ -127,7 +127,14 @@ const OhMyOpenCodeLite: Plugin = async (ctx) => {
127127
if (!configAgent[agentName]) {
128128
configAgent[agentName] = { ...agentConfig };
129129
}
130-
const agentPermission = (configAgent[agentName].permission ?? {}) as Record<string, unknown>;
130+
const agentConfigEntry = configAgent[agentName] as Record<
131+
string,
132+
unknown
133+
>;
134+
const agentPermission = (agentConfigEntry.permission ?? {}) as Record<
135+
string,
136+
unknown
137+
>;
131138

132139
// Parse mcps list with wildcard and exclusion support
133140
const allowedMcps = parseList(agentMcps, allMcpNames);
@@ -146,7 +153,7 @@ const OhMyOpenCodeLite: Plugin = async (ctx) => {
146153
}
147154

148155
// Update agent config with permissions
149-
configAgent[agentName].permission = agentPermission;
156+
agentConfigEntry.permission = agentPermission;
150157
}
151158
},
152159

src/tools/grep/grep.test.ts

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { afterAll, beforeAll, describe, expect, test } from 'bun:test';
2-
import { join } from 'node:path';
32
import { mkdir, rm, writeFile } from 'node:fs/promises';
43
import { tmpdir } from 'node:os';
4+
import { join } from 'node:path';
55
import { runRg, runRgCount } from './cli';
6-
import { formatGrepResult } from './utils';
76
import { grep } from './tools';
7+
import { formatGrepResult } from './utils';
88

99
describe('grep tool', () => {
1010
const testDir = join(tmpdir(), `grep-test-${Date.now()}`);
@@ -13,8 +13,14 @@ describe('grep tool', () => {
1313

1414
beforeAll(async () => {
1515
await mkdir(testDir, { recursive: true });
16-
await writeFile(testFile1, 'Hello world\nThis is a test file\nAnother line with match');
17-
await writeFile(testFile2, 'const x = \'Hello world\';\nconsole.log(\'test\');');
16+
await writeFile(
17+
testFile1,
18+
'Hello world\nThis is a test file\nAnother line with match',
19+
);
20+
await writeFile(
21+
testFile2,
22+
"const x = 'Hello world';\nconsole.log('test');",
23+
);
1824
});
1925

2026
afterAll(async () => {
@@ -46,9 +52,9 @@ describe('grep tool', () => {
4652
test('formats matches correctly', () => {
4753
const result = {
4854
matches: [
49-
{ file: 'file1.ts', line: 10, text: 'const foo = \'bar\'' },
55+
{ file: 'file1.ts', line: 10, text: "const foo = 'bar'" },
5056
{ file: 'file1.ts', line: 15, text: 'console.log(foo)' },
51-
{ file: 'file2.ts', line: 5, text: 'import { foo } from \'./file1\'' },
57+
{ file: 'file2.ts', line: 5, text: "import { foo } from './file1'" },
5258
],
5359
totalMatches: 3,
5460
filesSearched: 2,
@@ -57,10 +63,10 @@ describe('grep tool', () => {
5763

5864
const output = formatGrepResult(result);
5965
expect(output).toContain('file1.ts:');
60-
expect(output).toContain(' 10: const foo = \'bar\'');
66+
expect(output).toContain(" 10: const foo = 'bar'");
6167
expect(output).toContain(' 15: console.log(foo)');
6268
expect(output).toContain('file2.ts:');
63-
expect(output).toContain(' 5: import { foo } from \'./file1\'');
69+
expect(output).toContain(" 5: import { foo } from './file1'");
6470
expect(output).toContain('Found 3 matches in 2 files');
6571
});
6672

@@ -83,8 +89,16 @@ describe('grep tool', () => {
8389
});
8490

8591
expect(result.totalMatches).toBeGreaterThanOrEqual(2);
86-
expect(result.matches.some((m) => m.file.includes('test1.txt') && m.text.includes('Hello'))).toBe(true);
87-
expect(result.matches.some((m) => m.file.includes('test2.ts') && m.text.includes('Hello'))).toBe(true);
92+
expect(
93+
result.matches.some(
94+
(m) => m.file.includes('test1.txt') && m.text.includes('Hello'),
95+
),
96+
).toBe(true);
97+
expect(
98+
result.matches.some(
99+
(m) => m.file.includes('test2.ts') && m.text.includes('Hello'),
100+
),
101+
).toBe(true);
88102
});
89103

90104
test('respects file inclusion patterns', async () => {
@@ -94,8 +108,12 @@ describe('grep tool', () => {
94108
globs: ['*.txt'],
95109
});
96110

97-
expect(result.matches.some((m) => m.file.includes('test1.txt'))).toBe(true);
98-
expect(result.matches.some((m) => m.file.includes('test2.ts'))).toBe(false);
111+
expect(result.matches.some((m) => m.file.includes('test1.txt'))).toBe(
112+
true,
113+
);
114+
expect(result.matches.some((m) => m.file.includes('test2.ts'))).toBe(
115+
false,
116+
);
99117
});
100118

101119
test('handles no matches', async () => {
@@ -116,14 +134,14 @@ describe('grep tool', () => {
116134
const resultInsensitive = await runRg({
117135
pattern: 'hello',
118136
paths: [testDir],
119-
caseSensitive: false
137+
caseSensitive: false,
120138
});
121139
expect(resultInsensitive.totalMatches).toBeGreaterThan(0);
122140

123141
const resultSensitive = await runRg({
124142
pattern: 'hello', // File has "Hello"
125143
paths: [testDir],
126-
caseSensitive: true
144+
caseSensitive: true,
127145
});
128146
expect(resultSensitive.totalMatches).toBe(0);
129147
});
@@ -132,14 +150,14 @@ describe('grep tool', () => {
132150
const resultPartial = await runRg({
133151
pattern: 'Hell',
134152
paths: [testDir],
135-
wholeWord: false
153+
wholeWord: false,
136154
});
137155
expect(resultPartial.totalMatches).toBeGreaterThan(0);
138156

139157
const resultWhole = await runRg({
140158
pattern: 'Hell',
141159
paths: [testDir],
142-
wholeWord: true
160+
wholeWord: true,
143161
});
144162
expect(resultWhole.totalMatches).toBe(0);
145163
});
@@ -148,30 +166,32 @@ describe('grep tool', () => {
148166
const result = await runRg({
149167
pattern: 'Hello',
150168
paths: [testDir],
151-
maxCount: 1
169+
maxCount: 1,
152170
});
153171
// maxCount is per file
154-
expect(result.matches.filter(m => m.file.includes('test1.txt')).length).toBeLessThanOrEqual(1);
172+
expect(
173+
result.matches.filter((m) => m.file.includes('test1.txt')).length,
174+
).toBeLessThanOrEqual(1);
155175
});
156176
});
157177

158178
describe('runRgCount', () => {
159179
test('counts matches correctly', async () => {
160180
const results = await runRgCount({
161181
pattern: 'Hello',
162-
paths: [testDir]
182+
paths: [testDir],
163183
});
164184

165185
expect(results.length).toBeGreaterThan(0);
166-
const file1Result = results.find(r => r.file.includes('test1.txt'));
186+
const file1Result = results.find((r) => r.file.includes('test1.txt'));
167187
expect(file1Result).toBeDefined();
168188
expect(file1Result?.count).toBe(1);
169189
});
170190
});
171191

172192
describe('grep tool execute', () => {
173193
test('executes successfully', async () => {
174-
// @ts-ignore
194+
// @ts-expect-error
175195
const result = await grep.execute({
176196
pattern: 'Hello',
177197
path: testDir,
@@ -183,7 +203,7 @@ describe('grep tool', () => {
183203
});
184204

185205
test('handles errors gracefully', async () => {
186-
// @ts-ignore
206+
// @ts-expect-error
187207
const result = await grep.execute({
188208
pattern: 'Hello',
189209
path: '/non/existent/path/12345',
@@ -195,11 +215,11 @@ describe('grep tool', () => {
195215
});
196216

197217
test('respects include pattern in execute', async () => {
198-
// @ts-ignore
218+
// @ts-expect-error
199219
const result = await grep.execute({
200220
pattern: 'Hello',
201221
path: testDir,
202-
include: '*.txt'
222+
include: '*.txt',
203223
});
204224

205225
expect(result).toContain('test1.txt');

src/tools/lsp/client.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -241,20 +241,25 @@ export class LSPClient {
241241

242242
this.connection.onNotification(
243243
'textDocument/publishDiagnostics',
244-
(params: any) => {
244+
(params: { uri?: string; diagnostics?: Diagnostic[] }) => {
245245
if (params.uri) {
246246
this.diagnosticsStore.set(params.uri, params.diagnostics ?? []);
247247
}
248248
},
249249
);
250250

251-
this.connection.onRequest('workspace/configuration', (params: any) => {
252-
const items = params.items ?? [];
253-
return items.map((item: any) => {
254-
if (item.section === 'json') return { validate: { enable: true } };
255-
return {};
256-
});
257-
});
251+
this.connection.onRequest(
252+
'workspace/configuration',
253+
(params: { items?: unknown[] }) => {
254+
const items = params.items ?? [];
255+
return items.map((item: unknown) => {
256+
const configItem = item as { section?: string };
257+
if (configItem.section === 'json')
258+
return { validate: { enable: true } };
259+
return {};
260+
});
261+
},
262+
);
258263

259264
this.connection.onRequest('client/registerCapability', () => null);
260265
this.connection.onRequest('window/workDoneProgress/create', () => null);

src/utils/zip-extractor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export async function extractZip(
9696
const exitCode = await proc.exited;
9797

9898
if (exitCode !== 0) {
99-
const stderr = await new Response(proc.stderr as any).text();
99+
const stderr = await new Response(proc.stderr as ReadableStream).text();
100100
throw new Error(`zip extraction failed (exit ${exitCode}): ${stderr}`);
101101
}
102102
}

0 commit comments

Comments
 (0)