1092 lines
40 KiB
TypeScript
1092 lines
40 KiB
TypeScript
import Database from 'better-sqlite3';
|
|
import { logger } from '../logger.js';
|
|
import * as schemaRepo from './repositories/schema.js';
|
|
import * as jobsRepo from './repositories/jobs.js';
|
|
import { JobStatus, Job, CreateJobParams, SubtaskInfo } from './repositories/jobs.js';
|
|
import * as spacesRepo from './repositories/spaces.js';
|
|
import { Space, SpaceMemberRoleValue, SpaceMember, SpaceInviteRole, SpaceInvite, CreateSpaceParams } from './repositories/spaces.js';
|
|
import * as usersRepo from './repositories/users.js';
|
|
import { User, CreateUserParams, FindOrCreateByOAuthParams, CreateLocalUserParams, LocalOrg, LocalOrgMember, GiteaOrgInput, GiteaOrg } from './repositories/users.js';
|
|
import * as workerNodesRepo from './repositories/worker-nodes.js';
|
|
import { WorkerNode, UpsertWorkerNodeParams } from './repositories/worker-nodes.js';
|
|
import * as scheduledTasksRepo from './repositories/scheduled-tasks.js';
|
|
import { ScheduledTask, CreateScheduledTaskParams, UpdateScheduledTaskParams } from './repositories/scheduled-tasks.js';
|
|
import * as a2aRepo from './repositories/a2a.js';
|
|
import { A2aClientRow, A2aDelegationRow } from './repositories/a2a.js';
|
|
import * as reflectionRepo from './repositories/reflection.js';
|
|
import * as toolRequestsRepo from './repositories/tool-requests.js';
|
|
import { ToolRequestCategory, ToolRequestStatus, ToolRequest, ToolRequestAggregate, PackageRequest, PackageRequestStatus } from './repositories/tool-requests.js';
|
|
import * as gatewayRepo from './repositories/gateway.js';
|
|
import { GatewayVirtualKeySource, GatewayVirtualKey, GatewayKeyUsage } from './repositories/gateway.js';
|
|
import * as llmUsageRepo from './repositories/llm-usage.js';
|
|
import { LlmUsageIncrement, LlmUsageDailyAgg, LlmUsageHourlyIncrement, LlmUsageHourlyRow } from './repositories/llm-usage.js';
|
|
import * as notificationsRepo from './repositories/notifications.js';
|
|
import { PushSubscriptionRecord, UpsertPushSubscriptionInput, NotificationPrefs, NotificationPrefsUpdate } from './repositories/notifications.js';
|
|
import * as auditRepo from './repositories/audit.js';
|
|
import * as appSharesRepo from './repositories/app-shares.js';
|
|
import * as provenanceRepo from './repositories/provenance.js';
|
|
import * as localTasksRepo from './repositories/local-tasks.js';
|
|
import { LocalTask, MissionBrief, LocalTaskComment, CreateLocalTaskParams } from './repositories/local-tasks.js';
|
|
export { MISSION_BRIEF_FIELDS } from './repositories/local-tasks.js';
|
|
export type { TitleSource, LocalTask, MissionBriefField, MissionBrief, LocalTaskComment, CreateLocalTaskParams } from './repositories/local-tasks.js';
|
|
import * as taskSearchRepo from './repositories/task-search.js';
|
|
import * as calendarRepo from './repositories/calendar.js';
|
|
import { CalendarEvent, CalendarDayCounts, CalendarDayTask, CrossSpaceCalendarMonth } from './repositories/calendar.js';
|
|
export { enumerateLocalDays } from './repositories/calendar.js';
|
|
export type { CalendarEvent, CalendarDayCounts, CalendarDayTask, CrossCalendarSpace, CrossSpaceCalendarMonth } from './repositories/calendar.js';
|
|
export type { NotifyEventType, PushSubscriptionRecord, UpsertPushSubscriptionInput, NotificationPrefs, NotificationPrefsUpdate } from './repositories/notifications.js';
|
|
export type { LlmUsageIncrement, LlmUsageDailyAgg, LlmUsageHourlyIncrement, LlmUsageHourlyRow } from './repositories/llm-usage.js';
|
|
export type { GatewayVirtualKeySource, GatewayVirtualKey, GatewayKeyUsage } from './repositories/gateway.js';
|
|
export type { ToolRequestCategory, ToolRequestStatus, ToolRequest, ToolRequestAggregate, PackageRequest, PackageRequestStatus } from './repositories/tool-requests.js';
|
|
export type { A2aClientRow, A2aDelegationRow } from './repositories/a2a.js';
|
|
export type { ScheduledTaskKind, ScheduledTask, CreateScheduledTaskParams, UpdateScheduledTaskParams } from './repositories/scheduled-tasks.js';
|
|
export type { WorkerNode, UpsertWorkerNodeParams } from './repositories/worker-nodes.js';
|
|
export type { User, CreateUserParams, FindOrCreateByOAuthParams, CreateLocalUserParams, LocalOrg, LocalOrgMember, GiteaOrgInput, GiteaOrg } from './repositories/users.js';
|
|
export type { Space, SpaceMemberRoleValue, SpaceMember, SpaceInviteRole, SpaceInvite, CreateSpaceParams } from './repositories/spaces.js';
|
|
export type { JobStatus, JobRole, JobProfile, TaskClass, Job, CreateJobParams, SubtaskInfo } from './repositories/jobs.js';
|
|
export { localTaskRepoName } from './repositories/shared.js';
|
|
|
|
|
|
export class Repository {
|
|
private readonly db: Database.Database;
|
|
|
|
constructor(dbPath: string) {
|
|
this.db = new Database(dbPath);
|
|
this.db.pragma('journal_mode = WAL');
|
|
this.db.pragma('foreign_keys = ON');
|
|
this.db.pragma('busy_timeout = 5000');
|
|
this.initSchema();
|
|
logger.info(`Repository: initialized at ${dbPath}`);
|
|
}
|
|
|
|
private initSchema(): void {
|
|
return schemaRepo.initSchema(this.db);
|
|
}
|
|
|
|
private runPreSchemaCompatibilityMigrations(): void {
|
|
return schemaRepo.runPreSchemaCompatibilityMigrations(this.db);
|
|
}
|
|
|
|
private ensureColumn(tableName: string, columnName: string, definition: string): void {
|
|
return schemaRepo.ensureColumn(this.db, tableName, columnName, definition);
|
|
}
|
|
|
|
private migrateWaitingSubtasksStatus(): void {
|
|
return schemaRepo.migrateWaitingSubtasksStatus(this.db);
|
|
}
|
|
|
|
private insertJobSync(params: CreateJobParams): Job {
|
|
return jobsRepo.insertJobSync(this.db, params);
|
|
}
|
|
|
|
private getJobSync(id: string): Job | null {
|
|
return jobsRepo.getJobSync(this.db, id);
|
|
}
|
|
|
|
private async buildSubtaskInfos(subJobs: Job[], maxDepth: number = 3): Promise<SubtaskInfo[]> {
|
|
return jobsRepo.buildSubtaskInfos(this.db, subJobs, maxDepth);
|
|
}
|
|
|
|
async createJob(params: CreateJobParams): Promise<Job> {
|
|
return jobsRepo.createJob(this.db, params);
|
|
}
|
|
|
|
createJobIfNoPending(params: CreateJobParams, opts?: { blockOnToolRequestPause?: boolean }): { job: Job; created: boolean; blockedByToolRequest?: boolean } {
|
|
return jobsRepo.createJobIfNoPending(this.db, params, opts);
|
|
}
|
|
|
|
async getJob(id: string, opts?: { viewer?: Express.User }): Promise<Job | null> {
|
|
return jobsRepo.getJob(this.db, id, opts);
|
|
}
|
|
|
|
async createSpace(params: CreateSpaceParams): Promise<Space> {
|
|
return spacesRepo.createSpace(this.db, params);
|
|
}
|
|
|
|
async getSpace(id: string, opts?: { viewer?: Express.User }): Promise<Space | null> {
|
|
return spacesRepo.getSpace(this.db, id, opts);
|
|
}
|
|
|
|
async listSpaces(opts?: { viewer?: Express.User; includeArchived?: boolean }): Promise<Space[]> {
|
|
return spacesRepo.listSpaces(this.db, opts);
|
|
}
|
|
|
|
async updateSpace(id: string, patch: { title?: string; description?: string; brandColor?: string | null; visibility?: 'private' | 'org' | 'public'; visibilityScopeOrgId?: string | null }): Promise<Space | null> {
|
|
return spacesRepo.updateSpace(this.db, id, patch);
|
|
}
|
|
|
|
async archiveSpace(id: string): Promise<void> {
|
|
return spacesRepo.archiveSpace(this.db, id);
|
|
}
|
|
|
|
async setSpaceWorkspaceDir(id: string, workspaceDir: string): Promise<void> {
|
|
return spacesRepo.setSpaceWorkspaceDir(this.db, id, workspaceDir);
|
|
}
|
|
|
|
async hardDeleteSpace(id: string): Promise<void> {
|
|
return spacesRepo.hardDeleteSpace(this.db, id);
|
|
}
|
|
|
|
async ensurePersonalSpace(ownerId: string, displayName?: string): Promise<Space> {
|
|
return spacesRepo.ensurePersonalSpace(this.db, ownerId, displayName);
|
|
}
|
|
|
|
async addSpaceMember(params: {
|
|
spaceId: string;
|
|
userId: string;
|
|
role: SpaceMemberRoleValue;
|
|
invitedBy?: string | null;
|
|
}): Promise<void> {
|
|
return spacesRepo.addSpaceMember(this.db, params);
|
|
}
|
|
|
|
async listSpaceMembers(spaceId: string): Promise<SpaceMember[]> {
|
|
return spacesRepo.listSpaceMembers(this.db, spaceId);
|
|
}
|
|
|
|
getSpaceMemberRole(spaceId: string, userId: string): SpaceMemberRoleValue | null {
|
|
return spacesRepo.getSpaceMemberRole(this.db, spaceId, userId);
|
|
}
|
|
|
|
getSpaceToolPolicy(spaceId: string): string | null {
|
|
return spacesRepo.getSpaceToolPolicy(this.db, spaceId);
|
|
}
|
|
|
|
setSpaceToolPolicy(spaceId: string, policyJson: string | null): void {
|
|
return spacesRepo.setSpaceToolPolicy(this.db, spaceId, policyJson);
|
|
}
|
|
|
|
getSpacePythonPackages(spaceId: string): string | null {
|
|
return spacesRepo.getSpacePythonPackages(this.db, spaceId);
|
|
}
|
|
|
|
setSpacePythonPackages(spaceId: string, packagesJson: string | null): void {
|
|
return spacesRepo.setSpacePythonPackages(this.db, spaceId, packagesJson);
|
|
}
|
|
|
|
userCanViewSpace(spaceId: string, user: { id: string; role: string }): boolean {
|
|
return spacesRepo.userCanViewSpace(this.db, spaceId, user);
|
|
}
|
|
|
|
async updateSpaceMemberRole(spaceId: string, userId: string, role: SpaceMemberRoleValue): Promise<void> {
|
|
return spacesRepo.updateSpaceMemberRole(this.db, spaceId, userId, role);
|
|
}
|
|
|
|
async removeSpaceMember(spaceId: string, userId: string): Promise<void> {
|
|
return spacesRepo.removeSpaceMember(this.db, spaceId, userId);
|
|
}
|
|
|
|
private rowToSpaceInvite(row: {
|
|
token: string;
|
|
space_id: string;
|
|
role: string;
|
|
created_by: string | null;
|
|
created_at: string;
|
|
expires_at: string | null;
|
|
revoked_at: string | null;
|
|
}): SpaceInvite {
|
|
return spacesRepo.rowToSpaceInvite(row);
|
|
}
|
|
|
|
isSpaceInviteValid(invite: SpaceInvite | null | undefined): invite is SpaceInvite {
|
|
return spacesRepo.isSpaceInviteValid(this.db, invite);
|
|
}
|
|
|
|
createSpaceInvite(params: {
|
|
spaceId: string;
|
|
role: SpaceInviteRole;
|
|
createdBy?: string | null;
|
|
expiresInDays?: number | null;
|
|
}): SpaceInvite {
|
|
return spacesRepo.createSpaceInvite(this.db, params);
|
|
}
|
|
|
|
getSpaceInvite(spaceId: string): SpaceInvite | null {
|
|
return spacesRepo.getSpaceInvite(this.db, spaceId);
|
|
}
|
|
|
|
getSpaceInviteByToken(token: string): SpaceInvite | null {
|
|
return spacesRepo.getSpaceInviteByToken(this.db, token);
|
|
}
|
|
|
|
revokeSpaceInvite(spaceId: string): void {
|
|
return spacesRepo.revokeSpaceInvite(this.db, spaceId);
|
|
}
|
|
|
|
createAppShareLink(spaceId: string, appName: string, createdBy: string | null): { token: string } {
|
|
return appSharesRepo.createAppShareLink(this.db, spaceId, appName, createdBy);
|
|
}
|
|
|
|
getAppShareLink(spaceId: string, appName: string): { token: string; revokedAt: string | null } | null {
|
|
return appSharesRepo.getAppShareLink(this.db, spaceId, appName);
|
|
}
|
|
|
|
revokeAppShareLink(spaceId: string, appName: string): void {
|
|
return appSharesRepo.revokeAppShareLink(this.db, spaceId, appName);
|
|
}
|
|
|
|
resolveAppShareToken(token: string): { spaceId: string; appName: string } | null {
|
|
return appSharesRepo.resolveAppShareToken(this.db, token);
|
|
}
|
|
|
|
async resolveTaskFolderContext(taskId: number, userFolderRoot: string): Promise<import('../spaces/folder-resolver.js').FolderContext> {
|
|
return localTasksRepo.resolveTaskFolderContext(this.db, taskId, userFolderRoot);
|
|
}
|
|
|
|
async createLocalTask(params: CreateLocalTaskParams): Promise<LocalTask> {
|
|
return localTasksRepo.createLocalTask(this.db, params);
|
|
}
|
|
|
|
async getLocalTask(taskId: number, opts?: { viewer?: Express.User }): Promise<LocalTask | null> {
|
|
return localTasksRepo.getLocalTask(this.db, taskId, opts);
|
|
}
|
|
|
|
async shareLocalTask(taskId: number): Promise<string> {
|
|
return localTasksRepo.shareLocalTask(this.db, taskId);
|
|
}
|
|
|
|
async unshareLocalTask(taskId: number): Promise<void> {
|
|
return localTasksRepo.unshareLocalTask(this.db, taskId);
|
|
}
|
|
|
|
async updateMissionBrief(taskId: number, patch: Partial<MissionBrief>): Promise<MissionBrief | null> {
|
|
return localTasksRepo.updateMissionBrief(this.db, taskId, patch);
|
|
}
|
|
|
|
updateMissionBriefSync(taskId: number, patch: Partial<MissionBrief>): MissionBrief | null {
|
|
return localTasksRepo.updateMissionBriefSync(this.db, taskId, patch);
|
|
}
|
|
|
|
getMissionBriefSync(taskId: number): MissionBrief | null {
|
|
return localTasksRepo.getMissionBriefSync(this.db, taskId);
|
|
}
|
|
|
|
makeMissionBriefIO(taskId: number): import('../engine/tools/core.js').MissionBriefIO {
|
|
return localTasksRepo.makeMissionBriefIO(this.db, taskId);
|
|
}
|
|
|
|
makeTaskConversationIO(taskId: number, transcriptPath?: string): import('../engine/tools/core.js').TaskConversationIO {
|
|
return localTasksRepo.makeTaskConversationIO(this.db, taskId, transcriptPath);
|
|
}
|
|
|
|
makeTranscriptOnlyConversationIO(transcriptPath: string | undefined): import('../engine/tools/core.js').TaskConversationIO {
|
|
return localTasksRepo.makeTranscriptOnlyConversationIO(transcriptPath);
|
|
}
|
|
|
|
makeWorkspaceTaskSearchIO(currentTaskId: number, ownerId: string): import('../engine/tools/core.js').WorkspaceTaskSearchIO {
|
|
return taskSearchRepo.makeWorkspaceTaskSearchIO(this.db, currentTaskId, ownerId);
|
|
}
|
|
|
|
recordProvenance(params: {
|
|
workspacePath: string;
|
|
relPath: string;
|
|
event: 'create' | 'modify';
|
|
sourceKind?: import('../engine/tools/core.js').FileProvenanceSourceKind;
|
|
spaceId?: string | null;
|
|
taskId?: number | null;
|
|
jobId?: string | null;
|
|
piece?: string | null;
|
|
movement?: string | null;
|
|
checksum?: string | null;
|
|
note?: string | null;
|
|
}): void {
|
|
return provenanceRepo.recordProvenance(this.db, params);
|
|
}
|
|
|
|
getProvenance(workspacePath: string, relPath: string): import('../engine/tools/core.js').FileProvenanceRecord | null {
|
|
return provenanceRepo.getProvenance(this.db, workspacePath, relPath);
|
|
}
|
|
|
|
listProvenance(workspacePath: string, filters?: import('../engine/tools/core.js').FileProvenanceListFilters): import('../engine/tools/core.js').FileProvenanceRecord[] {
|
|
return provenanceRepo.listProvenance(this.db, workspacePath, filters);
|
|
}
|
|
|
|
makeFileProvenanceIO(workspacePath: string): import('../engine/tools/core.js').FileProvenanceIO {
|
|
return provenanceRepo.makeFileProvenanceIO(this.db, workspacePath);
|
|
}
|
|
|
|
async getLocalTaskByShareToken(token: string): Promise<LocalTask | null> {
|
|
return localTasksRepo.getLocalTaskByShareToken(this.db, token);
|
|
}
|
|
|
|
async listLocalTasks(filter?: { ownerId?: string; viewer?: Express.User }): Promise<LocalTask[]> {
|
|
return localTasksRepo.listLocalTasks(this.db, filter);
|
|
}
|
|
|
|
async updateLocalTask(taskId: number, updates: Partial<Omit<LocalTask, 'id' | 'createdAt' | 'latestJob'>>): Promise<void> {
|
|
return localTasksRepo.updateLocalTask(this.db, taskId, updates);
|
|
}
|
|
|
|
async updateFeedback(taskId: number, feedback: {
|
|
rating: 'good' | 'bad';
|
|
tags: string[];
|
|
comment: string | null;
|
|
}): Promise<void> {
|
|
return localTasksRepo.updateFeedback(this.db, taskId, feedback);
|
|
}
|
|
|
|
async addLocalTaskComment(taskId: number, author: string, body: string, kind: string = 'comment', attachments: string[] = []): Promise<LocalTaskComment> {
|
|
return localTasksRepo.addLocalTaskComment(this.db, taskId, author, body, kind, attachments);
|
|
}
|
|
|
|
indexTaskComment(commentId: number, taskId: number, author: string, kind: string, createdAt: string, body: string, attachments: string | null): void {
|
|
return taskSearchRepo.indexTaskComment(this.db, commentId, taskId, author, kind, createdAt, body, attachments);
|
|
}
|
|
|
|
private buildFtsMatch(terms: string[]): string {
|
|
return taskSearchRepo.buildFtsMatch(terms);
|
|
}
|
|
|
|
async searchWorkspaceTasks(currentTaskId: number, ownerId: string, query: string, opts: { limit?: number; kind?: string; author?: string; taskId?: number } = {}): Promise<Array<{ taskId: number; taskTitle: string; commentId: number; author: string; kind: string; createdAt: string; text: string }>> {
|
|
return taskSearchRepo.searchWorkspaceTasks(this.db, currentTaskId, ownerId, query, opts);
|
|
}
|
|
|
|
async readWorkspaceTaskAround(currentTaskId: number, ownerId: string, commentId: number, before: number, after: number) {
|
|
return taskSearchRepo.readWorkspaceTaskAround(this.db, currentTaskId, ownerId, commentId, before, after);
|
|
}
|
|
|
|
async listLocalTaskComments(taskId: number): Promise<LocalTaskComment[]> {
|
|
return localTasksRepo.listLocalTaskComments(this.db, taskId);
|
|
}
|
|
|
|
async getUninjectedComments(taskId: number, sinceId: number = 0): Promise<LocalTaskComment[]> {
|
|
return localTasksRepo.getUninjectedComments(this.db, taskId, sinceId);
|
|
}
|
|
|
|
markCommentsInjected(commentIds: number[]): void {
|
|
return localTasksRepo.markCommentsInjected(this.db, commentIds);
|
|
}
|
|
|
|
async getLatestResultComment(taskId: number): Promise<{ body: string; kind: string; createdAt: string } | null> {
|
|
return localTasksRepo.getLatestResultComment(this.db, taskId);
|
|
}
|
|
|
|
getJobStatusSync(id: string): JobStatus | null {
|
|
return jobsRepo.getJobStatusSync(this.db, id);
|
|
}
|
|
|
|
isWorkerBusy(workerId: string): boolean {
|
|
return jobsRepo.isWorkerBusy(this.db, workerId);
|
|
}
|
|
|
|
listRunningJobOwnersByWorker(): Map<string, Array<{ user: string; kind: string }>> {
|
|
return jobsRepo.listRunningJobOwnersByWorker(this.db);
|
|
}
|
|
|
|
async updateJob(id: string, updates: Partial<Omit<Job, 'id' | 'createdAt'>>): Promise<void> {
|
|
return jobsRepo.updateJob(this.db, id, updates);
|
|
}
|
|
|
|
touchJobUpdatedAt(id: string): void {
|
|
return jobsRepo.touchJobUpdatedAt(this.db, id);
|
|
}
|
|
|
|
resumeMcpWaitingJobs(ownerId: string, _serverId: string): number {
|
|
return jobsRepo.resumeMcpWaitingJobs(this.db, ownerId, _serverId);
|
|
}
|
|
|
|
resumeToolRequestJob(jobId: string): number {
|
|
return jobsRepo.resumeToolRequestJob(this.db, jobId);
|
|
}
|
|
|
|
resumePackageRequestJob(jobId: string): number {
|
|
return jobsRepo.resumePackageRequestJob(this.db, jobId);
|
|
}
|
|
|
|
async lockIssue(repo: string, issueNumber: number, jobId: string): Promise<boolean> {
|
|
return jobsRepo.lockIssue(this.db, repo, issueNumber, jobId);
|
|
}
|
|
|
|
async unlockIssue(repo: string, issueNumber: number): Promise<void> {
|
|
return jobsRepo.unlockIssue(this.db, repo, issueNumber);
|
|
}
|
|
|
|
async deleteJobsForIssue(repo: string, issueNumber: number): Promise<number> {
|
|
return jobsRepo.deleteJobsForIssue(this.db, repo, issueNumber);
|
|
}
|
|
|
|
async addAuditLog(jobId: string | null, action: string, actor: string, detail: object): Promise<void> {
|
|
return auditRepo.addAuditLog(this.db, jobId, action, actor, detail);
|
|
}
|
|
|
|
oidcUpsert(model: string, id: string, payload: object, opts: { expiresAt?: number | null; grantId?: string | null; userCode?: string | null; uid?: string | null } = {}): void {
|
|
return a2aRepo.oidcUpsert(this.db, model, id, payload, opts);
|
|
}
|
|
|
|
oidcFind(model: string, id: string): { payload: Record<string, unknown>; consumedAt: number | null } | undefined {
|
|
return a2aRepo.oidcFind(this.db, model, id);
|
|
}
|
|
|
|
oidcFindByUid(uid: string): { payload: Record<string, unknown> } | undefined {
|
|
return a2aRepo.oidcFindByUid(this.db, uid);
|
|
}
|
|
|
|
oidcFindByUserCode(userCode: string): { payload: Record<string, unknown> } | undefined {
|
|
return a2aRepo.oidcFindByUserCode(this.db, userCode);
|
|
}
|
|
|
|
oidcConsume(model: string, id: string, consumedAt: number): void {
|
|
return a2aRepo.oidcConsume(this.db, model, id, consumedAt);
|
|
}
|
|
|
|
oidcDestroy(model: string, id: string): void {
|
|
return a2aRepo.oidcDestroy(this.db, model, id);
|
|
}
|
|
|
|
oidcRevokeByGrantId(grantId: string): void {
|
|
return a2aRepo.oidcRevokeByGrantId(this.db, grantId);
|
|
}
|
|
|
|
createA2aClient(row: A2aClientRow): void {
|
|
return a2aRepo.createA2aClient(this.db, row);
|
|
}
|
|
|
|
getA2aClient(clientId: string): A2aClientRow | undefined {
|
|
return a2aRepo.getA2aClient(this.db, clientId);
|
|
}
|
|
|
|
listA2aClients(): A2aClientRow[] {
|
|
return a2aRepo.listA2aClients(this.db);
|
|
}
|
|
|
|
setA2aClientStatus(clientId: string, status: 'active' | 'disabled'): void {
|
|
return a2aRepo.setA2aClientStatus(this.db, clientId, status);
|
|
}
|
|
|
|
createA2aDelegation(row: A2aDelegationRow): void {
|
|
return a2aRepo.createA2aDelegation(this.db, row);
|
|
}
|
|
|
|
private mapDelegation(r: any): A2aDelegationRow {
|
|
return a2aRepo.mapDelegation(r);
|
|
}
|
|
|
|
getA2aDelegationByGrantId(grantId: string): A2aDelegationRow | undefined {
|
|
return a2aRepo.getA2aDelegationByGrantId(this.db, grantId);
|
|
}
|
|
|
|
listA2aDelegationsForUser(userId: string): A2aDelegationRow[] {
|
|
return a2aRepo.listA2aDelegationsForUser(this.db, userId);
|
|
}
|
|
|
|
revokeA2aDelegation(id: string, revokedAtIso: string): void {
|
|
return a2aRepo.revokeA2aDelegation(this.db, id, revokedAtIso);
|
|
}
|
|
|
|
getA2aDelegationById(id: string): A2aDelegationRow | undefined {
|
|
return a2aRepo.getA2aDelegationById(this.db, id);
|
|
}
|
|
|
|
listLiveA2aDelegationsForClient(clientId: string, nowIso: string): A2aDelegationRow[] {
|
|
return a2aRepo.listLiveA2aDelegationsForClient(this.db, clientId, nowIso);
|
|
}
|
|
|
|
listNonTerminalA2aTasksByGrant(grantId: string, limit = 500): Array<{ id: string; jobId: string | null; payload: Record<string, unknown> }> {
|
|
return a2aRepo.listNonTerminalA2aTasksByGrant(this.db, grantId, limit);
|
|
}
|
|
|
|
countNonTerminalA2aTasksByGrant(grantId: string): number {
|
|
return a2aRepo.countNonTerminalA2aTasksByGrant(this.db, grantId);
|
|
}
|
|
|
|
cancelA2aLinkedJob(jobId: string): boolean {
|
|
return a2aRepo.cancelA2aLinkedJob(this.db, jobId);
|
|
}
|
|
|
|
listA2aDelegationsForUserWithClient(userId: string): Array<A2aDelegationRow & { clientName: string | null; clientStatus: string | null }> {
|
|
return a2aRepo.listA2aDelegationsForUserWithClient(this.db, userId);
|
|
}
|
|
|
|
listA2aDelegationsAllWithClient(): Array<
|
|
A2aDelegationRow & { userId: string; clientName: string | null; clientStatus: string | null }
|
|
> {
|
|
return a2aRepo.listA2aDelegationsAllWithClient(this.db);
|
|
}
|
|
|
|
getSpaceA2aSkills(spaceId: string): string[] {
|
|
return spacesRepo.getSpaceA2aSkills(this.db, spaceId);
|
|
}
|
|
|
|
setSpaceA2aSkills(spaceId: string, skills: string[]): void {
|
|
return spacesRepo.setSpaceA2aSkills(this.db, spaceId, skills);
|
|
}
|
|
|
|
saveA2aTask(row: {
|
|
id: string;
|
|
contextId: string | null;
|
|
jobId: string | null;
|
|
localTaskId: number | null;
|
|
payload: object;
|
|
delegationId?: string;
|
|
grantId?: string;
|
|
actingUserId?: string;
|
|
}): void {
|
|
return a2aRepo.saveA2aTask(this.db, row);
|
|
}
|
|
|
|
loadA2aTask(id: string): { payload: Record<string, unknown> } | undefined {
|
|
return a2aRepo.loadA2aTask(this.db, id);
|
|
}
|
|
|
|
getA2aTaskByJobId(jobId: string): { id: string; payload: Record<string, unknown> } | undefined {
|
|
return a2aRepo.getA2aTaskByJobId(this.db, jobId);
|
|
}
|
|
|
|
listNonTerminalA2aTasks(limit = 500): Array<{ id: string; jobId: string | null; payload: Record<string, unknown> }> {
|
|
return a2aRepo.listNonTerminalA2aTasks(this.db, limit);
|
|
}
|
|
|
|
async upsertWorkerNode(params: UpsertWorkerNodeParams): Promise<void> {
|
|
return workerNodesRepo.upsertWorkerNode(this.db, params);
|
|
}
|
|
|
|
async updateWorkerNodeHealth(workerId: string, updates: { healthy: boolean; lastError?: string | null; inflightJobs?: number; availableModels?: string[]; enabled?: boolean }): Promise<void> {
|
|
return workerNodesRepo.updateWorkerNodeHealth(this.db, workerId, updates);
|
|
}
|
|
|
|
async getWorkerNode(workerId: string): Promise<WorkerNode | null> {
|
|
return workerNodesRepo.getWorkerNode(this.db, workerId);
|
|
}
|
|
|
|
async claimNextJob(workerId: string): Promise<Job | null> {
|
|
return jobsRepo.claimNextJob(this.db, workerId);
|
|
}
|
|
|
|
async claimNextRetryJob(workerId: string): Promise<Job | null> {
|
|
return jobsRepo.claimNextRetryJob(this.db, workerId);
|
|
}
|
|
|
|
async peekNextClaimable(workerId: string): Promise<Job | null> {
|
|
return jobsRepo.peekNextClaimable(this.db, workerId);
|
|
}
|
|
|
|
async getJobsByStatus(status: JobStatus): Promise<Job[]> {
|
|
return jobsRepo.getJobsByStatus(this.db, status);
|
|
}
|
|
|
|
async getLatestJobForIssue(repo: string, issueNumber: number): Promise<Job | null> {
|
|
return jobsRepo.getLatestJobForIssue(this.db, repo, issueNumber);
|
|
}
|
|
|
|
async updateJobContext(jobId: string, payload: { promptTokens: number; limitTokens: number }): Promise<void> {
|
|
return jobsRepo.updateJobContext(this.db, jobId, payload);
|
|
}
|
|
|
|
async recoverOrphanedJobs(): Promise<number> {
|
|
return jobsRepo.recoverOrphanedJobs(this.db);
|
|
}
|
|
|
|
recoverStuckRunningJobs(staleMinutes: number): number {
|
|
return jobsRepo.recoverStuckRunningJobs(this.db, staleMinutes);
|
|
}
|
|
|
|
requeueRunningJobs(): number {
|
|
return jobsRepo.requeueRunningJobs(this.db);
|
|
}
|
|
|
|
getDistinctRepos(): string[] {
|
|
return jobsRepo.getDistinctRepos(this.db);
|
|
}
|
|
|
|
getJobsByRepo(repoName: string): Job[] {
|
|
return jobsRepo.getJobsByRepo(this.db, repoName);
|
|
}
|
|
|
|
getLatestJobsPerIssue(repoName: string): Job[] {
|
|
return jobsRepo.getLatestJobsPerIssue(this.db, repoName);
|
|
}
|
|
|
|
async updateJobsVisibilityForTask(taskId: number, updates: { visibility: 'private' | 'org' | 'public'; visibilityScopeOrgId: string | null }): Promise<number> {
|
|
return jobsRepo.updateJobsVisibilityForTask(this.db, taskId, updates);
|
|
}
|
|
|
|
async getSubJobs(parentJobId: string): Promise<Job[]> {
|
|
return jobsRepo.getSubJobs(this.db, parentJobId);
|
|
}
|
|
|
|
async requeueParentJobIfAllSubtasksDone(parentJobId: string): Promise<boolean> {
|
|
return jobsRepo.requeueParentJobIfAllSubtasksDone(this.db, parentJobId);
|
|
}
|
|
|
|
async deleteLocalTask(taskId: number, worktreeDir?: string): Promise<void> {
|
|
return localTasksRepo.deleteLocalTask(this.db, taskId, worktreeDir);
|
|
}
|
|
|
|
requestJobCancel(jobId: string): boolean {
|
|
return jobsRepo.requestJobCancel(this.db, jobId);
|
|
}
|
|
|
|
private mapScheduledTask(row: any): ScheduledTask {
|
|
return scheduledTasksRepo.mapScheduledTask(row);
|
|
}
|
|
|
|
async createScheduledTask(params: CreateScheduledTaskParams): Promise<ScheduledTask> {
|
|
return scheduledTasksRepo.createScheduledTask(this.db, params);
|
|
}
|
|
|
|
private getScheduledTaskSync(id: number): ScheduledTask | null {
|
|
return scheduledTasksRepo.getScheduledTaskSync(this.db, id);
|
|
}
|
|
|
|
async getScheduledTask(id: number, opts?: { viewer?: Express.User }): Promise<ScheduledTask | null> {
|
|
return scheduledTasksRepo.getScheduledTask(this.db, id, opts);
|
|
}
|
|
|
|
async listScheduledTasks(filter?: { viewer?: Express.User; spaceId?: string | null }): Promise<ScheduledTask[]> {
|
|
return scheduledTasksRepo.listScheduledTasks(this.db, filter);
|
|
}
|
|
|
|
async getScheduledTasksDue(): Promise<ScheduledTask[]> {
|
|
return scheduledTasksRepo.getScheduledTasksDue(this.db);
|
|
}
|
|
|
|
async updateScheduledTask(id: number, params: UpdateScheduledTaskParams): Promise<ScheduledTask | null> {
|
|
return scheduledTasksRepo.updateScheduledTask(this.db, id, params);
|
|
}
|
|
|
|
async deleteScheduledTask(id: number): Promise<boolean> {
|
|
return scheduledTasksRepo.deleteScheduledTask(this.db, id);
|
|
}
|
|
|
|
createUser(params: CreateUserParams): User {
|
|
return usersRepo.createUser(this.db, params);
|
|
}
|
|
|
|
ensureLocalUser(): void {
|
|
return usersRepo.ensureLocalUser(this.db);
|
|
}
|
|
|
|
setLocalPassword(userId: string, plainPassword: string): void {
|
|
return usersRepo.setLocalPassword(this.db, userId, plainPassword);
|
|
}
|
|
|
|
verifyLocalPassword(userId: string, plainPassword: string): boolean {
|
|
return usersRepo.verifyLocalPassword(this.db, userId, plainPassword);
|
|
}
|
|
|
|
hasLocalCredential(userId: string): boolean {
|
|
return usersRepo.hasLocalCredential(this.db, userId);
|
|
}
|
|
|
|
createLocalUser(params: CreateLocalUserParams): User {
|
|
return usersRepo.createLocalUser(this.db, params);
|
|
}
|
|
|
|
upsertLocalSystemAdmin(params: { email: string; password: string; name?: string }): User {
|
|
return usersRepo.upsertLocalSystemAdmin(this.db, params);
|
|
}
|
|
|
|
private rowToLocalOrg(r: { id: string; name: string; created_by: string | null; created_at: string }): LocalOrg {
|
|
return usersRepo.rowToLocalOrg(r);
|
|
}
|
|
|
|
createLocalOrg(name: string, createdBy: string | null): LocalOrg {
|
|
return usersRepo.createLocalOrg(this.db, name, createdBy);
|
|
}
|
|
|
|
getLocalOrg(id: string): LocalOrg | null {
|
|
return usersRepo.getLocalOrg(this.db, id);
|
|
}
|
|
|
|
listLocalOrgs(): LocalOrg[] {
|
|
return usersRepo.listLocalOrgs(this.db);
|
|
}
|
|
|
|
renameLocalOrg(id: string, name: string): void {
|
|
return usersRepo.renameLocalOrg(this.db, id, name);
|
|
}
|
|
|
|
deleteLocalOrg(id: string): void {
|
|
return usersRepo.deleteLocalOrg(this.db, id);
|
|
}
|
|
|
|
addOrgMember(orgId: string, userId: string, role: string = 'member'): void {
|
|
return usersRepo.addOrgMember(this.db, orgId, userId, role);
|
|
}
|
|
|
|
removeOrgMember(orgId: string, userId: string): void {
|
|
return usersRepo.removeOrgMember(this.db, orgId, userId);
|
|
}
|
|
|
|
listOrgMembers(orgId: string): LocalOrgMember[] {
|
|
return usersRepo.listOrgMembers(this.db, orgId);
|
|
}
|
|
|
|
listUserLocalOrgs(userId: string): Array<{ orgId: string; name: string }> {
|
|
return usersRepo.listUserLocalOrgs(this.db, userId);
|
|
}
|
|
|
|
getUserById(id: string): User | null {
|
|
return usersRepo.getUserById(this.db, id);
|
|
}
|
|
|
|
getUserByEmail(email: string): User | null {
|
|
return usersRepo.getUserByEmail(this.db, email);
|
|
}
|
|
|
|
findOrCreateUserByOAuth(params: FindOrCreateByOAuthParams): User {
|
|
return usersRepo.findOrCreateUserByOAuth(this.db, params);
|
|
}
|
|
|
|
listUsers(): User[] {
|
|
return usersRepo.listUsers(this.db);
|
|
}
|
|
|
|
listActiveUsersInOrgs(orgIds: string[]): User[] {
|
|
return usersRepo.listActiveUsersInOrgs(this.db, orgIds);
|
|
}
|
|
|
|
updateUser(id: string, updates: {
|
|
status?: 'active' | 'pending' | 'disabled';
|
|
role?: 'admin' | 'user';
|
|
email?: string;
|
|
name?: string;
|
|
avatarUrl?: string | null;
|
|
defaultVisibility?: 'private' | 'org' | 'public';
|
|
defaultVisibilityOrgId?: string | null;
|
|
}): void {
|
|
return usersRepo.updateUser(this.db, id, updates);
|
|
}
|
|
|
|
deleteUser(id: string): void {
|
|
return usersRepo.deleteUser(this.db, id);
|
|
}
|
|
|
|
deleteSessionsByUserId(userId: string): void {
|
|
return usersRepo.deleteSessionsByUserId(this.db, userId);
|
|
}
|
|
|
|
replaceUserGiteaOrgs(userId: string, orgs: GiteaOrgInput[]): void {
|
|
return usersRepo.replaceUserGiteaOrgs(this.db, userId, orgs);
|
|
}
|
|
|
|
listUserGiteaOrgs(userId: string): GiteaOrg[] {
|
|
return usersRepo.listUserGiteaOrgs(this.db, userId);
|
|
}
|
|
|
|
recordPieceEdit(userId: string, pieceName: string, snapshotId: string): void {
|
|
return reflectionRepo.recordPieceEdit(this.db, userId, pieceName, snapshotId);
|
|
}
|
|
|
|
countRecentPieceEdits(userId: string, pieceName: string, sinceMs: number): number {
|
|
return reflectionRepo.countRecentPieceEdits(this.db, userId, pieceName, sinceMs);
|
|
}
|
|
|
|
recordReflectionRun(metric: {
|
|
reflection_job_id: string;
|
|
original_job_id: string | null;
|
|
user_id: string;
|
|
piece_name: string | null;
|
|
outcome: 'applied' | 'partial' | 'abstained' | 'rejected' | 'failed';
|
|
memory_changes: number;
|
|
piece_edited: 0 | 1;
|
|
tokens_in: number;
|
|
tokens_out: number;
|
|
duration_ms: number;
|
|
}, pieceEdit?: { pieceName: string; snapshotId: string }): void {
|
|
return reflectionRepo.recordReflectionRun(this.db, metric, pieceEdit);
|
|
}
|
|
|
|
recordReflectionMetric(row: {
|
|
reflection_job_id: string;
|
|
original_job_id: string | null;
|
|
user_id: string;
|
|
piece_name: string | null;
|
|
outcome: 'applied' | 'partial' | 'abstained' | 'rejected' | 'failed';
|
|
memory_changes: number;
|
|
piece_edited: 0 | 1;
|
|
tokens_in: number;
|
|
tokens_out: number;
|
|
duration_ms: number;
|
|
}): void {
|
|
return reflectionRepo.recordReflectionMetric(this.db, row);
|
|
}
|
|
|
|
aggregateReflectionMetrics(userId: string, sinceMs: number): {
|
|
applied: number;
|
|
partial: number;
|
|
abstained: number;
|
|
rejected: number;
|
|
failed: number;
|
|
tokensIn: number;
|
|
tokensOut: number;
|
|
pieceEdits: number;
|
|
totalRuns: number;
|
|
} {
|
|
return reflectionRepo.aggregateReflectionMetrics(this.db, userId, sinceMs);
|
|
}
|
|
|
|
private tzModifier(tzOffsetMin: number): string {
|
|
return calendarRepo.tzModifier(tzOffsetMin);
|
|
}
|
|
|
|
async createCalendarEvent(params: {
|
|
spaceId: string;
|
|
ownerId?: string | null;
|
|
date: string;
|
|
endDate?: string | null;
|
|
time?: string | null;
|
|
endTime?: string | null;
|
|
title: string;
|
|
description?: string | null;
|
|
createdBy?: 'user' | 'agent';
|
|
sourceTaskId?: number | null;
|
|
}): Promise<CalendarEvent> {
|
|
return calendarRepo.createCalendarEvent(this.db, params);
|
|
}
|
|
|
|
recordToolRequest(params: {
|
|
id?: string;
|
|
taskId?: string | null;
|
|
jobId?: string | null;
|
|
spaceId?: string | null;
|
|
pieceName: string;
|
|
movementName: string;
|
|
toolName: string;
|
|
reason?: string | null;
|
|
category?: ToolRequestCategory;
|
|
status?: ToolRequestStatus;
|
|
}): string {
|
|
return toolRequestsRepo.recordToolRequest(this.db, params);
|
|
}
|
|
|
|
listToolRequestsByTask(taskId: string): ToolRequest[] {
|
|
return toolRequestsRepo.listToolRequestsByTask(this.db, taskId);
|
|
}
|
|
|
|
aggregateToolRequestsByPiece(pieceName: string): ToolRequestAggregate[] {
|
|
return toolRequestsRepo.aggregateToolRequestsByPiece(this.db, pieceName);
|
|
}
|
|
|
|
getToolRequest(id: string): ToolRequest | null {
|
|
return toolRequestsRepo.getToolRequest(this.db, id);
|
|
}
|
|
|
|
decideToolRequest(id: string, decision: { status: Exclude<ToolRequestStatus, 'pending'>; grantScope?: 'task' | 'piece' | null; decidedBy?: string | null }): boolean {
|
|
return toolRequestsRepo.decideToolRequest(this.db, id, decision);
|
|
}
|
|
|
|
getGrantedTools(taskId: string): string[] {
|
|
return toolRequestsRepo.getGrantedTools(this.db, taskId);
|
|
}
|
|
|
|
addGrantedTool(taskId: string, toolName: string): string[] {
|
|
return toolRequestsRepo.addGrantedTool(this.db, taskId, toolName);
|
|
}
|
|
|
|
recordPackageRequest(params: {
|
|
id?: string;
|
|
taskId?: string | null;
|
|
jobId?: string | null;
|
|
spaceId?: string | null;
|
|
pieceName?: string | null;
|
|
movementName?: string | null;
|
|
spec: string;
|
|
normalizedName: string;
|
|
reason?: string | null;
|
|
status?: PackageRequestStatus;
|
|
}): string {
|
|
return toolRequestsRepo.recordPackageRequest(this.db, params);
|
|
}
|
|
|
|
listPackageRequestsByTask(taskId: string): PackageRequest[] {
|
|
return toolRequestsRepo.listPackageRequestsByTask(this.db, taskId);
|
|
}
|
|
|
|
listDeclinedPackageNamesByJob(jobId: string): string[] {
|
|
return toolRequestsRepo.listDeclinedPackageNamesByJob(this.db, jobId);
|
|
}
|
|
|
|
getPackageRequest(id: string): PackageRequest | null {
|
|
return toolRequestsRepo.getPackageRequest(this.db, id);
|
|
}
|
|
|
|
decidePackageRequest(id: string, decision: { status: Exclude<PackageRequestStatus, 'pending'>; decidedBy?: string | null }): boolean {
|
|
return toolRequestsRepo.decidePackageRequest(this.db, id, decision);
|
|
}
|
|
|
|
revertPackageRequestToPending(id: string): boolean {
|
|
return toolRequestsRepo.revertPackageRequestToPending(this.db, id);
|
|
}
|
|
|
|
async listCalendarEvents(spaceId: string, range?: { from?: string; to?: string }): Promise<CalendarEvent[]> {
|
|
return calendarRepo.listCalendarEvents(this.db, spaceId, range);
|
|
}
|
|
|
|
async getCalendarEvent(eventId: number): Promise<CalendarEvent | null> {
|
|
return calendarRepo.getCalendarEvent(this.db, eventId);
|
|
}
|
|
|
|
async updateCalendarEvent(eventId: number, fields: { date?: string; endDate?: string | null; time?: string | null; endTime?: string | null; title?: string; description?: string | null }): Promise<CalendarEvent | null> {
|
|
return calendarRepo.updateCalendarEvent(this.db, eventId, fields);
|
|
}
|
|
|
|
async deleteCalendarEvent(eventId: number): Promise<void> {
|
|
return calendarRepo.deleteCalendarEvent(this.db, eventId);
|
|
}
|
|
|
|
private calendarTaskScope(spaceId: string, personalOwnerId?: string | null, alias = ''): { clause: string; params: unknown[] } {
|
|
return calendarRepo.calendarTaskScope(spaceId, personalOwnerId, alias);
|
|
}
|
|
|
|
async getSpaceCalendarMonth(spaceId: string, opts: { monthStart: string; monthEnd: string; tzOffsetMin: number; personalOwnerId?: string | null }): Promise<{ days: Record<string, CalendarDayCounts>; events: CalendarEvent[] }> {
|
|
return calendarRepo.getSpaceCalendarMonth(this.db, spaceId, opts);
|
|
}
|
|
|
|
async getSpaceCalendarDay(spaceId: string, date: string, tzOffsetMin: number, personalOwnerId?: string | null): Promise<{ tasks: CalendarDayTask[]; events: CalendarEvent[] }> {
|
|
return calendarRepo.getSpaceCalendarDay(this.db, spaceId, date, tzOffsetMin, personalOwnerId);
|
|
}
|
|
|
|
async getCrossSpaceCalendarMonth(viewer: Express.User, opts: { monthStart: string; monthEnd: string; tzOffsetMin: number }): Promise<CrossSpaceCalendarMonth> {
|
|
return calendarRepo.getCrossSpaceCalendarMonth(this.db, viewer, opts);
|
|
}
|
|
|
|
createGatewayVirtualKey(params: {
|
|
id?: string;
|
|
keyHash: string;
|
|
keyPrefix: string;
|
|
team: string;
|
|
allowedModels?: string[] | null;
|
|
source?: GatewayVirtualKeySource;
|
|
createdBy?: string | null;
|
|
createdAt?: string;
|
|
/** Phase 2b: optional monthly tokens budget. null/undefined = unlimited. */
|
|
tokensBudget?: number | null;
|
|
/** Phase 2b: optional requests-per-minute cap. null/undefined = unlimited. */
|
|
rateLimitRpm?: number | null;
|
|
}): GatewayVirtualKey {
|
|
return gatewayRepo.createGatewayVirtualKey(this.db, params);
|
|
}
|
|
|
|
updateGatewayVirtualKey(id: string, patch: {
|
|
/**
|
|
* Phase 3a follow-up: team is now patchable so the config-migration
|
|
* importer can propagate a YAML-side team rename to the DB. Admin
|
|
* PATCH never sends this field (the team is intentionally immutable
|
|
* via the public API to avoid an admin accidentally rewriting the
|
|
* owner of a key); the only caller is importConfigKeysToDb.
|
|
*/
|
|
team?: string;
|
|
tokensBudget?: number | null;
|
|
rateLimitRpm?: number | null;
|
|
allowedModels?: string[] | null;
|
|
}): GatewayVirtualKey {
|
|
return gatewayRepo.updateGatewayVirtualKey(this.db, id, patch);
|
|
}
|
|
|
|
findGatewayVirtualKeyByHash(keyHash: string): GatewayVirtualKey | null {
|
|
return gatewayRepo.findGatewayVirtualKeyByHash(this.db, keyHash);
|
|
}
|
|
|
|
findGatewayVirtualKeyById(id: string): GatewayVirtualKey | null {
|
|
return gatewayRepo.findGatewayVirtualKeyById(this.db, id);
|
|
}
|
|
|
|
listGatewayVirtualKeys(opts?: { team?: string; activeOnly?: boolean }): GatewayVirtualKey[] {
|
|
return gatewayRepo.listGatewayVirtualKeys(this.db, opts);
|
|
}
|
|
|
|
revokeGatewayVirtualKey(id: string, revokedBy: string, at?: string): boolean {
|
|
return gatewayRepo.revokeGatewayVirtualKey(this.db, id, revokedBy, at);
|
|
}
|
|
|
|
deleteGatewayVirtualKey(id: string): boolean {
|
|
return gatewayRepo.deleteGatewayVirtualKey(this.db, id);
|
|
}
|
|
|
|
touchGatewayVirtualKeyLastUsed(id: string, at?: string): void {
|
|
return gatewayRepo.touchGatewayVirtualKeyLastUsed(this.db, id, at);
|
|
}
|
|
|
|
getGatewayKeyUsage(keyId: string, periodStart: string): GatewayKeyUsage | null {
|
|
return gatewayRepo.getGatewayKeyUsage(this.db, keyId, periodStart);
|
|
}
|
|
|
|
incrementGatewayKeyUsage(params: {
|
|
keyId: string;
|
|
period: string;
|
|
tokensIn?: number;
|
|
tokensOut?: number;
|
|
requests?: number;
|
|
at?: string;
|
|
}): void {
|
|
return gatewayRepo.incrementGatewayKeyUsage(this.db, params);
|
|
}
|
|
|
|
listGatewayKeyUsagesByKey(keyId: string, opts?: { limit?: number }): GatewayKeyUsage[] {
|
|
return gatewayRepo.listGatewayKeyUsagesByKey(this.db, keyId, opts);
|
|
}
|
|
|
|
incrementLlmUsage(params: LlmUsageIncrement): void {
|
|
return llmUsageRepo.incrementLlmUsage(this.db, params);
|
|
}
|
|
|
|
queryLlmUsageDaily(opts: { from: string; to: string; userId?: string }): LlmUsageDailyAgg[] {
|
|
return llmUsageRepo.queryLlmUsageDaily(this.db, opts);
|
|
}
|
|
|
|
incrementLlmUsageHourly(params: LlmUsageHourlyIncrement): void {
|
|
return llmUsageRepo.incrementLlmUsageHourly(this.db, params);
|
|
}
|
|
|
|
queryLlmUsageHourly(opts: {
|
|
fromHour: string;
|
|
toHour: string;
|
|
userId?: string;
|
|
}): LlmUsageHourlyRow[] {
|
|
return llmUsageRepo.queryLlmUsageHourly(this.db, opts);
|
|
}
|
|
|
|
getUsageOrgMap(): Map<string, string> {
|
|
return llmUsageRepo.getUsageOrgMap(this.db);
|
|
}
|
|
|
|
/** Return the underlying Database instance (needed by migrate.ts and session store) */
|
|
getDb(): Database.Database {
|
|
return this.db;
|
|
}
|
|
|
|
upsertPushSubscription(input: UpsertPushSubscriptionInput): { id: string } {
|
|
return notificationsRepo.upsertPushSubscription(this.db, input);
|
|
}
|
|
|
|
listPushSubscriptionsForUser(userId: string): PushSubscriptionRecord[] {
|
|
return notificationsRepo.listPushSubscriptionsForUser(this.db, userId);
|
|
}
|
|
|
|
getPushSubscriptionById(id: string): PushSubscriptionRecord | null {
|
|
return notificationsRepo.getPushSubscriptionById(this.db, id);
|
|
}
|
|
|
|
deletePushSubscription(id: string): void {
|
|
return notificationsRepo.deletePushSubscription(this.db, id);
|
|
}
|
|
|
|
markPushSubscriptionSuccess(id: string): void {
|
|
return notificationsRepo.markPushSubscriptionSuccess(this.db, id);
|
|
}
|
|
|
|
markPushSubscriptionFailure(id: string): void {
|
|
return notificationsRepo.markPushSubscriptionFailure(this.db, id);
|
|
}
|
|
|
|
getUserNotificationPrefs(userId: string): NotificationPrefs {
|
|
return notificationsRepo.getUserNotificationPrefs(this.db, userId);
|
|
}
|
|
|
|
upsertUserNotificationPrefs(userId: string, update: NotificationPrefsUpdate): void {
|
|
return notificationsRepo.upsertUserNotificationPrefs(this.db, userId, update);
|
|
}
|
|
|
|
markV1MigrationComplete(userId: string): boolean {
|
|
return notificationsRepo.markV1MigrationComplete(this.db, userId);
|
|
}
|
|
|
|
close(): void {
|
|
this.db.close();
|
|
}
|
|
}
|
|
|
|
export { BrowserSessionRepo } from './browser-session-repo.js';
|
|
export type { BrowserSessionProfile, CreateProfileInput, AuditInput } from './browser-session-repo.js';
|