This commit is contained in:
ZacharyZhang-NY committed 2026-05-15 19:40:20 -04:00
1 parent 2ab001b18a
commit 810e2d5967
28 files changed
+1015 -85

No files matched your search

@@ -0,0 +1,130 @@
import type { DatabaseSync } from "node:sqlite";
import { nowIso, tableExists } from "./types";
export const FILESYSTEM_TASK_WORKSPACES_SCHEMA_VERSION = 60;
export const FILESYSTEM_TASK_WORKSPACES_SCHEMA_NAME = "filesystem_task_workspaces";
const ACTIVE_TASK_STATUSES = "'backlog', 'todo', 'in_progress', 'blocked'";
export function migrateFilesystemTaskWorkspacesV60(db: DatabaseSync): void {
backfillProjectWorkspaces(db);
backfillAssigneeWorkspaces(db);
backfillSingleCompanyWorkspaces(db);
db
.prepare("insert or replace into schema_migrations (version, name, applied_at) values (?, ?, ?)")
.run(FILESYSTEM_TASK_WORKSPACES_SCHEMA_VERSION, FILESYSTEM_TASK_WORKSPACES_SCHEMA_NAME, nowIso());
assertFilesystemTaskWorkspacesV60(db);
}
export function assertFilesystemTaskWorkspacesV60(db: DatabaseSync): void {
if (!tableExists(db, "tasks") || !tableExists(db, "workspaces")) {
throw new Error("Schema v60 drift: tasks/workspaces tables are missing.");
}
const unresolved = db
.prepare(
`select count(*) as count
from tasks t
where t.requires_filesystem = 1
and t.workspace_id is null
and t.status in (${ACTIVE_TASK_STATUSES})
and (
select count(*)
from workspaces w
where w.company_id = t.company_id
) = 1`,
)
.get() as { count: number } | undefined;
if ((unresolved?.count ?? 0) > 0) {
throw new Error("Schema v60 drift: single-workspace companies still have unresolved filesystem tasks.");
}
}
function backfillProjectWorkspaces(db: DatabaseSync): void {
if (!hasRequiredTables(db)) return;
db
.prepare(
`update tasks
set workspace_id = (
select w.id
from workspaces w
where w.company_id = tasks.company_id
and w.project_id = tasks.project_id
order by w.is_primary desc, w.created_at asc
limit 1
),
updated_at = ?
where requires_filesystem = 1
and workspace_id is null
and status in (${ACTIVE_TASK_STATUSES})
and project_id is not null
and exists (
select 1
from workspaces w
where w.company_id = tasks.company_id
and w.project_id = tasks.project_id
)`,
)
.run(nowIso());
}
function backfillAssigneeWorkspaces(db: DatabaseSync): void {
if (!hasRequiredTables(db) || !tableExists(db, "agents")) return;
db
.prepare(
`update tasks
set workspace_id = (
select a.workspace_id
from agents a
join workspaces w
on w.id = a.workspace_id
and w.company_id = a.company_id
where a.id = tasks.assignee_agent_id
and a.company_id = tasks.company_id
limit 1
),
updated_at = ?
where requires_filesystem = 1
and workspace_id is null
and status in (${ACTIVE_TASK_STATUSES})
and assignee_agent_id is not null
and exists (
select 1
from agents a
join workspaces w
on w.id = a.workspace_id
and w.company_id = a.company_id
where a.id = tasks.assignee_agent_id
and a.company_id = tasks.company_id
)`,
)
.run(nowIso());
}
function backfillSingleCompanyWorkspaces(db: DatabaseSync): void {
if (!hasRequiredTables(db)) return;
db
.prepare(
`update tasks
set workspace_id = (
select w.id
from workspaces w
where w.company_id = tasks.company_id
order by w.is_primary desc, w.created_at asc
limit 1
),
updated_at = ?
where requires_filesystem = 1
and workspace_id is null
and status in (${ACTIVE_TASK_STATUSES})
and (
select count(*)
from workspaces w
where w.company_id = tasks.company_id
) = 1`,
)
.run(nowIso());
}
function hasRequiredTables(db: DatabaseSync): boolean {
return tableExists(db, "tasks") && tableExists(db, "workspaces");
}
+21 -6
View File
@@ -92,12 +92,27 @@ export function buildModelCapabilityMethods(
*/
function seedModelCapabilities(rows: Array<Omit<ModelCapability, "updatedAt">>): number {
return transaction(() => {
const existing = readAll<{ cnt: number }>(
"SELECT COUNT(*) AS cnt FROM model_capabilities",
)[0]?.cnt ?? 0;
if (existing > 0) return 0;
for (const row of rows) upsertModelCapability(row);
return rows.length;
let inserted = 0;
const ts = nowIso();
const stmt = getDb().prepare(
`INSERT OR IGNORE INTO model_capabilities (
provider, model_id, reasoning, coding, writing, tier, cost_per_mtok_out, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
);
for (const row of rows) {
const result = stmt.run(
row.provider,
row.modelId,
row.reasoning,
row.coding,
row.writing,
row.tier,
row.costPerMtokOut,
ts,
);
inserted += Number(result.changes ?? 0);
}
return inserted;
});
}
+23 -1
View File
@@ -24,12 +24,17 @@ import {
assertSocialCompanyScopeV59,
migrateSocialCompanyScopeV59,
} from "./migrations/v59-social-company-scope";
import {
FILESYSTEM_TASK_WORKSPACES_SCHEMA_VERSION,
assertFilesystemTaskWorkspacesV60,
migrateFilesystemTaskWorkspacesV60,
} from "./migrations/v60-filesystem-task-workspaces";
import {
type ReadAll,
type Transaction,
} from "./migrations/types";
const LATEST_SCHEMA_VERSION = SOCIAL_COMPANY_SCOPE_SCHEMA_VERSION;
const LATEST_SCHEMA_VERSION = FILESYSTEM_TASK_WORKSPACES_SCHEMA_VERSION;
export function initializeDatabase(
db: DatabaseSync,
@@ -50,6 +55,18 @@ export function initializeDatabase(
assertTaskLeasesV57(db);
assertApprovalPoliciesV58(db);
assertSocialCompanyScopeV59(db);
assertFilesystemTaskWorkspacesV60(db);
});
return;
}
if (currentVersion === SOCIAL_COMPANY_SCOPE_SCHEMA_VERSION) {
tx(() => {
seedSettings(db);
assertTaskLeasesV57(db);
assertApprovalPoliciesV58(db);
assertSocialCompanyScopeV59(db);
migrateFilesystemTaskWorkspacesV60(db);
});
return;
}
@@ -60,6 +77,7 @@ export function initializeDatabase(
assertTaskLeasesV57(db);
assertApprovalPoliciesV58(db);
migrateSocialCompanyScopeV59(db);
migrateFilesystemTaskWorkspacesV60(db);
});
return;
}
@@ -70,6 +88,7 @@ export function initializeDatabase(
assertTaskLeasesV57(db);
migrateApprovalPoliciesV58(db);
migrateSocialCompanyScopeV59(db);
migrateFilesystemTaskWorkspacesV60(db);
});
return;
}
@@ -83,6 +102,7 @@ export function initializeDatabase(
migrateTaskLeasesV57(db);
migrateApprovalPoliciesV58(db);
migrateSocialCompanyScopeV59(db);
migrateFilesystemTaskWorkspacesV60(db);
});
return;
}
@@ -97,6 +117,7 @@ export function initializeDatabase(
migrateTaskLeasesV57(db);
migrateApprovalPoliciesV58(db);
migrateSocialCompanyScopeV59(db);
migrateFilesystemTaskWorkspacesV60(db);
});
return;
}
@@ -109,6 +130,7 @@ export function initializeDatabase(
migrateTaskLeasesV57(db);
migrateApprovalPoliciesV58(db);
migrateSocialCompanyScopeV59(db);
migrateFilesystemTaskWorkspacesV60(db);
});
}