From cf9b0f72f3c68153dc263fbc0f7c37f3ca3dc53a Mon Sep 17 00:00:00 2001 From: Leo310 Date: Mon, 28 Sep 2026 11:39:01 +0200 Subject: [PATCH] chore(skills): drop the skill usage counters; keep the author stamp The load and revision counters were built for a curator that is on hold, and for a person in the Agent editor they rarely change anything: every revision already shows up as a tool card in its chat and as a change to the note. They cost a plugin-data write, and so a sync, on every skill load. Removed: the recording in load_skill and manage_skills, the stored list, the delete-path bookkeeping, and the usage line in the editor. The `metadata.author: agent` stamp on created skills stays as plain provenance, like `author: S2B` on the bundled ones. The 2.3.0 changelog entry for the usage line goes with it. Co-Authored-By: Claude --- CHANGELOG.md | 1 - src/agent/AgentManager.ts | 1 - src/agent/tools/loadSkill.ts | 14 +--- src/agent/tools/manageSkills.ts | 12 ++- src/components/modal/AgentEditorModal.svelte | 4 - src/skills/SkillsService.ts | 10 --- src/skills/usageSummary.ts | 55 ------------- src/stores/dataStore.svelte.ts | 58 -------------- src/types/plugin.ts | 29 ------- test/agent/loadSkill.test.ts | 24 ------ test/agent/manageSkills.test.ts | 55 +------------ test/skills/deleteSkill.test.ts | 20 +---- test/skills/usageSummary.test.ts | 49 ------------ test/stores/dataStore.test.ts | 84 -------------------- 14 files changed, 11 insertions(+), 405 deletions(-) delete mode 100644 src/skills/usageSummary.ts delete mode 100644 test/skills/usageSummary.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fce26d0..c2cdb3fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,6 @@ A reworked chat composer, especially on mobile, agents that keep their memory an - **Chat: attachments as preview tiles.** Images show a thumbnail and PDFs their first page; other files show a card. Click a tile to open the file, or use its corner × to remove it (#526). - **Chat: Take photo on mobile.** The attach menu has a Take photo row that goes straight to the camera (#520). - **Chat: one jump-to-bottom button** replaces the message-navigation arrows. It appears once you scroll away from the end, including while a reply streams below the fold (#522, #523, #527, #528). -- **Agents: where a skill came from and how it's used.** Skills the agent writes are marked as its own, and the Agent editor shows how often each custom skill has been used and revised (#516). - **What's new, in the plugin.** After an update, a notice opens a What's new tab with the notes for every release since the one you last saw. The Show release notes command and a row in Settings → Troubleshooting open it any time (#533). - **Update notices.** Once a day the plugin asks GitHub whether a newer version exists and says so, with a link to Community plugins. It sends nothing about you or your vault, stays quiet while Obsidian's own automatic update check is on, and can be turned off under Settings → General → Privacy (#534). diff --git a/src/agent/AgentManager.ts b/src/agent/AgentManager.ts index c11177e7..2f586ce5 100644 --- a/src/agent/AgentManager.ts +++ b/src/agent/AgentManager.ts @@ -982,7 +982,6 @@ export class AgentManager { tools.push( createLoadSkillTool(this.plugin.skillsService, { skillNames: loadableSkills, - recordUsage: (name) => getData().recordSkillLoad(name), isToolAvailable: (toolId) => { if (BUILT_IN_TOOL_IDS.includes(toolId as BuiltInToolId)) { return boundBuiltInTools.has(toolId); diff --git a/src/agent/tools/loadSkill.ts b/src/agent/tools/loadSkill.ts index c2a589d6..03e6016b 100644 --- a/src/agent/tools/loadSkill.ts +++ b/src/agent/tools/loadSkill.ts @@ -3,7 +3,6 @@ import { tool } from "@langchain/core/tools"; import { z } from "zod"; import type { SkillsService } from "../../skills/SkillsService"; import type { CommunityPluginStatus } from "../integrations/pluginIntegrations"; -import { Logger as Log } from "../../utils/logging"; import { recordSkillLoaded } from "./skillLoadRegistry"; /** Frontmatter key (under `metadata:`) listing community plugin ids a skill can make use of. */ @@ -47,12 +46,6 @@ export interface LoadSkillToolOptions { * that path exists, instead of letting it find out from a failed result. */ pluginStatus?: (pluginId: string) => { status: CommunityPluginStatus; displayName: string }; - /** - * Called after a skill's body was returned to the model. The plugin data store counts - * loads per skill (see `SkillUsageEntry`); injected rather than imported so the tool - * stays testable without a live store, and a missed record never fails a load. - */ - recordUsage?: (skillName: string) => void; } /** @@ -64,7 +57,7 @@ export interface LoadSkillToolOptions { * @returns A LangChain tool for loading skill content */ export function createLoadSkillTool(skillsService: SkillsService, options: LoadSkillToolOptions) { - const { skillNames, isToolAvailable, pluginStatus, recordUsage } = options; + const { skillNames, isToolAvailable, pluginStatus } = options; // If no skills available, return a tool that explains this if (skillNames.length === 0) { @@ -95,11 +88,6 @@ export function createLoadSkillTool(skillsService: SkillsService, options: LoadS // The model has now seen this skill's current text in this conversation, which is // what `manage_skills` requires before it will patch or rewrite it. recordSkillLoaded(config?.configurable?.thread_id, skillName, skill.content); - try { - recordUsage?.(skillName); - } catch (error) { - Log.warn(`load_skill: could not record usage of ${skillName}`, error); - } // Return the skill content with metadata const lines: string[] = []; diff --git a/src/agent/tools/manageSkills.ts b/src/agent/tools/manageSkills.ts index 34515c88..8a8f4bd9 100644 --- a/src/agent/tools/manageSkills.ts +++ b/src/agent/tools/manageSkills.ts @@ -130,11 +130,11 @@ function splitSkillMd(raw: string): { head: string; body: string } | null { } /** - * `metadata.author` value stamped on every skill the agent creates. Bundled skills carry - * `S2B` in the same key and hand-written ones carry whatever the user put there (or nothing), - * so one existing key tells the three apart — which is what lets anything autonomous later - * (a curator) confine itself to the agent's own skills. A fixed word rather than the agent's - * name: consumers need no list of agent names, and a renamed or deleted agent changes nothing. + * `metadata.author` value stamped on every skill the agent creates: plain provenance in the + * same key the bundled skills use for `S2B`, written once and never read by the plugin. It is + * the one fact about a skill that cannot be reconstructed later, so it is recorded even though + * nothing acts on it today. A fixed word rather than the agent's name, so a renamed or deleted + * agent changes nothing. */ export const AGENT_SKILL_AUTHOR = "agent"; @@ -331,7 +331,6 @@ export function createManageSkillsTool(skillsService: SkillsService | undefined, // counters so a later skill of the same name starts from zero. const agent = getData().getAgent(agentId) ?? getData().getSelectedAgent(); if (agent?.skills[input.name]) delete agent.skills[input.name]; - getData().forgetSkillUsage(input.name); return `Deleted the "${input.name}" skill.`; } @@ -408,7 +407,6 @@ export function createManageSkillsTool(skillsService: SkillsService | undefined, // history, so a revised core skill is flagged as customized rather than overwritten // by the next upgrade. await skillsService.writeSkillFile(skillName, newContent); - getData().recordSkillRevision(skillName); // The model wrote this text too, so a follow-up revision in the same turn needs no reload. recordSkillLoaded(threadId, skillName, parseFrontmatter(newContent).body); diff --git a/src/components/modal/AgentEditorModal.svelte b/src/components/modal/AgentEditorModal.svelte index 790fd64d..6878a681 100644 --- a/src/components/modal/AgentEditorModal.svelte +++ b/src/components/modal/AgentEditorModal.svelte @@ -38,7 +38,6 @@ import { agentDefinitionPath, agentDir } from "../../utils/agentPaths"; import { Logger } from "../../utils/logging"; import { extractErrorMessage } from "../../utils/errorMessage"; import { humanizeSkillName } from "../../skills"; -import { skillUsageSummary } from "../../skills/usageSummary"; import { DEFAULT_AGENT_ICON, type AgentConfig, @@ -299,8 +298,6 @@ const skills = $derived.by(() => { category: metadata.category ?? "custom", corePluginId: metadata.corePluginId, linkedPluginId: metadata.linkedPluginId, - author: metadata.frontmatter.metadata?.author, - usage: pluginData.getSkillUsage(skillName), }); } return result; @@ -1052,7 +1049,6 @@ function getServerToolsState(serverId: string): MCPServerToolsState | undefined class="skill-entity" name={ext.displayName} desc={ext.description} - meta={skillUsageSummary(ext.author, ext.usage)} > {#snippet actions()}