Menu
popagent
publicLatest change 6edc7e928c57dab23c0973ed3f7ee70b3ebb72d5 - Initial popagent baseline by AkurAI Build
import { beforeAll, describe, expect, test } from "bun:test";
import { storage } from "./storage";
type SettingsMigration = {
file: string;
table: string;
valueColumns: string[];
};
const migrations: SettingsMigration[] = [
{
file: "channel-settings.sql",
table: "popagent_channel_settings",
valueColumns: ["enabled", "dispatch_mode", "context_messages", "streaming", "tool_display"],
},
{
file: "browser-settings.sql",
table: "popagent_browser_settings",
valueColumns: [
"enabled", "scope", "viewport_width", "viewport_height", "timeout_ms",
"max_sessions", "idle_timeout_ms", "screencast_enabled", "screenshots_enabled",
"multi_tab_enabled", "forms_enabled", "dialogs_enabled", "drag_enabled",
"evaluate_enabled", "recording_enabled", "recording_retention_days",
"recording_max_files", "allow_hosts", "deny_hosts",
],
},
{
file: "memory-settings.sql",
table: "popagent_memory_settings",
valueColumns: [
"auto_compact",
"observation_tokens",
"reflection_tokens",
"recent_message_percent",
"buffer_on_idle",
],
},
{
file: "agent-runtime-settings.sql",
table: "popagent_agent_runtime_settings",
valueColumns: [
"default_model",
"supervisor_max_steps",
"specialist_max_steps",
"tool_concurrency",
"delegation_context_messages",
"delegation_result_characters",
"max_processor_retries",
"final_response_feedback",
"delegation_failure_feedback",
"delegation_result_truncation_marker",
"task_concurrency",
"task_poll_interval_ms",
"task_timeout_ms",
"task_stale_after_ms",
],
},
];
beforeAll(() => storage.init());
describe("settings migrations", () => {
for (const migration of migrations) {
test(`${migration.file} seeds configuration only once`, async () => {
const schemaName = `settings_migration_${crypto.randomUUID().replaceAll("-", "")}`;
const quotedSchema = `"${schemaName}"`;
const sql = await Bun.file(new URL(`./${migration.file}`, import.meta.url)).text();
await storage.db.tx(async (transaction) => {
await transaction.none(`CREATE SCHEMA ${quotedSchema}`);
try {
await transaction.none(`SET LOCAL search_path TO ${quotedSchema}`);
await transaction.none(sql);
expect(await transaction.one<{ count: number }>(
`SELECT COUNT(*)::int AS count FROM ${migration.table}`,
)).toEqual({ count: 1 });
const columns = await transaction.any<{ columnName: string; defaultValue: string | null }>(`
SELECT column_name AS "columnName", column_default AS "defaultValue"
FROM information_schema.columns
WHERE table_schema = $1 AND table_name = $2
`, [schemaName, migration.table]);
expect(columns.filter((column) => migration.valueColumns.includes(column.columnName)))
.toEqual(migration.valueColumns.map((columnName) => ({ columnName, defaultValue: null })));
await transaction.none(`DELETE FROM ${migration.table}`);
await transaction.none(sql);
expect(await transaction.one<{ count: number }>(
`SELECT COUNT(*)::int AS count FROM ${migration.table}`,
)).toEqual({ count: 0 });
} finally {
await transaction.none(`DROP SCHEMA ${quotedSchema} CASCADE`);
}
});
});
}
});