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:
dotta
2026-03-18 14:21:50 -05:00
parent 58d7f59477
commit cfc53bf96b
19 changed files with 497 additions and 501 deletions

View File

@@ -141,6 +141,7 @@ export type {
CompanySkillFileUpdateRequest,
AgentSkillSyncMode,
AgentSkillState,
AgentSkillOrigin,
AgentSkillEntry,
AgentSkillSnapshot,
AgentSkillSyncRequest,

View File

@@ -8,6 +8,12 @@ export type AgentSkillState =
| "stale"
| "external";
export type AgentSkillOrigin =
| "company_managed"
| "paperclip_required"
| "user_installed"
| "external_unknown";
export interface AgentSkillEntry {
key: string;
runtimeName: string | null;
@@ -16,6 +22,10 @@ export interface AgentSkillEntry {
required?: boolean;
requiredReason?: string | null;
state: AgentSkillState;
origin?: AgentSkillOrigin;
originLabel?: string | null;
locationLabel?: string | null;
readOnly?: boolean;
sourcePath?: string | null;
targetPath?: string | null;
detail?: string | null;

View File

@@ -24,6 +24,7 @@ export type {
export type {
AgentSkillSyncMode,
AgentSkillState,
AgentSkillOrigin,
AgentSkillEntry,
AgentSkillSnapshot,
AgentSkillSyncRequest,

View File

@@ -9,6 +9,13 @@ export const agentSkillStateSchema = z.enum([
"external",
]);
export const agentSkillOriginSchema = z.enum([
"company_managed",
"paperclip_required",
"user_installed",
"external_unknown",
]);
export const agentSkillSyncModeSchema = z.enum([
"unsupported",
"persistent",
@@ -23,6 +30,10 @@ export const agentSkillEntrySchema = z.object({
required: z.boolean().optional(),
requiredReason: z.string().nullable().optional(),
state: agentSkillStateSchema,
origin: agentSkillOriginSchema.optional(),
originLabel: z.string().nullable().optional(),
locationLabel: z.string().nullable().optional(),
readOnly: z.boolean().optional(),
sourcePath: z.string().nullable().optional(),
targetPath: z.string().nullable().optional(),
detail: z.string().nullable().optional(),