mirror of
https://github.com/logancyang/obsidian-copilot.git
synced 2026-07-22 07:50:24 +00:00
* feat(relevant-notes): dedicated pane with redesigned populated view
Move Relevant Notes out of the chat into its own command-opened pane
("Open Relevant Notes") and redesign the populated view: a toolbar with
the active-note context line + Build index, color-graded relevance
meters/percentages, a "Best" tag, hover quick actions, a live indexing
overlay, and a restyled hover preview card. Add-to-Chat routes a wikilink
into the open chat/agent view via a new INSERT_TEXT_TO_CHAT event.
Rank relevant notes by semantic similarity only so the displayed
percentages stay monotonic — links no longer boost the score (link-only
notes still appear, without a meter). Remove the old in-chat Relevant
Notes block and its showRelevantNotes setting; update docs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refine(relevant-notes): linear meter, link badges, excluded state, preview fixes
- Meter width now maps 1:1 to the similarity score (70% → 70%).
- Add an excluded-file empty state when the active note is outside the
index inclusion/exclusion settings (takes priority over build/list).
- Replace the "Best" badge with Outgoing-link / Backlink badges; the
badge+percentage cluster swaps for the action buttons on hover.
- Move row action buttons into the flex flow so the title never overlaps
them and truncates with an ellipsis in both states.
- Render preview snippet line breaks (whitespace-pre-line).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(relevant-notes): route Add to Chat to the last-focused chat view
The Relevant Notes "Add to Chat" action hardcoded agent-first when picking
the target chat (getLeavesOfType(CHAT_AGENT_VIEWTYPE)[0] ?? legacy), so with
both chats open the wikilink landed in the wrong one. Reuse the existing
lastActiveChatViewType tracking (added for the add-to-context commands in
#2555) via a shared pickContextChatViewType() helper, so the chat we reveal
and the chat we type into always agree.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refine(relevant-notes): show full note content in a scrollable preview
The hover-card preview truncated content two ways: the loaded text was
sliced to 1000 chars and the paragraph was clamped to 4 lines. Drop the
slice and replace line-clamp with a bounded, scrollable area (max-h-64 +
overflow-y-auto) so the full note is reachable in a slightly larger box.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refine(relevant-notes): replace mount-timing setTimeouts with reliable signals
Address PR review on the Relevant Notes work:
- insertTextIntoActiveChat: drop the 50ms guess. The chat views' event bus
(ChatViewEventTarget) now latches queued "insert text"; the view drains it
on mount and ChatInputContext buffers/flushes it when the Lexical editor
registers, so delivery no longer depends on mount timing.
- RelevantNotesView: drop the 50ms initial dispatch. useActiveFile now seeds
from the current active file on mount, so the pane populates immediately and
still updates via the active-leaf-change listener.
- RelevanceMeter: route the score-driven width/color through CSS variables
(.copilot-relevance-meter-fill) instead of an inline style.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1069 lines
38 KiB
TypeScript
1069 lines
38 KiB
TypeScript
import { CustomModel } from "@/aiParams";
|
|
import { type CopilotSettings } from "@/settings/model";
|
|
import { v4 as uuidv4 } from "uuid";
|
|
import { ChainType } from "./chainType";
|
|
import { PromptSortStrategy } from "./types";
|
|
|
|
export const BREVILABS_API_BASE_URL = "https://api.brevilabs.com/v1";
|
|
export const BREVILABS_MODELS_BASE_URL = "https://models.brevilabs.com/v1";
|
|
export const CHAT_VIEWTYPE = "copilot-chat-view";
|
|
export const CHAT_AGENT_VIEWTYPE = "copilot-agent-chat-view";
|
|
export const RELEVANT_NOTES_VIEWTYPE = "copilot-relevant-notes-view";
|
|
|
|
// Custom Obsidian icon for Agent Mode surfaces (view tab, ribbon, commands).
|
|
// The v4 monochrome brand mark, normalized from its source viewBox "4 4 152 127"
|
|
// into Obsidian's 0 0 100 100 icon space; currentColor lets it track the theme
|
|
// and the active/hover tab state instead of a fixed fill. Register via addIcon().
|
|
export const COPILOT_AGENT_ICON_ID = "copilot-agent";
|
|
export const COPILOT_AGENT_ICON_SVG = `<g transform="translate(0 8.2) scale(0.6579) translate(-4 -4)"><path fill="currentColor" d="M75.9 6.9c-6.8 1.4-12.5 6-35.5 29.3-33.5 33.8-33.5 33.9-34.2 62.2-0.3 12.4 0 20.2 0.7 22.7 2.4 7.8 10.8 11.2 17.6 7.1 1.7-1.1 14.9-14.1 29.5-29.1 14.5-14.9 26.7-27 27-26.9 0.3 0.2 12.4 12.4 27 27.3 14.6 14.8 27.6 27.8 29 28.7 5.1 3.6 13.6 1.4 16.5-4.2 1.2-2.3 1.5-6.9 1.5-22.3 0-22.9-1.2-28.6-8.3-37.9-7.6-10.2-50-52.3-54.9-54.6-5.1-2.4-10.9-3.2-15.9-2.3z"/></g>`;
|
|
|
|
export const USER_SENDER = "user";
|
|
export const AI_SENDER = "ai";
|
|
|
|
// Default folder names
|
|
export const COPILOT_FOLDER_ROOT = "copilot";
|
|
const DEFAULT_CHAT_HISTORY_FOLDER = `${COPILOT_FOLDER_ROOT}/copilot-conversations`;
|
|
const DEFAULT_CUSTOM_PROMPTS_FOLDER = `${COPILOT_FOLDER_ROOT}/copilot-custom-prompts`;
|
|
const DEFAULT_MEMORY_FOLDER = `${COPILOT_FOLDER_ROOT}/memory`;
|
|
const DEFAULT_SYSTEM_PROMPTS_FOLDER = `${COPILOT_FOLDER_ROOT}/system-prompts`;
|
|
const DEFAULT_PROJECTS_FOLDER = `${COPILOT_FOLDER_ROOT}/projects`;
|
|
export const DEFAULT_SKILLS_FOLDER = `${COPILOT_FOLDER_ROOT}/skills`;
|
|
const DEFAULT_CONVERTED_DOC_OUTPUT_FOLDER = "";
|
|
export const DEFAULT_QA_EXCLUSIONS_SETTING = COPILOT_FOLDER_ROOT;
|
|
export const DEFAULT_SYSTEM_PROMPT = `You are Obsidian Copilot, a helpful assistant that integrates AI to Obsidian note-taking.
|
|
1. Never mention that you do not have access to something. Always rely on the user provided context.
|
|
2. Always answer to the best of your knowledge. If you are unsure about something, say so and ask the user to provide more context.
|
|
3. If the user mentions "note", it most likely means an Obsidian note in the vault, not the generic meaning of a note.
|
|
4. If the user mentions "@vault", it means the user wants you to search the Obsidian vault for information relevant to the query. The search results will be provided to you in the context along with the user query, read it carefully and answer the question based on the information provided. If there's no relevant information in the vault, just say so.
|
|
5. If the user mentions any other tool with the @ symbol, check the context for their results. If nothing is found, just ignore the @ symbol in the query.
|
|
6. Always use $'s instead of \\[ etc. for LaTeX equations.
|
|
7. When showing note titles, use [[title]] format and do not wrap them in \` \`.
|
|
8. When showing **Obsidian internal** image links, use ![[link]] format and do not wrap them in \` \`.
|
|
9. When showing **web** image links, use  format and do not wrap them in \` \`.
|
|
10. When generating a table, format as github markdown tables, however, for table headings, immediately add ' |' after the table heading.
|
|
11. Always respond in the language of the user's query.
|
|
12. Do NOT mention the additional context provided such as getCurrentTime and getTimeRangeMs if it's irrelevant to the user message.
|
|
13. If the user mentions "tags", it most likely means tags in Obsidian note properties.
|
|
14. YouTube URLs: If the user provides YouTube URLs in their message, transcriptions will be automatically fetched and provided to you. You don't need to do anything special - just use the transcription content if available.
|
|
15. For markdown lists, always use '- ' (hyphen followed by exactly one space) for bullet points, with no leading spaces before the hyphen. Never use '*' (asterisk) for bullets.`;
|
|
|
|
export const COMPOSER_OUTPUT_INSTRUCTIONS = `Return the new note content or canvas JSON in <writeFile> tags.
|
|
|
|
# Steps to find the the target notes
|
|
1. Extract the target note information from user message and find out the note path from the context below.
|
|
2. If target note is not specified, use the <active_note> as the target note.
|
|
3. If still failed to find the target note or the note path, ask the user to specify the target note.
|
|
|
|
# Examples
|
|
|
|
Input: Add a new section to note A
|
|
Output:
|
|
<writeFile>
|
|
<path>path/to/file.md</path>
|
|
<content>The FULL CONTENT of the note A with added section goes here</content>
|
|
</writeFile>
|
|
|
|
Input: Create a new canvas with "Hello, world!"
|
|
Output:
|
|
<writeFile>
|
|
<path>path/to/file.canvas</path>
|
|
<content>
|
|
{
|
|
"nodes": [
|
|
{
|
|
"id": "1",
|
|
"type": "text",
|
|
"text": "Hello, world!",
|
|
"x": 0,
|
|
"y": 0,
|
|
"width": 200,
|
|
"height": 50
|
|
}
|
|
],
|
|
"edges": []
|
|
}
|
|
</content>
|
|
</writeFile>
|
|
|
|
Input: Create a canvas with a file node and a group
|
|
Output:
|
|
<writeFile>
|
|
<path>path/to/file.canvas</path>
|
|
<content>
|
|
{
|
|
"nodes": [
|
|
{"id": "1", "type": "file", "file": "note.md", "subpath": "#heading", "x": 100, "y": 100, "width": 300, "height": 200, "color": "2"},
|
|
{"id": "2", "type": "group", "label": "My Group", "x": 50, "y": 50, "width": 400, "height": 300, "color": "1"},
|
|
{"id": "3", "type": "link", "url": "https://example.com", "x": 500, "y": 100, "width": 200, "height": 100, "color": "#FF5733"}
|
|
],
|
|
"edges": [
|
|
{"id": "e1-2", "fromNode": "1", "toNode": "3", "fromSide": "right", "toSide": "left", "fromEnd": "arrow", "toEnd": "none", "color": "3", "label": "references"}
|
|
]
|
|
}
|
|
</content>
|
|
</writeFile>
|
|
|
|
# Canvas JSON Format (JSON Canvas spec 1.0)
|
|
Required node fields: id, type, x, y, width, height
|
|
Node types: "text" (needs text), "file" (needs file), "link" (needs url), "group" (optional label)
|
|
Optional node fields: color (hex #FF0000 or preset "1"-"6"), subpath (file nodes, starts with #)
|
|
Required edge fields: id, fromNode, toNode
|
|
Optional edge fields: fromSide/toSide ("top"/"right"/"bottom"/"left"), fromEnd/toEnd ("none"/"arrow"), color, label
|
|
All IDs must be unique. Edge nodes must reference existing node IDs.
|
|
Position nodes with reasonable spacing and logical visual flow.
|
|
`;
|
|
|
|
export const NOTE_CONTEXT_PROMPT_TAG = "note_context";
|
|
export const SELECTED_TEXT_TAG = "selected_text";
|
|
export const WEB_SELECTED_TEXT_TAG = "web_selected_text";
|
|
export const VARIABLE_TAG = "variable";
|
|
export const VARIABLE_NOTE_TAG = "variable_note";
|
|
export const EMBEDDED_PDF_TAG = "embedded_pdf";
|
|
export const EMBEDDED_NOTE_TAG = "embedded_note";
|
|
export const DATAVIEW_BLOCK_TAG = "dataview_block";
|
|
export const RETRIEVED_DOCUMENT_TAG = "retrieved_document";
|
|
export const WEB_TAB_CONTEXT_TAG = "web_tab_context";
|
|
export const ACTIVE_WEB_TAB_CONTEXT_TAG = "active_web_tab";
|
|
export const YOUTUBE_VIDEO_CONTEXT_TAG = "youtube_video_context";
|
|
/** Marker text used as placeholder for active web tab in serialized content */
|
|
export const ACTIVE_WEB_TAB_MARKER = "{activeWebTab}";
|
|
export const CHUNK_SIZE = 6000;
|
|
export const TEXT_WEIGHT = 0.4;
|
|
export const MAX_CHARS_FOR_LOCAL_SEARCH_CONTEXT = 448000;
|
|
export const LLM_TIMEOUT_MS = 30000; // 30 seconds timeout for LLM operations
|
|
const DEFAULT_MAX_SOURCE_CHUNKS = 30; // Default max chunks for search results (with diverse top-K)
|
|
export const AGENT_LOOP_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes timeout for agent loop
|
|
export const AGENT_MAX_ITERATIONS_LIMIT = 16; // Maximum allowed value for agent iterations setting
|
|
export const LOADING_MESSAGES = {
|
|
DEFAULT: "",
|
|
READING_FILES: "Reading files",
|
|
SEARCHING_WEB: "Searching the web",
|
|
READING_FILE_TREE: "Reading file tree",
|
|
COMPACTING: "Compacting",
|
|
};
|
|
export const PLUS_UTM_MEDIUMS = {
|
|
SETTINGS: "settings",
|
|
EXPIRED_MODAL: "expired_modal",
|
|
CHAT_MODE_SELECT: "chat_mode_select",
|
|
MODE_SELECT_TOOLTIP: "mode_select_tooltip",
|
|
};
|
|
export type PlusUtmMedium = (typeof PLUS_UTM_MEDIUMS)[keyof typeof PLUS_UTM_MEDIUMS];
|
|
|
|
/**
|
|
* Reasoning effort levels for OpenAI reasoning models
|
|
*/
|
|
export enum ReasoningEffort {
|
|
MINIMAL = "minimal",
|
|
LOW = "low",
|
|
MEDIUM = "medium",
|
|
HIGH = "high",
|
|
XHIGH = "xhigh",
|
|
}
|
|
|
|
/**
|
|
* Output verbosity levels for GPT-5 models
|
|
*/
|
|
export enum Verbosity {
|
|
LOW = "low",
|
|
MEDIUM = "medium",
|
|
HIGH = "high",
|
|
}
|
|
|
|
export const DEFAULT_MODEL_SETTING = {
|
|
MAX_TOKENS: 6000,
|
|
TEMPERATURE: 0.1,
|
|
REASONING_EFFORT: ReasoningEffort.LOW,
|
|
VERBOSITY: Verbosity.MEDIUM,
|
|
} as const;
|
|
|
|
// Reason: Ollama defaults to a small context window (2048). We override to 131072
|
|
// for backward compatibility (PR #2147), configurable via UI (#2275).
|
|
export const DEFAULT_OLLAMA_NUM_CTX = 131072;
|
|
|
|
export enum ChatModels {
|
|
COPILOT_PLUS_FLASH = "copilot-plus-flash",
|
|
GPT_5_5 = "gpt-5.5",
|
|
GPT_5_4_mini = "gpt-5.4-mini",
|
|
GPT_41 = "gpt-4.1",
|
|
GPT_41_mini = "gpt-4.1-mini",
|
|
GEMINI_3_PRO_PREVIEW = "gemini-3.1-pro-preview",
|
|
GEMINI_3_5_FLASH = "gemini-3.5-flash",
|
|
GEMINI_3_FLASH_LITE = "gemini-3.1-flash-lite",
|
|
GEMINI_PRO = "gemini-2.5-pro",
|
|
GEMINI_FLASH = "gemini-2.5-flash",
|
|
CLAUDE_OPUS_4_7 = "claude-opus-4-7",
|
|
CLAUDE_SONNET_4_6 = "claude-sonnet-4-6",
|
|
CLAUDE_HAIKU_4_5 = "claude-haiku-4-5",
|
|
GROK_4_3 = "grok-4.3",
|
|
GROQ_LLAMA_8b = "llama3-8b-8192",
|
|
COMMAND_R = "command-r",
|
|
MISTRAL_TINY = "mistral-tiny-latest",
|
|
DEEPSEEK_REASONER = "deepseek-reasoner",
|
|
DEEPSEEK_CHAT = "deepseek-chat",
|
|
OPENROUTER_GEMINI_3_5_FLASH = "google/gemini-3.5-flash",
|
|
OPENROUTER_GEMINI_3_PRO_PREVIEW = "google/gemini-3.1-pro-preview",
|
|
OPENROUTER_GEMINI_2_5_FLASH = "google/gemini-2.5-flash",
|
|
OPENROUTER_GEMINI_2_5_PRO = "google/gemini-2.5-pro",
|
|
OPENROUTER_GPT_5_5 = "openai/gpt-5.5",
|
|
OPENROUTER_GPT_5_4_MINI = "openai/gpt-5.4-mini",
|
|
OPENROUTER_GROK_4_3 = "x-ai/grok-4.3",
|
|
SILICONFLOW_DEEPSEEK_V3 = "deepseek-ai/DeepSeek-V3",
|
|
SILICONFLOW_DEEPSEEK_R1 = "deepseek-ai/DeepSeek-R1",
|
|
}
|
|
|
|
// Model Providers
|
|
export enum ChatModelProviders {
|
|
OPENROUTERAI = "openrouterai",
|
|
OPENAI = "openai",
|
|
OPENAI_FORMAT = "3rd party (openai-format)",
|
|
ANTHROPIC = "anthropic",
|
|
GOOGLE = "google",
|
|
XAI = "xai",
|
|
AMAZON_BEDROCK = "amazon-bedrock",
|
|
AZURE_OPENAI = "azure openai",
|
|
GROQ = "groq",
|
|
OLLAMA = "ollama",
|
|
LM_STUDIO = "lm-studio",
|
|
COPILOT_PLUS = "copilot-plus",
|
|
MISTRAL = "mistralai",
|
|
DEEPSEEK = "deepseek",
|
|
COHEREAI = "cohereai",
|
|
SILICONFLOW = "siliconflow",
|
|
GITHUB_COPILOT = "github-copilot",
|
|
}
|
|
|
|
export enum ModelCapability {
|
|
REASONING = "reasoning",
|
|
VISION = "vision",
|
|
WEB_SEARCH = "websearch",
|
|
}
|
|
|
|
export const MODEL_CAPABILITIES: Record<ModelCapability, string> = {
|
|
reasoning: "This model supports general reasoning tasks.",
|
|
vision: "This model supports image inputs.",
|
|
websearch: "This model can access the internet.",
|
|
};
|
|
|
|
export const BUILTIN_CHAT_MODELS: CustomModel[] = [
|
|
// Enabled models first
|
|
{
|
|
name: ChatModels.COPILOT_PLUS_FLASH,
|
|
provider: ChatModelProviders.COPILOT_PLUS,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
core: true,
|
|
plusExclusive: true,
|
|
projectEnabled: false,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.OPENROUTER_GEMINI_2_5_FLASH,
|
|
provider: ChatModelProviders.OPENROUTERAI,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
core: true,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.OPENROUTER_GEMINI_3_5_FLASH,
|
|
provider: ChatModelProviders.OPENROUTERAI,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION, ModelCapability.REASONING],
|
|
},
|
|
{
|
|
name: ChatModels.GPT_5_5,
|
|
provider: ChatModelProviders.OPENAI,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
core: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.GPT_5_4_mini,
|
|
provider: ChatModelProviders.OPENAI,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
core: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.CLAUDE_SONNET_4_6,
|
|
provider: ChatModelProviders.ANTHROPIC,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
capabilities: [ModelCapability.VISION, ModelCapability.REASONING],
|
|
},
|
|
{
|
|
name: ChatModels.GEMINI_3_5_FLASH,
|
|
provider: ChatModelProviders.GOOGLE,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION, ModelCapability.REASONING],
|
|
},
|
|
{
|
|
name: ChatModels.GEMINI_3_FLASH_LITE,
|
|
provider: ChatModelProviders.GOOGLE,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.GEMINI_FLASH,
|
|
provider: ChatModelProviders.GOOGLE,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
// Disabled models
|
|
{
|
|
name: ChatModels.OPENROUTER_GEMINI_3_PRO_PREVIEW,
|
|
provider: ChatModelProviders.OPENROUTERAI,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
capabilities: [ModelCapability.VISION, ModelCapability.REASONING],
|
|
},
|
|
{
|
|
name: ChatModels.OPENROUTER_GEMINI_2_5_PRO,
|
|
provider: ChatModelProviders.OPENROUTERAI,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
core: false,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.OPENROUTER_GPT_5_5,
|
|
provider: ChatModelProviders.OPENROUTERAI,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
core: false,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.OPENROUTER_GPT_5_4_MINI,
|
|
provider: ChatModelProviders.OPENROUTERAI,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
core: false,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.GROK_4_3,
|
|
provider: ChatModelProviders.XAI,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
core: false,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.OPENROUTER_GROK_4_3,
|
|
provider: ChatModelProviders.OPENROUTERAI,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
core: false,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.GPT_41,
|
|
provider: ChatModelProviders.OPENAI,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
core: false,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.GPT_41_mini,
|
|
provider: ChatModelProviders.OPENAI,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
core: false,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.CLAUDE_OPUS_4_7,
|
|
provider: ChatModelProviders.ANTHROPIC,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
capabilities: [ModelCapability.VISION, ModelCapability.REASONING],
|
|
},
|
|
{
|
|
name: ChatModels.CLAUDE_HAIKU_4_5,
|
|
provider: ChatModelProviders.ANTHROPIC,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
capabilities: [ModelCapability.VISION, ModelCapability.REASONING],
|
|
},
|
|
{
|
|
name: ChatModels.GEMINI_3_PRO_PREVIEW,
|
|
provider: ChatModelProviders.GOOGLE,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
capabilities: [ModelCapability.VISION, ModelCapability.REASONING],
|
|
},
|
|
{
|
|
name: ChatModels.GEMINI_PRO,
|
|
provider: ChatModelProviders.GOOGLE,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
projectEnabled: true,
|
|
capabilities: [ModelCapability.VISION],
|
|
},
|
|
{
|
|
name: ChatModels.DEEPSEEK_CHAT,
|
|
provider: ChatModelProviders.DEEPSEEK,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
},
|
|
{
|
|
name: ChatModels.DEEPSEEK_REASONER,
|
|
provider: ChatModelProviders.DEEPSEEK,
|
|
enabled: false,
|
|
isBuiltIn: true,
|
|
capabilities: [ModelCapability.REASONING],
|
|
},
|
|
{
|
|
name: ChatModels.SILICONFLOW_DEEPSEEK_V3,
|
|
provider: ChatModelProviders.SILICONFLOW,
|
|
enabled: false,
|
|
isBuiltIn: false,
|
|
baseUrl: "https://api.siliconflow.com/v1",
|
|
},
|
|
{
|
|
name: ChatModels.SILICONFLOW_DEEPSEEK_R1,
|
|
provider: ChatModelProviders.SILICONFLOW,
|
|
enabled: false,
|
|
isBuiltIn: false,
|
|
baseUrl: "https://api.siliconflow.com/v1",
|
|
capabilities: [ModelCapability.REASONING],
|
|
},
|
|
];
|
|
|
|
export enum EmbeddingModelProviders {
|
|
OPENAI = "openai",
|
|
OPENROUTERAI = "openrouterai",
|
|
COHEREAI = "cohereai",
|
|
GOOGLE = "google",
|
|
AZURE_OPENAI = "azure openai",
|
|
OLLAMA = "ollama",
|
|
LM_STUDIO = "lm-studio",
|
|
OPENAI_FORMAT = "3rd party (openai-format)",
|
|
COPILOT_PLUS = "copilot-plus",
|
|
COPILOT_PLUS_JINA = "copilot-plus-jina",
|
|
SILICONFLOW = "siliconflow",
|
|
}
|
|
|
|
export enum EmbeddingModels {
|
|
OPENAI_EMBEDDING_SMALL = "text-embedding-3-small",
|
|
OPENAI_EMBEDDING_LARGE = "text-embedding-3-large",
|
|
AZURE_OPENAI = "azure-openai",
|
|
COHEREAI_EMBED_MULTILINGUAL_LIGHT_V3_0 = "embed-multilingual-light-v3.0",
|
|
GOOGLE_ENG = "text-embedding-004",
|
|
GOOGLE_GEMINI_EMBEDDING = "gemini-embedding-001",
|
|
GOOGLE_GEMINI_EMBEDDING_2_PREVIEW = "gemini-embedding-2-preview",
|
|
COPILOT_PLUS_SMALL = "copilot-plus-small",
|
|
COPILOT_PLUS_LARGE = "copilot-plus-large",
|
|
COPILOT_PLUS_MULTILINGUAL = "copilot-plus-multilingual",
|
|
SILICONFLOW_QWEN3_EMBEDDING_0_6B = "Qwen/Qwen3-Embedding-0.6B",
|
|
OPENROUTER_OPENAI_EMBEDDING_SMALL = "openai/text-embedding-3-small",
|
|
}
|
|
|
|
export const BUILTIN_EMBEDDING_MODELS: CustomModel[] = [
|
|
{
|
|
name: EmbeddingModels.COPILOT_PLUS_SMALL,
|
|
provider: EmbeddingModelProviders.COPILOT_PLUS,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
isEmbeddingModel: true,
|
|
core: true,
|
|
plusExclusive: true,
|
|
},
|
|
{
|
|
name: EmbeddingModels.COPILOT_PLUS_LARGE,
|
|
provider: EmbeddingModelProviders.COPILOT_PLUS_JINA,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
isEmbeddingModel: true,
|
|
core: true,
|
|
plusExclusive: true,
|
|
believerExclusive: true,
|
|
dimensions: 1024,
|
|
},
|
|
{
|
|
name: EmbeddingModels.COPILOT_PLUS_MULTILINGUAL,
|
|
provider: EmbeddingModelProviders.COPILOT_PLUS_JINA,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
isEmbeddingModel: true,
|
|
core: true,
|
|
plusExclusive: true,
|
|
dimensions: 512,
|
|
},
|
|
{
|
|
name: EmbeddingModels.OPENROUTER_OPENAI_EMBEDDING_SMALL,
|
|
provider: EmbeddingModelProviders.OPENROUTERAI,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
isEmbeddingModel: true,
|
|
core: true,
|
|
},
|
|
{
|
|
name: EmbeddingModels.OPENAI_EMBEDDING_SMALL,
|
|
provider: EmbeddingModelProviders.OPENAI,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
isEmbeddingModel: true,
|
|
core: true,
|
|
},
|
|
{
|
|
name: EmbeddingModels.OPENAI_EMBEDDING_LARGE,
|
|
provider: EmbeddingModelProviders.OPENAI,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
isEmbeddingModel: true,
|
|
},
|
|
{
|
|
name: EmbeddingModels.COHEREAI_EMBED_MULTILINGUAL_LIGHT_V3_0,
|
|
provider: EmbeddingModelProviders.COHEREAI,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
isEmbeddingModel: true,
|
|
},
|
|
{
|
|
name: EmbeddingModels.GOOGLE_ENG,
|
|
provider: EmbeddingModelProviders.GOOGLE,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
isEmbeddingModel: true,
|
|
},
|
|
{
|
|
name: EmbeddingModels.GOOGLE_GEMINI_EMBEDDING,
|
|
provider: EmbeddingModelProviders.GOOGLE,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
isEmbeddingModel: true,
|
|
core: true,
|
|
},
|
|
{
|
|
name: EmbeddingModels.GOOGLE_GEMINI_EMBEDDING_2_PREVIEW,
|
|
provider: EmbeddingModelProviders.GOOGLE,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
isEmbeddingModel: true,
|
|
core: true,
|
|
},
|
|
{
|
|
name: EmbeddingModels.AZURE_OPENAI,
|
|
provider: EmbeddingModelProviders.AZURE_OPENAI,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
isEmbeddingModel: true,
|
|
},
|
|
{
|
|
name: EmbeddingModels.SILICONFLOW_QWEN3_EMBEDDING_0_6B,
|
|
provider: EmbeddingModelProviders.SILICONFLOW,
|
|
enabled: true,
|
|
isBuiltIn: true,
|
|
isEmbeddingModel: true,
|
|
core: true,
|
|
baseUrl: "https://api.siliconflow.com/v1",
|
|
},
|
|
];
|
|
|
|
// Embedding Models
|
|
export const NOMIC_EMBED_TEXT = "nomic-embed-text";
|
|
// export const DISTILBERT_NLI = 'sentence-transformers/distilbert-base-nli-mean-tokens';
|
|
// export const INSTRUCTOR_XL = 'hkunlp/instructor-xl'; // Inference API is off for this
|
|
// export const MPNET_V2 = 'sentence-transformers/all-mpnet-base-v2'; // Inference API returns 400
|
|
|
|
export type Provider = ChatModelProviders | EmbeddingModelProviders;
|
|
|
|
export type SettingKeyProviders = Exclude<
|
|
ChatModelProviders,
|
|
ChatModelProviders.OPENAI_FORMAT | ChatModelProviders.LM_STUDIO | ChatModelProviders.OLLAMA
|
|
>;
|
|
|
|
// Provider metadata interface
|
|
export interface ProviderMetadata {
|
|
label: string;
|
|
host: string;
|
|
/**
|
|
* Base URL used when generating example curl commands (and UI placeholders).
|
|
* This must be deterministic and must NOT include endpoint suffixes like `/chat/completions`.
|
|
* It intentionally does not affect runtime SDK configuration.
|
|
*/
|
|
curlBaseURL: string;
|
|
keyManagementURL: string;
|
|
listModelURL: string;
|
|
testModel?: ChatModels;
|
|
}
|
|
|
|
// Unified provider information
|
|
export const ProviderInfo: Record<Provider, ProviderMetadata> = {
|
|
[ChatModelProviders.OPENROUTERAI]: {
|
|
label: "OpenRouter",
|
|
host: "https://openrouter.ai/api/v1/",
|
|
curlBaseURL: "https://openrouter.ai/api/v1",
|
|
keyManagementURL: "https://openrouter.ai/keys",
|
|
listModelURL: "https://openrouter.ai/api/v1/models",
|
|
testModel: ChatModels.OPENROUTER_GPT_5_4_MINI,
|
|
},
|
|
[ChatModelProviders.GOOGLE]: {
|
|
label: "Gemini",
|
|
host: "https://generativelanguage.googleapis.com",
|
|
curlBaseURL: "https://generativelanguage.googleapis.com/v1beta",
|
|
keyManagementURL: "https://makersuite.google.com/app/apikey",
|
|
listModelURL: "https://generativelanguage.googleapis.com/v1beta/models",
|
|
testModel: ChatModels.GEMINI_FLASH,
|
|
},
|
|
[ChatModelProviders.ANTHROPIC]: {
|
|
label: "Anthropic",
|
|
host: "https://api.anthropic.com/",
|
|
curlBaseURL: "https://api.anthropic.com",
|
|
keyManagementURL: "https://console.anthropic.com/settings/keys",
|
|
listModelURL: "https://api.anthropic.com/v1/models",
|
|
testModel: ChatModels.CLAUDE_SONNET_4_6,
|
|
},
|
|
[ChatModelProviders.OPENAI]: {
|
|
label: "OpenAI",
|
|
host: "https://api.openai.com",
|
|
curlBaseURL: "https://api.openai.com/v1",
|
|
keyManagementURL: "https://platform.openai.com/api-keys",
|
|
listModelURL: "https://api.openai.com/v1/models",
|
|
testModel: ChatModels.GPT_5_5,
|
|
},
|
|
[ChatModelProviders.XAI]: {
|
|
label: "XAI",
|
|
host: "https://api.x.ai/v1",
|
|
curlBaseURL: "https://api.x.ai/v1",
|
|
keyManagementURL: "https://console.x.ai",
|
|
listModelURL: "https://api.x.ai/v1/models",
|
|
testModel: ChatModels.GROK_4_3,
|
|
},
|
|
[ChatModelProviders.AZURE_OPENAI]: {
|
|
label: "Azure",
|
|
host: "https://<resource>.services.ai.azure.com/models",
|
|
curlBaseURL: "https://<resource>.services.ai.azure.com/models",
|
|
keyManagementURL: "https://ai.azure.com",
|
|
listModelURL: "",
|
|
},
|
|
[ChatModelProviders.GROQ]: {
|
|
label: "Groq",
|
|
host: "https://api.groq.com/openai",
|
|
curlBaseURL: "https://api.groq.com/openai/v1",
|
|
keyManagementURL: "https://console.groq.com/keys",
|
|
listModelURL: "https://api.groq.com/openai/v1/models",
|
|
testModel: ChatModels.GROQ_LLAMA_8b,
|
|
},
|
|
[ChatModelProviders.COHEREAI]: {
|
|
label: "Cohere",
|
|
host: "https://api.cohere.ai/compatibility/v1",
|
|
curlBaseURL: "https://api.cohere.ai/compatibility/v1",
|
|
keyManagementURL: "https://dashboard.cohere.ai/api-keys",
|
|
listModelURL: "https://api.cohere.com/v1/models",
|
|
testModel: ChatModels.COMMAND_R,
|
|
},
|
|
[ChatModelProviders.SILICONFLOW]: {
|
|
label: "SiliconFlow",
|
|
host: "https://api.siliconflow.com/v1",
|
|
curlBaseURL: "https://api.siliconflow.com/v1",
|
|
keyManagementURL: "https://cloud.siliconflow.com/me/account/ak",
|
|
listModelURL: "https://api.siliconflow.com/v1/models",
|
|
testModel: ChatModels.SILICONFLOW_DEEPSEEK_V3,
|
|
},
|
|
[ChatModelProviders.OLLAMA]: {
|
|
label: "Ollama",
|
|
host: "http://localhost:11434/v1/",
|
|
curlBaseURL: "http://localhost:11434",
|
|
keyManagementURL: "",
|
|
listModelURL: "",
|
|
},
|
|
[ChatModelProviders.LM_STUDIO]: {
|
|
label: "LM Studio",
|
|
host: "http://localhost:1234/v1",
|
|
curlBaseURL: "http://localhost:1234/v1",
|
|
keyManagementURL: "",
|
|
listModelURL: "",
|
|
},
|
|
[ChatModelProviders.OPENAI_FORMAT]: {
|
|
label: "OpenAI Format",
|
|
host: "https://api.example.com/v1",
|
|
curlBaseURL: "https://api.example.com/v1",
|
|
keyManagementURL: "",
|
|
listModelURL: "",
|
|
},
|
|
[ChatModelProviders.MISTRAL]: {
|
|
label: "Mistral",
|
|
host: "https://api.mistral.ai/v1",
|
|
curlBaseURL: "https://api.mistral.ai/v1",
|
|
keyManagementURL: "https://console.mistral.ai/api-keys",
|
|
listModelURL: "https://api.mistral.ai/v1/models",
|
|
testModel: ChatModels.MISTRAL_TINY,
|
|
},
|
|
[ChatModelProviders.DEEPSEEK]: {
|
|
label: "DeepSeek",
|
|
host: "https://api.deepseek.com/",
|
|
curlBaseURL: "https://api.deepseek.com",
|
|
keyManagementURL: "https://platform.deepseek.com/api-keys",
|
|
listModelURL: "https://api.deepseek.com/models",
|
|
testModel: ChatModels.DEEPSEEK_CHAT,
|
|
},
|
|
[ChatModelProviders.AMAZON_BEDROCK]: {
|
|
label: "Amazon Bedrock",
|
|
host: "https://bedrock-runtime.{region}.amazonaws.com",
|
|
curlBaseURL: "https://bedrock-runtime.{region}.amazonaws.com",
|
|
keyManagementURL: "https://console.aws.amazon.com/iam/home#/security_credentials",
|
|
listModelURL: "",
|
|
},
|
|
[EmbeddingModelProviders.COPILOT_PLUS]: {
|
|
label: "Copilot Plus",
|
|
host: BREVILABS_MODELS_BASE_URL,
|
|
curlBaseURL: BREVILABS_MODELS_BASE_URL,
|
|
keyManagementURL: "",
|
|
listModelURL: "",
|
|
},
|
|
[EmbeddingModelProviders.COPILOT_PLUS_JINA]: {
|
|
label: "Copilot Plus",
|
|
host: BREVILABS_MODELS_BASE_URL,
|
|
curlBaseURL: BREVILABS_MODELS_BASE_URL,
|
|
keyManagementURL: "",
|
|
listModelURL: "",
|
|
},
|
|
[ChatModelProviders.GITHUB_COPILOT]: {
|
|
label: "GitHub Copilot",
|
|
host: "https://api.githubcopilot.com",
|
|
curlBaseURL: "https://api.githubcopilot.com",
|
|
keyManagementURL: "https://github.com/settings/apps/authorizations",
|
|
listModelURL: "",
|
|
},
|
|
};
|
|
|
|
// Map provider to its settings key for API key
|
|
export const ProviderSettingsKeyMap: Record<SettingKeyProviders, keyof CopilotSettings> = {
|
|
anthropic: "anthropicApiKey",
|
|
openai: "openAIApiKey",
|
|
"azure openai": "azureOpenAIApiKey",
|
|
google: "googleApiKey",
|
|
groq: "groqApiKey",
|
|
openrouterai: "openRouterAiApiKey",
|
|
cohereai: "cohereApiKey",
|
|
xai: "xaiApiKey",
|
|
"copilot-plus": "plusLicenseKey",
|
|
mistralai: "mistralApiKey",
|
|
deepseek: "deepseekApiKey",
|
|
"amazon-bedrock": "amazonBedrockApiKey",
|
|
siliconflow: "siliconflowApiKey",
|
|
"github-copilot": "githubCopilotToken",
|
|
};
|
|
|
|
export enum VAULT_VECTOR_STORE_STRATEGY {
|
|
NEVER = "NEVER",
|
|
ON_STARTUP = "ON STARTUP",
|
|
ON_MODE_SWITCH = "ON MODE SWITCH",
|
|
}
|
|
|
|
export const VAULT_VECTOR_STORE_STRATEGIES = [
|
|
VAULT_VECTOR_STORE_STRATEGY.NEVER,
|
|
VAULT_VECTOR_STORE_STRATEGY.ON_STARTUP,
|
|
VAULT_VECTOR_STORE_STRATEGY.ON_MODE_SWITCH,
|
|
];
|
|
|
|
export enum DEFAULT_OPEN_AREA {
|
|
EDITOR = "editor",
|
|
VIEW = "view",
|
|
}
|
|
|
|
export enum SEND_SHORTCUT {
|
|
ENTER = "enter",
|
|
SHIFT_ENTER = "shift+enter",
|
|
}
|
|
|
|
export const COMMAND_IDS = {
|
|
TRIGGER_QUICK_COMMAND: "trigger-quick-command",
|
|
CLEAR_LOCAL_COPILOT_INDEX: "clear-local-copilot-index",
|
|
CLEAR_COPILOT_CACHE: "clear-copilot-cache",
|
|
COUNT_WORD_AND_TOKENS_SELECTION: "count-word-and-tokens-selection",
|
|
COUNT_TOTAL_VAULT_TOKENS: "count-total-vault-tokens",
|
|
DEBUG_WORD_COMPLETION: "debug-word-completion",
|
|
FORCE_REINDEX_VAULT_TO_COPILOT_INDEX: "force-reindex-vault-to-copilot-index",
|
|
GARBAGE_COLLECT_COPILOT_INDEX: "garbage-collect-copilot-index",
|
|
INDEX_VAULT_TO_COPILOT_INDEX: "index-vault-to-copilot-index",
|
|
INSPECT_COPILOT_INDEX_BY_NOTE_PATHS: "copilot-inspect-index-by-note-paths",
|
|
LIST_INDEXED_FILES: "copilot-list-indexed-files",
|
|
LOAD_COPILOT_CHAT_CONVERSATION: "load-copilot-chat-conversation",
|
|
NEW_CHAT: "new-chat",
|
|
NEW_AGENT_CHAT: "new-agent-chat",
|
|
OPEN_COPILOT_CHAT_WINDOW: "chat-open-window",
|
|
OPEN_AGENT_CHAT_WINDOW: "agent-chat-open-window",
|
|
OPEN_RELEVANT_NOTES_VIEW: "open-relevant-notes-view",
|
|
SEARCH_ORAMA_DB: "copilot-search-orama-db",
|
|
TOGGLE_COPILOT_CHAT_WINDOW: "chat-toggle-window",
|
|
TOGGLE_AGENT_CHAT_WINDOW: "agent-chat-toggle-window",
|
|
ADD_SELECTION_TO_CHAT_CONTEXT: "add-selection-to-chat-context",
|
|
ADD_WEB_SELECTION_TO_CHAT_CONTEXT: "add-web-selection-to-chat-context",
|
|
ADD_CUSTOM_COMMAND: "add-custom-command",
|
|
APPLY_CUSTOM_COMMAND: "apply-custom-command",
|
|
OPEN_LOG_FILE: "open-log-file",
|
|
CLEAR_LOG_FILE: "clear-log-file",
|
|
DOWNLOAD_YOUTUBE_SCRIPT: "download-youtube-script",
|
|
TRIGGER_QUICK_ASK: "trigger-quick-ask",
|
|
} as const;
|
|
|
|
export const COMMAND_NAMES: Record<CommandId, string> = {
|
|
[COMMAND_IDS.TRIGGER_QUICK_COMMAND]: "Trigger quick command",
|
|
[COMMAND_IDS.CLEAR_LOCAL_COPILOT_INDEX]: "Clear local Copilot index",
|
|
[COMMAND_IDS.CLEAR_COPILOT_CACHE]: "Clear Copilot cache",
|
|
[COMMAND_IDS.COUNT_TOTAL_VAULT_TOKENS]: "Count total tokens in your vault",
|
|
[COMMAND_IDS.COUNT_WORD_AND_TOKENS_SELECTION]: "Count words and tokens in selection",
|
|
[COMMAND_IDS.DEBUG_WORD_COMPLETION]: "Word completion: Debug",
|
|
[COMMAND_IDS.FORCE_REINDEX_VAULT_TO_COPILOT_INDEX]: "Force reindex vault",
|
|
[COMMAND_IDS.GARBAGE_COLLECT_COPILOT_INDEX]:
|
|
"Garbage collect Copilot index (remove files that no longer exist in vault)",
|
|
[COMMAND_IDS.INDEX_VAULT_TO_COPILOT_INDEX]: "Index (refresh) vault",
|
|
[COMMAND_IDS.INSPECT_COPILOT_INDEX_BY_NOTE_PATHS]: "Inspect Copilot index by note paths (debug)",
|
|
[COMMAND_IDS.LIST_INDEXED_FILES]: "List all indexed files (debug)",
|
|
[COMMAND_IDS.LOAD_COPILOT_CHAT_CONVERSATION]: "Load Copilot chat conversation",
|
|
[COMMAND_IDS.NEW_CHAT]: "New Copilot Chat",
|
|
[COMMAND_IDS.NEW_AGENT_CHAT]: "New Copilot Agent Chat",
|
|
[COMMAND_IDS.OPEN_COPILOT_CHAT_WINDOW]: "Open Copilot Chat Window",
|
|
[COMMAND_IDS.OPEN_AGENT_CHAT_WINDOW]: "Open Copilot Agent Chat Window",
|
|
[COMMAND_IDS.OPEN_RELEVANT_NOTES_VIEW]: "Open Relevant Notes",
|
|
[COMMAND_IDS.SEARCH_ORAMA_DB]: "Search semantic index (debug)",
|
|
[COMMAND_IDS.TOGGLE_COPILOT_CHAT_WINDOW]: "Toggle Copilot Chat Window",
|
|
[COMMAND_IDS.TOGGLE_AGENT_CHAT_WINDOW]: "Toggle Copilot Agent Chat Window",
|
|
[COMMAND_IDS.ADD_SELECTION_TO_CHAT_CONTEXT]: "Add selection to chat context",
|
|
[COMMAND_IDS.ADD_WEB_SELECTION_TO_CHAT_CONTEXT]: "Add web selection to chat context",
|
|
[COMMAND_IDS.ADD_CUSTOM_COMMAND]: "Add new custom command",
|
|
[COMMAND_IDS.APPLY_CUSTOM_COMMAND]: "Apply custom command",
|
|
[COMMAND_IDS.OPEN_LOG_FILE]: "Create log file",
|
|
[COMMAND_IDS.CLEAR_LOG_FILE]: "Clear log file",
|
|
[COMMAND_IDS.DOWNLOAD_YOUTUBE_SCRIPT]: "Download YouTube Script (plus)",
|
|
[COMMAND_IDS.TRIGGER_QUICK_ASK]: "Quick Ask",
|
|
};
|
|
|
|
export type CommandId = (typeof COMMAND_IDS)[keyof typeof COMMAND_IDS];
|
|
|
|
/**
|
|
* Icons for commands displayed in the mobile toolbar.
|
|
* Uses Lucide icon names supported by Obsidian.
|
|
*/
|
|
export const COMMAND_ICONS: Partial<Record<CommandId, string>> = {
|
|
[COMMAND_IDS.NEW_CHAT]: "message-square-plus",
|
|
[COMMAND_IDS.NEW_AGENT_CHAT]: COPILOT_AGENT_ICON_ID,
|
|
[COMMAND_IDS.OPEN_COPILOT_CHAT_WINDOW]: "message-square",
|
|
[COMMAND_IDS.OPEN_AGENT_CHAT_WINDOW]: COPILOT_AGENT_ICON_ID,
|
|
[COMMAND_IDS.OPEN_RELEVANT_NOTES_VIEW]: "files",
|
|
[COMMAND_IDS.TOGGLE_COPILOT_CHAT_WINDOW]: "message-square",
|
|
[COMMAND_IDS.TOGGLE_AGENT_CHAT_WINDOW]: COPILOT_AGENT_ICON_ID,
|
|
[COMMAND_IDS.LOAD_COPILOT_CHAT_CONVERSATION]: "history",
|
|
[COMMAND_IDS.TRIGGER_QUICK_COMMAND]: "terminal-square",
|
|
[COMMAND_IDS.TRIGGER_QUICK_ASK]: "sparkles",
|
|
[COMMAND_IDS.ADD_SELECTION_TO_CHAT_CONTEXT]: "text-cursor-input",
|
|
[COMMAND_IDS.ADD_WEB_SELECTION_TO_CHAT_CONTEXT]: "globe",
|
|
[COMMAND_IDS.ADD_CUSTOM_COMMAND]: "plus-circle",
|
|
[COMMAND_IDS.APPLY_CUSTOM_COMMAND]: "play-circle",
|
|
[COMMAND_IDS.INDEX_VAULT_TO_COPILOT_INDEX]: "refresh-cw",
|
|
[COMMAND_IDS.FORCE_REINDEX_VAULT_TO_COPILOT_INDEX]: "rotate-cw",
|
|
[COMMAND_IDS.CLEAR_LOCAL_COPILOT_INDEX]: "trash-2",
|
|
[COMMAND_IDS.CLEAR_COPILOT_CACHE]: "eraser",
|
|
[COMMAND_IDS.GARBAGE_COLLECT_COPILOT_INDEX]: "filter-x",
|
|
[COMMAND_IDS.COUNT_TOTAL_VAULT_TOKENS]: "calculator",
|
|
[COMMAND_IDS.COUNT_WORD_AND_TOKENS_SELECTION]: "hash",
|
|
[COMMAND_IDS.OPEN_LOG_FILE]: "file-text",
|
|
[COMMAND_IDS.CLEAR_LOG_FILE]: "file-x",
|
|
[COMMAND_IDS.DOWNLOAD_YOUTUBE_SCRIPT]: "youtube",
|
|
};
|
|
|
|
/**
|
|
* Text-readable file extensions that all chains can process without Plus mode.
|
|
* These files can be read directly via `vault.read()` and don't require special parsers.
|
|
* Add new text-based extensions here to enable them everywhere (active note, context, chain).
|
|
*/
|
|
export const TEXT_READABLE_EXTENSIONS = ["md", "canvas", "base"];
|
|
|
|
/**
|
|
* Valid file extensions for note context.
|
|
* Includes text-readable files plus Plus-only formats like PDF.
|
|
* This does NOT include images - images are handled separately in the UI.
|
|
*/
|
|
export const ALLOWED_NOTE_CONTEXT_EXTENSIONS = [...TEXT_READABLE_EXTENSIONS, "pdf"];
|
|
|
|
export const RESTRICTION_MESSAGES = {
|
|
NON_MARKDOWN_FILES_RESTRICTED:
|
|
"Non-markdown files are only available in Copilot Plus mode. Please upgrade to access this file type.",
|
|
URL_PROCESSING_RESTRICTED:
|
|
"URL processing is only available in Copilot Plus mode. URLs will not be processed for context.",
|
|
UNSUPPORTED_FILE_TYPE: (extension: string) =>
|
|
`${extension.toUpperCase()} files are not supported in the current mode.`,
|
|
} as const;
|
|
|
|
export const OPENCODE_PINNED_VERSION = "1.15.13";
|
|
export const OPENCODE_RELEASE_TAG = `v${OPENCODE_PINNED_VERSION}`;
|
|
/**
|
|
* Minimum opencode the plugin supports. v1.15.13 (PR sst/opencode#29929,
|
|
* "promote next ACP implementation") dropped the dedicated ACP `models` state
|
|
* and moved the model catalog to a `category:"model"` config option; older
|
|
* binaries report no models to our picker, so we force an upgrade.
|
|
*/
|
|
export const OPENCODE_MIN_ACP_VERSION = "1.15.13";
|
|
export const OPENCODE_RELEASE_URL_TEMPLATE =
|
|
"https://github.com/sst/opencode/releases/download/v{version}/{asset}";
|
|
export const OPENCODE_RELEASE_API_URL_TEMPLATE =
|
|
"https://api.github.com/repos/sst/opencode/releases/tags/v{version}";
|
|
|
|
export const DEFAULT_SETTINGS: CopilotSettings = {
|
|
userId: uuidv4(),
|
|
isPlusUser: false,
|
|
plusLicenseKey: "",
|
|
openAIApiKey: "",
|
|
openAIOrgId: "",
|
|
huggingfaceApiKey: "",
|
|
cohereApiKey: "",
|
|
anthropicApiKey: "",
|
|
azureOpenAIApiKey: "",
|
|
azureOpenAIApiInstanceName: "",
|
|
azureOpenAIApiDeploymentName: "",
|
|
azureOpenAIApiVersion: "",
|
|
azureOpenAIApiEmbeddingDeploymentName: "",
|
|
googleApiKey: "",
|
|
openRouterAiApiKey: "",
|
|
xaiApiKey: "",
|
|
mistralApiKey: "",
|
|
deepseekApiKey: "",
|
|
amazonBedrockApiKey: "",
|
|
amazonBedrockRegion: "",
|
|
siliconflowApiKey: "",
|
|
// GitHub Copilot OAuth tokens
|
|
githubCopilotAccessToken: "",
|
|
githubCopilotToken: "",
|
|
githubCopilotTokenExpiresAt: 0,
|
|
defaultChainType: ChainType.LLM_CHAIN,
|
|
defaultModelKey: ChatModels.OPENROUTER_GEMINI_2_5_FLASH + "|" + ChatModelProviders.OPENROUTERAI,
|
|
embeddingModelKey:
|
|
EmbeddingModels.OPENROUTER_OPENAI_EMBEDDING_SMALL + "|" + EmbeddingModelProviders.OPENROUTERAI,
|
|
temperature: DEFAULT_MODEL_SETTING.TEMPERATURE,
|
|
maxTokens: DEFAULT_MODEL_SETTING.MAX_TOKENS,
|
|
contextTurns: 15,
|
|
userSystemPrompt: "",
|
|
openAIProxyBaseUrl: "",
|
|
openAIEmbeddingProxyBaseUrl: "",
|
|
stream: true,
|
|
defaultSaveFolder: DEFAULT_CHAT_HISTORY_FOLDER,
|
|
defaultConversationTag: "copilot-conversation",
|
|
autosaveChat: true,
|
|
generateAIChatTitleOnSave: true,
|
|
autoAddActiveContentToContext: true,
|
|
defaultOpenArea: DEFAULT_OPEN_AREA.VIEW,
|
|
defaultSendShortcut: SEND_SHORTCUT.ENTER,
|
|
customPromptsFolder: DEFAULT_CUSTOM_PROMPTS_FOLDER,
|
|
indexVaultToVectorStore: VAULT_VECTOR_STORE_STRATEGY.ON_MODE_SWITCH,
|
|
qaExclusions: DEFAULT_QA_EXCLUSIONS_SETTING,
|
|
qaInclusions: "",
|
|
chatNoteContextPath: "",
|
|
chatNoteContextTags: [],
|
|
enableIndexSync: true,
|
|
debug: false,
|
|
maxSourceChunks: DEFAULT_MAX_SOURCE_CHUNKS,
|
|
enableInlineCitations: true,
|
|
groqApiKey: "",
|
|
activeModels: BUILTIN_CHAT_MODELS,
|
|
activeEmbeddingModels: BUILTIN_EMBEDDING_MODELS,
|
|
embeddingRequestsPerMin: 60,
|
|
embeddingBatchSize: 16,
|
|
disableIndexOnMobile: true,
|
|
showSuggestedPrompts: true,
|
|
numPartitions: 1,
|
|
lexicalSearchRamLimit: 100, // Default 100 MB
|
|
promptUsageTimestamps: {},
|
|
promptSortStrategy: PromptSortStrategy.TIMESTAMP,
|
|
chatHistorySortStrategy: "recent",
|
|
projectListSortStrategy: "recent",
|
|
projectsFolder: DEFAULT_PROJECTS_FOLDER,
|
|
defaultConversationNoteName: "{$topic}@{$date}_{$time}",
|
|
/** @deprecated */
|
|
inlineEditCommands: [],
|
|
projectList: [],
|
|
lastDismissedVersion: null,
|
|
passMarkdownImages: true,
|
|
enableAutonomousAgent: true,
|
|
enableCustomPromptTemplating: true,
|
|
enableSemanticSearchV3: false,
|
|
enableSelfHostMode: false,
|
|
enableMiyo: false,
|
|
miyoSearchAll: false,
|
|
selfHostModeValidatedAt: null,
|
|
selfHostValidationCount: 0,
|
|
selfHostUrl: "",
|
|
selfHostApiKey: "",
|
|
miyoServerUrl: "",
|
|
selfHostSearchProvider: "firecrawl",
|
|
firecrawlApiKey: "",
|
|
perplexityApiKey: "",
|
|
supadataApiKey: "",
|
|
enableLexicalBoosts: true,
|
|
suggestedDefaultCommands: false,
|
|
autonomousAgentMaxIterations: 4,
|
|
autonomousAgentEnabledToolIds: [
|
|
"localSearch",
|
|
"readNote",
|
|
"webSearch",
|
|
"pomodoro",
|
|
"youtubeTranscription",
|
|
"writeFile",
|
|
"editFile",
|
|
"updateMemory",
|
|
],
|
|
reasoningEffort: DEFAULT_MODEL_SETTING.REASONING_EFFORT,
|
|
verbosity: DEFAULT_MODEL_SETTING.VERBOSITY,
|
|
memoryFolderName: DEFAULT_MEMORY_FOLDER,
|
|
enableRecentConversations: true,
|
|
maxRecentConversations: 30,
|
|
enableSavedMemory: true,
|
|
quickCommandModelKey: undefined,
|
|
quickCommandIncludeNoteContext: true,
|
|
autoIncludeTextSelection: false,
|
|
autoAddSelectionToContext: false,
|
|
autoAcceptEdits: false,
|
|
diffViewMode: "split",
|
|
userSystemPromptsFolder: DEFAULT_SYSTEM_PROMPTS_FOLDER,
|
|
defaultSystemPromptTitle: "",
|
|
autoCompactThreshold: 128000,
|
|
convertedDocOutputFolder: DEFAULT_CONVERTED_DOC_OUTPUT_FOLDER,
|
|
agentMode: {
|
|
byok: {},
|
|
mcpServers: [],
|
|
activeBackend: "opencode",
|
|
backends: {},
|
|
debugFullFrames: false,
|
|
skills: {
|
|
folder: DEFAULT_SKILLS_FOLDER,
|
|
},
|
|
},
|
|
providers: {},
|
|
configuredModels: [],
|
|
backends: {},
|
|
};
|
|
|
|
export const EVENT_NAMES = {
|
|
CHAT_IS_VISIBLE: "chat-is-visible",
|
|
ACTIVE_LEAF_CHANGE: "active-leaf-change",
|
|
ABORT_STREAM: "abort-stream",
|
|
INSERT_TEXT_TO_CHAT: "insert-text-to-chat",
|
|
};
|
|
|
|
export enum ABORT_REASON {
|
|
USER_STOPPED = "user-stopped",
|
|
NEW_CHAT = "new-chat",
|
|
UNMOUNT = "component-unmount",
|
|
}
|