Release 1.1.5

Fixed newlines in the header
This commit is contained in:
Justice Vellacott 2025-05-07 20:22:26 -04:00
parent 866979ad73
commit 45f0cc024b
16 changed files with 4794 additions and 4818 deletions

View file

@ -5,6 +5,7 @@ root = true
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 4
tab_width = 4
indent_style = space
indent_size = 2
tab_width = 2
max_line_length = 100

View file

@ -32,4 +32,4 @@ jobs:
gh release create "$tag" \
--title="$tag" \
--draft \
main.js manifest.json styles.css
main.js manifest.json styles.css

View file

@ -2,48 +2,48 @@ import esbuild from "esbuild";
import process from "process";
import builtins from "builtin-modules";
const banner =
`/*
const banner = `/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
`;
const prod = (process.argv[2] === "production");
const prod = process.argv[2] === "production";
const context = await esbuild.context({
banner: {
js: banner,
},
entryPoints: ["src/main.ts"],
bundle: true,
external: [
"obsidian",
"electron",
"@codemirror/autocomplete",
"@codemirror/collab",
"@codemirror/commands",
"@codemirror/language",
"@codemirror/lint",
"@codemirror/search",
"@codemirror/state",
"@codemirror/view",
"@lezer/common",
"@lezer/highlight",
"@lezer/lr",
...builtins],
format: "cjs",
target: "es2018",
logLevel: "info",
sourcemap: prod ? false : "inline",
treeShaking: true,
outfile: "main.js",
minify: prod,
banner: {
js: banner,
},
entryPoints: ["src/main.ts"],
bundle: true,
external: [
"obsidian",
"electron",
"@codemirror/autocomplete",
"@codemirror/collab",
"@codemirror/commands",
"@codemirror/language",
"@codemirror/lint",
"@codemirror/search",
"@codemirror/state",
"@codemirror/view",
"@lezer/common",
"@lezer/highlight",
"@lezer/lr",
...builtins,
],
format: "cjs",
target: "es2018",
logLevel: "info",
sourcemap: prod ? false : "inline",
treeShaking: true,
outfile: "main.js",
minify: prod,
});
if (prod) {
await context.rebuild();
process.exit(0);
await context.rebuild();
process.exit(0);
} else {
await context.watch();
await context.watch();
}

View file

@ -1,7 +1,7 @@
{
"id": "pure-chat-llm",
"name": "Pure Chat LLM",
"version": "1.1.4",
"version": "1.1.5",
"minAppVersion": "1.8.10",
"description": "Turn notes into conversations with chatGPT",
"author": "Justice Vellacott",

4620
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,31 +1,32 @@
{
"name": "pure-chat-llm",
"version": "1.1.4",
"description": "Turn notes into conversations with chatGPT",
"main": "main.js",
"scripts": {
"dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"version": "node version-bump.mjs && git add manifest.json versions.json"
},
"keywords": [
"obsidian",
"plugin",
"chatbot",
"language model",
"LLM",
"notes"
],
"author": "Justice Vellacott",
"license": "MIT",
"devDependencies": {
"@types/node": "^16.11.6",
"@typescript-eslint/eslint-plugin": "5.29.0",
"@typescript-eslint/parser": "5.29.0",
"builtin-modules": "3.3.0",
"esbuild": "^0.17.3",
"obsidian": "latest",
"tslib": "2.4.0",
"typescript": "4.7.4"
}
"name": "pure-chat-llm",
"version": "1.1.5",
"description": "Turn notes into conversations with chatGPT",
"main": "main.js",
"scripts": {
"dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"version": "node version-bump.mjs && git add manifest.json versions.json",
"release": "bash Release.sh"
},
"keywords": [
"obsidian",
"plugin",
"chatbot",
"language model",
"LLM",
"notes"
],
"author": "Justice Vellacott",
"license": "MIT",
"devDependencies": {
"@types/node": "^16.11.6",
"@typescript-eslint/eslint-plugin": "5.29.0",
"@typescript-eslint/parser": "5.29.0",
"builtin-modules": "3.3.0",
"esbuild": "^0.17.3",
"obsidian": "latest",
"tslib": "2.4.0",
"typescript": "4.7.4"
}
}

View file

@ -1,11 +1,11 @@
import {
Editor,
EditorPosition,
EditorSelectionOrCaret,
EditorRange,
EditorSelection,
EditorCommandName,
EditorTransaction,
Editor,
EditorPosition,
EditorSelectionOrCaret,
EditorRange,
EditorSelection,
EditorCommandName,
EditorTransaction,
} from "obsidian";
/**
@ -13,246 +13,246 @@ import {
* allowing multiple operations to be performed fluently.
*/
export class ChainableEditor {
/**
* The underlying editor instance.
* @private
*/
private editor: Editor;
/**
* The underlying editor instance.
* @private
*/
private editor: Editor;
/**
* Creates a new ChainableEditor wrapping the provided editor.
* @param {Editor} editor - The editor instance to wrap.
*/
constructor(editor: Editor) {
this.editor = editor;
}
/**
* Creates a new ChainableEditor wrapping the provided editor.
* @param {Editor} editor - The editor instance to wrap.
*/
constructor(editor: Editor) {
this.editor = editor;
}
/**
* Sets the editor content to the specified string.
* @param {string} content - The content to set in the editor.
* @returns {this} - The current ChainableEditor instance.
*/
setValue(content: string): this {
this.editor.setValue(content);
return this;
}
/**
* Sets the editor content to the specified string.
* @param {string} content - The content to set in the editor.
* @returns {this} - The current ChainableEditor instance.
*/
setValue(content: string): this {
this.editor.setValue(content);
return this;
}
/**
* Inserts or replaces the specified line with provided text.
* @param {number} n - Zero-based line number.
* @param {string} text - The text to set at the specified line.
* @returns {this} - The current ChainableEditor instance.
*/
setLine(n: number, text: string): this {
this.editor.setLine(n, text);
return this;
}
/**
* Inserts or replaces the specified line with provided text.
* @param {number} n - Zero-based line number.
* @param {string} text - The text to set at the specified line.
* @returns {this} - The current ChainableEditor instance.
*/
setLine(n: number, text: string): this {
this.editor.setLine(n, text);
return this;
}
/**
* Sets the cursor position.
* @param {EditorPosition|number} pos - The position as an object or offset.
* @param {number} [ch] - Optional character position when using offset.
* @returns {this} - The current ChainableEditor instance.
*/
setCursor(pos: EditorPosition | number, ch?: number): this {
this.editor.setCursor(pos, ch);
return this;
}
/**
* Sets the cursor position.
* @param {EditorPosition|number} pos - The position as an object or offset.
* @param {number} [ch] - Optional character position when using offset.
* @returns {this} - The current ChainableEditor instance.
*/
setCursor(pos: EditorPosition | number, ch?: number): this {
this.editor.setCursor(pos, ch);
return this;
}
/**
* Sets the selection range in the editor.
* @param {EditorPosition} anchor - The start position.
* @param {EditorPosition} [head] - The end position (optional).
* @returns {this} - The current ChainableEditor instance.
*/
setSelection(anchor: EditorPosition, head?: EditorPosition): this {
this.editor.setSelection(anchor, head);
return this;
}
/**
* Sets the selection range in the editor.
* @param {EditorPosition} anchor - The start position.
* @param {EditorPosition} [head] - The end position (optional).
* @returns {this} - The current ChainableEditor instance.
*/
setSelection(anchor: EditorPosition, head?: EditorPosition): this {
this.editor.setSelection(anchor, head);
return this;
}
/**
* Replaces the current selection in the editor with the provided text.
*
* @param text - The text to insert in place of the current selection.
* @returns The current instance for method chaining.
*/
replaceSelection(text: string): this {
this.editor.replaceSelection(text);
return this;
}
/**
* Replaces the current selection in the editor with the provided text.
*
* @param text - The text to insert in place of the current selection.
* @returns The current instance for method chaining.
*/
replaceSelection(text: string): this {
this.editor.replaceSelection(text);
return this;
}
/**
* Sets multiple selections in the editor.
* @param {EditorSelectionOrCaret[]} ranges - Array of selection ranges or carets.
* @param {number} [main] - Index of the primary selection (optional).
* @returns {this} - The current ChainableEditor instance.
*/
setSelections(ranges: EditorSelectionOrCaret[], main?: number): this {
this.editor.setSelections(ranges, main);
return this;
}
/**
* Sets multiple selections in the editor.
* @param {EditorSelectionOrCaret[]} ranges - Array of selection ranges or carets.
* @param {number} [main] - Index of the primary selection (optional).
* @returns {this} - The current ChainableEditor instance.
*/
setSelections(ranges: EditorSelectionOrCaret[], main?: number): this {
this.editor.setSelections(ranges, main);
return this;
}
/**
* Scrolls the editor view to the specified coordinates.
* @param {number|null} [x] - Horizontal scroll position (optional).
* @param {number|null} [y] - Vertical scroll position (optional).
* @returns {this} - The current ChainableEditor instance.
*/
scrollTo(x?: number | null, y?: number | null): this {
this.editor.scrollTo(x, y);
return this;
}
/**
* Scrolls the editor view to the specified coordinates.
* @param {number|null} [x] - Horizontal scroll position (optional).
* @param {number|null} [y] - Vertical scroll position (optional).
* @returns {this} - The current ChainableEditor instance.
*/
scrollTo(x?: number | null, y?: number | null): this {
this.editor.scrollTo(x, y);
return this;
}
/**
* Scrolls the editor to bring a range into view.
* @param {EditorRange} range - The range to scroll into view.
* @param {boolean} [center=false] - Whether to center the range (optional).
* @returns {this} - The current ChainableEditor instance.
*/
scrollIntoView(range: EditorRange, center?: boolean): this {
this.editor.scrollIntoView(range, center);
return this;
}
/**
* Scrolls the editor to bring a range into view.
* @param {EditorRange} range - The range to scroll into view.
* @param {boolean} [center=false] - Whether to center the range (optional).
* @returns {this} - The current ChainableEditor instance.
*/
scrollIntoView(range: EditorRange, center?: boolean): this {
this.editor.scrollIntoView(range, center);
return this;
}
/**
* Performs an undo operation.
* @returns {this} - The current ChainableEditor instance.
*/
undo(): this {
this.editor.undo();
return this;
}
/**
* Performs an undo operation.
* @returns {this} - The current ChainableEditor instance.
*/
undo(): this {
this.editor.undo();
return this;
}
/**
* Performs a redo operation.
* @returns {this} - The current ChainableEditor instance.
*/
redo(): this {
this.editor.redo();
return this;
}
/**
* Performs a redo operation.
* @returns {this} - The current ChainableEditor instance.
*/
redo(): this {
this.editor.redo();
return this;
}
/**
* Focuses the editor.
* @returns {this} - The current ChainableEditor instance.
*/
focus(): this {
this.editor.focus();
return this;
}
/**
* Focuses the editor.
* @returns {this} - The current ChainableEditor instance.
*/
focus(): this {
this.editor.focus();
return this;
}
/**
* Removes focus from the editor.
* @returns {this} - The current ChainableEditor instance.
*/
blur(): this {
this.editor.blur();
return this;
}
/**
* Removes focus from the editor.
* @returns {this} - The current ChainableEditor instance.
*/
blur(): this {
this.editor.blur();
return this;
}
// Read-only methods - no chaining
/**
* Retrieves the current content of the editor.
* @returns {string} - The editor's current value.
*/
getValue(): string {
return this.editor.getValue();
}
// Read-only methods - no chaining
/**
* Retrieves the current content of the editor.
* @returns {string} - The editor's current value.
*/
getValue(): string {
return this.editor.getValue();
}
/**
* Retrieves the content of a specific line.
* @param {number} line - Zero-based line number.
* @returns {string} - The content of the specified line.
*/
getLine(line: number): string {
return this.editor.getLine(line);
}
/**
* Retrieves the content of a specific line.
* @param {number} line - Zero-based line number.
* @returns {string} - The content of the specified line.
*/
getLine(line: number): string {
return this.editor.getLine(line);
}
/**
* Gets the currently selected text.
* @returns {string} - The selected text.
*/
getSelection(): string {
return this.editor.getSelection();
}
/**
* Gets the currently selected text.
* @returns {string} - The selected text.
*/
getSelection(): string {
return this.editor.getSelection();
}
/**
* Lists all current selections.
* @returns {EditorSelection[]} - Array of selection objects.
*/
listSelections(): EditorSelection[] {
return this.editor.listSelections();
}
/**
* Lists all current selections.
* @returns {EditorSelection[]} - Array of selection objects.
*/
listSelections(): EditorSelection[] {
return this.editor.listSelections();
}
/**
* Gets scroll information.
* @returns {{ top: number; left: number }} - Scroll positions.
*/
getScrollInfo(): { top: number; left: number } {
return this.editor.getScrollInfo();
}
/**
* Gets scroll information.
* @returns {{ top: number; left: number }} - Scroll positions.
*/
getScrollInfo(): { top: number; left: number } {
return this.editor.getScrollInfo();
}
/**
* Checks if the editor currently has focus.
* @returns {boolean} - True if focused, false otherwise.
*/
hasFocus(): boolean {
return this.editor.hasFocus();
}
/**
* Checks if the editor currently has focus.
* @returns {boolean} - True if focused, false otherwise.
*/
hasFocus(): boolean {
return this.editor.hasFocus();
}
/**
* Retrieves the cursor position.
* @param {'from'|'to'|'head'|'anchor'} [position] - Specific position type (optional).
* @returns {EditorPosition} - The cursor position object.
*/
getCursor(position?: "from" | "to" | "head" | "anchor"): EditorPosition {
return this.editor.getCursor(position);
}
/**
* Retrieves the cursor position.
* @param {'from'|'to'|'head'|'anchor'} [position] - Specific position type (optional).
* @returns {EditorPosition} - The cursor position object.
*/
getCursor(position?: "from" | "to" | "head" | "anchor"): EditorPosition {
return this.editor.getCursor(position);
}
/**
* Converts an editor position to an offset.
* @param {EditorPosition} pos - The position to convert.
* @returns {number} - The corresponding offset.
*/
posToOffset(pos: EditorPosition): number {
return this.editor.posToOffset(pos);
}
/**
* Converts an editor position to an offset.
* @param {EditorPosition} pos - The position to convert.
* @returns {number} - The corresponding offset.
*/
posToOffset(pos: EditorPosition): number {
return this.editor.posToOffset(pos);
}
/**
* Converts an offset to an editor position.
* @param {number} offset - The offset to convert.
* @returns {EditorPosition} - The corresponding position object.
*/
offsetToPos(offset: number): EditorPosition {
return this.editor.offsetToPos(offset);
}
/**
* Converts an offset to an editor position.
* @param {number} offset - The offset to convert.
* @returns {EditorPosition} - The corresponding position object.
*/
offsetToPos(offset: number): EditorPosition {
return this.editor.offsetToPos(offset);
}
/**
* Executes a command in the editor.
* @param {EditorCommandName} command - The name of the command to execute.
* @returns {this} - The current ChainableEditor instance.
*/
exec(command: EditorCommandName): this {
this.editor.exec(command);
return this;
}
/**
* Executes a command in the editor.
* @param {EditorCommandName} command - The name of the command to execute.
* @returns {this} - The current ChainableEditor instance.
*/
exec(command: EditorCommandName): this {
this.editor.exec(command);
return this;
}
/**
* Performs a transaction, optionally with an origin description.
* @param {EditorTransaction} tx - The transaction function to run.
* @param {string} [origin] - Optional description of transaction origin.
* @returns {this} - The current ChainableEditor instance.
*/
transaction(tx: EditorTransaction, origin?: string): this {
this.editor.transaction(tx, origin);
return this;
}
/**
* Performs a transaction, optionally with an origin description.
* @param {EditorTransaction} tx - The transaction function to run.
* @param {string} [origin] - Optional description of transaction origin.
* @returns {this} - The current ChainableEditor instance.
*/
transaction(tx: EditorTransaction, origin?: string): this {
this.editor.transaction(tx, origin);
return this;
}
/**
* Exposes the underlying editor instance.
* @returns {Editor} - The original editor object.
*/
getEditor(): Editor {
return this.editor;
}
/**
* Exposes the underlying editor instance.
* @returns {Editor} - The original editor object.
*/
getEditor(): Editor {
return this.editor;
}
}

File diff suppressed because it is too large Load diff

View file

@ -14,58 +14,58 @@
* ```
*/
export class BrowserConsole {
private originalConsole: Console = console;
enabled: boolean;
consoleName: string;
private originalConsole: Console = console;
enabled: boolean;
consoleName: string;
/**
* Creates an instance of the class with the specified console state and name.
*
* @param enable - Determines whether the console is enabled.
* @param consoleName - The name to assign to the console instance.
*/
constructor(enable: boolean, consoleName: string) {
this.enabled = enable;
this.consoleName = consoleName;
}
/**
* Creates an instance of the class with the specified console state and name.
*
* @param enable - Determines whether the console is enabled.
* @param consoleName - The name to assign to the console instance.
*/
constructor(enable: boolean, consoleName: string) {
this.enabled = enable;
this.consoleName = consoleName;
}
/**
* Logs messages to the browser console if logging is enabled.
* Prepends the console name to the log output.
*
* @param {...any[]} args - The items to log to the console.
*/
log(...args: any[]): void {
if (this.enabled) this.originalConsole.log(this.consoleName, ...args);
}
/**
* Logs messages to the browser console if logging is enabled.
* Prepends the console name to the log output.
*
* @param {...any[]} args - The items to log to the console.
*/
log(...args: any[]): void {
if (this.enabled) this.originalConsole.log(this.consoleName, ...args);
}
/**
* Logs informational messages to the console if logging is enabled.
* Prepends the console name to the output.
*
* @param {...any[]} args - The messages or objects to log.
*/
info(...args: any[]): void {
if (this.enabled) this.originalConsole.info(this.consoleName, ...args);
}
/**
* Logs informational messages to the console if logging is enabled.
* Prepends the console name to the output.
*
* @param {...any[]} args - The messages or objects to log.
*/
info(...args: any[]): void {
if (this.enabled) this.originalConsole.info(this.consoleName, ...args);
}
/**
* Logs a warning message to the console with the specified console name prefix,
* if logging is enabled. Accepts any number of arguments to be logged.
*
* @param args - The items to log as a warning message.
*/
warn(...args: any[]): void {
if (this.enabled) this.originalConsole.warn(this.consoleName, ...args);
}
/**
* Logs a warning message to the console with the specified console name prefix,
* if logging is enabled. Accepts any number of arguments to be logged.
*
* @param args - The items to log as a warning message.
*/
warn(...args: any[]): void {
if (this.enabled) this.originalConsole.warn(this.consoleName, ...args);
}
/**
* Logs error messages to the console with the specified console name prefix,
* if logging is enabled. Accepts any number of arguments to be logged.
*
* @param args - The error messages or objects to log.
*/
error(...args: any[]): void {
if (this.enabled) this.originalConsole.error(this.consoleName, ...args);
}
/**
* Logs error messages to the console with the specified console name prefix,
* if logging is enabled. Accepts any number of arguments to be logged.
*
* @param args - The error messages or objects to log.
*/
error(...args: any[]): void {
if (this.enabled) this.originalConsole.error(this.consoleName, ...args);
}
}

View file

@ -1,16 +1,16 @@
import {
ItemView,
WorkspaceLeaf,
Editor,
MarkdownView,
setIcon,
MarkdownRenderer,
EditorRange,
Notice,
ButtonComponent,
Platform,
Menu,
DropdownComponent,
ItemView,
WorkspaceLeaf,
Editor,
MarkdownView,
setIcon,
MarkdownRenderer,
EditorRange,
Notice,
ButtonComponent,
Platform,
Menu,
DropdownComponent,
} from "obsidian";
import { PureChatLLMChat } from "./Chat";
import PureChatLLM, { AskForAPI, CodeHandling, SectionHandling } from "./main";
@ -41,270 +41,223 @@ import { BrowserConsole } from "./MyBrowserConsole";
* @see Editor
*/
export class PureChatLLMSideView extends ItemView {
plugin: PureChatLLM;
console: BrowserConsole;
viewText: string;
plugin: PureChatLLM;
console: BrowserConsole;
viewText: string;
constructor(leaf: WorkspaceLeaf, plugin: PureChatLLM) {
super(leaf);
this.icon = "text";
this.plugin = plugin;
this.console = new BrowserConsole(
plugin.settings.debug,
"PureChatLLMSideView"
);
this.viewText = "Conversation Overview";
}
constructor(leaf: WorkspaceLeaf, plugin: PureChatLLM) {
super(leaf);
this.icon = "text";
this.plugin = plugin;
this.console = new BrowserConsole(plugin.settings.debug, "PureChatLLMSideView");
this.viewText = "Conversation Overview";
}
getViewType() {
return PURE_CHAT_LLM_VIEW_TYPE;
}
getViewType() {
return PURE_CHAT_LLM_VIEW_TYPE;
}
getDisplayText() {
return this.viewText;
}
getDisplayText() {
return this.viewText;
}
async onOpen() {
// when a file is loaded or changed, update the view
async onOpen() {
// when a file is loaded or changed, update the view
this.registerEvent(
this.app.workspace.on(
"editor-change",
(editor: Editor, view: MarkdownView) => {
// if the user is typing in the editor, update the view
if (!this.plugin.isresponding) this.update(editor, view);
}
)
);
this.registerEvent(
this.app.workspace.on("file-open", () => {
const view =
this.app.workspace.getActiveViewOfType(MarkdownView);
const editor = view?.editor;
if (!editor) return;
if (!view) return;
this.update(editor, view);
})
);
this.registerEvent(
this.app.workspace.on("active-leaf-change", (leaf) => {
if (!leaf) return;
const v = leaf.view;
if (!(v instanceof MarkdownView)) return;
const e = v.editor;
this.update(e, v);
})
);
// check it the editor is open
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
if (view) {
const editor = view.editor;
if (editor) {
this.update(editor, view);
}
}
}
this.registerEvent(
this.app.workspace.on("editor-change", (editor: Editor, view: MarkdownView) => {
// if the user is typing in the editor, update the view
if (!this.plugin.isresponding) this.update(editor, view);
})
);
this.registerEvent(
this.app.workspace.on("file-open", () => {
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
const editor = view?.editor;
if (!editor) return;
if (!view) return;
this.update(editor, view);
})
);
this.registerEvent(
this.app.workspace.on("active-leaf-change", (leaf) => {
if (!leaf) return;
const v = leaf.view;
if (!(v instanceof MarkdownView)) return;
const e = v.editor;
this.update(e, v);
})
);
// check it the editor is open
const view = this.app.workspace.getActiveViewOfType(MarkdownView);
if (view) {
const editor = view.editor;
if (editor) {
this.update(editor, view);
}
}
}
menumodels(e: MouseEvent, editor: Editor) {
//if (!this.plugin.isresponding) return;
const endpoint =
this.plugin.settings.endpoints[this.plugin.settings.endpoint];
if (endpoint.apiKey === EmptyApiKey) {
new AskForAPI(this.app, this.plugin).open();
return;
}
new PureChatLLMChat(this.plugin).getAllModels().then((models) => {
const m = new Menu();
this.plugin.modellist = models;
models.forEach((model) => {
m.addItem((item) => {
item.setTitle(model);
item.onClick(() => {
editor.setValue(
new PureChatLLMChat(this.plugin)
.setMarkdown(editor.getValue())
.setModel(model).Markdown
);
// this.plugin.saveSettings();
new Notice("Model changed to " + model);
});
});
});
m.showAtMouseEvent(e);
});
}
menumodels(e: MouseEvent, editor: Editor) {
//if (!this.plugin.isresponding) return;
const endpoint = this.plugin.settings.endpoints[this.plugin.settings.endpoint];
if (endpoint.apiKey === EmptyApiKey) {
new AskForAPI(this.app, this.plugin).open();
return;
}
new PureChatLLMChat(this.plugin).getAllModels().then((models) => {
const m = new Menu();
this.plugin.modellist = models;
models.forEach((model) => {
m.addItem((item) => {
item.setTitle(model);
item.onClick(() => {
editor.setValue(
new PureChatLLMChat(this.plugin).setMarkdown(editor.getValue()).setModel(model)
.Markdown
);
// this.plugin.saveSettings();
new Notice("Model changed to " + model);
});
});
});
m.showAtMouseEvent(e);
});
}
update(editor: Editor, view: MarkdownView) {
const editorValue = editor.getValue();
const chat = new PureChatLLMChat(this.plugin);
chat.Markdown = editorValue;
const container = this.contentEl;
container.empty();
container.createDiv({ text: "" }, (contain) => {
contain.addClass("PURE", "floattop");
new ButtonComponent(contain)
//.setIcon("box")
.setButtonText("Models")
.setTooltip("Change model")
.onClick((e) => {
this.menumodels(e, editor);
});
new DropdownComponent(contain)
.addOptions(
Object.fromEntries(
this.plugin.settings.endpoints.map((e, i) => [
i.toString(),
e.name,
])
)
)
.setValue(this.plugin.settings.endpoint.toString())
.onChange(async (value) => {
this.plugin.settings.endpoint = parseInt(value, 10);
editor.setValue(
new PureChatLLMChat(this.plugin)
.setMarkdown(editor.getValue())
.setModel(
this.plugin.settings.endpoints[
this.plugin.settings.endpoint
].defaultmodel
).Markdown
);
this.plugin.modellist = [];
await this.plugin.saveSettings();
});
});
update(editor: Editor, view: MarkdownView) {
const editorValue = editor.getValue();
const chat = new PureChatLLMChat(this.plugin);
chat.Markdown = editorValue;
const container = this.contentEl;
container.empty();
container.createDiv({ text: "" }, (contain) => {
contain.addClass("PURE", "floattop");
new ButtonComponent(contain)
//.setIcon("box")
.setButtonText("Models")
.setTooltip("Change model")
.onClick((e) => {
this.menumodels(e, editor);
});
new DropdownComponent(contain)
.addOptions(
Object.fromEntries(this.plugin.settings.endpoints.map((e, i) => [i.toString(), e.name]))
)
.setValue(this.plugin.settings.endpoint.toString())
.onChange(async (value) => {
this.plugin.settings.endpoint = parseInt(value, 10);
editor.setValue(
new PureChatLLMChat(this.plugin)
.setMarkdown(editor.getValue())
.setModel(this.plugin.settings.endpoints[this.plugin.settings.endpoint].defaultmodel)
.Markdown
);
this.plugin.modellist = [];
await this.plugin.saveSettings();
});
});
// Process markdown messages
chat.messages.forEach((message) => {
const preview =
message.content.substring(0, 400) +
(message.content.length > 200 ? "\n... " : "");
// Process markdown messages
chat.messages.forEach((message) => {
const preview =
message.content.substring(0, 400) + (message.content.length > 200 ? "\n... " : "");
// Role header with clickable position jump
container.createDiv({ text: "" }, (contain) => {
contain.addClass("PURE", "messageContainer", message.role);
contain.createEl(
"h1",
{ text: toSentanceCase(message.role) },
(el) => {
el.onClickEvent(() =>
this.goToPostion(editor, message.cline)
);
el.addClass("PURE", "messageHeader", message.role);
}
);
// Preview of message content with copy button
if (preview)
contain.createEl("div", "", (div) => {
div.addClass("PURE", "preview", message.role);
div.createDiv({ text: "" }, (el) => {
el.onClickEvent(() =>
this.goToPostion(editor, message.cline, true)
);
el.addClass(
"PURE",
"messageMarkdown",
message.role
);
MarkdownRenderer.render(
this.app,
preview,
el,
view.file?.basename || "",
this
);
});
new ButtonComponent(div)
.setIcon("copy")
.setTooltip("Copy message to clipboard")
.onClick(() => {
navigator.clipboard.writeText(message.content);
new Notice("Copied message to clipboard");
});
new ButtonComponent(div)
.setIcon("message-square-x")
.setTooltip("Delete message")
.onClick(() => {
editor.replaceRange(
"",
{
line: message.cline.from.line - 1,
ch: 0,
},
message.cline.to
);
new Notice("Deleted message");
});
if (/# \w+/gm.test(message.content))
new ButtonComponent(div)
.setIcon("table-of-contents")
.setTooltip("View and edit sections")
.onClick(() => {
new SectionHandling(
this.app,
this.plugin,
message.content
).open();
});
if (/```[\w\W]*?```/gm.test(message.content))
new ButtonComponent(div)
.setIcon("code")
.setTooltip("View and edit code")
.onClick(() => {
new CodeHandling(
this.app,
this.plugin,
message.content
).open();
});
new ButtonComponent(div)
.setIcon("refresh-cw")
.setTooltip("Regenerate response")
.onClick(() => {
editor.replaceRange(
"",
{ line: message.cline.to.line, ch: 0 },
{
line: editor.lastLine(),
ch: editor.getLine(editor.lastLine())
.length,
}
);
this.plugin.CompleteChatResponse(editor, view);
});
});
});
});
// scroll to bottom of container
// if the editor is focused
if (editor.hasFocus()) {
container.scrollTo(0, container.scrollHeight);
}
}
// Role header with clickable position jump
container.createDiv({ text: "" }, (contain) => {
contain.addClass("PURE", "messageContainer", message.role);
contain.createEl("h1", { text: toSentanceCase(message.role) }, (el) => {
el.onClickEvent(() => this.goToPostion(editor, message.cline));
el.addClass("PURE", "messageHeader", message.role);
});
// Preview of message content with copy button
if (preview)
contain.createEl("div", "", (div) => {
div.addClass("PURE", "preview", message.role);
div.createDiv({ text: "" }, (el) => {
el.onClickEvent(() => this.goToPostion(editor, message.cline, true));
el.addClass("PURE", "messageMarkdown", message.role);
MarkdownRenderer.render(this.app, preview, el, view.file?.basename || "", this);
});
new ButtonComponent(div)
.setIcon("copy")
.setTooltip("Copy message to clipboard")
.onClick(() => {
navigator.clipboard.writeText(message.content);
new Notice("Copied message to clipboard");
});
new ButtonComponent(div)
.setIcon("message-square-x")
.setTooltip("Delete message")
.onClick(() => {
editor.replaceRange(
"",
{
line: message.cline.from.line - 1,
ch: 0,
},
message.cline.to
);
new Notice("Deleted message");
});
if (/# \w+/gm.test(message.content))
new ButtonComponent(div)
.setIcon("table-of-contents")
.setTooltip("View and edit sections")
.onClick(() => {
new SectionHandling(this.app, this.plugin, message.content).open();
});
if (/```[\w\W]*?```/gm.test(message.content))
new ButtonComponent(div)
.setIcon("code")
.setTooltip("View and edit code")
.onClick(() => {
new CodeHandling(this.app, this.plugin, message.content).open();
});
new ButtonComponent(div)
.setIcon("refresh-cw")
.setTooltip("Regenerate response")
.onClick(() => {
editor.replaceRange(
"",
{ line: message.cline.to.line, ch: 0 },
{
line: editor.lastLine(),
ch: editor.getLine(editor.lastLine()).length,
}
);
this.plugin.CompleteChatResponse(editor, view);
});
});
});
});
// scroll to bottom of container
// if the editor is focused
if (editor.hasFocus()) {
container.scrollTo(0, container.scrollHeight);
}
}
private goToPostion(editor: Editor, position: EditorRange, select = false) {
if (select) {
editor.setSelections([
{ anchor: position.from, head: position.to },
]);
//editor.setSelection(position.from, position.to);
editor.scrollIntoView(position);
} else {
editor.setCursor(position.from);
editor.scrollTo(0, editor.posToOffset(position.from));
}
editor.focus();
// if it's mobile, wait 100ms to focus the editor again
// this will make the selection work on mobile
if (Platform.isMobile) {
window.setTimeout(() => {
editor.focus();
}, 100);
}
}
private goToPostion(editor: Editor, position: EditorRange, select = false) {
if (select) {
editor.setSelections([{ anchor: position.from, head: position.to }]);
//editor.setSelection(position.from, position.to);
editor.scrollIntoView(position);
} else {
editor.setCursor(position.from);
editor.scrollTo(0, editor.posToOffset(position.from));
}
editor.focus();
// if it's mobile, wait 100ms to focus the editor again
// this will make the selection work on mobile
if (Platform.isMobile) {
window.setTimeout(() => {
editor.focus();
}, 100);
}
}
async onClose() {
// Nothing to clean up.
}
async onClose() {
// Nothing to clean up.
}
}

View file

@ -1,394 +1,394 @@
export type codelanguage =
| "plaintext"
| "markup"
| "html"
| "xml"
| "svg"
| "mathml"
| "ssml"
| "atom"
| "rss"
| "css"
| "clike"
| "javascript"
| "js"
| "abap"
| "abnf"
| "actionscript"
| "ada"
| "agda"
| "al"
| "antlr4"
| "g4"
| "apacheconf"
| "apex"
| "apl"
| "applescript"
| "aql"
| "arduino"
| "ino"
| "arff"
| "asm"
| "arturo"
| "art"
| "asciidoc"
| "adoc"
| "aspnet"
| "asm6502"
| "asmatmel"
| "autohotkey"
| "autoit"
| "avisynth"
| "avs"
| "idl"
| "avdl"
| "awk"
| "gawk"
| "bash"
| "sh"
| "shell"
| "basic"
| "batch"
| "bbcode"
| "shortcode"
| "bbj"
| "bicep"
| "birb"
| "bison"
| "bnf"
| "rbnf"
| "bqn"
| "brainfuck"
| "brightscript"
| "bro"
| "bsl"
| "oscript"
| "c"
| "csharp"
| "cs"
| "dotnet"
| "cpp"
| "cfscript"
| "cfc"
| "chaiscript"
| "cil"
| "c"
| "cpp"
| "cilk"
| "clojure"
| "cmake"
| "cobol"
| "coffeescript"
| "coffee"
| "concurnas"
| "conc"
| "csp"
| "cooklang"
| "coq"
| "crystal"
| "extras"
| "csv"
| "cue"
| "cypher"
| "d"
| "dart"
| "dataweave"
| "dax"
| "dhall"
| "diff"
| "django"
| "jinja2"
| "zone"
| "docker"
| "dockerfile"
| "dot"
| "gv"
| "ebnf"
| "editorconfig"
| "eiffel"
| "ejs"
| "eta"
| "elixir"
| "elm"
| "etlua"
| "erb"
| "erlang"
| "formula"
| "xlsx"
| "xls"
| "fsharp"
| "factor"
| "false"
| "rules"
| "flow"
| "fortran"
| "ftl"
| "gml"
| "gamemakerlanguage"
| "gap"
| "gcode"
| "gdscript"
| "gedcom"
| "gettext"
| "po"
| "gherkin"
| "git"
| "glsl"
| "gn"
| "gni"
| "script"
| "ld"
| "go"
| "mod"
| "gradle"
| "graphql"
| "groovy"
| "haml"
| "handlebars"
| "hbs"
| "mustache"
| "haskell"
| "hs"
| "haxe"
| "hcl"
| "hlsl"
| "hoon"
| "http"
| "hpkp"
| "hsts"
| "ichigojam"
| "icon"
| "format"
| "idris"
| "idr"
| "ignore"
| "gitignore"
| "hgignore"
| "npmignore"
| "inform7"
| "ini"
| "io"
| "j"
| "java"
| "javadoc"
| "javadoclike"
| "javastacktrace"
| "jexl"
| "jolie"
| "jq"
| "jsdoc"
| "extras"
| "json"
| "webmanifest"
| "json5"
| "jsonp"
| "jsstacktrace"
| "templates"
| "julia"
| "keepalived"
| "keyman"
| "kotlin"
| "kt"
| "kts"
| "kumir"
| "kum"
| "kusto"
| "latex"
| "tex"
| "context"
| "latte"
| "less"
| "lilypond"
| "ly"
| "liquid"
| "lisp"
| "livescript"
| "llvm"
| "log"
| "lolcode"
| "lua"
| "magma"
| "makefile"
| "markdown"
| "md"
| "templating"
| "mata"
| "matlab"
| "maxscript"
| "mel"
| "mermaid"
| "metafont"
| "mizar"
| "mongodb"
| "monkey"
| "moonscript"
| "moon"
| "n1ql"
| "n4js"
| "n4jsd"
| "hdl"
| "naniscript"
| "nani"
| "nasm"
| "neon"
| "nevod"
| "nginx"
| "nim"
| "nix"
| "nsis"
| "objectivec"
| "objc"
| "ocaml"
| "odin"
| "opencl"
| "openqasm"
| "qasm"
| "oz"
| "parigp"
| "parser"
| "pascal"
| "objectpascal"
| "pascaligo"
| "psl"
| "pcaxis"
| "px"
| "peoplecode"
| "pcode"
| "perl"
| "php"
| "phpdoc"
| "extras"
| "uml"
| "plantuml"
| "plsql"
| "powerquery"
| "pq"
| "mscript"
| "powershell"
| "processing"
| "prolog"
| "promql"
| "properties"
| "protobuf"
| "pug"
| "puppet"
| "pure"
| "purebasic"
| "pbfasm"
| "purescript"
| "purs"
| "python"
| "py"
| "qsharp"
| "qs"
| "q"
| "qml"
| "qore"
| "r"
| "racket"
| "rkt"
| "cshtml"
| "razor"
| "jsx"
| "tsx"
| "reason"
| "regex"
| "rego"
| "renpy"
| "rpy"
| "rescript"
| "res"
| "rest"
| "rip"
| "roboconf"
| "robotframework"
| "robot"
| "ruby"
| "rb"
| "rust"
| "sas"
| "sass"
| "scss"
| "scala"
| "scheme"
| "session"
| "shellsession"
| "smali"
| "smalltalk"
| "smarty"
| "sml"
| "smlnj"
| "solidity"
| "sol"
| "file"
| "sln"
| "soy"
| "sparql"
| "rq"
| "spl"
| "sqf"
| "sql"
| "squirrel"
| "stan"
| "stata"
| "iecst"
| "stylus"
| "supercollider"
| "sclang"
| "swift"
| "systemd"
| "templating"
| "cs"
| "t4"
| "vb"
| "tap"
| "tcl"
| "tt2"
| "textile"
| "toml"
| "tremor"
| "trickle"
| "troy"
| "turtle"
| "trig"
| "twig"
| "typescript"
| "ts"
| "typoscript"
| "tsconfig"
| "unrealscript"
| "uscript"
| "uc"
| "uorazor"
| "uri"
| "url"
| "v"
| "vala"
| "vbnet"
| "velocity"
| "verilog"
| "vhdl"
| "vim"
| "basic"
| "vb"
| "vba"
| "warpscript"
| "wasm"
| "idl"
| "webidl"
| "wgsl"
| "wiki"
| "wolfram"
| "mathematica"
| "nb"
| "wl"
| "wren"
| "xeora"
| "xeoracube"
| "doc"
| "xojo"
| "xquery"
| "yaml"
| "yml"
| "yang"
| "zig";
| "plaintext"
| "markup"
| "html"
| "xml"
| "svg"
| "mathml"
| "ssml"
| "atom"
| "rss"
| "css"
| "clike"
| "javascript"
| "js"
| "abap"
| "abnf"
| "actionscript"
| "ada"
| "agda"
| "al"
| "antlr4"
| "g4"
| "apacheconf"
| "apex"
| "apl"
| "applescript"
| "aql"
| "arduino"
| "ino"
| "arff"
| "asm"
| "arturo"
| "art"
| "asciidoc"
| "adoc"
| "aspnet"
| "asm6502"
| "asmatmel"
| "autohotkey"
| "autoit"
| "avisynth"
| "avs"
| "idl"
| "avdl"
| "awk"
| "gawk"
| "bash"
| "sh"
| "shell"
| "basic"
| "batch"
| "bbcode"
| "shortcode"
| "bbj"
| "bicep"
| "birb"
| "bison"
| "bnf"
| "rbnf"
| "bqn"
| "brainfuck"
| "brightscript"
| "bro"
| "bsl"
| "oscript"
| "c"
| "csharp"
| "cs"
| "dotnet"
| "cpp"
| "cfscript"
| "cfc"
| "chaiscript"
| "cil"
| "c"
| "cpp"
| "cilk"
| "clojure"
| "cmake"
| "cobol"
| "coffeescript"
| "coffee"
| "concurnas"
| "conc"
| "csp"
| "cooklang"
| "coq"
| "crystal"
| "extras"
| "csv"
| "cue"
| "cypher"
| "d"
| "dart"
| "dataweave"
| "dax"
| "dhall"
| "diff"
| "django"
| "jinja2"
| "zone"
| "docker"
| "dockerfile"
| "dot"
| "gv"
| "ebnf"
| "editorconfig"
| "eiffel"
| "ejs"
| "eta"
| "elixir"
| "elm"
| "etlua"
| "erb"
| "erlang"
| "formula"
| "xlsx"
| "xls"
| "fsharp"
| "factor"
| "false"
| "rules"
| "flow"
| "fortran"
| "ftl"
| "gml"
| "gamemakerlanguage"
| "gap"
| "gcode"
| "gdscript"
| "gedcom"
| "gettext"
| "po"
| "gherkin"
| "git"
| "glsl"
| "gn"
| "gni"
| "script"
| "ld"
| "go"
| "mod"
| "gradle"
| "graphql"
| "groovy"
| "haml"
| "handlebars"
| "hbs"
| "mustache"
| "haskell"
| "hs"
| "haxe"
| "hcl"
| "hlsl"
| "hoon"
| "http"
| "hpkp"
| "hsts"
| "ichigojam"
| "icon"
| "format"
| "idris"
| "idr"
| "ignore"
| "gitignore"
| "hgignore"
| "npmignore"
| "inform7"
| "ini"
| "io"
| "j"
| "java"
| "javadoc"
| "javadoclike"
| "javastacktrace"
| "jexl"
| "jolie"
| "jq"
| "jsdoc"
| "extras"
| "json"
| "webmanifest"
| "json5"
| "jsonp"
| "jsstacktrace"
| "templates"
| "julia"
| "keepalived"
| "keyman"
| "kotlin"
| "kt"
| "kts"
| "kumir"
| "kum"
| "kusto"
| "latex"
| "tex"
| "context"
| "latte"
| "less"
| "lilypond"
| "ly"
| "liquid"
| "lisp"
| "livescript"
| "llvm"
| "log"
| "lolcode"
| "lua"
| "magma"
| "makefile"
| "markdown"
| "md"
| "templating"
| "mata"
| "matlab"
| "maxscript"
| "mel"
| "mermaid"
| "metafont"
| "mizar"
| "mongodb"
| "monkey"
| "moonscript"
| "moon"
| "n1ql"
| "n4js"
| "n4jsd"
| "hdl"
| "naniscript"
| "nani"
| "nasm"
| "neon"
| "nevod"
| "nginx"
| "nim"
| "nix"
| "nsis"
| "objectivec"
| "objc"
| "ocaml"
| "odin"
| "opencl"
| "openqasm"
| "qasm"
| "oz"
| "parigp"
| "parser"
| "pascal"
| "objectpascal"
| "pascaligo"
| "psl"
| "pcaxis"
| "px"
| "peoplecode"
| "pcode"
| "perl"
| "php"
| "phpdoc"
| "extras"
| "uml"
| "plantuml"
| "plsql"
| "powerquery"
| "pq"
| "mscript"
| "powershell"
| "processing"
| "prolog"
| "promql"
| "properties"
| "protobuf"
| "pug"
| "puppet"
| "pure"
| "purebasic"
| "pbfasm"
| "purescript"
| "purs"
| "python"
| "py"
| "qsharp"
| "qs"
| "q"
| "qml"
| "qore"
| "r"
| "racket"
| "rkt"
| "cshtml"
| "razor"
| "jsx"
| "tsx"
| "reason"
| "regex"
| "rego"
| "renpy"
| "rpy"
| "rescript"
| "res"
| "rest"
| "rip"
| "roboconf"
| "robotframework"
| "robot"
| "ruby"
| "rb"
| "rust"
| "sas"
| "sass"
| "scss"
| "scala"
| "scheme"
| "session"
| "shellsession"
| "smali"
| "smalltalk"
| "smarty"
| "sml"
| "smlnj"
| "solidity"
| "sol"
| "file"
| "sln"
| "soy"
| "sparql"
| "rq"
| "spl"
| "sqf"
| "sql"
| "squirrel"
| "stan"
| "stata"
| "iecst"
| "stylus"
| "supercollider"
| "sclang"
| "swift"
| "systemd"
| "templating"
| "cs"
| "t4"
| "vb"
| "tap"
| "tcl"
| "tt2"
| "textile"
| "toml"
| "tremor"
| "trickle"
| "troy"
| "turtle"
| "trig"
| "twig"
| "typescript"
| "ts"
| "typoscript"
| "tsconfig"
| "unrealscript"
| "uscript"
| "uc"
| "uorazor"
| "uri"
| "url"
| "v"
| "vala"
| "vbnet"
| "velocity"
| "verilog"
| "vhdl"
| "vim"
| "basic"
| "vb"
| "vba"
| "warpscript"
| "wasm"
| "idl"
| "webidl"
| "wgsl"
| "wiki"
| "wolfram"
| "mathematica"
| "nb"
| "wl"
| "wren"
| "xeora"
| "xeoracube"
| "doc"
| "xojo"
| "xquery"
| "yaml"
| "yml"
| "yang"
| "zig";

File diff suppressed because it is too large Load diff

View file

@ -14,9 +14,9 @@
* ```
*/
export function toSentanceCase(str: string): string {
return str
.toLowerCase()
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
return str
.toLowerCase()
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
}

View file

@ -1,120 +1,117 @@
import { EditorRange } from "obsidian";
export interface PureChatLLMSettings {
AutogenerateTitle: number;
SystemPrompt: string;
debug: boolean;
endpoint: number;
endpoints: PureChatLLMAPI[];
chatParser: number;
AutogenerateTitle: number;
SystemPrompt: string;
debug: boolean;
endpoint: number;
endpoints: PureChatLLMAPI[];
chatParser: number;
}
export const DEFAULT_SETTINGS: PureChatLLMSettings = {
AutogenerateTitle: 4,
SystemPrompt: `You are ChatGPT, a large language model trained by OpenAI. Carefully heed the user's instructions. Respond using Markdown.\n\nBe attentive, thoughtful, and precise—provide clear, well-structured answers that honor the complexity of each query. Avoid generic responses; instead, offer insights that encourage creativity, reflection, and learning. Employ subtle, dry humor or depth when appropriate. Respect the users individuality and values, adapting your tone and approach as needed to foster a conversational, meaningful, and genuinely supportive exchange.`,
debug: false,
endpoint: 0,
endpoints: [],
chatParser: 0,
AutogenerateTitle: 4,
SystemPrompt: `You are ChatGPT, a large language model trained by OpenAI. Carefully heed the user's instructions. Respond using Markdown.\n\nBe attentive, thoughtful, and precise—provide clear, well-structured answers that honor the complexity of each query. Avoid generic responses; instead, offer insights that encourage creativity, reflection, and learning. Employ subtle, dry humor or depth when appropriate. Respect the users individuality and values, adapting your tone and approach as needed to foster a conversational, meaningful, and genuinely supportive exchange.`,
debug: false,
endpoint: 0,
endpoints: [],
chatParser: 0,
};
export interface PureChatLLMAPI {
name: string;
apiKey: string;
endpoint: string;
defaultmodel: string;
listmodels: string;
getapiKey: string;
name: string;
apiKey: string;
endpoint: string;
defaultmodel: string;
listmodels: string;
getapiKey: string;
}
interface ChatParser {
name: string;
description: string;
SplitMessages: RegExp;
getRole: RegExp;
rolePlacement: string;
isChat?: RegExp;
name: string;
description: string;
SplitMessages: RegExp;
getRole: RegExp;
rolePlacement: string;
isChat?: RegExp;
}
export const chatParser: ChatParser[] = [
{
name: "SimpleMarkdownHeader",
description: "Simple markdown header parser",
SplitMessages: /^# role: (?=system|user|assistant|developer)/im,
getRole: /^(system|user|assistant|developer)[^\n]+\n/i,
rolePlacement: "# role: {role}",
isChat: /^# role: (system|user|assistant|developer)/i,
},
{
name: "NoteMarkdownHeader",
description: "Note markdown header parser",
SplitMessages:
/^\n> \[!note\] \w+\n> # role: (?=system|user|assistant|developer)/im,
getRole: /^(system|user|assistant|developer)[^\n]+\n/i,
rolePlacement: "\n> [!note] {role}\n> # role: {role}\n",
isChat: /^> \[!note\] \w+\n> # role: (system|user|assistant|developer)/i,
},
{
name: "SimpleMarkdownHeader",
description: "Simple markdown header parser",
SplitMessages: /^# role: (?=system|user|assistant|developer)/im,
getRole: /^(system|user|assistant|developer)[^\n]+\n/i,
rolePlacement: "# role: {role}",
isChat: /^# role: (system|user|assistant|developer)/i,
},
{
name: "NoteMarkdownHeader",
description: "Note markdown header parser",
SplitMessages: /^\n> \[!note\] \w+\n> # role: (?=system|user|assistant|developer)/im,
getRole: /^(system|user|assistant|developer)[^\n]+\n/i,
rolePlacement: "\n> [!note] {role}\n> # role: {role}\n",
isChat: /^> \[!note\] \w+\n> # role: (system|user|assistant|developer)/i,
},
];
export const EmptyApiKey = "sk-XXXXXXXXX";
export const ENDPOINTS: PureChatLLMAPI[] = [
{
name: "OpenAI",
apiKey: EmptyApiKey,
defaultmodel: "gpt-4.1-nano",
endpoint: "https://api.openai.com/v1/chat/completions",
listmodels: "https://api.openai.com/v1/models",
getapiKey: "https://platform.openai.com/api-keys",
},
{
name: "Gemini",
apiKey: EmptyApiKey,
defaultmodel: "gemini-2.0-flash-lite",
endpoint:
"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions",
listmodels:
"https://generativelanguage.googleapis.com/v1beta/openai/models",
getapiKey: "https://aistudio.google.com/apikey",
},
{
name: "xAI",
apiKey: EmptyApiKey,
defaultmodel: "grok-3-mini",
endpoint: "https://api.x.ai/v1/chat/completions",
listmodels: "https://api.x.ai/v1/models",
getapiKey: "https://console.x.ai",
},
{
name: "Anthropic",
apiKey: EmptyApiKey,
defaultmodel: "claude-3-7-sonnet-20250219",
endpoint: "https://api.anthropic.com/v1/messages",
listmodels: "https://api.anthropic.com/v1/models",
getapiKey: "https://console.anthropic.com/settings/keys",
},
{
name: "Cohere",
apiKey: EmptyApiKey,
defaultmodel: "command",
endpoint: "https://api.cohere.ai/v1/generate",
listmodels: "https://api.cohere.ai/v1/models",
getapiKey: "https://dashboard.cohere.com/api-keys",
},
{
name: "Mistral AI",
apiKey: EmptyApiKey,
defaultmodel: "mixtral-8x7b",
endpoint: "https://api.mistral.ai/v1/chat/completions",
listmodels: "https://api.mistral.ai/v1/models",
getapiKey: "https://console.mistral.ai/api-keys",
},
{
name: "DeepSeek",
apiKey: EmptyApiKey,
defaultmodel: "deepseek-llm",
endpoint: "https://api.deepseek.com/v1/chat/completions",
listmodels: "https://api.deepseek.com/v1/models",
getapiKey: "https://platform.deepseek.com/api_keys",
},
{
name: "OpenAI",
apiKey: EmptyApiKey,
defaultmodel: "gpt-4.1-nano",
endpoint: "https://api.openai.com/v1/chat/completions",
listmodels: "https://api.openai.com/v1/models",
getapiKey: "https://platform.openai.com/api-keys",
},
{
name: "Gemini",
apiKey: EmptyApiKey,
defaultmodel: "gemini-2.0-flash-lite",
endpoint: "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions",
listmodels: "https://generativelanguage.googleapis.com/v1beta/openai/models",
getapiKey: "https://aistudio.google.com/apikey",
},
{
name: "xAI",
apiKey: EmptyApiKey,
defaultmodel: "grok-3-mini",
endpoint: "https://api.x.ai/v1/chat/completions",
listmodels: "https://api.x.ai/v1/models",
getapiKey: "https://console.x.ai",
},
{
name: "Anthropic",
apiKey: EmptyApiKey,
defaultmodel: "claude-3-7-sonnet-20250219",
endpoint: "https://api.anthropic.com/v1/messages",
listmodels: "https://api.anthropic.com/v1/models",
getapiKey: "https://console.anthropic.com/settings/keys",
},
{
name: "Cohere",
apiKey: EmptyApiKey,
defaultmodel: "command",
endpoint: "https://api.cohere.ai/v1/generate",
listmodels: "https://api.cohere.ai/v1/models",
getapiKey: "https://dashboard.cohere.com/api-keys",
},
{
name: "Mistral AI",
apiKey: EmptyApiKey,
defaultmodel: "mixtral-8x7b",
endpoint: "https://api.mistral.ai/v1/chat/completions",
listmodels: "https://api.mistral.ai/v1/models",
getapiKey: "https://console.mistral.ai/api-keys",
},
{
name: "DeepSeek",
apiKey: EmptyApiKey,
defaultmodel: "deepseek-llm",
endpoint: "https://api.deepseek.com/v1/chat/completions",
listmodels: "https://api.deepseek.com/v1/models",
getapiKey: "https://platform.deepseek.com/api_keys",
},
];
/**
@ -134,7 +131,7 @@ export const ENDPOINTS: PureChatLLMAPI[] = [
* ```
*/
export interface PureChatLLMInstructPrompts {
[key: string]: PureChatLLMInstructPrompt;
[key: string]: PureChatLLMInstructPrompt;
}
/**
@ -144,32 +141,32 @@ export interface PureChatLLMInstructPrompts {
* @property template - The template string used for the prompt's content.
*/
export interface PureChatLLMInstructPrompt {
name: string;
template: string;
name: string;
template: string;
}
export type RoleType = "system" | "user" | "assistant" | "developer";
export interface ChatMessage {
role: RoleType;
content: string;
cline: EditorRange;
role: RoleType;
content: string;
cline: EditorRange;
}
export const PURE_CHAT_LLM_VIEW_TYPE = "pure-chat-llm-left-pane";
export const DEFAULT_PROCESS_CHAT_TEMPLATES: PureChatLLMInstructPrompts = {
"Conversation titler": {
name: "Conversation titler",
template: `Summarize the conversation in 5 words or fewer:
"Conversation titler": {
name: "Conversation titler",
template: `Summarize the conversation in 5 words or fewer:
Be as concise as possible without losing the context of the conversation.
Your goal is to extract the key point of the conversation.`,
},
"Conversation analizer": {
name: "Conversation analizer",
template: `Analyze the conversation.
},
"Conversation analizer": {
name: "Conversation analizer",
template: `Analyze the conversation.
The role's are the \`user\` chatting with the \`assistant\` on the \`system\`.
- The roles include the \`user\`, the \`assistant\`, and the \`system\` (instructions).
@ -179,48 +176,48 @@ Write a better system prompt based on what the user was trying to use the system
Write another prompt by condensing all the user requests into one to get the final assistant response with just one user message.
`,
},
},
};
export const DEFAULT_SELECTION_TEMPLATES: PureChatLLMInstructPrompts = {
Summarize: {
name: "Summarize",
template:
"Create a bullet-point summary of the provided selection.\nEach bullet point should capture a key point.\nReturn only the bullet-point summary.",
},
Simplify: {
name: "Simplify",
template:
"Simplify the provided selection to a 6th-grade reading level (ages 11-12).\nUse simple sentences, common words, and clear explanations.\nMaintain the original key concepts.\nReturn only the simplified selection.",
},
"Add Emojis": {
name: "Add Emojis",
template:
"Add relevant emojis to enhance the provided selection. Follow these rules:\n1. Insert emojis at natural breaks in the text\n2. Never place two emojis next to each other\n3. Keep all original text unchanged\n4. Choose emojis that match the context and tone\nReturn only the emojified selection.",
},
"Correct Grammar & Spelling": {
name: "Correct Grammar & Spelling",
template:
"Fix the grammar and spelling of the provided selection. Preserve all formatting, line breaks, and special characters. Do not add or remove any content. Return only the corrected text.",
},
Concentrate: {
name: "Concentrate",
template:
"Reduce the provided selection to half its length while preserving the following elements:\n1. Main ideas and key points\n2. Essential details\n3. Original tone and style\nReturn only the shortened selection.",
},
Expand: {
name: "Expand",
template:
"Expand the provided selection to twice its length by:\n1. Adding relevant details and examples\n2. Elaborating on key points\n3. Maintaining the original tone and style\nReturn only the expanded selection.",
},
"Clarify & Expand Instructions": {
name: "Clarify & Expand Instructions",
template:
"The provided selection contains instructions that need to be expanded and clarified. Expand these instructions so that someone new to the task fully understands what needs to be done. Use clear, detailed explanations, examples if necessary, and break down any complex points into simpler parts. Ensure the expanded instructions maintain the original meaning and provide a comprehensive understanding. Return only the expanded instructions.",
},
"Clarify & Expand Role Description": {
name: "Clarify & Expand Role Description",
template:
"The provided selection contains a brief role description. Expand and clarify this description by explaining the responsibilities, goals, and perspective someone playing this role should adopt. Use detailed and clear language, including relevant context or examples. Maintain the original intent while making the explanation comprehensive. Return only the expanded role description.",
},
Summarize: {
name: "Summarize",
template:
"Create a bullet-point summary of the provided selection.\nEach bullet point should capture a key point.\nReturn only the bullet-point summary.",
},
Simplify: {
name: "Simplify",
template:
"Simplify the provided selection to a 6th-grade reading level (ages 11-12).\nUse simple sentences, common words, and clear explanations.\nMaintain the original key concepts.\nReturn only the simplified selection.",
},
"Add Emojis": {
name: "Add Emojis",
template:
"Add relevant emojis to enhance the provided selection. Follow these rules:\n1. Insert emojis at natural breaks in the text\n2. Never place two emojis next to each other\n3. Keep all original text unchanged\n4. Choose emojis that match the context and tone\nReturn only the emojified selection.",
},
"Correct Grammar & Spelling": {
name: "Correct Grammar & Spelling",
template:
"Fix the grammar and spelling of the provided selection. Preserve all formatting, line breaks, and special characters. Do not add or remove any content. Return only the corrected text.",
},
Concentrate: {
name: "Concentrate",
template:
"Reduce the provided selection to half its length while preserving the following elements:\n1. Main ideas and key points\n2. Essential details\n3. Original tone and style\nReturn only the shortened selection.",
},
Expand: {
name: "Expand",
template:
"Expand the provided selection to twice its length by:\n1. Adding relevant details and examples\n2. Elaborating on key points\n3. Maintaining the original tone and style\nReturn only the expanded selection.",
},
"Clarify & Expand Instructions": {
name: "Clarify & Expand Instructions",
template:
"The provided selection contains instructions that need to be expanded and clarified. Expand these instructions so that someone new to the task fully understands what needs to be done. Use clear, detailed explanations, examples if necessary, and break down any complex points into simpler parts. Ensure the expanded instructions maintain the original meaning and provide a comprehensive understanding. Return only the expanded instructions.",
},
"Clarify & Expand Role Description": {
name: "Clarify & Expand Role Description",
template:
"The provided selection contains a brief role description. Expand and clarify this description by explaining the responsibilities, goals, and perspective someone playing this role should adopt. Use detailed and clear language, including relevant context or examples. Maintain the original intent while making the explanation comprehensive. Return only the expanded role description.",
},
};

View file

@ -21,130 +21,130 @@ Customization:
*/
.PURE {
--noshadow: 0 0 0 var(--text-normal);
--littleshadow: 1px 1px 4px var(--text-normal);
--littleshadowhover: 4px 4px 16px var(--text-normal);
--bigshadow: 2px 2px 8px var(--text-normal);
--bigshadowhover: 8px 8px 32px var(--text-normal);
--noshadow: 0 0 0 var(--text-normal);
--littleshadow: 1px 1px 4px var(--text-normal);
--littleshadowhover: 4px 4px 16px var(--text-normal);
--bigshadow: 2px 2px 8px var(--text-normal);
--bigshadowhover: 8px 8px 32px var(--text-normal);
}
.PURE.floattop {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: var(--background-secondary);
border-bottom: var(--border-width) solid var(--background-modifier-border);
padding: 1em;
z-index: 100;
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: var(--background-secondary);
border-bottom: var(--border-width) solid var(--background-modifier-border);
padding: 1em;
z-index: 100;
}
.PURE.messageContainer.user {
text-align: right;
gap: 10px;
text-align: right;
gap: 10px;
}
.PURE.messageContainer.system,
.PURE.messageContainer.developer {
text-align: center;
gap: 10px;
text-align: center;
gap: 10px;
}
.PURE.messageContainer.assistant {
text-align: left;
gap: 10px;
text-align: left;
gap: 10px;
}
.PURE.messageHeader {
text-shadow: var(--noshadow);
transition: text-shadow 0.3s ease;
text-shadow: var(--noshadow);
transition: text-shadow 0.3s ease;
}
.PURE.messageHeader:hover {
text-shadow: var(--littleshadowhover);
text-shadow: var(--littleshadowhover);
}
.PURE.preview.user,
.PURE.preview.system,
.PURE.preview.developer,
.PURE.preview.assistant {
max-width: 90%;
display: inline-block;
max-width: 90%;
display: inline-block;
}
.PURE.preview.user {
margin-left: auto;
margin-right: 0;
margin-left: auto;
margin-right: 0;
}
.PURE.preview.system,
.PURE.preview.developer {
margin: auto;
margin: auto;
}
.PURE.preview.assistant {
margin-left: 0;
margin-right: auto;
margin-left: 0;
margin-right: auto;
}
.PURE.messageMarkdown {
padding: 0 var(--size-4-4);
max-height: 10em;
overflow: hidden;
border: var(--border-width) solid var(--background-modifier-border);
border-radius: var(--radius-m);
font-size: 0.75em;
text-align: left;
box-shadow: var(--bigshadow);
transition: box-shadow 0.3s ease;
padding: 0 var(--size-4-4);
max-height: 10em;
overflow: hidden;
border: var(--border-width) solid var(--background-modifier-border);
border-radius: var(--radius-m);
font-size: 0.75em;
text-align: left;
box-shadow: var(--bigshadow);
transition: box-shadow 0.3s ease;
}
.PURE.messageMarkdown:hover {
box-shadow: var(--bigshadowhover);
box-shadow: var(--bigshadowhover);
}
.PURE.messageMarkdown.user {
border-radius: 0 var(--radius-xl);
border-radius: 0 var(--radius-xl);
}
.PURE.messageMarkdown.assistant {
border-radius: var(--radius-xl) 0;
border-radius: var(--radius-xl) 0;
}
.PURE.messageMarkdown.system {
border-radius: var(--radius-xl) var(--radius-xl) 0 0;
border-radius: var(--radius-xl) var(--radius-xl) 0 0;
}
.PURE.messageMarkdown pre .copy-code-button {
display: none;
display: none;
}
.PURE.preview button {
margin: 0.5em;
box-shadow: var(--littleshadow);
transition: box-shadow 0.3s ease;
margin: 0.5em;
box-shadow: var(--littleshadow);
transition: box-shadow 0.3s ease;
}
.PURE.preview button:hover {
box-shadow: var(--littleshadowhover);
box-shadow: var(--littleshadowhover);
}
.PURE.preview.user button {
border-radius: 0 var(--radius-m);
border-radius: 0 var(--radius-m);
}
.PURE.preview.assistant button {
border-radius: var(--radius-m) 0;
border-radius: var(--radius-m) 0;
}
.PURE.setting-item textarea {
width: 100%;
height: 7em;
resize: none;
width: 100%;
height: 7em;
resize: none;
}
.PUREcodePreview {
width: 100%;
min-height: 10em;
resize: vertical;
width: 100%;
min-height: 10em;
resize: vertical;
}

View file

@ -9,5 +9,6 @@
"1.1.1": "1.8.10",
"1.1.2": "1.8.10",
"1.1.3": "1.8.10",
"1.1.4": "1.8.10"
"1.1.4": "1.8.10",
"1.1.5": "1.8.10"
}