Skip to content

Commit

Permalink
some cleanup, debug, eslint, etc../..
Browse files Browse the repository at this point in the history
  • Loading branch information
dlants committed Dec 7, 2024
1 parent 494249a commit be56f2f
Show file tree
Hide file tree
Showing 8 changed files with 1,012 additions and 124 deletions.
26 changes: 26 additions & 0 deletions rplugin/node/magenta/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";


/** @type {import('eslint').Linter.Config[]} */
export default [
{ files: ["**/*.{js,mjs,cjs,ts}"] },
{ languageOptions: { globals: globals.browser } },
pluginJs.configs.recommended,
...tseslint.configs.recommendedTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
},
{
rules: {
'@typescript-eslint/no-floating-promises': 'error',
'no-void': ['error', { allowAsStatement: true }]
}
}
];
7 changes: 6 additions & 1 deletion rplugin/node/magenta/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
"neovim": "^5.3.0",
"typescript": "^5.3.3"
},
"devDependencies": {},
"devDependencies": {
"@eslint/js": "^9.16.0",
"eslint": "^9.16.0",
"globals": "^15.13.0",
"typescript-eslint": "^8.17.0"
},
"module": "src/index.js",
"main": "src/index.js",
"repository": "[email protected]:dlants/magenta.nvim.git",
Expand Down
12 changes: 9 additions & 3 deletions rplugin/node/magenta/src/anthropic.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Anthropic from '@anthropic-ai/sdk';
import {Logger} from './logger'

export class AnthropicClient {
private client: Anthropic;

constructor() {
constructor(private logger: Logger) {
const apiKey = process.env.ANTHROPIC_API_KEY;

if (!apiKey) {
Expand All @@ -15,11 +16,16 @@ export class AnthropicClient {
});
}

sendMessage(messages: Array<Anthropic.MessageParam>, onText: (text: string) => void) {
sendMessage(messages: Array<Anthropic.MessageParam>, onText: (text: string) => Promise<void>) {
this.logger.trace(`initializing stream`)
this.client.messages.stream({
messages,
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
}).on('text', onText);
}).on('text', (text: string) => {
onText(text).catch((err: Error) => {
this.logger.error(err)
})
});
}
}
13 changes: 6 additions & 7 deletions rplugin/node/magenta/src/chat.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { MessageParam } from '@anthropic-ai/sdk';
import { Neovim, NvimPlugin } from 'neovim';
import Anthropic from '@anthropic-ai/sdk';

export interface Part {
content: string;
Expand All @@ -17,9 +16,9 @@ export interface Message {

export class Chat {
private messages: Message[] = [];
private currentMessage: Message | null = null;
private currentMessage?: Message;

constructor(private nvim: Neovim) {}
constructor() { }

addMessage(role: Message['role'], content: string): Message {
const message: Message = {
Expand Down Expand Up @@ -55,15 +54,15 @@ export class Chat {
}

finishCurrentMessage() {
this.currentMessage = null;
delete this.currentMessage;
}

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

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

clear() {
this.messages = [];
this.currentMessage = null;
delete this.currentMessage;
}

render(): string {
Expand Down
37 changes: 37 additions & 0 deletions rplugin/node/magenta/src/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Neovim } from "neovim";

export type Options = {
level: 'debug' | 'info' | 'trace'
}

export class Logger {
constructor(private nvim: Neovim, private options: Options = { level: 'debug' }) { }

log(message: string) {
console.log(message);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.nvim.outWriteLine(message);
}

debug(message: string) {
if (this.options.level == 'debug' || this.options.level == 'trace') {
console.log(message);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.nvim.outWriteLine(message);
}
}

trace(message: string) {
if (this.options.level == 'trace') {
console.log(message);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.nvim.outWriteLine(message);
}
}

error(error: Error | string) {
console.error(error);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.nvim.errWriteLine(typeof error == 'string' ? error : error.toString());
}
}
41 changes: 27 additions & 14 deletions rplugin/node/magenta/src/magenta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,34 @@ import { AnthropicClient } from './anthropic';
import { Neovim, NvimPlugin } from 'neovim';
import { Sidebar } from './sidebar';
import { Chat } from './chat';
import { Logger } from './logger'

class Magenta {
private anthropicClient: AnthropicClient;
private sidebar: Sidebar;
private chat: Chat;
private logger: Logger;

constructor(private nvim: Neovim, plugin: NvimPlugin) {
console.error('Hello from magenta')
this.anthropicClient = new AnthropicClient();
this.sidebar = new Sidebar(this.nvim);
this.chat = new Chat(this.nvim);
this.logger = new Logger(this.nvim, { level: 'trace' });
this.logger.debug(`Initializing plugin`)
this.anthropicClient = new AnthropicClient(this.logger);
this.sidebar = new Sidebar(this.nvim, this.logger);
this.chat = new Chat();

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

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

case 'send':
await this.sendMessage();
Expand All @@ -35,33 +40,41 @@ class Magenta {
break;

default:
await this.nvim.outWrite(`Unrecognized command ${args[0]}\n`);
this.logger.error(`Unrecognized command ${args[0]}\n`);
}
}

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

// Add user message to chat and display
this.chat.addMessage('user', message);
await this.sidebar.appendToMain({
this.chat.addMessage('assistant', '');
await this.sidebar.appendToDisplayBuffer({
text: `\nUser: ${message}\n\nAssistant: `,
scrollTop: false
});

// Stream the assistant's response
this.anthropicClient.sendMessage(this.chat.getMessages(), (text) => {
this.anthropicClient.sendMessage(this.chat.getMessages(), async (text) => {
this.logger.trace(`stream received text ${text}`)
this.chat.appendToCurrentMessage(text);
this.sidebar.appendToMain({
await this.sidebar.appendToDisplayBuffer({
text,
scrollTop: false
});
});
}
}

let singleton: Magenta | undefined = undefined;

module.exports = (plugin: NvimPlugin) => {
console.log('registering plugin')
new Magenta(plugin.nvim, plugin)
plugin.setOptions({
// dev: true,
// alwaysInit: true
})
if (!singleton) {
singleton = new Magenta(plugin.nvim, plugin)
}
}
Loading

0 comments on commit be56f2f

Please sign in to comment.