Skip to content

Commit

Permalink
Extension prompt runner and Ailly: Edit
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidSouther committed May 4, 2024
1 parent 4f02650 commit 6dc0c81
Show file tree
Hide file tree
Showing 14 changed files with 359 additions and 128 deletions.
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
"--profile-temp",
"--extensionDevelopmentPath=${workspaceFolder}/extension"
],
"outFiles": ["${workspaceFolder}/extension/out/**/*.js"],
"preLaunchTask": "${defaultBuildTask}"
"outFiles": ["${workspaceFolder}/extension/out/**/*.js"]
// "preLaunchTask": "${defaultBuildTask}"
},
{
"name": "Ailly Extension Tests",
Expand Down
14 changes: 9 additions & 5 deletions core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const content = {
};

export const Ailly = aillyModule;
export const version = getVersion(import.meta.url);
export const version = getVersion(import.meta?.url ?? "file://" + __filename);

// TODO move this to jiffies
import { execSync } from "node:child_process";
Expand All @@ -27,10 +27,14 @@ import { normalize, join } from "node:path";
import { readFileSync } from "node:fs";

export function getVersion(root: /*ImportMeta.URL*/ string) {
const cwd = normalize(join(fileURLToPath(root), ".."));
const packageJson = join(cwd, "./package.json");
const pkg = JSON.parse(readFileSync(packageJson, { encoding: "utf8" }));
return pkg.version;
try {
const cwd = normalize(join(fileURLToPath(root), ".."));
const packageJson = join(cwd, "./package.json");
const pkg = JSON.parse(readFileSync(packageJson, { encoding: "utf8" }));
return pkg.version;
} catch (_) {
return "unknown";
}
}

export function getRevision(root: /* ImportMeta.URL */ string) {
Expand Down
4 changes: 2 additions & 2 deletions core/src/actions/prompt_thread.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,12 +192,12 @@ async function generateOne(
messages: meta?.messages
?.map((m) => ({
role: m.role,
content: m.content.replaceAll("\n", " ").substring(0, 150) + "...",
content: m.content.replace(/\n/g, " ").substring(0, 150) + "...",
// tokens: m.tokens,
}))
// Skip the last `assistant` message
.filter((m, i, a) => !(m.role == "assistant" && i === a.length - 1))
.map(({ role, content }) => `${role}: ${content.replaceAll("\n", "\\n")}`)
.map(({ role, content }) => `${role}: ${content.replace(/\n/g, "\\n")}`)
.join("\n\t"),
});
const generated = await engine.generate(c, settings);
Expand Down
1 change: 1 addition & 0 deletions core/src/engine/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface Engine {
): Promise<{ debug: D; message: string }>;
vector(s: string, parameters: ContentMeta): Promise<number[]>;
view?(): Promise<View>;
models?(): string[];
}

export interface Message {
Expand Down
9 changes: 5 additions & 4 deletions core/src/engine/mistral/mistral.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ export async function generate(
}

let cwd = dirname(
import.meta.url
.replace(/^file:/, "")
.replace("ailly/core/dist", "ailly/core/src")
(import.meta?.url.replace(/^file:/, "") ?? __filename).replace(
"ailly/core/dist",
"ailly/core/src"
)
);
let command = join(cwd, normalize(".venv/bin/python3"));
let args = [join(cwd, "mistral.py"), prompt];
Expand All @@ -35,7 +36,7 @@ export async function generate(
child.on("disconnect", done);

const error = (cause: unknown) =>
reject(new Error("child_process had a problem", { cause }));
reject(new Error("child_process had a problem" /*, { cause }*/));
child.on("error", error);
});
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/engine/noop.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { getLogger } from "@davidsouther/jiffies/lib/esm/log.js";
import { Content } from "../content/content.js";
import { LOGGER as ROOT_LOGGER } from "../util.js";
import type { PipelineSettings } from "../ailly";
import type { Message } from "./index";
import type { PipelineSettings } from "../ailly.js";
import type { Message } from "./index.js";

const LOGGER = getLogger("@ailly/core:noop");

Expand Down
8 changes: 4 additions & 4 deletions core/src/engine/openai.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { OpenAI, toFile } from "openai";
import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js";
import type { Content } from "../content/content";
import type { PipelineSettings } from "../ailly";
import type { Message, Summary } from "./index";
import type { Content } from "../content/content.js";
import type { PipelineSettings } from "../ailly.js";
import type { Message, Summary } from "./index.js";
import { LOGGER, isDefined } from "../util.js";
import { encode } from "../encoding.js";

Expand Down Expand Up @@ -85,7 +85,7 @@ async function callOpenAiWithRateLimit(
} catch (e: any) {
LOGGER.warn("Error calling openai", e.message);
if (retry == 0) {
throw new Error("Failed 3 times to call openai", { cause: e });
throw new Error("Failed 3 times to call openai" /*, { cause: e }*/);
}
if (e.error.code == "rate_limit_exceeded") {
await new Promise((resolve) => {
Expand Down
41 changes: 40 additions & 1 deletion extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
{
"command": "ailly.generate",
"title": "Ailly: Generate"
},
{
"command": "ailly.edit",
"title": "Ailly: Edit"
}
],
"menus": {
Expand All @@ -36,6 +40,40 @@
{
"title": "Ailly",
"properties": {
"ailly.engine": {
"type": "string",
"default": "bedrock",
"enum": [
"bedrock",
"openai"
],
"description": "The Ailly engine to use when making LLM calls."
},
"ailly.model": {
"type": [
"string",
"null"
],
"default": "haiku",
"description": "The default model to use when making LLM calls."
},
"ailly.log-level": {
"type": "string",
"default": "info",
"enum": [
"debug",
"info",
"warn",
"error",
"silent"
],
"description": "The log level to record Ailly details."
},
"ailly.log-pretty": {
"type": "boolean",
"default": false,
"description": "JSON (false) or pretty print (true) logs."
},
"ailly.openai-api-key": {
"type": [
"string",
Expand All @@ -50,11 +88,12 @@
},
"scripts": {
"vscode:prepublish": "npm run esbuild-base -- --minify",
"esbuild-base": "esbuild ./src/extension.cts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node",
"esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node",
"esbuild": "npm run esbuild-base -- --sourcemap",
"esbuild-watch": "npm run esbuild-base -- --sourcemap --watch",
"test-compile": "tsc -p ./",
"compile": "tsc -p ./",
"build": "esbuild",
"watch": "tsc -watch -p ./",
"pretest": "npm run compile && npm run lint",
"lint": "eslint src --ext ts",
Expand Down
57 changes: 0 additions & 57 deletions extension/src/extension.cts

This file was deleted.

118 changes: 118 additions & 0 deletions extension/src/extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from "vscode";
import { basename } from "path";
import { generate } from "./generate.js";
import { LOGGER, resetLogger } from "./settings";

// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
export function activate(context: vscode.ExtensionContext) {
resetLogger();
// Use the console to output diagnostic information (console.log) and errors (console.error)
// This line of code will only be executed once when your extension is activated
LOGGER.info('Congratulations, your extension "ailly" is now active!');

// The command has been defined in the package.json file
// Now provide the implementation of the command with registerCommand
// The commandId parameter must match the command field in package.json
context.subscriptions.push(
vscode.commands.registerCommand(
"ailly.generate",
async (uri?: vscode.Uri, ..._args) => {
try {
let path: string;
if (uri) {
path = uri.path;
} else {
path = vscode.window.activeTextEditor?.document.uri.fsPath ?? "";
if (!path) {
return;
}
}

try {
vscode.window.showInformationMessage(
`Ailly generating ${basename(path)}`
);
await generate(path);
vscode.window.showInformationMessage(
`Ailly generated ${basename(path)}`
);
} catch (err) {
vscode.window.showWarningMessage(
`Ailly failed to generate ${basename(path)}: ${err}`
);

LOGGER.error("Failed to generate", { err });
}
} catch (err) {
LOGGER.error("Unknown failure", { err });
}
}
)
);

context.subscriptions.push(
vscode.commands.registerCommand(
"ailly.edit",
async (uri?: vscode.Uri, ..._args) => {
if (!vscode.window.activeTextEditor) return;
try {
let path: string;
if (uri) {
path = uri.path;
} else {
path = vscode.window.activeTextEditor.document.uri.fsPath ?? "";
if (!path) {
return;
}
}

const prompt = await vscode.window.showInputBox({
title: "Prompt",
prompt: "What edits should Ailly make?",
});

if (!prompt) return;

const start = vscode.window.activeTextEditor.selection.start.line;
const end = vscode.window.activeTextEditor.selection.end.line;

try {
vscode.window.showInformationMessage(
`Ailly generating ${basename(path)}`
);
await generate(path, { prompt, start, end });
vscode.window.showInformationMessage(
`Ailly edited ${basename(path)}`
);
} catch (err) {
vscode.window.showWarningMessage(
`Ailly failed to generate ${basename(path)}: ${err}`
);

LOGGER.error("Error doing edit", { err });
}
} catch (err) {
LOGGER.error("Unknown error editing", { err });
}
}
)
);

context.subscriptions.push(
vscode.commands.registerCommand("ailly.set-engine", async () => {
vscode.window.showInformationMessage(`Ailly setting engine`);
})
);

context.subscriptions.push(
vscode.commands.registerCommand("ailly.set-model", async () => {
vscode.window.showInformationMessage(`Ailly setting model`);
})
);
}

// This method is called when your extension is deactivated
export function deactivate() {}
4 changes: 4 additions & 0 deletions extension/src/fs.mts → extension/src/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export class VSCodeFileSystemAdapter implements FileSystemAdapter {
return Promise.resolve();
}

mkdir(path: string): Promise<void> {
return Promise.resolve(workspace.fs.createDirectory(Uri.file(path)));
}

readFile(path: string): Promise<string> {
return Promise.resolve(
workspace.fs
Expand Down
Loading

0 comments on commit 6dc0c81

Please sign in to comment.