update
This commit is contained in:
1 parent
09971cabc2
commit
9145572422
163 files changed
+3348
-2874
No files matched your search
@@ -112,8 +112,8 @@ export function buildAgentCrudMethods(
|
||||
};
|
||||
const changedKeys = Object.keys(afterConfig).filter(
|
||||
(k) =>
|
||||
JSON.stringify((afterConfig as any)[k]) !==
|
||||
JSON.stringify((beforeConfig as any)[k]),
|
||||
JSON.stringify((afterConfig as Record<string, unknown>)[k]) !==
|
||||
JSON.stringify((beforeConfig as Record<string, unknown>)[k]),
|
||||
);
|
||||
if (changedKeys.length > 0) {
|
||||
try {
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import type { DatabaseSync } from "node:sqlite";
|
||||
import type { WorkflowPipelineRecord } from "@shared/types";
|
||||
import type { ReadAll } from "./helpers";
|
||||
import type { ReadAll, SqliteRow } from "./helpers";
|
||||
import { ensureId, nowIso } from "./helpers";
|
||||
|
||||
type SqliteRow = Record<string, any>;
|
||||
|
||||
export function buildAutomationMethods(
|
||||
getDb: () => DatabaseSync,
|
||||
readAll: ReadAll,
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import type { DatabaseSync, SQLInputValue } from "node:sqlite";
|
||||
import type { BudgetIncidentRecord, BudgetPolicyRecord } from "@shared/types";
|
||||
import type { ReadAll, Transaction } from "./helpers";
|
||||
import type { ReadAll, SqliteRow, Transaction } from "./helpers";
|
||||
import { nowIso } from "./helpers";
|
||||
|
||||
type SqliteRow = Record<string, any>;
|
||||
|
||||
function mapPolicyRow(r: SqliteRow): BudgetPolicyRecord {
|
||||
return {
|
||||
id: r.id,
|
||||
|
||||
@@ -52,13 +52,16 @@ export function buildCompanySettingsMethods(
|
||||
).length;
|
||||
|
||||
// Avg run duration
|
||||
const finishedRuns = agentRuns.filter((r) => r.startedAt && r.finishedAt);
|
||||
const finishedRuns = agentRuns.filter(
|
||||
(r): r is typeof r & { startedAt: string; finishedAt: string } =>
|
||||
Boolean(r.startedAt && r.finishedAt),
|
||||
);
|
||||
const avgDuration =
|
||||
finishedRuns.length > 0
|
||||
? finishedRuns.reduce(
|
||||
(sum, r) =>
|
||||
sum +
|
||||
(new Date(r.finishedAt!).getTime() - new Date(r.startedAt!).getTime()) / 1000,
|
||||
(new Date(r.finishedAt).getTime() - new Date(r.startedAt).getTime()) / 1000,
|
||||
0,
|
||||
) / finishedRuns.length
|
||||
: 0;
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Pure helpers for crash-recovery logic, extracted for testability.
|
||||
*
|
||||
* These encode the behavioral contract of the corresponding AppDatabase methods:
|
||||
* - interruptStaleRuns
|
||||
* - retryInterruptedTask
|
||||
* - markInterruptedTaskFailed
|
||||
*
|
||||
* The helpers take narrowly-typed "statement runner" interfaces so they can be
|
||||
* exercised in unit tests without a live SQLite connection.
|
||||
*/
|
||||
|
||||
export interface StaleRunDb {
|
||||
/** Update all running runs to 'interrupted' and return number of rows changed. */
|
||||
interruptRunningRuns(ts: string): number;
|
||||
/** Mark tasks associated with interrupted runs as 'blocked'. */
|
||||
blockInterruptedTasks(ts: string): void;
|
||||
/** Clear active_run_id on tasks whose run is now interrupted. */
|
||||
clearActiveRunIds(): void;
|
||||
/** Reset all running agents to idle. */
|
||||
resetAgentsToIdle(ts: string): void;
|
||||
/** Release all workspace locks. */
|
||||
releaseAllWorkspaceLocks(): void;
|
||||
}
|
||||
|
||||
export interface RetryTaskDb {
|
||||
/** Set task status to 'todo'. */
|
||||
setTaskTodo(ts: string, taskId: string): void;
|
||||
/** Reset retry_count and last_failure_at. */
|
||||
resetTaskRetryFields(ts: string, taskId: string): void;
|
||||
}
|
||||
|
||||
export interface FailTaskDb {
|
||||
/** Set task status to 'cancelled'. */
|
||||
setTaskCancelled(ts: string, taskId: string): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transactionally marks all running runs as interrupted and associated tasks
|
||||
* as blocked. Returns the number of interrupted runs.
|
||||
*/
|
||||
export function interruptStaleRunsLogic(
|
||||
db: StaleRunDb,
|
||||
transaction: (fn: () => void) => void,
|
||||
nowIso: () => string,
|
||||
): number {
|
||||
let interruptedCount = 0;
|
||||
transaction(() => {
|
||||
const ts = nowIso();
|
||||
interruptedCount = db.interruptRunningRuns(ts);
|
||||
if (interruptedCount > 0) {
|
||||
db.blockInterruptedTasks(ts);
|
||||
}
|
||||
db.clearActiveRunIds();
|
||||
db.resetAgentsToIdle(ts);
|
||||
db.releaseAllWorkspaceLocks();
|
||||
});
|
||||
return interruptedCount;
|
||||
}
|
||||
|
||||
/** Resets a task to 'todo' and clears its retry state. */
|
||||
export function retryInterruptedTaskLogic(
|
||||
db: RetryTaskDb,
|
||||
taskId: string,
|
||||
nowIso: () => string,
|
||||
): void {
|
||||
const ts = nowIso();
|
||||
db.setTaskTodo(ts, taskId);
|
||||
db.resetTaskRetryFields(ts, taskId);
|
||||
}
|
||||
|
||||
/** Marks a task as 'cancelled'. */
|
||||
export function markInterruptedTaskFailedLogic(
|
||||
db: FailTaskDb,
|
||||
taskId: string,
|
||||
nowIso: () => string,
|
||||
): void {
|
||||
const ts = nowIso();
|
||||
db.setTaskCancelled(ts, taskId);
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import type { DatabaseSync, SQLInputValue } from "node:sqlite";
|
||||
import type { AgentRecord } from "@shared/types";
|
||||
import type { ReadAll, Transaction } from "./helpers";
|
||||
import type { ReadAll, SqliteRow, Transaction } from "./helpers";
|
||||
import { ensureId, nowIso, parseJson } from "./helpers";
|
||||
|
||||
type SqliteRow = Record<string, any>;
|
||||
|
||||
export function buildDocumentMethods(
|
||||
getDb: () => DatabaseSync,
|
||||
readAll: ReadAll,
|
||||
@@ -218,10 +216,10 @@ export function buildDocumentMethods(
|
||||
source: string; rolledBackFromRevisionId: string | null;
|
||||
createdByAgentId: string | null; createdByUserId: string | null; createdAt: string;
|
||||
}> {
|
||||
return readAll<any>(
|
||||
return readAll<SqliteRow>(
|
||||
"SELECT id, agent_id, revision_number, changed_keys, source, rolled_back_from_revision_id, created_by_agent_id, created_by_user_id, created_at FROM agent_config_revisions WHERE agent_id = ? AND company_id = ? ORDER BY revision_number DESC",
|
||||
agentId, companyId
|
||||
).map((row: SqliteRow) => ({
|
||||
).map((row) => ({
|
||||
id: row.id, agentId: row.agent_id, revisionNumber: row.revision_number,
|
||||
changedKeys: parseJson<string[]>(row.changed_keys, []),
|
||||
source: row.source, rolledBackFromRevisionId: row.rolled_back_from_revision_id ?? null,
|
||||
@@ -238,7 +236,12 @@ export function buildDocumentMethods(
|
||||
} {
|
||||
const row = getDb().prepare(
|
||||
"SELECT * FROM agent_config_revisions WHERE id = ? AND company_id = ?"
|
||||
).get(revisionId, companyId) as any;
|
||||
).get(revisionId, companyId) as {
|
||||
id: string; agent_id: string; revision_number: number; changed_keys: string;
|
||||
config_before: string; config_after: string; source: string;
|
||||
rolled_back_from_revision_id: string | null;
|
||||
created_by_agent_id: string | null; created_by_user_id: string | null; created_at: string;
|
||||
} | undefined;
|
||||
if (!row) throw new Error(`Config revision ${revisionId} not found.`);
|
||||
return {
|
||||
id: row.id, agentId: row.agent_id, revisionNumber: row.revision_number,
|
||||
@@ -252,14 +255,24 @@ export function buildDocumentMethods(
|
||||
},
|
||||
|
||||
rollbackConfigRevision(agentId: string, revisionId: string, companyId: string, selfDeps: {
|
||||
getConfigRevision: (revisionId: string, companyId: string) => any;
|
||||
getConfigRevision: (revisionId: string, companyId: string) => {
|
||||
id: string; agentId: string; revisionNumber: number; changedKeys: string[];
|
||||
configBefore: Record<string, unknown>; configAfter: Record<string, unknown>;
|
||||
source: string; rolledBackFromRevisionId: string | null;
|
||||
createdByAgentId: string | null; createdByUserId: string | null; createdAt: string;
|
||||
};
|
||||
getAgent: (id: string) => AgentRecord;
|
||||
recordConfigRevision: (input: any) => string;
|
||||
recordConfigRevision: (input: {
|
||||
companyId: string; agentId: string; changedKeys: string[];
|
||||
configBefore: Record<string, unknown>; configAfter: Record<string, unknown>;
|
||||
source?: string; rolledBackFromRevisionId?: string | null;
|
||||
createdByAgentId?: string | null; createdByUserId?: string | null;
|
||||
}) => string;
|
||||
}): string {
|
||||
return transaction(() => {
|
||||
const revision = selfDeps.getConfigRevision(revisionId, companyId);
|
||||
if (revision.agentId !== agentId) throw new Error("Revision does not belong to this agent.");
|
||||
const before = revision.configBefore as Record<string, any>;
|
||||
const before = revision.configBefore as Record<string, string | number | null>;
|
||||
const ts = nowIso();
|
||||
getDb().prepare(
|
||||
"UPDATE agents SET name = ?, role = ?, title = ?, department = ?, capabilities = ?, connector_id = ?, model = ?, budget_monthly_usd = ?, metadata_json = ?, updated_at = ? WHERE id = ? AND company_id = ?"
|
||||
@@ -270,7 +283,7 @@ export function buildDocumentMethods(
|
||||
before.metadataJson ?? before.metadata_json ?? "{}", ts, agentId, companyId
|
||||
);
|
||||
const agent = selfDeps.getAgent(agentId);
|
||||
const currentConfig = { name: agent.name, role: agent.role, title: agent.title, department: (agent as any).department, capabilities: agent.capabilities, connectorId: agent.connectorId, model: agent.model, budgetMonthlyUsd: agent.budgetMonthlyUsd, metadataJson: agent.metadataJson };
|
||||
const currentConfig = { name: agent.name, role: agent.role, title: agent.title, department: agent.department, capabilities: agent.capabilities, connectorId: agent.connectorId, model: agent.model, budgetMonthlyUsd: agent.budgetMonthlyUsd, metadataJson: agent.metadataJson };
|
||||
return selfDeps.recordConfigRevision({
|
||||
companyId, agentId,
|
||||
changedKeys: revision.changedKeys,
|
||||
|
||||
@@ -15,7 +15,7 @@ export function buildEntityCrudMethods(
|
||||
getTask(id: string): TaskRecord {
|
||||
const row = getDb()
|
||||
.prepare(
|
||||
"select id, company_id as companyId, project_id as projectId, goal_id as goalId, parent_id as parentId, title, description, assignee_agent_id as assigneeAgentId, workspace_id as workspaceId, status, priority, active_run_id as activeRunId, session_json as sessionJson, session_display_id as sessionDisplayId, cost_usd as costUsd, requires_user_review as requiresUserReview, started_at as startedAt, completed_at as completedAt, cancelled_at as cancelledAt, created_at as createdAt, updated_at as updatedAt from tasks where id = ?",
|
||||
"select id, company_id as companyId, project_id as projectId, goal_id as goalId, parent_id as parentId, title, description, assignee_agent_id as assigneeAgentId, workspace_id as workspaceId, status, priority, active_run_id as activeRunId, session_json as sessionJson, session_display_id as sessionDisplayId, cost_usd as costUsd, task_type as taskType, requires_user_review as requiresUserReview, started_at as startedAt, completed_at as completedAt, cancelled_at as cancelledAt, created_at as createdAt, updated_at as updatedAt from tasks where id = ?",
|
||||
)
|
||||
.get(id) as TaskRecord | undefined;
|
||||
if (!row) throw new Error(`Task not found: ${id}`);
|
||||
@@ -152,8 +152,19 @@ export function buildEntityCrudMethods(
|
||||
budgetMonthlyUsd: number; payloadSummary: string; impactSummary: string;
|
||||
payloadJson?: string | null;
|
||||
}, selfDeps: {
|
||||
saveAgent: (input: any) => string;
|
||||
requestApproval: (input: any) => string;
|
||||
saveAgent: (input: {
|
||||
companyId: string; name: string; role: string; title: string;
|
||||
department: string | null; status: AgentRecord["status"];
|
||||
reportsTo: string | null; connectorId: ConnectorId;
|
||||
workspaceId: string | null; model: string | null;
|
||||
metadataJson: string; capabilities: string; budgetMonthlyUsd: number;
|
||||
}) => string;
|
||||
requestApproval: (input: {
|
||||
companyId: string; requestedByAgentId: string | null;
|
||||
relatedAgentId: string; type: string;
|
||||
payloadSummary: string; impactSummary: string;
|
||||
payloadJson: string | null;
|
||||
}) => string;
|
||||
}) {
|
||||
return transaction(() => {
|
||||
const agentId = selfDeps.saveAgent({
|
||||
|
||||
@@ -4,9 +4,7 @@ import { appendFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import type { DatabaseSync, SQLInputValue } from "node:sqlite";
|
||||
import type { ConnectorId, RunLogChunk, RunRecord } from "@shared/types";
|
||||
import { type ReadAll, type Transaction, nowIso, toBoolean } from "./helpers";
|
||||
|
||||
type SqliteRow = Record<string, any>;
|
||||
import { type ReadAll, type SqliteRow, type Transaction, nowIso, toBoolean } from "./helpers";
|
||||
|
||||
/**
|
||||
* Find the last complete UTF-8 character boundary in a buffer.
|
||||
@@ -325,7 +323,7 @@ export function buildRunMethods(
|
||||
}> {
|
||||
const offset = opts?.offset ?? 0;
|
||||
const limit = opts?.limit ?? 500;
|
||||
return readAll<any>(
|
||||
return readAll<SqliteRow>(
|
||||
"SELECT id, run_id, agent_id, seq, event_type, stream, level, message, payload, created_at FROM run_events WHERE run_id = ? AND company_id = ? ORDER BY seq ASC LIMIT ? OFFSET ?",
|
||||
runId, companyId, limit, offset
|
||||
).map((row: SqliteRow) => ({
|
||||
|
||||
@@ -182,7 +182,8 @@ export function runMigrations(
|
||||
let skipped = 0;
|
||||
for (const task of tasksWithSessions) {
|
||||
try {
|
||||
JSON.parse(task.sessionJson!);
|
||||
if (!task.sessionJson) continue;
|
||||
JSON.parse(task.sessionJson);
|
||||
const agent = task.assigneeAgentId ? db.prepare("SELECT connector_id FROM agents WHERE id = ?").get(task.assigneeAgentId) as { connector_id: string } | undefined : undefined;
|
||||
const adapterType = agent?.connector_id ?? "unknown";
|
||||
const sessionId = randomUUID();
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { DatabaseSync } from "node:sqlite";
|
||||
import type { SkillRecord, FileInventoryEntry, SkillSourceType, TrustLevel } from "../skill-types.js";
|
||||
import type { ReadAll } from "./helpers";
|
||||
import type { ReadAll, SqliteRow } from "./helpers";
|
||||
import { nowIso, parseJson } from "./helpers";
|
||||
|
||||
type SqliteRow = Record<string, any>;
|
||||
|
||||
export function buildSkillMethods(
|
||||
getDb: () => DatabaseSync,
|
||||
readAll: ReadAll,
|
||||
|
||||
@@ -5,6 +5,7 @@ import type {
|
||||
ApprovalRecord,
|
||||
CompanyRecord,
|
||||
CommentRecord,
|
||||
ConnectorRecord,
|
||||
CostRecord,
|
||||
GoalRecord,
|
||||
ProfileSnapshot,
|
||||
@@ -14,9 +15,7 @@ import type {
|
||||
TaskRecord,
|
||||
WorkspaceRecord,
|
||||
} from "@shared/types";
|
||||
import { type ReadAll, toBoolean } from "./helpers";
|
||||
|
||||
type SqliteRow = Record<string, any>;
|
||||
import { type ReadAll, type SqliteRow, toBoolean } from "./helpers";
|
||||
const BOARD_READER_ID = "__board__";
|
||||
|
||||
export function buildSnapshotMethods(
|
||||
@@ -25,7 +24,7 @@ export function buildSnapshotMethods(
|
||||
deps: {
|
||||
getCurrentCompanyId: () => string | null;
|
||||
getSetting: (key: string) => string | null;
|
||||
readConnectors: () => any[];
|
||||
readConnectors: () => ConnectorRecord[];
|
||||
profileDir: string;
|
||||
vaultBackendLabel: () => string;
|
||||
},
|
||||
@@ -64,7 +63,7 @@ export function buildSnapshotMethods(
|
||||
`select id, company_id as companyId, name, local_path as localPath, repo_url as repoUrl, repo_ref as repoRef, project_id as projectId, state, is_primary as isPrimary, created_at as createdAt, updated_at as updatedAt from workspaces${companyWhere} order by created_at desc`,
|
||||
...companyArgs,
|
||||
).map((record) => ({ ...record, isPrimary: toBoolean(record.isPrimary) })) as WorkspaceRecord[],
|
||||
agents: readAll<any>(
|
||||
agents: readAll<SqliteRow>(
|
||||
`select id, company_id as companyId, name, role, title, department, status, reports_to as reportsTo, connector_id as connectorId, workspace_id as workspaceId, model, capabilities, budget_monthly_usd as budgetMonthlyUsd, spent_monthly_usd as spentMonthlyUsd, metadata_json as metadataJson, heartbeat_enabled as heartbeatEnabled, heartbeat_interval_sec as heartbeatIntervalSec, last_heartbeat_at as lastHeartbeatAt, created_at as createdAt, updated_at as updatedAt from agents${companyWhere} order by created_at asc`,
|
||||
...companyArgs,
|
||||
).map((record: SqliteRow) => ({ ...record, heartbeatEnabled: toBoolean(record.heartbeatEnabled) })) as AgentRecord[],
|
||||
@@ -77,7 +76,7 @@ export function buildSnapshotMethods(
|
||||
...companyArgs,
|
||||
),
|
||||
tasks: readAll<TaskRecord>(
|
||||
`select id, company_id as companyId, project_id as projectId, goal_id as goalId, parent_id as parentId, title, description, assignee_agent_id as assigneeAgentId, workspace_id as workspaceId, status, priority, active_run_id as activeRunId, session_json as sessionJson, session_display_id as sessionDisplayId, cost_usd as costUsd, requires_user_review as requiresUserReview, started_at as startedAt, completed_at as completedAt, cancelled_at as cancelledAt, created_at as createdAt, updated_at as updatedAt from tasks${companyWhere} order by created_at desc`,
|
||||
`select id, company_id as companyId, project_id as projectId, goal_id as goalId, parent_id as parentId, title, description, assignee_agent_id as assigneeAgentId, workspace_id as workspaceId, status, priority, active_run_id as activeRunId, session_json as sessionJson, session_display_id as sessionDisplayId, cost_usd as costUsd, task_type as taskType, requires_user_review as requiresUserReview, started_at as startedAt, completed_at as completedAt, cancelled_at as cancelledAt, created_at as createdAt, updated_at as updatedAt from tasks${companyWhere} order by created_at desc`,
|
||||
...companyArgs,
|
||||
).map((record) => ({ ...record, requiresUserReview: toBoolean(record.requiresUserReview), startedAt: record.startedAt ?? null, completedAt: record.completedAt ?? null, cancelledAt: record.cancelledAt ?? null })) as TaskRecord[],
|
||||
approvals: readAll<ApprovalRecord>(
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { randomUUID } from "node:crypto";
|
||||
import type { DatabaseSync, SQLInputValue } from "node:sqlite";
|
||||
import type { BrowserActionRecord, SocialAccountRecord } from "@shared/types";
|
||||
import type { ReadAll, Transaction } from "./helpers";
|
||||
import type { ReadAll, SqliteRow, Transaction } from "./helpers";
|
||||
import { ensureId, nowIso, toBoolean } from "./helpers";
|
||||
|
||||
type SqliteRow = Record<string, any>;
|
||||
|
||||
export function buildSocialMethods(
|
||||
getDb: () => DatabaseSync,
|
||||
readAll: ReadAll,
|
||||
|
||||
@@ -141,7 +141,7 @@ export function buildTaskCrudMethods(
|
||||
listAgentTasks(agentId: string, companyId: string, statuses: string[]): TaskRecord[] {
|
||||
const placeholders = statuses.map(() => "?").join(",");
|
||||
return readAll<TaskRecord>(
|
||||
`select id, company_id as companyId, project_id as projectId, goal_id as goalId, parent_id as parentId, title, description, assignee_agent_id as assigneeAgentId, workspace_id as workspaceId, status, priority, active_run_id as activeRunId, session_json as sessionJson, session_display_id as sessionDisplayId, cost_usd as costUsd, created_at as createdAt, updated_at as updatedAt
|
||||
`select id, company_id as companyId, project_id as projectId, goal_id as goalId, parent_id as parentId, title, description, assignee_agent_id as assigneeAgentId, workspace_id as workspaceId, status, priority, active_run_id as activeRunId, session_json as sessionJson, session_display_id as sessionDisplayId, cost_usd as costUsd, task_type as taskType, created_at as createdAt, updated_at as updatedAt
|
||||
from tasks
|
||||
where company_id = ? and assignee_agent_id = ? and status in (${placeholders})
|
||||
order by
|
||||
|
||||
@@ -13,13 +13,7 @@ import type {
|
||||
ThreadWaitingFor,
|
||||
ThreadWaitStateRecord,
|
||||
} from "@shared/types";
|
||||
|
||||
type SqliteRow = Record<string, any>;
|
||||
type ReadAll = <T>(sql: string, ...params: SQLInputValue[]) => T[];
|
||||
|
||||
function nowIso(): string {
|
||||
return new Date().toISOString();
|
||||
}
|
||||
import { type ReadAll, type SqliteRow, nowIso } from "./helpers";
|
||||
|
||||
export function buildThreadMethods(getDb: () => DatabaseSync, readAll: ReadAll) {
|
||||
function getThread(threadId: string, companyId: string): ConversationThreadRecord | null {
|
||||
|
||||
@@ -132,13 +132,14 @@ export function buildWakeupMethods(
|
||||
promoted = deferred.length;
|
||||
} else {
|
||||
const [first, ...rest] = deferred;
|
||||
if (!first) return 0;
|
||||
getDb().prepare(
|
||||
`UPDATE wakeup_requests SET status = 'queued', updated_at = ? WHERE id = ?`,
|
||||
).run(ts, first!.id);
|
||||
).run(ts, first.id);
|
||||
if (rest.length > 0) {
|
||||
const firstTriggers: Array<{ trigger: string; at: string; detail: string }> = first!.trigger_detail ? JSON.parse(first!.trigger_detail) : [];
|
||||
const firstTriggers: Array<{ trigger: string; at: string; detail: string }> = first.trigger_detail ? JSON.parse(first.trigger_detail) : [];
|
||||
let addedCount = 0;
|
||||
let mergedCtx = first!.context_snapshot;
|
||||
let mergedCtx = first.context_snapshot;
|
||||
for (const d of rest) {
|
||||
const dTriggers: Array<{ trigger: string; at: string; detail: string }> = d.trigger_detail ? JSON.parse(d.trigger_detail) : [];
|
||||
firstTriggers.push(...dTriggers);
|
||||
@@ -147,7 +148,7 @@ export function buildWakeupMethods(
|
||||
}
|
||||
getDb().prepare(
|
||||
`UPDATE wakeup_requests SET trigger_detail = ?, coalesced_count = coalesced_count + ?, context_snapshot = ?, updated_at = ? WHERE id = ?`,
|
||||
).run(JSON.stringify(firstTriggers), addedCount, mergedCtx, ts, first!.id);
|
||||
).run(JSON.stringify(firstTriggers), addedCount, mergedCtx, ts, first.id);
|
||||
for (const d of rest) {
|
||||
getDb().prepare("DELETE FROM wakeup_requests WHERE id = ?").run(d.id);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user