make webhook

This commit is contained in:
2026-07-13 18:50:38 +02:00
parent 2f128550fc
commit 40c822d3bf
67 changed files with 6286 additions and 2053 deletions
+125
View File
@@ -0,0 +1,125 @@
import type { DatabaseSync } from "node:sqlite";
import type { Mode, Result } from "../../core/contracts.js";
export type JobState =
| "admitted"
| "queued"
| "running"
| "publishing"
| "succeeded"
| "failed"
| "cancelled";
export type TriggerKind = "label" | "command";
export type Row = Record<string, string | number | bigint | null>;
export interface DatabaseContext {
db: DatabaseSync;
transaction<T>(operation: () => T): T;
audit(jobId: string | null, event: string, detail: string): void;
}
export interface Job {
id: string;
repositoryId: number;
issueNumber: number;
mode: Mode;
triggerKind: TriggerKind;
triggerKey: string;
triggerLabel?: string;
actorId: number;
actorLogin: string;
instruction: string;
state: JobState;
cancelRequested: boolean;
attempts: number;
leaseOwner?: string;
leaseExpiresAt?: number;
workspace?: string;
result?: Result;
error?: string;
createdAt: number;
updatedAt: number;
}
export interface NewJob {
repositoryId: number;
issueNumber: number;
mode: Mode;
triggerKind: TriggerKind;
triggerKey: string;
triggerLabel?: string;
actorId: number;
actorLogin: string;
instruction?: string;
}
export interface Delivery {
id: string;
event: string;
eventType: string;
bodyHash: string;
payload: unknown;
attempts: number;
}
export interface OutboxItem {
id: string;
jobId: string;
kind: "claim" | "publish";
attempts: number;
}
export interface Conversation {
repositoryId: number;
issueNumber: number;
role: "planner" | "implementer";
scope: string;
sessionId: string;
updatedAt: number;
}
export const now = (): number => Date.now();
export function mapJob(row: Row): Job {
const resultJson =
row.result_json === null ? undefined : String(row.result_json);
return {
id: String(row.id),
repositoryId: Number(row.repository_id),
issueNumber: Number(row.issue_number),
mode: String(row.mode) as Mode,
triggerKind: String(row.trigger_kind) as TriggerKind,
triggerKey: String(row.trigger_key),
...(row.trigger_label === null
? {}
: { triggerLabel: String(row.trigger_label) }),
actorId: Number(row.actor_id),
actorLogin: String(row.actor_login),
instruction: String(row.instruction),
state: String(row.state) as JobState,
cancelRequested: Number(row.cancel_requested) === 1,
attempts: Number(row.attempts),
...(row.lease_owner === null
? {}
: { leaseOwner: String(row.lease_owner) }),
...(row.lease_expires_at === null
? {}
: { leaseExpiresAt: Number(row.lease_expires_at) }),
...(row.workspace === null ? {} : { workspace: String(row.workspace) }),
...(resultJson ? { result: JSON.parse(resultJson) as Result } : {}),
...(row.error === null ? {} : { error: String(row.error) }),
createdAt: Number(row.created_at),
updatedAt: Number(row.updated_at),
};
}
export function mapConversation(row: Row): Conversation {
return {
repositoryId: Number(row.repository_id),
issueNumber: Number(row.issue_number),
role: String(row.role) as Conversation["role"],
scope: String(row.scope),
sessionId: String(row.session_id),
updatedAt: Number(row.updated_at),
};
}