chore: fix all automated-scan lint warnings, bump to v0.3.6

- vault-service: use fileManager.trashFile() to respect user deletion pref
- Replace bare JSON.parse() with explicit type assertions across all files
- MessageList/DiffReviewBlock/ConversationList: eliminate unsafe-any in Svelte
- main.ts: cast loadData() result to the expected migrateSettings parameter type
- conversation.ts: import ToolCall type, use Message["role"] cast for parsed role

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
This commit is contained in:
Bin-Home 2026-05-16 22:47:07 +08:00
parent 0369205720
commit a5cb829dd6
12 changed files with 18 additions and 17 deletions

View file

@ -1,7 +1,7 @@
{
"id": "smart-note-agent",
"name": "Smart Note Agent",
"version": "0.3.5",
"version": "0.3.6",
"minAppVersion": "1.7.2",
"description": "Agentic AI assistant for reading and editing vault notes.",
"author": "Bin Hong",

View file

@ -1,6 +1,6 @@
{
"name": "smart-note-agent",
"version": "0.3.5",
"version": "0.3.6",
"main": "index.js",
"directories": {
"doc": "docs"

View file

@ -106,7 +106,7 @@ export class AgentLoop {
const result = await tool.handler(tc.args);
console.debug(`[agent] tool result (${tc.name}):`, result.slice(0, 300));
if (result.startsWith(PENDING_PREFIX)) {
const payload = JSON.parse(result.slice(PENDING_PREFIX.length));
const payload = JSON.parse(result.slice(PENDING_PREFIX.length)) as { tool: string; args: Record<string, unknown> };
if (this.opts.autoApprove) {
await this.opts.autoApprove(payload);
const applied = JSON.stringify({ status: "applied" });

View file

@ -1,4 +1,4 @@
import type { Mode, Message, ProviderId } from "../types";
import type { Mode, Message, ProviderId, ToolCall } from "../types";
export interface ConversationMeta {
id: string;
@ -66,7 +66,7 @@ export function parseConversation(md: string): Conversation {
const fm: Record<string, string> = {};
for (const line of m[1].split("\n")) {
const kv = line.match(/^(\w+):\s*(.*)$/); if (!kv) continue;
fm[kv[1]] = kv[2].startsWith("\"") ? JSON.parse(kv[2]) : kv[2];
fm[kv[1]] = kv[2].startsWith("\"") ? JSON.parse(kv[2]) as string : kv[2];
}
let bodyText = m[2] ?? "";
@ -86,7 +86,7 @@ export function parseConversation(md: string): Conversation {
for (const block of bodyText.split(SEP).filter(x => x.trim())) {
const meta = block.match(/^<!-- meta: (.+?) -->\n([\s\S]*)$/);
if (!meta) continue;
const parsed = JSON.parse(meta[1]);
const parsed = JSON.parse(meta[1]) as { role: Message["role"]; toolCalls?: ToolCall[]; toolCallId?: string; reasoningContent?: string };
messages.push({ role: parsed.role, content: meta[2], toolCalls: parsed.toolCalls, toolCallId: parsed.toolCallId, reasoningContent: parsed.reasoningContent });
}

View file

@ -32,7 +32,7 @@ export default class ObsidianNoteAgentPlugin extends Plugin {
private currentLoop: AgentLoop | null = null;
async onload() {
this.settings = migrateSettings(await this.loadData());
this.settings = migrateSettings(await this.loadData() as Parameters<typeof migrateSettings>[0]);
this.i18n = new I18n(detectLocale(this.settings.locale, moment.locale()));
this.vault = new VaultService(this.app);
this.conversations = new ConversationStore(this.app, () => this.settings.chatsFolder);

View file

@ -57,7 +57,7 @@ export class AnthropicProvider implements LLMProvider {
} else if (o.type === "content_block_stop" && o.index !== undefined) {
const b = blocks[o.index];
if (b?.type === "tool_use") {
let args: Record<string, unknown> = {}; try { args = JSON.parse(b.buf || "{}"); } catch { args = { _raw: b.buf }; }
let args: Record<string, unknown> = {}; try { args = JSON.parse(b.buf || "{}") as Record<string, unknown>; } catch { args = { _raw: b.buf }; }
yield { type: "tool_call", toolCall: { id: b.id!, name: b.name!, args } };
}
} else if (o.type === "message_stop") break;

View file

@ -28,7 +28,7 @@ function sleep(ms: number, signal?: AbortSignal): Promise<void> {
}
function parseRateMsg(raw: string): string {
try { return JSON.parse(raw)?.error?.message ?? raw; } catch { return raw; }
try { return (JSON.parse(raw) as { error?: { message?: string } })?.error?.message ?? raw; } catch { return raw; }
}
export async function httpJson<T = unknown>(o: HttpOptions): Promise<T> {

View file

@ -44,7 +44,7 @@ export class OpenAIProvider implements LLMProvider {
}
for (const i of Object.keys(pending)) {
const p = pending[+i]; let args: Record<string, unknown> = {};
try { args = JSON.parse(p.args || "{}"); } catch { args = { _raw: p.args }; }
try { args = JSON.parse(p.args || "{}") as Record<string, unknown>; } catch { args = { _raw: p.args }; }
yield { type: "tool_call", toolCall: { id: p.id ?? `tc_${i}`, name: p.name, args } };
}
yield { type: "done" };

View file

@ -38,7 +38,7 @@ export class VaultService {
const p = validatePath(path);
const f = this.app.vault.getAbstractFileByPath(p);
if (!f) throw new Error(`not found: ${p}`);
await this.app.vault.delete(f);
await this.app.fileManager.trashFile(f);
}
async moveNote(oldPath: string, newPath: string): Promise<void> {

View file

@ -6,7 +6,7 @@
const dispatch = createEventDispatcher<{ select: void; newChat: void }>();
let paths: string[] = [];
let active = plugin.currentConversation?.path ?? "";
let active = "";
onMount(async () => { paths = await plugin.conversations.list(); });

View file

@ -43,7 +43,7 @@
}
$: diffLines = p.diff ? parseDiff(p.diff) : [];
$: filePath = p.args?.path ?? p.args?.from ?? p.args?.to ?? "";
$: filePath = (p.args?.path ?? p.args?.from ?? p.args?.to ?? "") as string;
$: fileName = filePath ? filePath.split("/").pop() ?? filePath : "";
async function approveItem() {

View file

@ -46,15 +46,16 @@
function previewResult(content: string): string {
try {
const json = JSON.parse(content);
const json: unknown = JSON.parse(content);
if (Array.isArray(json)) {
if (json.length === 0) return "no results";
const label = json[0]?.path !== undefined ? "note" : "item";
const label = (json[0] as Record<string, unknown> | null)?.path !== undefined ? "note" : "item";
return `${json.length} ${label}${json.length === 1 ? "" : "s"}`;
}
if (json && typeof json === "object") {
if ("error" in json) return `error: ${String(json.error).slice(0, 60)}`;
if ("status" in json) return String(json.status);
const obj = json as Record<string, unknown>;
if ("error" in obj) return `error: ${String(obj.error).slice(0, 60)}`;
if ("status" in obj) return String(obj.status);
}
if (typeof json === "string") return json.slice(0, 80);
} catch { /* not JSON */ }