vault backup: 2026-01-30 10:38:04

This commit is contained in:
windyboy
2026-01-30 10:38:04 +08:00
parent f7aacd5bd4
commit bf57be8355
16 changed files with 465 additions and 164 deletions
+3 -4
View File
@@ -1,5 +1,5 @@
{ {
"userName": "", "userName": "windy",
"enableBlocklist": true, "enableBlocklist": true,
"blockedCommands": { "blockedCommands": {
"unix": [ "unix": [
@@ -46,12 +46,11 @@
"lastNonPlanPermissionMode": "normal", "lastNonPlanPermissionMode": "normal",
"permissions": [], "permissions": [],
"excludedTags": [], "excludedTags": [],
"mediaFolder": "", "mediaFolder": "05_Attachments",
"environmentVariables": "", "environmentVariables": "",
"envSnippets": [], "envSnippets": [],
"systemPrompt": "", "systemPrompt": "",
"allowedExportPaths": [ "allowedExportPaths": [
"~/Desktop",
"~/Downloads" "~/Downloads"
], ],
"allowedContextPaths": [], "allowedContextPaths": [],
@@ -60,5 +59,5 @@
"scrollDownKey": "s", "scrollDownKey": "s",
"focusInputKey": "i" "focusInputKey": "i"
}, },
"claudeCliPath": "" "claudeCliPath": "/Users/windy/.local/bin/claude"
} }
+2 -1
View File
@@ -24,5 +24,6 @@
"obsidian-opencode", "obsidian-opencode",
"opencode-obsidian", "opencode-obsidian",
"highlightr-plugin", "highlightr-plugin",
"code-styler" "code-styler",
"note-buddy"
] ]
+317 -38
View File
@@ -40,18 +40,30 @@ var import_obsidian = require("obsidian");
var defaultSettings = { var defaultSettings = {
serviceUrl: "http://127.0.0.1:4096" serviceUrl: "http://127.0.0.1:4096"
}; };
var MODELS_CACHE_TTL = 5 * 60 * 1e3;
// src/service.ts // src/service.ts
var OpenCodeClient = class { var OpenCodeClient = class _OpenCodeClient {
constructor(serviceUrl) { constructor(serviceUrl, defaultModelId, onModelUnavailable) {
this.session = null; this.session = null;
this.cachedProviders = null;
this.providersCacheTime = 0;
this.cachedDefaults = null;
this.serviceUrl = serviceUrl; this.serviceUrl = serviceUrl;
this.defaultModelId = defaultModelId;
this.onModelUnavailable = onModelUnavailable;
} }
async request(options) { static {
this.DEFAULT_REQUEST_TIMEOUT_MS = 1e4;
}
static {
this.MESSAGE_REQUEST_TIMEOUT_MS = 6e4;
}
async request(options, timeoutMs = _OpenCodeClient.DEFAULT_REQUEST_TIMEOUT_MS) {
return await Promise.race([ return await Promise.race([
(0, import_obsidian.requestUrl)(options), (0, import_obsidian.requestUrl)(options),
new Promise( new Promise(
(_, reject) => setTimeout(() => reject(new Error("Request timeout after 10 seconds")), 1e4) (_, reject) => setTimeout(() => reject(new Error(`Request timeout after ${timeoutMs / 1e3} seconds`)), timeoutMs)
) )
]); ]);
} }
@@ -97,36 +109,79 @@ var OpenCodeClient = class {
if (response.status === 200) { if (response.status === 200) {
const data = response.json; const data = response.json;
return { return {
sessionID: data.sessionID, sessionID: data.id,
createTime: data.createTime, createTime: data.time.created,
title: data.title title: data.title
}; };
} else {
throw new Error(`HTTP ${response.status}: ${response.text}`);
} }
if (response.status === 400) {
const details = this.formatBadRequest(response.json, response.text);
throw new Error(details);
}
throw new Error(`HTTP ${response.status}: ${response.text}`);
} catch (error) { } catch (error) {
const err = error; const err = error;
throw new Error(`Failed to create session: ${err.message}`); throw new Error(`Failed to create session: ${err.message}`);
} }
} }
formatBadRequest(payload, fallbackText) {
if (!payload || typeof payload !== "object") {
return `Bad request: ${fallbackText || "Unknown error"}`;
}
const p = payload;
const errText = typeof p.errors === "string" ? p.errors : p.errors ? JSON.stringify(p.errors) : "";
const dataText = p.data ? JSON.stringify(p.data) : "";
const msg = [errText, dataText].filter(Boolean).join(" ");
return msg ? `Bad request: ${msg}` : `Bad request: ${fallbackText || "Unknown error"}`;
}
formatNotFound(payload, fallbackText) {
if (!payload || typeof payload !== "object") {
return fallbackText || "Not found";
}
const p = payload;
const name = typeof p.name === "string" ? p.name : "";
const data = p.data ? JSON.stringify(p.data) : "";
return [name, data].filter(Boolean).join(" ") || fallbackText || "Not found";
}
async sendMessageInternal(sessionID, message) { async sendMessageInternal(sessionID, message) {
const url = `${this.serviceUrl}/session/${sessionID}/message`; const url = `${this.serviceUrl}/session/${sessionID}/message`;
try { try {
const response = await this.request({ const response = await this.request(
{
url, url,
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json" "Content-Type": "application/json"
}, },
body: JSON.stringify(message) body: JSON.stringify(message)
}); },
_OpenCodeClient.MESSAGE_REQUEST_TIMEOUT_MS
);
if (response.status === 200) { if (response.status === 200) {
return response.json; const raw = (response.text ?? "").trim();
} else if (response.status === 404) { if (!raw) {
throw new Error("Session not found"); throw new Error("Server returned empty response");
} else {
throw new Error(`HTTP ${response.status}: ${response.text}`);
} }
let data;
try {
data = JSON.parse(raw);
} catch {
throw new Error(`Invalid JSON response: ${raw.slice(0, 50)}${raw.length > 50 ? "..." : ""}`);
}
if (!data || typeof data !== "object" || !Array.isArray(data.parts)) {
throw new Error("Invalid response shape (expected {info, parts[]})");
}
return data;
}
if (response.status === 400) {
const payload = response.json;
throw new Error(this.formatBadRequest(payload, response.text));
}
if (response.status === 404) {
const payload = response.json;
throw new Error(`Session not found: ${this.formatNotFound(payload, response.text)}`);
}
throw new Error(`HTTP ${response.status}: ${response.text}`);
} catch (error) { } catch (error) {
const err = error; const err = error;
throw new Error(`Failed to send message: ${err.message}`); throw new Error(`Failed to send message: ${err.message}`);
@@ -137,16 +192,99 @@ var OpenCodeClient = class {
this.session = await this.createSession(); this.session = await this.createSession();
} }
const message = { const message = {
parts: [{ text: input, role: "user" }] parts: [{ type: "text", text: input }]
}; };
const response = await this.sendMessageInternal(this.session.sessionID, message); if (this.defaultModelId) {
const assistantParts = response.parts.filter((part) => part.role === "assistant"); const parts = this.defaultModelId.split("/");
const assistantText = assistantParts.map((part) => part.text).join("\n"); if (parts.length === 2) {
message.model = {
providerID: parts[0],
modelID: parts[1]
};
}
}
let response;
try {
response = await this.sendMessageInternal(this.session.sessionID, message);
} catch (error) {
const err = error;
if (message.model && this.isLikelyModelError(err)) {
console.log("[NoteBuddy] Selected model unavailable, falling back to server default");
if (this.onModelUnavailable) {
this.onModelUnavailable();
}
const fallbackMessage = {
parts: message.parts
};
response = await this.sendMessageInternal(this.session.sessionID, fallbackMessage);
} else {
throw error;
}
}
const assistantText = response.parts.filter((part) => part.type === "text").map((part) => part.type === "text" ? part.text : "").filter(Boolean).join("\n");
return assistantText; return assistantText;
} }
async sendMessageToSession(sessionID, message) { async sendMessageToSession(sessionID, message) {
return await this.sendMessageInternal(sessionID, message); return await this.sendMessageInternal(sessionID, message);
} }
isModelsCacheValid() {
if (!this.cachedProviders) {
return false;
}
const now = Date.now();
return now - this.providersCacheTime < MODELS_CACHE_TTL;
}
clearModelsCache() {
this.cachedProviders = null;
this.providersCacheTime = 0;
this.cachedDefaults = null;
}
async getCapabilities(forceRefresh = false) {
const now = Date.now();
if (!forceRefresh && this.cachedProviders && now - this.providersCacheTime < MODELS_CACHE_TTL) {
return this.cachedProviders;
}
const url = `${this.serviceUrl}/config/providers`;
try {
const response = await this.request({
url,
method: "GET"
});
if (response.status === 200) {
let data;
try {
data = response.json;
} catch {
const preview = (response.text || "").trim().slice(0, 50);
if (preview.toLowerCase().startsWith("<!")) {
throw new Error(
"Server returned HTML instead of JSON. Check the Service URL and ensure the server exposes /config/providers."
);
}
throw new Error(`Invalid JSON response: ${preview}...`);
}
const raw = data.providers || [];
this.cachedDefaults = data.default || {};
const providers = raw.map((p) => ({
id: p.id,
name: p.name,
models: Object.entries(p.models || {}).map(([id, m]) => ({ id, name: m?.name ?? id }))
}));
this.cachedProviders = providers;
this.providersCacheTime = now;
return providers;
} else {
throw new Error(`HTTP ${response.status}: ${response.text}`);
}
} catch (error) {
const err = error;
throw new Error(`Failed to get capabilities: ${err.message}`);
}
}
isLikelyModelError(err) {
const msg = (err.message || "").toLowerCase();
return msg.includes("model") && (msg.includes("not found") || msg.includes("invalid") || msg.includes("unknown"));
}
}; };
// src/chat-view.ts // src/chat-view.ts
@@ -156,7 +294,11 @@ var ChatView = class extends import_obsidian2.ItemView {
super(leaf); super(leaf);
this.plugin = plugin; this.plugin = plugin;
this.messages = []; this.messages = [];
this.client = new OpenCodeClient(plugin.settings.serviceUrl); this.client = new OpenCodeClient(
plugin.settings.serviceUrl,
plugin.settings.defaultModelId,
plugin.onModelUnavailable?.bind(plugin)
);
} }
getViewType() { getViewType() {
return VIEW_TYPE_CHAT; return VIEW_TYPE_CHAT;
@@ -233,7 +375,7 @@ var ChatView = class extends import_obsidian2.ItemView {
const sendMessage = async () => { const sendMessage = async () => {
const message = textarea.value.trim(); const message = textarea.value.trim();
if (!message) return; if (!message) return;
this.messages.push({ text: message, role: "user" }); this.messages.push({ kind: "userText", text: message });
this.renderMessages(); this.renderMessages();
textarea.value = ""; textarea.value = "";
try { try {
@@ -241,25 +383,32 @@ var ChatView = class extends import_obsidian2.ItemView {
this.plugin.sessionState = await this.client.createSession(); this.plugin.sessionState = await this.client.createSession();
} }
const sendData = { const sendData = {
parts: [{ text: message, role: "user" }], parts: [{ type: "text", text: message }]
model: {
providerID: "anthropic",
modelID: "claude-3-5-sonnet-20241022"
}
}; };
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; let response;
try { try {
response = await this.client.sendMessageToSession(this.plugin.sessionState.sessionID, sendData); response = await this.client.sendMessageToSession(this.plugin.sessionState.sessionID, sendData);
} catch (sendError) { } catch (sendError) {
const err = sendError; const err = sendError;
if (err.message.includes("Session not found") || err.message.includes("404")) { if (err.message.includes("Session not found")) {
this.plugin.sessionState = await this.client.createSession(); this.plugin.sessionState = await this.client.createSession();
response = await this.client.sendMessageToSession(this.plugin.sessionState.sessionID, sendData); response = await this.client.sendMessageToSession(this.plugin.sessionState.sessionID, sendData);
} else { } else {
throw sendError; throw sendError;
} }
} }
this.messages.push(...response.parts); for (const part of response.parts) {
this.messages.push({ kind: "assistantPart", part });
}
this.renderMessages(); this.renderMessages();
this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight; this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;
} catch (error) { } catch (error) {
@@ -292,19 +441,78 @@ var ChatView = class extends import_obsidian2.ItemView {
`; `;
return; return;
} }
for (const message of this.messages) { for (const item of this.messages) {
const messageEl = this.messagesContainer.createDiv({ if (item.kind === "userText") {
cls: `nb-message nb-message-${message.role}` const messageEl2 = this.messagesContainer.createDiv({ cls: "nb-message nb-message-user" });
}); messageEl2.createSpan({ text: item.text });
messageEl.createSpan({ text: message.text }); messageEl2.style.cssText = `
messageEl.style.cssText = `
padding: 0.75rem; padding: 0.75rem;
background-color: ${message.role === "user" ? "var(--background-modifier-accent)" : "var(--background-secondary)"}; background-color: var(--background-modifier-accent);
border-radius: 0.5rem; border-radius: 0.5rem;
font-size: 0.9rem; font-size: 0.9rem;
align-self: ${message.role === "user" ? "flex-end" : "flex-start"}; align-self: flex-end;
max-width: 70%; max-width: 70%;
`; `;
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 });
break;
case "reasoning":
messageEl.createSpan({ text: part.text });
break;
case "tool":
messageEl.createEl("strong", { text: `Tool: ${part.tool}` });
messageEl.createEl("pre", { text: JSON.stringify(part.state ?? {}, null, 2) });
break;
case "patch":
messageEl.createEl("strong", { text: `Patch: ${part.hash}` });
messageEl.createEl("pre", { text: (part.files || []).join("\n") });
break;
case "file":
messageEl.createEl("strong", { text: `File: ${part.filename ?? part.url}` });
messageEl.createEl("div", { text: `mime: ${part.mime}` });
messageEl.createEl("div", { text: `url: ${part.url}` });
break;
case "agent":
messageEl.createEl("strong", { text: `Agent: ${part.name}` });
break;
case "step_start":
messageEl.createEl("strong", { text: `Step start${part.title ? `: ${part.title}` : ""}` });
break;
case "step_finish":
messageEl.createEl("strong", { text: `Step finish${part.title ? `: ${part.title}` : ""}` });
break;
case "snapshot":
messageEl.createEl("strong", { text: "Snapshot" });
messageEl.createEl("pre", { text: JSON.stringify(part, null, 2) });
break;
case "retry":
messageEl.createEl("strong", { text: "Retry" });
messageEl.createEl("pre", { text: JSON.stringify(part, null, 2) });
break;
case "compaction":
messageEl.createEl("strong", { text: "Compaction" });
messageEl.createEl("pre", { text: JSON.stringify(part, null, 2) });
break;
case "unknown":
messageEl.createEl("strong", {
text: `Unsupported part type: ${part.originalType}`
});
messageEl.createEl("pre", { text: JSON.stringify(part, null, 2) });
break;
}
} }
} }
}; };
@@ -314,12 +522,20 @@ var import_obsidian3 = require("obsidian");
var NoteBuddySettingTab = class extends import_obsidian3.PluginSettingTab { var NoteBuddySettingTab = class extends import_obsidian3.PluginSettingTab {
constructor(app, plugin) { constructor(app, plugin) {
super(app, plugin); super(app, plugin);
this.providers = [];
this.isLoadingModels = false;
this.plugin = plugin; this.plugin = plugin;
} }
display() { async display(useCachedProviders) {
const { containerEl } = this; const { containerEl } = this;
containerEl.empty(); containerEl.empty();
containerEl.createEl("h2", { text: "NoteBuddy Settings" }); containerEl.createEl("h2", { text: "NoteBuddy Settings" });
if (!useCachedProviders) {
try {
await this.loadProviders();
} catch {
}
}
new import_obsidian3.Setting(containerEl).setName("Service URL").setDesc("The URL of the OpenCode service (must include protocol, hostname, and port)").addText( new import_obsidian3.Setting(containerEl).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) => { (text) => text.setPlaceholder("http://127.0.0.1:4096").setValue(this.plugin.settings.serviceUrl).onChange(async (value) => {
if (!value.startsWith("http://") && !value.startsWith("https://")) { if (!value.startsWith("http://") && !value.startsWith("https://")) {
@@ -346,7 +562,7 @@ var NoteBuddySettingTab = class extends import_obsidian3.PluginSettingTab {
); );
new import_obsidian3.Setting(containerEl).setName("Test Connection").setDesc("Test the connection to the service").addButton( new import_obsidian3.Setting(containerEl).setName("Test Connection").setDesc("Test the connection to the service").addButton(
(button) => button.setButtonText("Test").setCta().onClick(async () => { (button) => button.setButtonText("Test").setCta().onClick(async () => {
const client = new OpenCodeClient(this.plugin.settings.serviceUrl); const client = new OpenCodeClient(this.plugin.settings.serviceUrl, this.plugin.settings.defaultModelId);
const result = await client.healthCheck(); const result = await client.healthCheck();
if (result.status === "connected") { if (result.status === "connected") {
new import_obsidian3.Notice("Connection successful!"); new import_obsidian3.Notice("Connection successful!");
@@ -355,6 +571,65 @@ var NoteBuddySettingTab = class extends import_obsidian3.PluginSettingTab {
} }
}) })
); );
this.displayModelSelection(containerEl);
this.displayRefreshButton(containerEl);
}
async loadProviders(client, forceRefresh) {
if (this.isLoadingModels) {
return;
}
this.isLoadingModels = true;
try {
const c = client ?? new OpenCodeClient(this.plugin.settings.serviceUrl, this.plugin.settings.defaultModelId);
this.providers = await c.getCapabilities(forceRefresh ?? false);
} catch (error) {
this.providers = [];
console.error("[NoteBuddy] Failed to load providers:", error);
throw error;
} finally {
this.isLoadingModels = false;
}
}
displayModelSelection(containerEl) {
const modelOptions = {};
modelOptions[""] = "Use server default";
for (const provider of this.providers) {
for (const model of provider.models) {
const value = `${provider.id}/${model.id}`;
modelOptions[value] = `${provider.name} - ${model.name}`;
}
}
const currentValue = this.getCurrentModelSelection();
new import_obsidian3.Setting(containerEl).setName("Default Model").setDesc("Select the default AI model to use for conversations").addDropdown(
(dropdown) => dropdown.addOptions(modelOptions).setValue(currentValue).onChange(async (value) => {
if (value) {
this.plugin.settings.defaultModelId = value;
} else {
this.plugin.settings.defaultModelId = void 0;
}
await this.plugin.saveSettings();
})
);
}
getCurrentModelSelection() {
return this.plugin.settings.defaultModelId || "";
}
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 () => {
const client = new OpenCodeClient(this.plugin.settings.serviceUrl, this.plugin.settings.defaultModelId);
client.clearModelsCache();
try {
await this.loadProviders(client, true);
new import_obsidian3.Notice("Models refreshed");
await this.display(true);
} catch (error) {
console.error("[NoteBuddy] Failed to load providers:", error);
new import_obsidian3.Notice(`Failed to refresh models: ${error.message}`);
await this.display(true);
}
})
);
} }
}; };
@@ -407,6 +682,10 @@ var NoteBuddyPlugin = class extends import_obsidian4.Plugin {
async loadSettings() { async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
} }
// Callback for when selected model is unavailable
onModelUnavailable() {
new import_obsidian4.Notice("Selected model is unavailable. Using server default instead.");
}
async saveSettings() { async saveSettings() {
await this.saveData(this.settings); await this.saveData(this.settings);
} }
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -5,7 +5,7 @@
"isDesktopOnly": false, "isDesktopOnly": false,
"js": "main.js", "js": "main.js",
"fundingUrl": "https://ko-fi.com/vinzent", "fundingUrl": "https://ko-fi.com/vinzent",
"version": "1.46.0", "version": "1.46.1",
"author": "Vinzent", "author": "Vinzent",
"authorUrl": "https://github.com/Vinzent03" "authorUrl": "https://github.com/Vinzent03"
} }
+1 -1
View File
@@ -123,7 +123,7 @@
"mdBorderColor": "Black", "mdBorderColor": "Black",
"mdCSS": "", "mdCSS": "",
"scriptEngineSettings": {}, "scriptEngineSettings": {},
"previousRelease": "2.19.2", "previousRelease": "2.20.0",
"showReleaseNotes": true, "showReleaseNotes": true,
"compareManifestToPluginVersion": true, "compareManifestToPluginVersion": true,
"showNewVersionNotification": true, "showNewVersionNotification": true,
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"id": "obsidian-excalidraw-plugin", "id": "obsidian-excalidraw-plugin",
"name": "Excalidraw", "name": "Excalidraw",
"version": "2.19.2", "version": "2.20.0",
"minAppVersion": "1.5.7", "minAppVersion": "1.5.7",
"description": "Sketch Your Mind. An Obsidian plugin to edit and view Excalidraw drawings. Enter the world of 4D Visual PKM.", "description": "Sketch Your Mind. An Obsidian plugin to edit and view Excalidraw drawings. Enter the world of 4D Visual PKM.",
"author": "Zsolt Viczian", "author": "Zsolt Viczian",
File diff suppressed because one or more lines are too long
+3 -1
View File
@@ -65,7 +65,9 @@
"generalSettings": {}, "generalSettings": {},
"headingOpened": { "headingOpened": {
"核心状态": true, "核心状态": true,
"自定义状态": true "自定义状态": true,
"Core Statuses": true,
"Custom Statuses": true
}, },
"debugSettings": { "debugSettings": {
"ignoreSortInstructions": false, "ignoreSortInstructions": false,
+17 -2
View File
@@ -1,10 +1,12 @@
{ {
"choices": [], "choices": [],
"inputPrompt": "single-line", "inputPrompt": "single-line",
"persistInputPromptDrafts": true,
"useSelectionAsCaptureValue": true,
"devMode": false, "devMode": false,
"templateFolderPath": "06_Metadata/Templates", "templateFolderPath": "06_Metadata/Templates",
"announceUpdates": "all", "announceUpdates": "all",
"version": "2.9.4", "version": "2.10.0",
"globalVariables": {}, "globalVariables": {},
"onePageInputEnabled": false, "onePageInputEnabled": false,
"disableOnlineFeatures": true, "disableOnlineFeatures": true,
@@ -12,6 +14,17 @@
"showCaptureNotification": true, "showCaptureNotification": true,
"showInputCancellationNotification": false, "showInputCancellationNotification": false,
"enableTemplatePropertyTypes": true, "enableTemplatePropertyTypes": true,
"dateAliases": {
"t": "today",
"tm": "tomorrow",
"yd": "yesterday",
"nw": "next week",
"nm": "next month",
"ny": "next year",
"lw": "last week",
"lm": "last month",
"ly": "last year"
},
"ai": { "ai": {
"defaultModel": "Ask me", "defaultModel": "Ask me",
"defaultSystemPrompt": "As an AI assistant within Obsidian, your primary goal is to help users manage their ideas and knowledge more effectively. Format your responses using Markdown syntax. Please use the [[Obsidian]] link format. You can write aliases for the links by writing [[Obsidian|the alias after the pipe symbol]]. To use mathematical notation, use LaTeX syntax. LaTeX syntax for larger equations should be on separate lines, surrounded with double dollar signs ($$). You can also inline math expressions by wrapping it in $ symbols. For example, use $$w_{ij}^{\text{new}}:=w_{ij}^{\text{current}}+etacdotdelta_jcdot x_{ij}$$ on a separate line, but you can write \"($eta$ = learning rate, $delta_j$ = error term, $x_{ij}$ = input)\" inline.", "defaultSystemPrompt": "As an AI assistant within Obsidian, your primary goal is to help users manage their ideas and knowledge more effectively. Format your responses using Markdown syntax. Please use the [[Obsidian]] link format. You can write aliases for the links by writing [[Obsidian|the alias after the pipe symbol]]. To use mathematical notation, use LaTeX syntax. LaTeX syntax for larger equations should be on separate lines, surrounded with double dollar signs ($$). You can also inline math expressions by wrapping it in $ symbols. For example, use $$w_{ij}^{\text{new}}:=w_{ij}^{\text{current}}+etacdotdelta_jcdot x_{ij}$$ on a separate line, but you can write \"($eta$ = learning rate, $delta_j$ = error term, $x_{ij}$ = input)\" inline.",
@@ -99,6 +112,8 @@
"addDefaultAIProviders": true, "addDefaultAIProviders": true,
"removeMacroIndirection": true, "removeMacroIndirection": true,
"migrateFileOpeningSettings": true, "migrateFileOpeningSettings": true,
"setProviderModelDiscoveryMode": true "setProviderModelDiscoveryMode": true,
"backfillFileOpeningDefaults": true,
"migrateProviderApiKeysToSecretStorage": true
} }
} }
+78 -73
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -1,8 +1,8 @@
{ {
"id": "quickadd", "id": "quickadd",
"name": "QuickAdd", "name": "QuickAdd",
"version": "2.9.4", "version": "2.10.0",
"minAppVersion": "1.6.0", "minAppVersion": "1.11.4",
"description": "Quickly add new pages or content to your vault.", "description": "Quickly add new pages or content to your vault.",
"author": "Christian B. B. Houmann", "author": "Christian B. B. Houmann",
"authorUrl": "https://bagerbach.com", "authorUrl": "https://bagerbach.com",
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"id": "templater-obsidian", "id": "templater-obsidian",
"name": "Templater", "name": "Templater",
"version": "2.17.0", "version": "2.18.1",
"description": "Create and use templates", "description": "Create and use templates",
"minAppVersion": "1.5.0", "minAppVersion": "1.5.0",
"author": "SilentVoid", "author": "SilentVoid",