mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-15 10:30:37 +09:00
Fix agent skills autosave hydration\n\nCo-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
8460fee380
commit
bb46423969
3 changed files with 118 additions and 14 deletions
58
ui/src/lib/agent-skills-state.test.ts
Normal file
58
ui/src/lib/agent-skills-state.test.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { applyAgentSkillSnapshot } from "./agent-skills-state";
|
||||
|
||||
describe("applyAgentSkillSnapshot", () => {
|
||||
it("hydrates the initial snapshot without arming autosave", () => {
|
||||
const result = applyAgentSkillSnapshot(
|
||||
{
|
||||
draft: [],
|
||||
lastSaved: [],
|
||||
hasHydratedSnapshot: false,
|
||||
},
|
||||
["paperclip", "para-memory-files"],
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
draft: ["paperclip", "para-memory-files"],
|
||||
lastSaved: ["paperclip", "para-memory-files"],
|
||||
hasHydratedSnapshot: true,
|
||||
shouldSkipAutosave: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps unsaved local edits when a fresh snapshot arrives", () => {
|
||||
const result = applyAgentSkillSnapshot(
|
||||
{
|
||||
draft: ["paperclip", "custom-skill"],
|
||||
lastSaved: ["paperclip"],
|
||||
hasHydratedSnapshot: true,
|
||||
},
|
||||
["paperclip"],
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
draft: ["paperclip", "custom-skill"],
|
||||
lastSaved: ["paperclip"],
|
||||
hasHydratedSnapshot: true,
|
||||
shouldSkipAutosave: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("adopts server state after a successful save and skips the follow-up autosave pass", () => {
|
||||
const result = applyAgentSkillSnapshot(
|
||||
{
|
||||
draft: ["paperclip", "custom-skill"],
|
||||
lastSaved: ["paperclip", "custom-skill"],
|
||||
hasHydratedSnapshot: true,
|
||||
},
|
||||
["paperclip", "custom-skill"],
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
draft: ["paperclip", "custom-skill"],
|
||||
lastSaved: ["paperclip", "custom-skill"],
|
||||
hasHydratedSnapshot: true,
|
||||
shouldSkipAutosave: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
29
ui/src/lib/agent-skills-state.ts
Normal file
29
ui/src/lib/agent-skills-state.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
export interface AgentSkillDraftState {
|
||||
draft: string[];
|
||||
lastSaved: string[];
|
||||
hasHydratedSnapshot: boolean;
|
||||
}
|
||||
|
||||
export interface AgentSkillSnapshotApplyResult extends AgentSkillDraftState {
|
||||
shouldSkipAutosave: boolean;
|
||||
}
|
||||
|
||||
export function arraysEqual(a: string[], b: string[]): boolean {
|
||||
if (a === b) return true;
|
||||
if (a.length !== b.length) return false;
|
||||
return a.every((value, index) => value === b[index]);
|
||||
}
|
||||
|
||||
export function applyAgentSkillSnapshot(
|
||||
state: AgentSkillDraftState,
|
||||
desiredSkills: string[],
|
||||
): AgentSkillSnapshotApplyResult {
|
||||
const shouldReplaceDraft = !state.hasHydratedSnapshot || arraysEqual(state.draft, state.lastSaved);
|
||||
|
||||
return {
|
||||
draft: shouldReplaceDraft ? desiredSkills : state.draft,
|
||||
lastSaved: desiredSkills,
|
||||
hasHydratedSnapshot: true,
|
||||
shouldSkipAutosave: shouldReplaceDraft,
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue