mirror of
https://github.com/harivansh-afk/clanker-agent.git
synced 2026-04-16 22:03:48 +00:00
move pi-mono into companion-cloud as apps/companion-os
- Copy all pi-mono source into apps/companion-os/ - Update Dockerfile to COPY pre-built binary instead of downloading from GitHub Releases - Update deploy-staging.yml to build pi from source (bun compile) before Docker build - Add apps/companion-os/** to path triggers - No more cross-repo dispatch needed Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
0250f72976
579 changed files with 206942 additions and 0 deletions
214
packages/coding-agent/test/session-selector-search.test.ts
Normal file
214
packages/coding-agent/test/session-selector-search.test.ts
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import type { SessionInfo } from "../src/core/session-manager.js";
|
||||
import { filterAndSortSessions } from "../src/modes/interactive/components/session-selector-search.js";
|
||||
|
||||
function makeSession(
|
||||
overrides: Partial<SessionInfo> & {
|
||||
id: string;
|
||||
modified: Date;
|
||||
allMessagesText: string;
|
||||
},
|
||||
): SessionInfo {
|
||||
return {
|
||||
path: `/tmp/${overrides.id}.jsonl`,
|
||||
id: overrides.id,
|
||||
cwd: overrides.cwd ?? "",
|
||||
name: overrides.name,
|
||||
created: overrides.created ?? new Date(0),
|
||||
modified: overrides.modified,
|
||||
messageCount: overrides.messageCount ?? 1,
|
||||
firstMessage: overrides.firstMessage ?? "(no messages)",
|
||||
allMessagesText: overrides.allMessagesText,
|
||||
};
|
||||
}
|
||||
|
||||
describe("session selector search", () => {
|
||||
it("filters by quoted phrase with whitespace normalization", () => {
|
||||
const sessions: SessionInfo[] = [
|
||||
makeSession({
|
||||
id: "a",
|
||||
modified: new Date("2026-01-01T00:00:00.000Z"),
|
||||
allMessagesText: "node\n\n cve was discussed",
|
||||
}),
|
||||
makeSession({
|
||||
id: "b",
|
||||
modified: new Date("2026-01-02T00:00:00.000Z"),
|
||||
allMessagesText: "node something else",
|
||||
}),
|
||||
];
|
||||
|
||||
const result = filterAndSortSessions(sessions, '"node cve"', "recent");
|
||||
expect(result.map((s) => s.id)).toEqual(["a"]);
|
||||
});
|
||||
|
||||
it("filters by regex (re:) and is case-insensitive", () => {
|
||||
const sessions: SessionInfo[] = [
|
||||
makeSession({
|
||||
id: "a",
|
||||
modified: new Date("2026-01-02T00:00:00.000Z"),
|
||||
allMessagesText: "Brave is great",
|
||||
}),
|
||||
makeSession({
|
||||
id: "b",
|
||||
modified: new Date("2026-01-03T00:00:00.000Z"),
|
||||
allMessagesText: "bravery is not the same",
|
||||
}),
|
||||
];
|
||||
|
||||
const result = filterAndSortSessions(sessions, "re:\\bbrave\\b", "recent");
|
||||
expect(result.map((s) => s.id)).toEqual(["a"]);
|
||||
});
|
||||
|
||||
it("recent sort preserves input order", () => {
|
||||
const sessions: SessionInfo[] = [
|
||||
makeSession({
|
||||
id: "newer",
|
||||
modified: new Date("2026-01-03T00:00:00.000Z"),
|
||||
allMessagesText: "brave",
|
||||
}),
|
||||
makeSession({
|
||||
id: "older",
|
||||
modified: new Date("2026-01-01T00:00:00.000Z"),
|
||||
allMessagesText: "brave",
|
||||
}),
|
||||
makeSession({
|
||||
id: "nomatch",
|
||||
modified: new Date("2026-01-04T00:00:00.000Z"),
|
||||
allMessagesText: "something else",
|
||||
}),
|
||||
];
|
||||
|
||||
const result = filterAndSortSessions(sessions, '"brave"', "recent");
|
||||
expect(result.map((s) => s.id)).toEqual(["newer", "older"]);
|
||||
});
|
||||
|
||||
it("relevance sort orders by score and tie-breaks by modified desc", () => {
|
||||
const sessions: SessionInfo[] = [
|
||||
makeSession({
|
||||
id: "late",
|
||||
modified: new Date("2026-01-03T00:00:00.000Z"),
|
||||
allMessagesText: "xxxx brave",
|
||||
}),
|
||||
makeSession({
|
||||
id: "early",
|
||||
modified: new Date("2026-01-01T00:00:00.000Z"),
|
||||
allMessagesText: "brave xxxx",
|
||||
}),
|
||||
];
|
||||
|
||||
const result1 = filterAndSortSessions(sessions, '"brave"', "relevance");
|
||||
expect(result1.map((s) => s.id)).toEqual(["early", "late"]);
|
||||
|
||||
const tieSessions: SessionInfo[] = [
|
||||
makeSession({
|
||||
id: "newer",
|
||||
modified: new Date("2026-01-03T00:00:00.000Z"),
|
||||
allMessagesText: "brave",
|
||||
}),
|
||||
makeSession({
|
||||
id: "older",
|
||||
modified: new Date("2026-01-01T00:00:00.000Z"),
|
||||
allMessagesText: "brave",
|
||||
}),
|
||||
];
|
||||
|
||||
const result2 = filterAndSortSessions(tieSessions, '"brave"', "relevance");
|
||||
expect(result2.map((s) => s.id)).toEqual(["newer", "older"]);
|
||||
});
|
||||
|
||||
it("returns empty list for invalid regex", () => {
|
||||
const sessions: SessionInfo[] = [
|
||||
makeSession({
|
||||
id: "a",
|
||||
modified: new Date("2026-01-01T00:00:00.000Z"),
|
||||
allMessagesText: "brave",
|
||||
}),
|
||||
];
|
||||
|
||||
const result = filterAndSortSessions(sessions, "re:(", "recent");
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
describe("name filter", () => {
|
||||
const sessions: SessionInfo[] = [
|
||||
makeSession({
|
||||
id: "named1",
|
||||
name: "My Project",
|
||||
modified: new Date("2026-01-03T00:00:00.000Z"),
|
||||
allMessagesText: "blueberry",
|
||||
}),
|
||||
makeSession({
|
||||
id: "named2",
|
||||
name: "Another Named",
|
||||
modified: new Date("2026-01-02T00:00:00.000Z"),
|
||||
allMessagesText: "blueberry",
|
||||
}),
|
||||
makeSession({
|
||||
id: "other1",
|
||||
modified: new Date("2026-01-04T00:00:00.000Z"),
|
||||
allMessagesText: "blueberry",
|
||||
}),
|
||||
makeSession({
|
||||
id: "other2",
|
||||
modified: new Date("2026-01-01T00:00:00.000Z"),
|
||||
allMessagesText: "blueberry",
|
||||
}),
|
||||
];
|
||||
|
||||
it("returns all sessions when nameFilter is 'all'", () => {
|
||||
const result = filterAndSortSessions(sessions, "", "recent", "all");
|
||||
expect(result.map((session) => session.id)).toEqual([
|
||||
"named1",
|
||||
"named2",
|
||||
"other1",
|
||||
"other2",
|
||||
]);
|
||||
});
|
||||
|
||||
it("returns only named sessions when nameFilter is 'named'", () => {
|
||||
const result = filterAndSortSessions(sessions, "", "recent", "named");
|
||||
expect(result.map((session) => session.id)).toEqual(["named1", "named2"]);
|
||||
});
|
||||
|
||||
it("applies name filter before search query", () => {
|
||||
const result = filterAndSortSessions(
|
||||
sessions,
|
||||
"blueberry",
|
||||
"recent",
|
||||
"named",
|
||||
);
|
||||
expect(result.map((session) => session.id)).toEqual(["named1", "named2"]);
|
||||
});
|
||||
|
||||
it("excludes whitespace-only names from named filter", () => {
|
||||
const sessionsWithWhitespace: SessionInfo[] = [
|
||||
makeSession({
|
||||
id: "whitespace",
|
||||
name: " ",
|
||||
modified: new Date("2026-01-01T00:00:00.000Z"),
|
||||
allMessagesText: "test",
|
||||
}),
|
||||
makeSession({
|
||||
id: "empty",
|
||||
name: "",
|
||||
modified: new Date("2026-01-02T00:00:00.000Z"),
|
||||
allMessagesText: "test",
|
||||
}),
|
||||
makeSession({
|
||||
id: "named",
|
||||
name: "Real Name",
|
||||
modified: new Date("2026-01-03T00:00:00.000Z"),
|
||||
allMessagesText: "test",
|
||||
}),
|
||||
];
|
||||
|
||||
const result = filterAndSortSessions(
|
||||
sessionsWithWhitespace,
|
||||
"",
|
||||
"recent",
|
||||
"named",
|
||||
);
|
||||
expect(result.map((session) => session.id)).toEqual(["named"]);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue