Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 132 additions & 34 deletions extensions/positron-assistant/package-lock.json

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion extensions/positron-assistant/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@
"title": "%commands.toggleInlineCompletions.title%",
"category": "%commands.category%",
"enablement": "config.positron.assistant.enable"
},
{
"command": "positron-assistant.managePromptFiles",
"title": "%commands.managePromptFiles.title%",
"category": "%commands.category%",
"enablement": "config.positron.assistant.enable && isDevelopment"
}
],
"configuration": [
Expand Down Expand Up @@ -698,7 +704,9 @@
"@anthropic-ai/sdk": "^0.57.0",
"@github/copilot-language-server": "^1.367.0",
"@vscode/prompt-tsx": "^0.4.0-alpha.5",
"vscode-languageclient": "^9.0.1"
"squirrelly": "^9.1.0",
"vscode-languageclient": "^9.0.1",
"yaml": "^2.8.1"
},
"extensionDependencies": [
"positron.positron-supervisor"
Expand Down
1 change: 1 addition & 0 deletions extensions/positron-assistant/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"commands.generateCommitMessage.title": "Generate Commit Message",
"commands.cancelGenerateCommitMessage.title": "Cancel Generate Commit Message",
"commands.toggleInlineCompletions.title": "Toggle (Enable/Disable) Completions",
"commands.managePromptFiles.title": "Manage Prompt Files",
"commands.copilot.signin.title": "Copilot Sign In",
"commands.copilot.signout.title": "Copilot Sign Out",
"commands.category": "Positron Assistant",
Expand Down
15 changes: 4 additions & 11 deletions extensions/positron-assistant/src/commands/doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as fs from 'fs';

import { MD_DIR } from '../constants';
import { PositronAssistantEditorParticipant, PositronAssistantChatContext } from '../participants.js';
import { PositronAssistantChatContext } from '../participants.js';
import { PromptRenderer } from '../promptRender.js';

export const DOC_COMMAND = 'doc';

Expand All @@ -21,16 +20,10 @@ export async function docHandler(
_token: vscode.CancellationToken,
handleDefault: () => Promise<vscode.ChatResult | void>
) {
const { systemPrompt } = context;

response.progress(vscode.l10n.t('Generating documentation...'));

const prompt = await fs.promises.readFile(`${MD_DIR}/prompts/chat/doc.md`, 'utf8');
context.systemPrompt = `${systemPrompt}\n\n${prompt}`;
const prompt = PromptRenderer.renderCommandPrompt(DOC_COMMAND, _request, context).content;
context.systemPrompt += `\n\n${prompt}`;

return handleDefault();
}

export function registerDocCommand() {
PositronAssistantEditorParticipant.registerCommand(DOC_COMMAND, docHandler);
}
19 changes: 5 additions & 14 deletions extensions/positron-assistant/src/commands/explain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as fs from 'fs';

import { MD_DIR } from '../constants';
import { PositronAssistantChatParticipant, PositronAssistantEditorParticipant, PositronAssistantChatContext } from '../participants.js';

import { PositronAssistantChatContext } from '../participants.js';
import { PromptRenderer } from '../promptRender.js';

export const EXPLAIN_COMMAND = 'explain';

Expand All @@ -22,15 +19,9 @@ export async function explainHandler(
_token: vscode.CancellationToken,
handleDefault: () => Promise<vscode.ChatResult | void>
) {
const defaultPrompt = await fs.promises.readFile(`${MD_DIR}/prompts/chat/default.md`, 'utf8');
const explainPrompt = await fs.promises.readFile(`${MD_DIR}/prompts/chat/explain.md`, 'utf8');
const warningPrompt = await fs.promises.readFile(`${MD_DIR}/prompts/chat/warning.md`, 'utf8');

context.systemPrompt = defaultPrompt + '\n\n' + explainPrompt + '\n\n' + warningPrompt;
return handleDefault();
}
const prompt = PromptRenderer.renderCommandPrompt(EXPLAIN_COMMAND, _request, context).content;
context.systemPrompt += `\n\n${prompt}`;

export function registerExplainCommand() {
PositronAssistantChatParticipant.registerCommand(EXPLAIN_COMMAND, explainHandler);
PositronAssistantEditorParticipant.registerCommand(EXPLAIN_COMMAND, explainHandler);
return handleDefault();
}
28 changes: 4 additions & 24 deletions extensions/positron-assistant/src/commands/fix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as fs from 'fs';

import { MD_DIR } from '../constants';
import { ParticipantID, PositronAssistantChatParticipant, PositronAssistantEditorParticipant, PositronAssistantChatContext } from '../participants.js';
import { PositronAssistantToolName } from '../types.js';
import { PositronAssistantChatContext } from '../participants.js';
import { PromptRenderer } from '../promptRender.js';

export const FIX_COMMAND = 'fix';

Expand All @@ -22,27 +19,10 @@ export async function fixHandler(
_token: vscode.CancellationToken,
handleDefault: () => Promise<vscode.ChatResult | void>
) {
const { systemPrompt, participantId } = context;

if (participantId !== ParticipantID.Chat && participantId !== ParticipantID.Editor) {
return handleDefault();
}

response.progress('Preparing edits...');

if (participantId === ParticipantID.Chat) {
const prompt = await fs.promises.readFile(`${MD_DIR}/prompts/chat/fix.md`, 'utf8');
context.systemPrompt = `${systemPrompt}\n\n${prompt}`;
context.toolAvailability.set(PositronAssistantToolName.ProjectTree, true);
} else {
const prompt = await fs.promises.readFile(`${MD_DIR}/prompts/chat/fixEditor.md`, 'utf8');
context.systemPrompt = `${systemPrompt}\n\n${prompt}`;
}
const prompt = PromptRenderer.renderCommandPrompt(FIX_COMMAND, _request, context).content;
context.systemPrompt += `\n\n${prompt}`;

return handleDefault();
}

export function registerFixCommand() {
PositronAssistantChatParticipant.registerCommand(FIX_COMMAND, fixHandler);
PositronAssistantEditorParticipant.registerCommand(FIX_COMMAND, fixHandler);
}
58 changes: 49 additions & 9 deletions extensions/positron-assistant/src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,22 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { PositronAssistantChatContext } from '../participants.js';
import { registerFixCommand } from './fix.js';
import { registerQuartoCommand } from './quarto.js';
import { registerExplainCommand } from './explain.js';
import { registerDocCommand } from './doc.js';
import * as positron from 'positron';
import { FIX_COMMAND, fixHandler } from './fix.js';
import { EXPORT_QUARTO_COMMAND, quartoHandler } from './quarto.js';
import { EXPLAIN_COMMAND, explainHandler } from './explain.js';
import { DOC_COMMAND, docHandler } from './doc.js';
import { log } from '../extension.js';
import {
PositronAssistantAgentParticipant,
PositronAssistantChatContext,
PositronAssistantChatParticipant,
PositronAssistantEditorParticipant,
PositronAssistantEditParticipant,
PositronAssistantNotebookParticipant,
PositronAssistantTerminalParticipant
} from '../participants.js';
import { PromptRenderer } from '../promptRender.js';

/**
* A function that handles chat requests.
Expand All @@ -29,9 +40,38 @@ export interface IChatRequestHandler {
): Promise<vscode.ChatResult | void>;
}

function registerAssistantCommand(command: string, handler: IChatRequestHandler) {
const metadata = PromptRenderer.getCommandMetadata(command);
const modes = metadata.mode ?? [];
for (const mode of modes) {
switch (mode) {
case positron.PositronChatMode.Ask:
PositronAssistantChatParticipant.registerCommand(command, handler);
break;
case positron.PositronChatMode.Edit:
PositronAssistantEditParticipant.registerCommand(command, handler);
break;
case positron.PositronChatMode.Agent:
PositronAssistantAgentParticipant.registerCommand(command, handler);
break;
case positron.PositronChatAgentLocation.Editor:
PositronAssistantEditorParticipant.registerCommand(command, handler);
break;
case positron.PositronChatAgentLocation.Terminal:
PositronAssistantTerminalParticipant.registerCommand(command, handler);
break;
case positron.PositronChatAgentLocation.Notebook:
PositronAssistantNotebookParticipant.registerCommand(command, handler);
break;
default:
log.trace('[commands] Unsupported command mode:', mode);
}
}
}

export function registerAssistantCommands() {
registerFixCommand();
registerExplainCommand();
registerQuartoCommand();
registerDocCommand();
registerAssistantCommand(DOC_COMMAND, docHandler);
registerAssistantCommand(FIX_COMMAND, fixHandler);
registerAssistantCommand(EXPLAIN_COMMAND, explainHandler);
registerAssistantCommand(EXPORT_QUARTO_COMMAND, quartoHandler);
}
11 changes: 2 additions & 9 deletions extensions/positron-assistant/src/commands/quarto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as fs from 'fs';

import { MD_DIR } from '../constants';
import { toLanguageModelChatMessage } from '../utils';
import { PositronAssistantChatParticipant } from '../participants.js';
import { PromptRenderer } from '../promptRender.js';

export const EXPORT_QUARTO_COMMAND = 'exportQuarto';

Expand All @@ -21,7 +18,7 @@ export async function quartoHandler(
response: vscode.ChatResponseStream,
token: vscode.CancellationToken
) {
const system = await fs.promises.readFile(`${MD_DIR}/prompts/chat/quarto.md`, 'utf8');
const system = PromptRenderer.renderCommandPrompt(EXPORT_QUARTO_COMMAND, request, context).content;

response.markdown(vscode.l10n.t('Okay!'));
response.progress(vscode.l10n.t('Creating new Quarto document...'));
Expand Down Expand Up @@ -67,7 +64,3 @@ export async function quartoHandler(
}
}
}

export function registerQuartoCommand() {
PositronAssistantChatParticipant.registerCommand(EXPORT_QUARTO_COMMAND, quartoHandler);
}
5 changes: 3 additions & 2 deletions extensions/positron-assistant/src/completion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import * as vscode from 'vscode';
import * as positron from 'positron';
import * as ai from 'ai';
import * as fs from 'fs';
import * as path from 'path';

import { ModelConfig } from './config';
import { createAnthropic } from '@ai-sdk/anthropic';
import { MD_DIR } from './constants';
import { MARKDOWN_DIR } from './constants';
import { createOpenAI } from '@ai-sdk/openai';
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock';
Expand Down Expand Up @@ -404,7 +405,7 @@ abstract class FimPromptCompletion extends CompletionModel {
const signal = controller.signal;
token.onCancellationRequested(() => controller.abort());

const system: string = await fs.promises.readFile(`${MD_DIR}/prompts/completion/fim.md`, 'utf8');
const system: string = await fs.promises.readFile(path.join(MARKDOWN_DIR, 'prompts', 'completion', 'fim.md'), 'utf8');
const { textStream } = await ai.streamText({
model: this.model,
system: system,
Expand Down
3 changes: 0 additions & 3 deletions extensions/positron-assistant/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,5 @@ export const TOOL_TAG_REQUIRES_WORKSPACE = 'requires-workspace';
*/
export const TOOL_TAG_REQUIRES_ACTIVE_SESSION = 'requires-session';

/** The absolute path to the directory containing markdown files (e.g. prompt templates). */
export const MD_DIR = `${EXTENSION_ROOT_DIR}/src/md/`;

/** Max number of variables to include in language session context */
export const MAX_CONTEXT_VARIABLES = 400;
5 changes: 3 additions & 2 deletions extensions/positron-assistant/src/edits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';

import { MD_DIR } from './constants';
import { MARKDOWN_DIR } from './constants';
import { ParticipantService } from './participants.js';

type LMTextEdit = { append: string } | { delete: string; replace: string };
Expand Down Expand Up @@ -134,7 +135,7 @@ async function* mapEdit(
token: vscode.CancellationToken,
) {
// Read the system prompt for the language model from the markdown file
const system: string = await fs.promises.readFile(`${MD_DIR}/prompts/chat/mapedit.md`, 'utf8');
const system: string = await fs.promises.readFile(path.join(MARKDOWN_DIR, 'prompts', 'chat', 'mapedit.md'), 'utf8');

// Send a request to the language model with the document and code block
const response = await model.sendRequest([
Expand Down
2 changes: 2 additions & 0 deletions extensions/positron-assistant/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { AnthropicLanguageModel } from './anthropic.js';
import { registerParticipantDetectionProvider } from './participantDetection.js';
import { registerAssistantCommands } from './commands/index.js';
import { PositronAssistantApi } from './api.js';
import { registerPromptManagement } from './promptRender.js';

const hasChatModelsContextKey = 'positron-assistant.hasChatModels';

Expand Down Expand Up @@ -296,6 +297,7 @@ function registerAssistant(context: vscode.ExtensionContext) {
registerGenerateCommitMessageCommand(context, participantService, log);
registerExportChatCommands(context);
registerToggleInlineCompletionsCommand(context);
registerPromptManagement(context);

// Register mapped edits provider
registerMappedEditsProvider(context, participantService, log);
Expand Down
4 changes: 2 additions & 2 deletions extensions/positron-assistant/src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import * as path from 'path';

import { ParticipantService } from './participants.js';
import { API as GitAPI, GitExtension, Repository, Status, Change } from '../../git/src/api/git.js';
import { MD_DIR } from './constants';
import { MARKDOWN_DIR } from './constants';

const generatingGitCommitKey = 'positron-assistant.generatingCommitMessage';

Expand Down Expand Up @@ -155,7 +155,7 @@ export async function generateCommitMessage(
const gitChanges = stagedChanges.length > 0 ? stagedChanges : allChanges;
log.trace(`[git] Sending changes ${JSON.stringify(gitChanges)} to model provider.`);

const system: string = await fs.promises.readFile(`${MD_DIR}/prompts/git/commit.md`, 'utf8');
const system: string = await fs.promises.readFile(path.join(MARKDOWN_DIR, 'prompts', 'git', 'commit.md'), 'utf8');
try {
await Promise.all(gitChanges.map(async ({ repo, changes }) => {
if (changes.length > 0) {
Expand Down
16 changes: 16 additions & 0 deletions extensions/positron-assistant/src/md/prompts/chat/activation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
mode:
- ask
- edit
- agent
- editor
- notebook
order: 0
description: Keywords to steer the LLM
---
<activation-steering>
R for Data Science, Tidy Modeling with R, Happy Git with R, Advanced R, tidyverse, ggplot2, tidyr, dplyr, .by, shiny, reactivity, R6, plumber, pak, reticulate, torch, tidymodels, parsnip, quarto, renv, reproducibility, reprex, here::here, Wickham, Bryan, Cheng, Kuhn, Silge, Robinson, Frick, DRY, test fixtures
Python Polars: The Definitive Guide, Janssens, Nieuwdorp, polars, numpy, seaborn, plotnine, shiny for python, great tables, uv, astral, jupyter, notebook
quarto, markdown, yaml, literal programming, pandoc, observable, reactive
Posit, data science, research, knowledge, technical communication, open-source
</activation-steering>
5 changes: 5 additions & 0 deletions extensions/positron-assistant/src/md/prompts/chat/agent.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
mode: agent
order: 50
description: Prompt for Agent mode
---
You will be given a task that may require editing multiple files and executing
code to achieve.

Expand Down
8 changes: 8 additions & 0 deletions extensions/positron-assistant/src/md/prompts/chat/ask.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
---
mode:
- ask
- editor
- notebook
order: 50
description: Prompt for Ask mode
---
<communication>
You are running in "Ask" mode.

Expand Down
Loading