Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| Initial g1t: services, event bus, intents and attempts | 1 | /** |
| 2 | * Every state change in g1t is published as an event. Services react to | |
| 3 | * each other through events rather than direct calls, and the same stream | |
| 4 | * feeds timelines, webhooks and automations. | |
| 5 | * | |
| 6 | * The envelope follows CloudEvents: `type` says what happened, `subject` | |
| 7 | * says to what, `data` is the type-specific payload. | |
| 8 | */ | |
| 9 | export type EventPayloads = { | |
| 10 | "repo.created": { repoId: string; namespace: string; name: string; isPrivate: boolean }; | |
| Issues and pull requests replace intents and attempts | 11 | "repo.forked": { repoId: string; sourceRepoId: string; pullId: string }; |
| Initial g1t: services, event bus, intents and attempts | 12 | /** `after` is the commit the ref points to once the push has landed. */ |
| 13 | "git.push": { repoId: string; ref: string; after: string }; | |
| Issues and pull requests replace intents and attempts | 14 | "issue.opened": { issueId: string; repoId: string; number: number; title: string }; |
| 15 | "issue.updated": { issueId: string; repoId: string; number: number }; | |
| 16 | /** `resolvedBy` is the number of the pull request whose merge closed it. */ | |
| 17 | "issue.closed": { | |
| 18 | issueId: string; | |
| 19 | repoId: string; | |
| 20 | number: number; | |
| 21 | reason: "completed" | "not_planned"; | |
| 22 | resolvedBy?: number; | |
| 23 | }; | |
| 24 | "issue.reopened": { issueId: string; repoId: string; number: number }; | |
| 25 | /** `issue` is the number of the issue the pull request is for. */ | |
| 26 | "pull.opened": { pullId: string; repoId: string; number: number; issue?: number; agent: string }; | |
| 27 | "pull.ready": { pullId: string; repoId: string; number: number; issue?: number }; | |
| 28 | "pull.closed": { pullId: string; repoId: string; number: number; issue?: number }; | |
| 29 | "pull.merged": { pullId: string; repoId: string; number: number; issue?: number; commit: string }; | |
| 30 | /** `number` is the issue or pull request commented on. */ | |
| 31 | "comment.created": { commentId: string; repoId: string; number: number }; | |
| 32 | "session.appended": { pullId: string; repoId: string; number: number; count: number }; | |
| Initial g1t: services, event bus, intents and attempts | 33 | }; |
| 34 | ||
| 35 | export type EventType = keyof EventPayloads; | |
| 36 | ||
| 37 | export type G1tEvent<T extends EventType = EventType> = { | |
| 38 | [K in T]: { | |
| 39 | id: string; | |
| 40 | type: K; | |
| 41 | /** The service that published it. */ | |
| 42 | source: string; | |
| 43 | /** Milliseconds since the epoch. */ | |
| 44 | time: number; | |
| 45 | /** The repo the event concerns, used to scope timelines and deliveries. */ | |
| 46 | repoId: string | null; | |
| 47 | /** The user or agent that caused it, if any. */ | |
| 48 | actor: string | null; | |
| 49 | data: EventPayloads[K]; | |
| 50 | }; | |
| 51 | }[T]; | |
| 52 | ||
| 53 | /** What a publisher supplies; the bus fills in `id` and `time`. */ | |
| 54 | export type NewEvent<T extends EventType = EventType> = { | |
| 55 | [K in T]: Omit<G1tEvent<K>, "id" | "time">; | |
| 56 | }[T]; | |
| 57 | ||
| 58 | export type EventQuery = { | |
| 59 | repoId?: string; | |
| 60 | types?: EventType[]; | |
| 61 | /** Return events older than this event id. */ | |
| 62 | before?: string; | |
| 63 | limit?: number; | |
| 64 | }; | |
| 65 | ||
| 66 | /** The event bus and its durable log. */ | |
| 67 | export interface EventsApi { | |
| 68 | publish(events: NewEvent[]): Promise<void>; | |
| 69 | /** Newest first. */ | |
| 70 | list(query: EventQuery): Promise<G1tEvent[]>; | |
| 71 | } | |
| 72 | ||
| 73 | /** Implemented by services that consume events from the bus. */ | |
| 74 | export interface EventSubscriber { | |
| 75 | onEvents(events: G1tEvent[]): Promise<void>; | |
| 76 | } |