mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-16 19:00:38 +09:00
Add unmanaged skill provenance to agent skills
Expose adapter-discovered user-installed skills with provenance metadata, share persistent skill snapshot classification across local adapters, and render unmanaged skills as a read-only section in the agent skills UI. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
58d7f59477
commit
cfc53bf96b
19 changed files with 497 additions and 501 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { applyAgentSkillSnapshot } from "./agent-skills-state";
|
||||
import { applyAgentSkillSnapshot, isReadOnlyUnmanagedSkillEntry } from "./agent-skills-state";
|
||||
|
||||
describe("applyAgentSkillSnapshot", () => {
|
||||
it("hydrates the initial snapshot without arming autosave", () => {
|
||||
|
|
@ -55,4 +55,36 @@ describe("applyAgentSkillSnapshot", () => {
|
|||
shouldSkipAutosave: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("treats user-installed entries outside the company library as read-only unmanaged skills", () => {
|
||||
expect(isReadOnlyUnmanagedSkillEntry({
|
||||
key: "crack-python",
|
||||
runtimeName: "crack-python",
|
||||
desired: false,
|
||||
managed: false,
|
||||
state: "external",
|
||||
origin: "user_installed",
|
||||
}, new Set(["paperclip"]))).toBe(true);
|
||||
});
|
||||
|
||||
it("keeps company-library entries in the managed section even when the adapter reports an external conflict", () => {
|
||||
expect(isReadOnlyUnmanagedSkillEntry({
|
||||
key: "paperclip",
|
||||
runtimeName: "paperclip",
|
||||
desired: true,
|
||||
managed: false,
|
||||
state: "external",
|
||||
origin: "company_managed",
|
||||
}, new Set(["paperclip"]))).toBe(false);
|
||||
});
|
||||
|
||||
it("falls back to legacy snapshots that only mark unmanaged external entries", () => {
|
||||
expect(isReadOnlyUnmanagedSkillEntry({
|
||||
key: "legacy-external",
|
||||
runtimeName: "legacy-external",
|
||||
desired: false,
|
||||
managed: false,
|
||||
state: "external",
|
||||
}, new Set())).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import type { AgentSkillEntry } from "@paperclipai/shared";
|
||||
|
||||
export interface AgentSkillDraftState {
|
||||
draft: string[];
|
||||
lastSaved: string[];
|
||||
|
|
@ -27,3 +29,12 @@ export function applyAgentSkillSnapshot(
|
|||
shouldSkipAutosave: shouldReplaceDraft,
|
||||
};
|
||||
}
|
||||
|
||||
export function isReadOnlyUnmanagedSkillEntry(
|
||||
entry: AgentSkillEntry,
|
||||
companySkillKeys: Set<string>,
|
||||
): boolean {
|
||||
if (companySkillKeys.has(entry.key)) return false;
|
||||
if (entry.origin === "user_installed" || entry.origin === "external_unknown") return true;
|
||||
return entry.managed === false && entry.state === "external";
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue