Resolve merge conflicts - keep local plugin versions and settings

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
windyboy
2026-02-24 08:19:53 +08:00
co-authored by Claude Sonnet 4.6
124 changed files with 962 additions and 187 deletions
+2 -3
View File
@@ -14,12 +14,11 @@
"highlightr-plugin",
"obsidian-excalidraw-plugin",
"code-styler",
"note-buddy",
"claudian",
"calendar",
"better-word-count",
"table-editor-obsidian",
"obsidian-advanced-uri",
"advanced-canvas",
"obsidian-git"
"obsidian-git",
"claudian"
]
+497 -98
View File
@@ -239,6 +239,16 @@ var OpenCodeClient = class _OpenCodeClient {
this.providersCacheTime = 0;
this.cachedDefaults = null;
}
/**
* Fetches available AI providers and models from the OpenCode server.
*
* Results are cached for 5 minutes to reduce API calls. The cache can be bypassed
* by setting forceRefresh to true or by calling clearModelsCache() first.
*
* @param forceRefresh - If true, bypasses cache and fetches fresh data from server
* @returns Array of providers with their available models
* @throws Error if the server is unreachable, returns invalid JSON, or responds with non-200 status
*/
async getCapabilities(forceRefresh = false) {
const now = Date.now();
if (!forceRefresh && this.cachedProviders && now - this.providersCacheTime < MODELS_CACHE_TTL) {
@@ -294,12 +304,360 @@ var ChatView = class extends import_obsidian2.ItemView {
super(leaf);
this.plugin = plugin;
this.messages = [];
this.isUserNearBottom = true;
this.hasInitialScroll = false;
this.previousScrollTop = 0;
this.previousWasNearBottom = true;
this.isInitialized = false;
this.handleMessagesScroll = () => {
const threshold = 32;
const distanceToBottom = this.messagesContainer.scrollHeight - this.messagesContainer.scrollTop - this.messagesContainer.clientHeight;
this.isUserNearBottom = distanceToBottom <= threshold;
this.previousScrollTop = this.messagesContainer.scrollTop;
this.previousWasNearBottom = this.isUserNearBottom;
if (this.isUserNearBottom) {
this.hideNewMessageIndicator();
}
};
this.client = new OpenCodeClient(
plugin.settings.serviceUrl,
plugin.settings.defaultModelId,
plugin.onModelUnavailable?.bind(plugin)
);
}
/**
* Show loading indicator
*/
showLoading() {
if (this.loadingIndicator) return;
this.loadingIndicator = this.messagesContainer.createDiv({ cls: "nb-loading-indicator" });
const dotsContainer = this.loadingIndicator.createDiv({ cls: "nb-loading-dots" });
dotsContainer.createDiv({ cls: "nb-loading-dot" });
dotsContainer.createDiv({ cls: "nb-loading-dot" });
dotsContainer.createDiv({ cls: "nb-loading-dot" });
this.maybeAutoScroll();
}
/**
* Hide loading indicator
*/
hideLoading() {
if (this.loadingIndicator) {
this.loadingIndicator.remove();
this.loadingIndicator = void 0;
}
}
/**
* Scroll to bottom of messages
*/
scrollToBottom() {
this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
this.hideNewMessageIndicator();
}
showNewMessageIndicator() {
if (!this.newMessageIndicator) return;
this.newMessageIndicator.style.display = "flex";
}
hideNewMessageIndicator() {
if (!this.newMessageIndicator) return;
this.newMessageIndicator.style.display = "none";
}
maybeAutoScroll() {
if (!this.messagesContainer) return;
if (!this.hasInitialScroll) {
this.scrollToBottom();
this.hasInitialScroll = true;
return;
}
if (this.isUserNearBottom) {
this.scrollToBottom();
} else {
this.showNewMessageIndicator();
}
}
/**
* Render error message with retry button
*/
renderErrorMessage(errorText, retryMessage) {
const errorContainer = this.messagesContainer.createDiv({ cls: "nb-error-container" });
errorContainer.createDiv({ cls: "nb-error-message", text: errorText });
if (retryMessage) {
const retryButton = errorContainer.createEl("button", {
cls: "nb-retry-button",
text: "Retry"
});
retryButton.onclick = () => {
const errorIndex = this.messages.findIndex((m) => m.kind === "error" && m.text === errorText);
if (errorIndex !== -1) {
this.messages.splice(errorIndex, 1);
}
this.retrySendMessage(retryMessage);
};
}
}
/**
* Send message with timeout
*/
async sendWithTimeout(promise, timeoutMs) {
return Promise.race([
promise,
new Promise(
(_, reject) => setTimeout(() => reject(new Error("Request timed out after 30 seconds")), timeoutMs)
)
]);
}
/**
* Retry sending a message
*/
async retrySendMessage(message) {
this.renderMessages();
this.showLoading();
try {
if (!this.plugin.sessionState) {
this.plugin.sessionState = await this.sendWithTimeout(
this.client.createSession(),
3e4
);
}
const sendData = {
parts: [{ type: "text", text: message }]
};
if (this.plugin.settings.defaultModelId) {
const parts = this.plugin.settings.defaultModelId.split("/");
if (parts.length === 2) {
sendData.model = {
providerID: parts[0],
modelID: parts[1]
};
}
}
let response;
try {
response = await this.sendWithTimeout(
this.client.sendMessageToSession(this.plugin.sessionState.sessionID, sendData),
3e4
);
} catch (sendError) {
const err = sendError;
if (err.message.includes("Session not found")) {
this.plugin.sessionState = await this.sendWithTimeout(
this.client.createSession(),
3e4
);
response = await this.sendWithTimeout(
this.client.sendMessageToSession(this.plugin.sessionState.sessionID, sendData),
3e4
);
} else {
throw sendError;
}
}
this.hideLoading();
for (const part of response.parts) {
this.messages.push({ kind: "assistantPart", part });
}
this.renderMessages();
await this.saveChatState();
} catch (error) {
this.hideLoading();
this.messages.push({
kind: "error",
text: `Failed to send message: ${error.message}`,
retryMessage: message
});
this.renderMessages();
await this.saveChatState();
}
}
/**
* Clear chat history with confirmation
*/
async clearChat() {
const confirmed = confirm("Are you sure you want to clear the chat history? This cannot be undone.");
if (!confirmed) return;
this.messages = [];
this.plugin.sessionState = void 0;
await this.saveChatState();
this.renderMessages();
try {
this.plugin.sessionState = await this.sendWithTimeout(
this.client.createSession(),
3e4
);
await this.saveChatState();
} catch (error) {
console.error("[NoteBuddy] Failed to create new session after clearing chat:", error);
}
}
/**
* Render markdown text to HTML elements
* Supports: code blocks, inline code, bold, italic, lists
*/
renderMarkdown(text, container) {
const lines = text.split("\n");
let inCodeBlock = false;
let codeBlockContent = [];
let listItems = [];
let inList = false;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.trim().startsWith("```")) {
if (inCodeBlock) {
const pre = container.createEl("pre");
const code = pre.createEl("code");
code.textContent = codeBlockContent.join("\n");
codeBlockContent = [];
inCodeBlock = false;
} else {
inCodeBlock = true;
}
continue;
}
if (inCodeBlock) {
codeBlockContent.push(line);
continue;
}
const listMatch = line.match(/^(\s*)([-*]|\d+\.)\s+(.+)$/);
if (listMatch) {
if (!inList) {
inList = true;
listItems = [];
}
listItems.push(listMatch[3]);
continue;
} else if (inList) {
const ul = container.createEl("ul");
listItems.forEach((item) => {
const li = ul.createEl("li");
this.renderInlineMarkdown(item, li);
});
listItems = [];
inList = false;
}
if (line.trim()) {
const p = container.createEl("span");
this.renderInlineMarkdown(line, p);
if (i < lines.length - 1) {
container.createEl("br");
}
}
}
if (inList) {
const ul = container.createEl("ul");
listItems.forEach((item) => {
const li = ul.createEl("li");
this.renderInlineMarkdown(item, li);
});
}
}
/**
* Render inline markdown (bold, italic, inline code)
*/
renderInlineMarkdown(text, container) {
const codeRegex = /`([^`]+)`/g;
let lastIndex = 0;
let match;
const parts = [];
while ((match = codeRegex.exec(text)) !== null) {
if (match.index > lastIndex) {
parts.push({ type: "text", content: text.substring(lastIndex, match.index) });
}
parts.push({ type: "code", content: match[1] });
lastIndex = match.index + match[0].length;
}
if (lastIndex < text.length) {
parts.push({ type: "text", content: text.substring(lastIndex) });
}
parts.forEach((part) => {
if (part.type === "code") {
container.createEl("code", { text: part.content });
} else {
this.renderTextWithFormatting(part.content, container);
}
});
}
/**
* Render a message bubble with appropriate styling
*/
renderMessageBubble(kind, content, container) {
const messageEl = container.createDiv({
cls: `nb-message nb-message-${kind}`
});
this.renderMarkdown(content, messageEl);
return messageEl;
}
/**
* Render text with bold and italic formatting
*/
renderTextWithFormatting(text, container) {
const boldRegex = /\*\*([^*]+)\*\*/g;
const italicRegex = /\*([^*]+)\*/g;
let result = text;
const elements = [];
let match;
while ((match = boldRegex.exec(text)) !== null) {
elements.push({ start: match.index, end: match.index + match[0].length, type: "bold" });
}
while ((match = italicRegex.exec(text)) !== null) {
const currentMatch = match;
const isBold = elements.some((e) => e.start <= currentMatch.index && currentMatch.index < e.end);
if (!isBold) {
elements.push({
start: currentMatch.index,
end: currentMatch.index + currentMatch[0].length,
type: "italic"
});
}
}
elements.sort((a, b) => a.start - b.start);
let lastIndex = 0;
elements.forEach((el) => {
if (el.start > lastIndex) {
container.appendText(text.substring(lastIndex, el.start));
}
const content = text.substring(el.start, el.end);
if (el.type === "bold") {
const cleaned = content.replace(/\*\*/g, "");
container.createEl("strong", { text: cleaned });
} else {
const cleaned = content.replace(/\*/g, "");
container.createEl("em", { text: cleaned });
}
lastIndex = el.end;
});
if (lastIndex < text.length) {
container.appendText(text.substring(lastIndex));
}
}
/**
* Save chat state to plugin data
*/
async saveChatState() {
try {
const chatState = {
messages: this.messages,
sessionState: this.plugin.sessionState
};
await this.plugin.saveData({ ...this.plugin.settings, chatState });
} catch (error) {
console.error("[NoteBuddy] Failed to save chat state:", error);
}
}
/**
* Load chat state from plugin data
*/
async loadChatState() {
try {
const data = await this.plugin.loadData();
if (data?.chatState) {
this.messages = data.chatState.messages || [];
if (data.chatState.sessionState) {
this.plugin.sessionState = data.chatState.sessionState;
}
}
} catch (error) {
console.error("[NoteBuddy] Failed to load chat state:", error);
}
}
getViewType() {
return VIEW_TYPE_CHAT;
}
@@ -307,80 +665,63 @@ var ChatView = class extends import_obsidian2.ItemView {
return "NoteBuddy Chat";
}
async onOpen() {
if (!this.isInitialized) {
await this.loadChatState();
this.isInitialized = true;
}
const container = this.containerEl.children[1];
container.empty();
container.addClass("note-buddy-chat-view");
const chatContainer = container.createDiv({ cls: "nb-chat-container" });
chatContainer.style.cssText = `
display: flex;
flex-direction: column;
height: 100%;
gap: 1rem;
`;
const toolbar = chatContainer.createDiv({ cls: "nb-toolbar" });
toolbar.createDiv({ cls: "nb-toolbar-title", text: "NoteBuddy Chat" });
const toolbarActions = toolbar.createDiv({ cls: "nb-toolbar-actions" });
const clearButton = toolbarActions.createEl("button", {
cls: "nb-toolbar-button",
attr: { "aria-label": "Clear chat", title: "Clear chat" }
});
(0, import_obsidian2.setIcon)(clearButton, "trash-2");
clearButton.onclick = () => this.clearChat();
const messagesContainer = chatContainer.createDiv({ cls: "nb-messages-container" });
this.messagesContainer = messagesContainer;
messagesContainer.style.cssText = `
flex: 1;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 0.5rem;
padding: 1rem;
`;
this.messagesContainer.addEventListener("scroll", this.handleMessagesScroll);
this.previousScrollTop = 0;
this.previousWasNearBottom = true;
const newMessageIndicator = chatContainer.createDiv({ cls: "nb-new-message-indicator" });
const indicatorButton = newMessageIndicator.createEl("button", {
cls: "nb-new-message-button",
text: "\u65B0\u6D88\u606F",
attr: { "aria-label": "New messages" }
});
indicatorButton.onclick = () => {
this.scrollToBottom();
};
this.newMessageIndicator = newMessageIndicator;
this.hideNewMessageIndicator();
this.renderMessages();
const welcomeMessage = messagesContainer.createDiv({ cls: "nb-message nb-message-system" });
welcomeMessage.createSpan({ text: "Welcome to NoteBuddy! Chat with your notes here." });
welcomeMessage.style.cssText = `
padding: 0.75rem;
background-color: var(--background-secondary);
border-radius: 0.5rem;
font-size: 0.9rem;
color: var(--text-muted);
`;
const inputContainer = chatContainer.createDiv({ cls: "nb-input-container" });
inputContainer.style.cssText = `
display: flex;
gap: 0.5rem;
padding: 1rem;
border-top: 1px solid var(--background-modifier-border);
`;
const textarea = inputContainer.createEl("textarea", {
cls: "nb-chat-input",
attr: { placeholder: "Type your message..." }
});
textarea.style.cssText = `
flex: 1;
min-height: 60px;
max-height: 150px;
padding: 0.5rem;
border: 1px solid var(--background-modifier-border);
border-radius: 0.375rem;
background-color: var(--background-primary);
color: var(--text-normal);
resize: vertical;
font-family: inherit;
`;
const sendButton = inputContainer.createEl("button", {
cls: "nb-send-button",
text: "Send"
attr: { "aria-label": "Send message", title: "Send message" }
});
sendButton.style.cssText = `
padding: 0.5rem 1rem;
background-color: var(--interactive-accent);
color: var(--text-on-accent);
border: none;
border-radius: 0.375rem;
cursor: pointer;
font-weight: 500;
`;
(0, import_obsidian2.setIcon)(sendButton, "send");
const sendMessage = async () => {
const message = textarea.value.trim();
if (!message) return;
this.messages.push({ kind: "userText", text: message });
this.renderMessages();
textarea.value = "";
this.showLoading();
try {
if (!this.plugin.sessionState) {
this.plugin.sessionState = await this.client.createSession();
this.plugin.sessionState = await this.sendWithTimeout(
this.client.createSession(),
3e4
);
}
const sendData = {
parts: [{ type: "text", text: message }]
@@ -396,24 +737,41 @@ var ChatView = class extends import_obsidian2.ItemView {
}
let response;
try {
response = await this.client.sendMessageToSession(this.plugin.sessionState.sessionID, sendData);
response = await this.sendWithTimeout(
this.client.sendMessageToSession(this.plugin.sessionState.sessionID, sendData),
3e4
);
} catch (sendError) {
const err = sendError;
if (err.message.includes("Session not found")) {
this.plugin.sessionState = await this.client.createSession();
response = await this.client.sendMessageToSession(this.plugin.sessionState.sessionID, sendData);
this.plugin.sessionState = await this.sendWithTimeout(
this.client.createSession(),
3e4
);
response = await this.sendWithTimeout(
this.client.sendMessageToSession(this.plugin.sessionState.sessionID, sendData),
3e4
);
} else {
throw sendError;
}
}
this.hideLoading();
for (const part of response.parts) {
this.messages.push({ kind: "assistantPart", part });
}
this.renderMessages();
this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
await this.saveChatState();
} catch (error) {
this.hideLoading();
console.error("[NoteBuddy] Send failed:", error);
new import_obsidian2.Notice(`Failed to send message: ${error.message}`);
this.messages.push({
kind: "error",
text: `Failed to send message: ${error.message}`,
retryMessage: message
});
this.renderMessages();
await this.saveChatState();
}
};
sendButton.onclick = sendMessage;
@@ -428,49 +786,38 @@ var ChatView = class extends import_obsidian2.ItemView {
console.log("[NoteBuddy] Chat view closed");
}
renderMessages() {
const shouldRestoreScroll = !this.isUserNearBottom;
const previousScrollTop = this.previousScrollTop;
this.messagesContainer.empty();
if (this.messages.length === 0) {
const welcomeMessage = this.messagesContainer.createDiv({ cls: "nb-message nb-message-system" });
welcomeMessage.createSpan({ text: "Welcome to NoteBuddy! Chat with your notes here." });
welcomeMessage.style.cssText = `
padding: 0.75rem;
background-color: var(--background-secondary);
border-radius: 0.5rem;
font-size: 0.9rem;
color: var(--text-muted);
`;
const emptyState = this.messagesContainer.createDiv({ cls: "nb-empty-state" });
emptyState.createDiv({ cls: "nb-empty-title", text: "Welcome to NoteBuddy" });
emptyState.createDiv({
cls: "nb-empty-subtitle",
text: "Ask your notes a question or start a new conversation."
});
this.hideNewMessageIndicator();
this.hasInitialScroll = true;
return;
}
for (const item of this.messages) {
if (item.kind === "userText") {
const messageEl2 = this.messagesContainer.createDiv({ cls: "nb-message nb-message-user" });
messageEl2.createSpan({ text: item.text });
messageEl2.style.cssText = `
padding: 0.75rem;
background-color: var(--background-modifier-accent);
border-radius: 0.5rem;
font-size: 0.9rem;
align-self: flex-end;
max-width: 70%;
`;
this.renderMessageBubble("user", item.text, this.messagesContainer);
continue;
}
if (item.kind === "error") {
this.renderErrorMessage(item.text, item.retryMessage);
continue;
}
const part = item.part;
const messageEl = this.messagesContainer.createDiv({ cls: "nb-message nb-message-assistant" });
messageEl.style.cssText = `
padding: 0.75rem;
background-color: var(--background-secondary);
border-radius: 0.5rem;
font-size: 0.9rem;
align-self: flex-start;
max-width: 70%;
`;
switch (part.type) {
case "text":
messageEl.createSpan({ text: part.text });
this.renderMarkdown(part.text, messageEl);
break;
case "reasoning":
messageEl.createSpan({ text: part.text });
messageEl.createEl("div", { text: "Reasoning:", cls: "nb-part-label" });
this.renderMarkdown(part.text, messageEl);
break;
case "tool":
messageEl.createEl("strong", { text: `Tool: ${part.tool}` });
@@ -514,6 +861,12 @@ var ChatView = class extends import_obsidian2.ItemView {
break;
}
}
if (shouldRestoreScroll) {
this.messagesContainer.scrollTop = previousScrollTop;
this.showNewMessageIndicator();
} else {
this.maybeAutoScroll();
}
}
};
@@ -536,44 +889,81 @@ var NoteBuddySettingTab = class extends import_obsidian3.PluginSettingTab {
} catch {
}
}
new import_obsidian3.Setting(containerEl).setName("Service URL").setDesc("The URL of the OpenCode service (must include protocol, hostname, and port)").addText(
const connectionGroup = containerEl.createDiv({ cls: "nb-settings-group" });
connectionGroup.createEl("h3", { text: "Connection Settings", cls: "nb-settings-group-title" });
new import_obsidian3.Setting(connectionGroup).setName("Service URL").setDesc("The URL of the OpenCode service (must include protocol, hostname, and port)").addText(
(text) => text.setPlaceholder("http://127.0.0.1:4096").setValue(this.plugin.settings.serviceUrl).onChange(async (value) => {
const previousServiceUrl = this.plugin.settings.serviceUrl;
const validationEl = text.inputEl.parentElement?.querySelector(".nb-settings-validation-error, .nb-settings-validation-success");
if (validationEl) {
validationEl.remove();
}
if (!value.startsWith("http://") && !value.startsWith("https://")) {
new import_obsidian3.Notice("Service URL must start with http:// or https://");
const errorEl = text.inputEl.parentElement?.createDiv({ cls: "nb-settings-validation-error" });
if (errorEl) errorEl.textContent = "Service URL must start with http:// or https://";
return;
}
try {
const url = new URL(value);
if (!url.hostname || url.hostname === "") {
new import_obsidian3.Notice("Service URL must include a valid hostname");
const errorEl = text.inputEl.parentElement?.createDiv({ cls: "nb-settings-validation-error" });
if (errorEl) errorEl.textContent = "Service URL must include a valid hostname";
return;
}
if (!url.port || url.port === "") {
new import_obsidian3.Notice("Service URL must include a port number");
const errorEl = text.inputEl.parentElement?.createDiv({ cls: "nb-settings-validation-error" });
if (errorEl) errorEl.textContent = "Service URL must include a port number";
return;
}
const successEl = text.inputEl.parentElement?.createDiv({ cls: "nb-settings-validation-success" });
if (successEl) successEl.textContent = "\u2713 Valid URL format";
} catch (e) {
new import_obsidian3.Notice("Service URL must be a valid URL format");
const errorEl = text.inputEl.parentElement?.createDiv({ cls: "nb-settings-validation-error" });
if (errorEl) errorEl.textContent = "Service URL must be a valid URL format";
return;
}
if (this.plugin.sessionState && previousServiceUrl !== value) {
if (this.lastServiceUrlWarning !== value) {
new import_obsidian3.Notice("Active chat detected. Clear the current conversation before switching the Service URL.");
this.lastServiceUrlWarning = value;
}
text.setValue(previousServiceUrl);
return;
}
this.plugin.settings.serviceUrl = value;
await this.plugin.saveSettings();
})
);
new import_obsidian3.Setting(containerEl).setName("Test Connection").setDesc("Test the connection to the service").addButton(
(button) => button.setButtonText("Test").setCta().onClick(async () => {
new import_obsidian3.Setting(connectionGroup).setName("Test Connection").setDesc("Test the connection to the service").addButton(
(button) => button.setIcon("plug").setButtonText("Test").setCta().onClick(async () => {
button.setButtonText("Testing...");
button.setDisabled(true);
const client = new OpenCodeClient(this.plugin.settings.serviceUrl, this.plugin.settings.defaultModelId);
const result = await client.healthCheck();
button.setButtonText("Test");
button.setDisabled(false);
if (result.status === "connected") {
new import_obsidian3.Notice("Connection successful!");
new import_obsidian3.Notice("\u2713 Connection successful!");
} else {
new import_obsidian3.Notice(`Connection failed: ${result.lastError}`);
new import_obsidian3.Notice(`\u2717 Connection failed: ${result.lastError}`);
}
})
);
this.displayModelSelection(containerEl);
this.displayRefreshButton(containerEl);
const modelGroup = containerEl.createDiv({ cls: "nb-settings-group" });
modelGroup.createEl("h3", { text: "Model Selection", cls: "nb-settings-group-title" });
this.displayModelSelection(modelGroup);
this.displayRefreshButton(modelGroup);
}
/**
* Loads available AI providers and models from the OpenCode server.
*
* Sets the loading state and updates the providers list. On error, sets providers
* to an empty array and logs the error. The loading state is always cleared in finally.
*
* @param client - Optional OpenCodeClient instance to use (creates new one if not provided)
* @param forceRefresh - If true, bypasses cache and fetches fresh data from server
* @throws Error if the server request fails (error is logged and re-thrown)
*/
async loadProviders(client, forceRefresh) {
if (this.isLoadingModels) {
return;
@@ -590,6 +980,15 @@ var NoteBuddySettingTab = class extends import_obsidian3.PluginSettingTab {
this.isLoadingModels = false;
}
}
/**
* Displays the model selection dropdown in the settings UI.
*
* Builds a dropdown with options in "Provider Name - Model Name" format, including
* a "Use server default" option. The current selection is restored from settings,
* and changes are immediately persisted via plugin.saveSettings().
*
* @param containerEl - The HTML element to add the dropdown setting to
*/
displayModelSelection(containerEl) {
const modelOptions = {};
modelOptions[""] = "Use server default";
@@ -616,7 +1015,7 @@ var NoteBuddySettingTab = class extends import_obsidian3.PluginSettingTab {
}
displayRefreshButton(container) {
new import_obsidian3.Setting(container).setName("Refresh Models").setDesc("Reload the list of available models from the service").addButton(
(button) => button.setButtonText("Refresh").onClick(async () => {
(button) => button.setIcon("refresh-cw").setButtonText("Refresh").onClick(async () => {
const client = new OpenCodeClient(this.plugin.settings.serviceUrl, this.plugin.settings.defaultModelId);
client.clearModelsCache();
try {
+56 -1
View File
@@ -1,5 +1,60 @@
{
"choices": [],
"choices": [
{
"id": "daily-note-choice",
"name": "📅 Daily Note",
"type": "Template",
"command": true,
"templatePath": "06_Metadata/Templates/Daily Note Template.md",
"fileNameFormat": {
"enabled": true,
"format": "{{DATE:YYYY-MM-DD}}"
},
"folder": {
"enabled": true,
"folders": ["00_Inbox"],
"chooseWhenCreatingNote": false,
"createFolder": false,
"chooseFromSubfolders": false
},
"appendLink": false,
"incrementFileName": false,
"openFileInNewTab": {
"enabled": true,
"direction": "vertical",
"focus": true
},
"openFile": true,
"openFileInMode": "default"
},
{
"id": "quick-capture-choice",
"name": "💡 Quick Capture",
"type": "Template",
"command": true,
"templatePath": "06_Metadata/Templates/quick-note.md",
"fileNameFormat": {
"enabled": true,
"format": "{{DATE:YYYY-MM-DD-HHmm}} - {{VALUE}}"
},
"folder": {
"enabled": true,
"folders": ["00_Inbox"],
"chooseWhenCreatingNote": false,
"createFolder": false,
"chooseFromSubfolders": false
},
"appendLink": false,
"incrementFileName": false,
"openFileInNewTab": {
"enabled": true,
"direction": "vertical",
"focus": true
},
"openFile": true,
"openFileInMode": "default"
}
],
"inputPrompt": "single-line",
"persistInputPromptDrafts": true,
"useSelectionAsCaptureValue": true,