138 lines
4.2 KiB
TypeScript
138 lines
4.2 KiB
TypeScript
import { App, Notice, PluginSettingTab, Setting } from "obsidian";
|
|
import { BeaverApiError, apiBase, listAgents, listApiAgents } from "./api";
|
|
import type BeaverPlugin from "./main";
|
|
|
|
export interface BeaverSettings {
|
|
baseUrl: string;
|
|
apiBaseUrl: string;
|
|
token: string;
|
|
vaultSubpath: string;
|
|
}
|
|
|
|
export const DEFAULT_SETTINGS: BeaverSettings = {
|
|
baseUrl: "http://localhost:62993",
|
|
apiBaseUrl: "",
|
|
token: "",
|
|
vaultSubpath: "",
|
|
};
|
|
|
|
export function normalizeSubpath(raw: string): string {
|
|
return raw.trim().replace(/^\/+|\/+$/g, "");
|
|
}
|
|
|
|
function errorText(err: unknown): string {
|
|
return err instanceof BeaverApiError
|
|
? `${err.status}: ${err.message}`
|
|
: err instanceof Error
|
|
? err.message
|
|
: String(err);
|
|
}
|
|
|
|
export class BeaverSettingsTab extends PluginSettingTab {
|
|
plugin: BeaverPlugin;
|
|
|
|
constructor(app: App, plugin: BeaverPlugin) {
|
|
super(app, plugin);
|
|
this.plugin = plugin;
|
|
}
|
|
|
|
display(): void {
|
|
const { containerEl } = this;
|
|
containerEl.empty();
|
|
|
|
new Setting(containerEl)
|
|
.setName("Base URL")
|
|
.setDesc("Markdown frontend root, e.g. http://localhost:62993")
|
|
.addText((text) =>
|
|
text
|
|
.setPlaceholder("http://localhost:62993")
|
|
.setValue(this.plugin.settings.baseUrl)
|
|
.onChange(async (value) => {
|
|
this.plugin.settings.baseUrl = value.trim().replace(/\/+$/, "");
|
|
await this.plugin.saveSettings();
|
|
}),
|
|
);
|
|
|
|
new Setting(containerEl)
|
|
.setName("API origin")
|
|
.setDesc(
|
|
"Origin of the conversations API; `/api/…` is appended to it. " +
|
|
"Leave empty to derive from Base URL (`…/md` → `…`, port 62993 → 62994). " +
|
|
"Example: https://beaver.example.com or http://localhost:62994.",
|
|
)
|
|
.addText((text) =>
|
|
text
|
|
.setPlaceholder("(derived)")
|
|
.setValue(this.plugin.settings.apiBaseUrl)
|
|
.onChange(async (value) => {
|
|
this.plugin.settings.apiBaseUrl = value.trim().replace(/\/+$/, "");
|
|
await this.plugin.saveSettings();
|
|
}),
|
|
);
|
|
|
|
new Setting(containerEl)
|
|
.setName("Bearer token")
|
|
.setDesc(
|
|
"Token with the `messages` scope for sending and the `api` scope " +
|
|
"for the activity panel (or a `*` bootstrap token).",
|
|
)
|
|
.addText((text) => {
|
|
text.inputEl.type = "password";
|
|
text
|
|
.setPlaceholder("paste token")
|
|
.setValue(this.plugin.settings.token)
|
|
.onChange(async (value) => {
|
|
this.plugin.settings.token = value;
|
|
await this.plugin.saveSettings();
|
|
});
|
|
});
|
|
|
|
new Setting(containerEl)
|
|
.setName("Vault subpath")
|
|
.setDesc(
|
|
"Folder in this Obsidian vault that maps to the gateway's vault root. " +
|
|
"Leave empty if the two vault roots match. Example: `💬 чаты`.",
|
|
)
|
|
.addText((text) =>
|
|
text
|
|
.setPlaceholder("")
|
|
.setValue(this.plugin.settings.vaultSubpath)
|
|
.onChange(async (value) => {
|
|
this.plugin.settings.vaultSubpath = normalizeSubpath(value);
|
|
await this.plugin.saveSettings();
|
|
}),
|
|
);
|
|
|
|
new Setting(containerEl)
|
|
.setName("Test connection")
|
|
.setDesc("Calls GET /agents on the markdown frontend and reports the count.")
|
|
.addButton((btn) =>
|
|
btn.setButtonText("Test").onClick(async () => {
|
|
try {
|
|
const agents = await listAgents(this.plugin.settings);
|
|
this.plugin.cacheAgents(agents);
|
|
new Notice(`Beaver: found ${agents.length} agents`);
|
|
} catch (err) {
|
|
new Notice(`Beaver: ${errorText(err)}`, 8000);
|
|
}
|
|
}),
|
|
);
|
|
|
|
new Setting(containerEl)
|
|
.setName("Test API")
|
|
.setDesc("Calls GET /api/agents on the API origin (needs the `api` scope).")
|
|
.addButton((btn) =>
|
|
btn.setButtonText("Test").onClick(async () => {
|
|
try {
|
|
const agents = await listApiAgents(this.plugin.settings);
|
|
new Notice(
|
|
`Beaver: API at ${apiBase(this.plugin.settings)} - ${agents.length} agents`,
|
|
);
|
|
} catch (err) {
|
|
new Notice(`Beaver: ${errorText(err)}`, 8000);
|
|
}
|
|
}),
|
|
);
|
|
}
|
|
}
|