release: 0.13.4 — warning cleanup (trashFile, builtin-modules, unused vars)

This commit is contained in:
Denis Berekchiyan 2026-06-14 11:39:05 -07:00
parent 694874f7ac
commit c2477d08bc
13 changed files with 139 additions and 125 deletions

View file

@ -1,5 +1,13 @@
# Changelog
## 0.13.4 — 2026-06-14
Further community-review cleanup (all non-blocking warnings). No user-facing behavior changes.
- **Deletions respect your trash preference** — file/folder removals now go through `FileManager.trashFile` instead of `Vault.delete`/`Vault.trash`, so they honor your "move to system trash vs. permanently delete" setting.
- Replaced the `builtin-modules` build dependency with Node's built-in `module.builtinModules`.
- Removed a few unused local variables.
## 0.13.3 — 2026-06-14
Clears the blocking errors from the Obsidian Community Plugins automated review. No user-facing behavior changes.

View file

@ -1,5 +1,9 @@
import esbuild from "esbuild";
import builtins from "builtin-modules";
import { builtinModules } from "node:module";
// Node built-ins (plus their `node:` aliases) are external — the plugin runs in
// Electron's Node context and must not bundle them.
const builtins = [...builtinModules, ...builtinModules.map((m) => `node:${m}`)];
const prod = process.argv.includes("production");

178
main.js

File diff suppressed because one or more lines are too long

View file

@ -1,7 +1,7 @@
{
"id": "agent-fleet",
"name": "Agent Fleet",
"version": "0.13.3",
"version": "0.13.4",
"minAppVersion": "1.11.4",
"description": "File-backed AI agents with task scheduling, channels, memory, and MCP — running on Claude Code or OpenAI Codex, all as plain markdown.",
"author": "Denis Berekchiyan",

View file

@ -1,6 +1,6 @@
{
"name": "obsidian-agent-fleet",
"version": "0.13.3",
"version": "0.13.4",
"description": "Obsidian plugin for file-backed AI agents, task scheduling, channels (Slack), heartbeat, and interactive chat.",
"license": "MIT",
"main": "plugin/main.js",
@ -27,7 +27,6 @@
"devDependencies": {
"@types/node": "^24.5.2",
"@types/ws": "^8.18.1",
"builtin-modules": "^4.0.0",
"esbuild": "^0.25.9",
"obsidian": "^1.8.10",
"tslib": "^2.8.1",

View file

@ -1,5 +1,5 @@
import { join } from "path";
import { FileSystemAdapter, TFile, TFolder, Vault, normalizePath } from "obsidian";
import { App, FileSystemAdapter, TFile, TFolder, Vault, normalizePath } from "obsidian";
import {
DEFAULT_SETTINGS,
DEFAULT_MEMORY_TOKEN_BUDGET,
@ -145,7 +145,10 @@ export class FleetRepository {
* reflection path and the lock-held capture path can't double-seed raw. */
private migratingMemory = new Set<string>();
constructor(private readonly vault: Vault, private readonly settings: FleetSettings) {}
private readonly vault: Vault;
constructor(private readonly app: App, private readonly settings: FleetSettings) {
this.vault = app.vault;
}
/** Inject a live credential getter so validation reads from the credential store
* instead of the (possibly empty post-migration) settings.channelCredentials. */
@ -1182,19 +1185,19 @@ export class FleetRepository {
const path = this.getConversationPath(agent, conversationId);
const file = this.vault.getAbstractFileByPath(path);
if (file instanceof TFile) {
await this.vault.delete(file);
await this.app.fileManager.trashFile(file);
}
const threadsDir = path.replace(/\.json$/, ".threads");
const threadsFolder = this.vault.getAbstractFileByPath(threadsDir);
if (threadsFolder instanceof TFolder) {
await this.vault.delete(threadsFolder, true);
await this.app.fileManager.trashFile(threadsFolder);
}
const dir = this.getConversationsDir(agent);
const folder = this.vault.getAbstractFileByPath(dir);
if (folder instanceof TFolder && folder.children.length === 0) {
await this.vault.delete(folder, true);
await this.app.fileManager.trashFile(folder);
}
}
@ -1706,7 +1709,7 @@ export class FleetRepository {
}
} else if (permFile instanceof TFile) {
// Remove permissions.json if both lists are empty
await this.vault.trash(permFile, true);
await this.app.fileManager.trashFile(permFile);
}
}
} else {
@ -1757,7 +1760,7 @@ export class FleetRepository {
await this.vault.create(sidecarPath, content);
}
} else if (sidecarFile instanceof TFile) {
await this.vault.trash(sidecarFile, true);
await this.app.fileManager.trashFile(sidecarFile);
}
}
}
@ -1882,7 +1885,7 @@ export class FleetRepository {
const folderPath = normalizePath(skill.filePath.replace(/\/skill\.md$/, ""));
const folder = this.vault.getAbstractFileByPath(folderPath);
if (folder instanceof TFolder) {
await this.vault.trash(folder, true);
await this.app.fileManager.trashFile(folder);
}
} else {
await this.trashFile(skill.filePath);
@ -1944,7 +1947,7 @@ export class FleetRepository {
);
const folder = this.vault.getAbstractFileByPath(sessionsFolder);
if (folder instanceof TFolder) {
await this.vault.trash(folder, true);
await this.app.fileManager.trashFile(folder);
}
}
@ -2072,7 +2075,7 @@ export class FleetRepository {
for (const f of files) {
trashedFiles.push(f.path);
}
await this.vault.trash(folder, true);
await this.app.fileManager.trashFile(folder);
}
} else {
// Trash the single agent definition file
@ -2089,7 +2092,7 @@ export class FleetRepository {
const memoryDir = this.getMemoryDir(agentName);
const memoryFolder = this.vault.getAbstractFileByPath(memoryDir);
if (memoryFolder instanceof TFolder) {
await this.vault.trash(memoryFolder, true);
await this.app.fileManager.trashFile(memoryFolder);
trashedFiles.push(memoryDir);
}
@ -2108,7 +2111,7 @@ export class FleetRepository {
async trashFile(path: string): Promise<void> {
const file = this.vault.getAbstractFileByPath(path);
if (file) {
await this.vault.trash(file, true);
await this.app.fileManager.trashFile(file);
}
}

View file

@ -60,7 +60,7 @@ export default class AgentFleetPlugin extends Plugin {
async onload(): Promise<void> {
await this.loadSettings();
this.settings.claudeCliPath = await this.resolveClaudeCliPath(this.settings.claudeCliPath);
this.repository = new FleetRepository(this.app.vault, this.settings);
this.repository = new FleetRepository(this.app, this.settings);
this.repository.setChannelCredentialGetter(() => this.channelCredentials.toRecord());
this.runtime = new FleetRuntime(this.repository, this.settings, this.mcpAuth);
@ -301,7 +301,7 @@ export default class AgentFleetPlugin extends Plugin {
// task crons run alongside the new one's, producing duplicate runs and
// making schedule edits appear not to take effect until full reload.
this.runtime.shutdown();
this.repository = new FleetRepository(this.app.vault, this.settings);
this.repository = new FleetRepository(this.app, this.settings);
this.repository.setChannelCredentialGetter(() => this.channelCredentials.toRecord());
this.runtime = new FleetRuntime(this.repository, this.settings, this.mcpAuth);
await this.repository.ensureFleetStructure();

View file

@ -497,7 +497,6 @@ export class SlackAdapter implements ChannelAdapter {
const actions = payload.actions as Array<Record<string, unknown>> | undefined;
const user = payload.user as Record<string, unknown> | undefined;
const channel = payload.channel as Record<string, unknown> | undefined;
const message = payload.message as Record<string, unknown> | undefined;
if (!actions?.length || !user || !channel) return;
const action = actions[0];

View file

@ -568,10 +568,9 @@ export class ChatSession {
/** Clear persisted state — for "New Chat" */
async clearPersistedState(): Promise<void> {
const path = this.getChatFilePath();
const file = this.vault.getAbstractFileByPath(path);
if (file instanceof TFile) {
await this.vault.delete(file);
}
// Route through the repository so deletion respects the user's trash
// preference (FileManager.trashFile).
await this.repository.trashFile(path);
this.messages = [];
this.claudeSessionId = null;
this.basePromptSent = false;

View file

@ -446,7 +446,7 @@ export class AgentFleetSettingTab extends PluginSettingTab {
if (!ok) return;
try {
await deleteWikiKeeperAgent(
this.plugin.app.vault,
this.plugin.app,
this.plugin.settings.fleetFolder,
agent.name,
);

View file

@ -850,7 +850,6 @@ export class FleetDashboardView extends ItemView {
): void {
const state = this.plugin.runtime.getAgentState(agent.name);
const agentRuns = this.plugin.runtime.getRecentRuns().filter((r) => r.agent === agent.name);
const agentTasks = snapshot.tasks.filter((t) => t.agent === agent.name);
const card = container.createDiv({ cls: `af-agent-card${agent.enabled ? "" : " disabled"}` });
@ -2087,7 +2086,7 @@ export class FleetDashboardView extends ItemView {
const headerInfo = headerLeft.createDiv();
headerInfo.createDiv({ cls: "af-detail-header-name", text: "Create New Channel" });
headerInfo.createDiv({ cls: "af-detail-header-desc", text: "Connect an external chat transport to an agent" });
header.createDiv({ cls: "af-detail-header-actions" });
const headerActions = header.createDiv({ cls: "af-detail-header-actions" });
// Form state
const state = {
@ -2349,7 +2348,7 @@ export class FleetDashboardView extends ItemView {
const headerInfo = headerLeft.createDiv();
headerInfo.createDiv({ cls: "af-detail-header-name", text: `Edit Channel: ${channel.name}` });
headerInfo.createDiv({ cls: "af-detail-header-desc", text: `Status: ${status}` });
header.createDiv({ cls: "af-detail-header-actions" });
const headerActions = header.createDiv({ cls: "af-detail-header-actions" });
// Form state pre-filled
const state = {
@ -4735,7 +4734,7 @@ export class FleetDashboardView extends ItemView {
headerInfo.createDiv({ cls: "af-detail-header-name", text: "Create New Task" });
headerInfo.createDiv({ cls: "af-detail-header-desc", text: "Configure a new task for your fleet" });
header.createDiv({ cls: "af-detail-header-actions" });
const headerActions = header.createDiv({ cls: "af-detail-header-actions" });
// Form state
const state = {
@ -5039,7 +5038,7 @@ export class FleetDashboardView extends ItemView {
headerInfo.createDiv({ cls: "af-detail-header-name", text: `Edit Task: ${task.taskId}` });
headerInfo.createDiv({ cls: "af-detail-header-desc", text: "Modify task configuration" });
header.createDiv({ cls: "af-detail-header-actions" });
const headerActions = header.createDiv({ cls: "af-detail-header-actions" });
const hasSchedule = !!(task.schedule || task.runAt);
@ -5860,7 +5859,7 @@ export class FleetDashboardView extends ItemView {
const headerInfo = headerLeft.createDiv();
headerInfo.createDiv({ cls: "af-detail-header-name", text: "Add MCP Server" });
headerInfo.createDiv({ cls: "af-detail-header-desc", text: "Register a new MCP server for agents to use" });
header.createDiv({ cls: "af-detail-header-actions" });
const headerActions = header.createDiv({ cls: "af-detail-header-actions" });
// Form state
const state: {

View file

@ -1,4 +1,4 @@
import { normalizePath, TFile, TFolder, type Vault } from "obsidian";
import { type App, normalizePath, TFile, TFolder, type Vault } from "obsidian";
import { parseMarkdownWithFrontmatter, slugify, stringifyMarkdownWithFrontmatter } from "./utils/markdown";
/** User-supplied inputs when creating a Wiki Keeper instance. */
@ -585,22 +585,24 @@ export async function updateWikiKeeperAgent(
/** Delete a Wiki Keeper agent folder. Leaves the scope's own content
* (inbox, topics, index, log) untouched that's the user's wiki, not ours. */
export async function deleteWikiKeeperAgent(
vault: Vault,
app: App,
fleetFolder: string,
agentName: string,
): Promise<void> {
const vault = app.vault;
const folderPath = normalizePath(`${fleetFolder}/agents/${agentName}`);
const folder = vault.getAbstractFileByPath(folderPath);
if (!folder) return;
if (!(folder instanceof TFolder)) {
throw new Error(`Expected folder at ${folderPath}`);
}
await vault.adapter.rmdir(folderPath, true);
// Trash (don't hard-delete) so it respects the user's deletion preference.
await app.fileManager.trashFile(folder);
// Also delete the sibling lint task file, if present.
// Also trash the sibling lint task file, if present.
const taskPath = lintTaskPath(fleetFolder, agentName);
const taskFile = vault.getAbstractFileByPath(taskPath);
if (taskFile instanceof TFile) {
await vault.delete(taskFile);
await app.fileManager.trashFile(taskFile);
}
}

View file

@ -25,5 +25,6 @@
"0.13.0": "1.6.0",
"0.13.1": "1.6.0",
"0.13.2": "1.6.0",
"0.13.3": "1.11.4"
"0.13.3": "1.11.4",
"0.13.4": "1.11.4"
}