Skip to content

Commit ddb16af

Browse files
feat(miyo): add customizable vault name setting (#2311)
* feat(miyo): add customizable vault name setting for Miyo indexing Allows users to set a custom vault name that Miyo uses as the source ID for indexing, instead of the auto-detected vault path. When changed while Miyo is enabled, clears the old index and triggers a full re-index under the new name. Includes guidance for remote/multi-device setups to use a consistent vault name across devices. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(miyo): compare resolved source IDs before clearing index on vault name change Avoids unnecessary index clear and full re-index when the user types the auto-detected vault path (the value that the blank field resolves to), since the effective Miyo source ID is unchanged in that case. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(miyo): prevent applying an empty vault name The Apply button is hidden when the input is blank, and the handler guards against an empty string, so users cannot accidentally clear the vault name and submit it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(miyo): allow clearing vault name to restore auto-detected vault path An empty vault name is valid — it falls back to the auto-detected vault path as the Miyo source ID. Removes the empty-string guard so users can clear a previously set name and revert to the default behaviour. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d308423 commit ddb16af

File tree

4 files changed

+134
-4
lines changed

4 files changed

+134
-4
lines changed

src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,7 @@ export const DEFAULT_SETTINGS: CopilotSettings = {
966966
selfHostUrl: "",
967967
selfHostApiKey: "",
968968
miyoServerUrl: "",
969+
miyoVaultName: "",
969970
selfHostSearchProvider: "firecrawl",
970971
firecrawlApiKey: "",
971972
perplexityApiKey: "",

src/miyo/miyoUtils.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CopilotSettings } from "@/settings/model";
1+
import { CopilotSettings, getSettings } from "@/settings/model";
22
import { App, FileSystemAdapter } from "obsidian";
33

44
/**
@@ -15,10 +15,36 @@ export function getMiyoCustomUrl(settings: CopilotSettings): string {
1515
/**
1616
* Resolve the Miyo source id for the current vault.
1717
*
18+
* Uses the user-configured vault name when set, otherwise falls back to the
19+
* vault filesystem path or vault name.
20+
*
1821
* @param app - Obsidian application instance.
19-
* @returns Vault folder path when available, otherwise vault name.
22+
* @returns Custom vault name when configured, vault folder path when available, otherwise vault name.
2023
*/
2124
export function getMiyoSourceId(app: App): string {
25+
const customName = (getSettings().miyoVaultName || "").trim();
26+
if (customName) {
27+
return customName;
28+
}
29+
const vaultPath = getVaultBasePath(app);
30+
if (vaultPath) {
31+
return vaultPath;
32+
}
33+
return app.vault.getName();
34+
}
35+
36+
/**
37+
* Resolve the Miyo source id that would apply if a given vault name override were saved.
38+
*
39+
* @param app - Obsidian application instance.
40+
* @param vaultNameOverride - The vault name value to use (empty string = auto-detect).
41+
* @returns Resolved source id string.
42+
*/
43+
export function resolveMiyoSourceId(app: App, vaultNameOverride: string): string {
44+
const trimmed = vaultNameOverride.trim();
45+
if (trimmed) {
46+
return trimmed;
47+
}
2248
const vaultPath = getVaultBasePath(app);
2349
if (vaultPath) {
2450
return vaultPath;

src/settings/model.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ export interface CopilotSettings {
141141
selfHostApiKey: string;
142142
/** Custom Miyo server URL, e.g. "http://192.168.1.10:8742" (empty = use local service discovery) */
143143
miyoServerUrl: string;
144+
/** Custom vault name for Miyo indexing (overrides auto-detected vault path/name) */
145+
miyoVaultName: string;
144146
/** Which provider to use for self-host web search */
145147
selfHostSearchProvider: "firecrawl" | "perplexity";
146148
/** Firecrawl API key for self-host web search */
@@ -416,6 +418,11 @@ export function sanitizeSettings(settings: CopilotSettings): CopilotSettings {
416418
sanitizedSettings.enableMiyo = DEFAULT_SETTINGS.enableMiyo;
417419
}
418420

421+
// Ensure miyoVaultName has a default value
422+
if (typeof sanitizedSettings.miyoVaultName !== "string") {
423+
sanitizedSettings.miyoVaultName = DEFAULT_SETTINGS.miyoVaultName;
424+
}
425+
419426
// Ensure selfHostSearchProvider is a valid value
420427
const validSearchProviders = ["firecrawl", "perplexity"] as const;
421428
if (

src/settings/v2/components/CopilotPlusSettings.tsx

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
import { ConfirmModal } from "@/components/modals/ConfirmModal";
22
import { Badge } from "@/components/ui/badge";
33
import { HelpTooltip } from "@/components/ui/help-tooltip";
4+
import { Input } from "@/components/ui/input";
45
import { SettingItem } from "@/components/ui/setting-item";
56
import { DEFAULT_SETTINGS } from "@/constants";
7+
import { logWarn } from "@/logger";
68
import { MiyoClient } from "@/miyo/MiyoClient";
7-
import { getMiyoCustomUrl } from "@/miyo/miyoUtils";
9+
import { getMiyoCustomUrl, resolveMiyoSourceId } from "@/miyo/miyoUtils";
810
import { useIsSelfHostEligible, validateSelfHostMode } from "@/plusUtils";
911
import { updateSetting, useSettingsValue } from "@/settings/model";
1012
import { Notice } from "obsidian";
11-
import React, { useState } from "react";
13+
import React, { useEffect, useState } from "react";
1214
import { ToolSettingsSection } from "./ToolSettingsSection";
1315

1416
export const CopilotPlusSettings: React.FC = () => {
1517
const settings = useSettingsValue();
1618
const [isValidatingSelfHost, setIsValidatingSelfHost] = useState(false);
1719
const isSelfHostEligible = useIsSelfHostEligible();
20+
const [pendingVaultName, setPendingVaultName] = useState(settings.miyoVaultName || "");
21+
22+
// Keep local input in sync if settings change externally (e.g. settings reset)
23+
useEffect(() => {
24+
setPendingVaultName(settings.miyoVaultName || "");
25+
}, [settings.miyoVaultName]);
1826

1927
/**
2028
* Toggle self-host mode and handle validation requirements.
@@ -91,6 +99,60 @@ export const CopilotPlusSettings: React.FC = () => {
9199
).open();
92100
};
93101

102+
/**
103+
* Apply a vault name change for Miyo. When Miyo is enabled and the name actually changed,
104+
* shows a confirmation modal warning that the existing Miyo index will be deleted and a
105+
* full re-index will be triggered under the new name.
106+
*/
107+
const handleVaultNameApply = async () => {
108+
const newName = pendingVaultName.trim();
109+
const oldName = (settings.miyoVaultName || "").trim();
110+
if (newName === oldName) return;
111+
112+
// Compare resolved source IDs — if the user typed the auto-detected value
113+
// (e.g. the vault path), the effective Miyo namespace is unchanged and we
114+
// must not clear the existing index or trigger an unnecessary re-index.
115+
const oldSourceId = resolveMiyoSourceId(app, oldName);
116+
const newSourceId = resolveMiyoSourceId(app, newName);
117+
118+
if (!settings.enableMiyo || newSourceId === oldSourceId) {
119+
// Miyo is off, or the effective source ID hasn't changed — save silently.
120+
updateSetting("miyoVaultName", newName);
121+
return;
122+
}
123+
const confirmChange = async () => {
124+
try {
125+
const miyoClient = new MiyoClient();
126+
const baseUrl = await miyoClient.resolveBaseUrl(getMiyoCustomUrl(settings));
127+
await miyoClient.clearIndex(baseUrl, oldSourceId);
128+
} catch (e) {
129+
logWarn("Failed to clear Miyo index for old vault name", e);
130+
}
131+
132+
updateSetting("miyoVaultName", newName);
133+
134+
const VectorStoreManager = (await import("@/search/vectorStoreManager")).default;
135+
await VectorStoreManager.getInstance().indexVaultToVectorStore(false, {
136+
userInitiated: true,
137+
});
138+
};
139+
140+
const cancelChange = () => {
141+
// Reset input back to the saved value if user cancels
142+
setPendingVaultName(oldName);
143+
};
144+
145+
new ConfirmModal(
146+
app,
147+
confirmChange,
148+
`Changing the vault name will delete the existing Miyo index for "${oldSourceId || "(auto-detected)"}" and trigger a full re-index under the new name. This cannot be undone. Continue?`,
149+
"Change Vault Name",
150+
"Change & Re-index",
151+
"Cancel",
152+
cancelChange
153+
).open();
154+
};
155+
94156
return (
95157
<div className="tw-flex tw-flex-col tw-gap-4">
96158
<section className="tw-flex tw-flex-col tw-gap-4">
@@ -228,6 +290,40 @@ export const CopilotPlusSettings: React.FC = () => {
228290
placeholder="http://127.0.0.1:8742"
229291
/>
230292

293+
<SettingItem
294+
type="custom"
295+
title="Vault Name"
296+
description={
297+
<span>
298+
This is how Miyo identifies and remembers your vault&apos;s index — think of
299+
it as the unique label for all your indexed notes. Leave blank to use the
300+
auto-detected vault path. <strong>Set this before enabling Miyo.</strong> If
301+
you access Miyo from multiple devices or a remote server, use the same vault
302+
name on every device so they all share the same index.
303+
</span>
304+
}
305+
>
306+
<div className="tw-flex tw-items-center tw-gap-2">
307+
<Input
308+
value={pendingVaultName}
309+
onChange={(e) => setPendingVaultName(e.target.value)}
310+
onKeyDown={(e) => {
311+
if (e.key === "Enter") handleVaultNameApply();
312+
}}
313+
placeholder="Default: vault path"
314+
className="tw-w-full sm:tw-w-[200px]"
315+
/>
316+
{pendingVaultName.trim() !== (settings.miyoVaultName || "").trim() && (
317+
<button
318+
onClick={handleVaultNameApply}
319+
className="tw-rounded-md tw-bg-interactive-accent tw-px-3 tw-py-1.5 tw-text-sm tw-font-medium tw-text-on-accent hover:tw-bg-interactive-accent-hover"
320+
>
321+
Apply
322+
</button>
323+
)}
324+
</div>
325+
</SettingItem>
326+
231327
<SettingItem
232328
type="switch"
233329
title="Enable Miyo"

0 commit comments

Comments
 (0)