Skip to content

Commit be56f2f

Browse files
committed
some cleanup, debug, eslint, etc../..
1 parent 494249a commit be56f2f

File tree

8 files changed

+1012
-124
lines changed

8 files changed

+1012
-124
lines changed
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import globals from "globals";
2+
import pluginJs from "@eslint/js";
3+
import tseslint from "typescript-eslint";
4+
5+
6+
/** @type {import('eslint').Linter.Config[]} */
7+
export default [
8+
{ files: ["**/*.{js,mjs,cjs,ts}"] },
9+
{ languageOptions: { globals: globals.browser } },
10+
pluginJs.configs.recommended,
11+
...tseslint.configs.recommendedTypeChecked,
12+
{
13+
languageOptions: {
14+
parserOptions: {
15+
projectService: true,
16+
tsconfigRootDir: import.meta.dirname,
17+
},
18+
},
19+
},
20+
{
21+
rules: {
22+
'@typescript-eslint/no-floating-promises': 'error',
23+
'no-void': ['error', { allowAsStatement: true }]
24+
}
25+
}
26+
];

rplugin/node/magenta/package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
"neovim": "^5.3.0",
1111
"typescript": "^5.3.3"
1212
},
13-
"devDependencies": {},
13+
"devDependencies": {
14+
"@eslint/js": "^9.16.0",
15+
"eslint": "^9.16.0",
16+
"globals": "^15.13.0",
17+
"typescript-eslint": "^8.17.0"
18+
},
1419
"module": "src/index.js",
1520
"main": "src/index.js",
1621
"repository": "git@github.com:dlants/magenta.nvim.git",

rplugin/node/magenta/src/anthropic.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import Anthropic from '@anthropic-ai/sdk';
2+
import {Logger} from './logger'
23

34
export class AnthropicClient {
45
private client: Anthropic;
56

6-
constructor() {
7+
constructor(private logger: Logger) {
78
const apiKey = process.env.ANTHROPIC_API_KEY;
89

910
if (!apiKey) {
@@ -15,11 +16,16 @@ export class AnthropicClient {
1516
});
1617
}
1718

18-
sendMessage(messages: Array<Anthropic.MessageParam>, onText: (text: string) => void) {
19+
sendMessage(messages: Array<Anthropic.MessageParam>, onText: (text: string) => Promise<void>) {
20+
this.logger.trace(`initializing stream`)
1921
this.client.messages.stream({
2022
messages,
2123
model: 'claude-3-5-sonnet-20241022',
2224
max_tokens: 1024,
23-
}).on('text', onText);
25+
}).on('text', (text: string) => {
26+
onText(text).catch((err: Error) => {
27+
this.logger.error(err)
28+
})
29+
});
2430
}
2531
}

rplugin/node/magenta/src/chat.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { MessageParam } from '@anthropic-ai/sdk';
2-
import { Neovim, NvimPlugin } from 'neovim';
1+
import Anthropic from '@anthropic-ai/sdk';
32

43
export interface Part {
54
content: string;
@@ -17,9 +16,9 @@ export interface Message {
1716

1817
export class Chat {
1918
private messages: Message[] = [];
20-
private currentMessage: Message | null = null;
19+
private currentMessage?: Message;
2120

22-
constructor(private nvim: Neovim) {}
21+
constructor() { }
2322

2423
addMessage(role: Message['role'], content: string): Message {
2524
const message: Message = {
@@ -55,15 +54,15 @@ export class Chat {
5554
}
5655

5756
finishCurrentMessage() {
58-
this.currentMessage = null;
57+
delete this.currentMessage;
5958
}
6059

6160
getCurrentMessage(): string {
6261
if (!this.currentMessage) return '';
6362
return this.currentMessage.parts.map(part => part.content).join('');
6463
}
6564

66-
getMessages(): MessageParam[] {
65+
getMessages(): Anthropic.MessageParam[] {
6766
return this.messages.map(msg => ({
6867
role: msg.role,
6968
content: msg.parts.map(part => part.content).join('')
@@ -72,7 +71,7 @@ export class Chat {
7271

7372
clear() {
7473
this.messages = [];
75-
this.currentMessage = null;
74+
delete this.currentMessage;
7675
}
7776

7877
render(): string {

rplugin/node/magenta/src/logger.ts

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Neovim } from "neovim";
2+
3+
export type Options = {
4+
level: 'debug' | 'info' | 'trace'
5+
}
6+
7+
export class Logger {
8+
constructor(private nvim: Neovim, private options: Options = { level: 'debug' }) { }
9+
10+
log(message: string) {
11+
console.log(message);
12+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
13+
this.nvim.outWriteLine(message);
14+
}
15+
16+
debug(message: string) {
17+
if (this.options.level == 'debug' || this.options.level == 'trace') {
18+
console.log(message);
19+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
20+
this.nvim.outWriteLine(message);
21+
}
22+
}
23+
24+
trace(message: string) {
25+
if (this.options.level == 'trace') {
26+
console.log(message);
27+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
28+
this.nvim.outWriteLine(message);
29+
}
30+
}
31+
32+
error(error: Error | string) {
33+
console.error(error);
34+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
35+
this.nvim.errWriteLine(typeof error == 'string' ? error : error.toString());
36+
}
37+
}

rplugin/node/magenta/src/magenta.ts

+27-14
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,34 @@ import { AnthropicClient } from './anthropic';
22
import { Neovim, NvimPlugin } from 'neovim';
33
import { Sidebar } from './sidebar';
44
import { Chat } from './chat';
5+
import { Logger } from './logger'
56

67
class Magenta {
78
private anthropicClient: AnthropicClient;
89
private sidebar: Sidebar;
910
private chat: Chat;
11+
private logger: Logger;
1012

1113
constructor(private nvim: Neovim, plugin: NvimPlugin) {
12-
console.error('Hello from magenta')
13-
this.anthropicClient = new AnthropicClient();
14-
this.sidebar = new Sidebar(this.nvim);
15-
this.chat = new Chat(this.nvim);
14+
this.logger = new Logger(this.nvim, { level: 'trace' });
15+
this.logger.debug(`Initializing plugin`)
16+
this.anthropicClient = new AnthropicClient(this.logger);
17+
this.sidebar = new Sidebar(this.nvim, this.logger);
18+
this.chat = new Chat();
1619

1720
plugin.registerCommand('Magenta', (args: string[]) => this.command(args), {
1821
nargs: '1'
1922
})
2023
}
2124

2225
async command(args: string[]): Promise<void> {
26+
this.logger.debug(`Received command ${args[0]}`)
2327
switch (args[0]) {
24-
case 'toggle':
28+
case 'toggle': {
2529
const inputBuffer = await this.sidebar.toggle();
26-
this.nvim.lua(`vim.keymap.set('n', '<leader>x', ':Magenta send<CR>', { buffer = ${inputBuffer.id} })`);
30+
await this.nvim.lua(`vim.keymap.set('n', '<leader>x', ':Magenta send<CR>', { buffer = ${inputBuffer.id} })`);
2731
break;
32+
}
2833

2934
case 'send':
3035
await this.sendMessage();
@@ -35,33 +40,41 @@ class Magenta {
3540
break;
3641

3742
default:
38-
await this.nvim.outWrite(`Unrecognized command ${args[0]}\n`);
43+
this.logger.error(`Unrecognized command ${args[0]}\n`);
3944
}
4045
}
4146

4247
private async sendMessage() {
4348
const message = await this.sidebar.getMessage();
49+
this.logger.trace(`current message: ${message}`)
4450
if (!message) return;
4551

46-
// Add user message to chat and display
4752
this.chat.addMessage('user', message);
48-
await this.sidebar.appendToMain({
53+
this.chat.addMessage('assistant', '');
54+
await this.sidebar.appendToDisplayBuffer({
4955
text: `\nUser: ${message}\n\nAssistant: `,
5056
scrollTop: false
5157
});
5258

53-
// Stream the assistant's response
54-
this.anthropicClient.sendMessage(this.chat.getMessages(), (text) => {
59+
this.anthropicClient.sendMessage(this.chat.getMessages(), async (text) => {
60+
this.logger.trace(`stream received text ${text}`)
5561
this.chat.appendToCurrentMessage(text);
56-
this.sidebar.appendToMain({
62+
await this.sidebar.appendToDisplayBuffer({
5763
text,
5864
scrollTop: false
5965
});
6066
});
6167
}
6268
}
6369

70+
let singleton: Magenta | undefined = undefined;
71+
6472
module.exports = (plugin: NvimPlugin) => {
65-
console.log('registering plugin')
66-
new Magenta(plugin.nvim, plugin)
73+
plugin.setOptions({
74+
// dev: true,
75+
// alwaysInit: true
76+
})
77+
if (!singleton) {
78+
singleton = new Magenta(plugin.nvim, plugin)
79+
}
6780
}

0 commit comments

Comments
 (0)