mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-15 19:05:11 +00:00
Types: - SessionEntryBase with type field, extended by all entry types - CustomEntry for hooks (type: 'custom', customType, data) - Remove XXXContent types and TreeNode (redundant) API: - Rename saveXXX to appendXXX with JSDoc explaining tree semantics - Rename branchInPlace to branch() with better docs - Add createBranchedSession(leafId) replacing index-based version - Add getTree() returning SessionTreeNode[] for tree traversal - Add appendCustomEntry(customType, data) for hooks Tests: - tree-traversal.test.ts: 28 tests covering append, getPath, getTree, branch, branchWithSummary, createBranchedSession - save-entry.test.ts: custom entry integration Docs: - Class-level JSDoc explaining append-only tree model - Method docs explaining leaf advancement and branching - CHANGELOG.md entry for all changes
55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { type CustomEntry, SessionManager } from "../../src/core/session-manager.js";
|
|
|
|
describe("SessionManager.saveCustomEntry", () => {
|
|
it("saves custom entries and includes them in tree traversal", () => {
|
|
const session = SessionManager.inMemory();
|
|
|
|
// Save a message
|
|
const msgId = session.appendMessage({ role: "user", content: "hello", timestamp: 1 });
|
|
|
|
// Save a custom entry
|
|
const customId = session.appendCustomEntry("my_hook", { foo: "bar" });
|
|
|
|
// Save another message
|
|
const msg2Id = session.appendMessage({
|
|
role: "assistant",
|
|
content: [{ type: "text", text: "hi" }],
|
|
api: "anthropic-messages",
|
|
provider: "anthropic",
|
|
model: "test",
|
|
usage: {
|
|
input: 1,
|
|
output: 1,
|
|
cacheRead: 0,
|
|
cacheWrite: 0,
|
|
totalTokens: 2,
|
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
},
|
|
stopReason: "stop",
|
|
timestamp: 2,
|
|
});
|
|
|
|
// Custom entry should be in entries
|
|
const entries = session.getEntries();
|
|
expect(entries).toHaveLength(3);
|
|
|
|
const customEntry = entries.find((e) => e.type === "custom") as CustomEntry;
|
|
expect(customEntry).toBeDefined();
|
|
expect(customEntry.customType).toBe("my_hook");
|
|
expect(customEntry.data).toEqual({ foo: "bar" });
|
|
expect(customEntry.id).toBe(customId);
|
|
expect(customEntry.parentId).toBe(msgId);
|
|
|
|
// Tree structure should be correct
|
|
const path = session.getPath();
|
|
expect(path).toHaveLength(3);
|
|
expect(path[0].id).toBe(msgId);
|
|
expect(path[1].id).toBe(customId);
|
|
expect(path[2].id).toBe(msg2Id);
|
|
|
|
// buildSessionContext should work (custom entries skipped in messages)
|
|
const ctx = session.buildSessionContext();
|
|
expect(ctx.messages).toHaveLength(2); // only message entries
|
|
});
|
|
});
|