g1t

syntaqx/g1t

public

Git for AI scale: a forge for thousands of agents working on the same code at once.

g1t/packages/contracts/src/events.ts

84 lines3,323 bytes
/**
 * Every state change in g1t is published as an event. Services react to
 * each other through events rather than direct calls, and the same stream
 * feeds timelines, webhooks and automations.
 *
 * The envelope follows CloudEvents: `type` says what happened, `subject`
 * says to what, `data` is the type-specific payload.
 */
export type EventPayloads = {
  "repo.created": { repoId: string; namespace: string; name: string; isPrivate: boolean };
  "repo.forked": { repoId: string; sourceRepoId: string; pullId: string };
  /**
   * One branch moved by a push. `ref` is the full ref, `after` the commit it
   * points to now, and `defaultBranch` whether it is the default branch.
   */
  "git.push": { repoId: string; ref: string; after: string; defaultBranch: boolean };
  "issue.opened": { issueId: string; repoId: string; number: number; title: string };
  "issue.updated": { issueId: string; repoId: string; number: number };
  /** `resolvedBy` is the number of the pull request whose merge closed it. */
  "issue.closed": {
    issueId: string;
    repoId: string;
    number: number;
    reason: "completed" | "not_planned";
    resolvedBy?: number;
  };
  "issue.reopened": { issueId: string; repoId: string; number: number };
  /** `issue` is the number of the issue the pull request is for. */
  "pull.opened": { pullId: string; repoId: string; number: number; issue?: number; agent: string };
  "pull.ready": { pullId: string; repoId: string; number: number; issue?: number };
  /** A push moved the head of a pull request that is ready for review. */
  "pull.updated": { pullId: string; repoId: string; number: number; issue?: number; commit: string };
  "pull.closed": { pullId: string; repoId: string; number: number; issue?: number };
  "pull.merged": { pullId: string; repoId: string; number: number; issue?: number; commit: string };
  /** A run of the acceptance checks finished. `commit` is what was checked. */
  "checks.completed": {
    pullId: string;
    repoId: string;
    number: number;
    status: "passed" | "failed" | "errored";
    commit: string;
  };
  /** `number` is the issue or pull request commented on. */
  "comment.created": { commentId: string; repoId: string; number: number };
  "session.appended": { pullId: string; repoId: string; number: number; count: number };
};

export type EventType = keyof EventPayloads;

export type G1tEvent<T extends EventType = EventType> = {
  [K in T]: {
    id: string;
    type: K;
    /** The service that published it. */
    source: string;
    /** RFC 3339. */
    time: string;
    /** The repo the event concerns, used to scope timelines and deliveries. */
    repoId: string | null;
    /** The user or agent that caused it, if any. */
    actor: string | null;
    data: EventPayloads[K];
  };
}[T];

/** What a publisher supplies; the bus fills in `id` and `time`. */
export type NewEvent<T extends EventType = EventType> = {
  [K in T]: Omit<G1tEvent<K>, "id" | "time">;
}[T];

export type EventQuery = {
  repoId?: string;
  types?: EventType[];
  /** Return events older than this event id. */
  before?: string;
  limit?: number;
};

/** The event bus and its durable log. */
export interface EventsApi {
  publish(events: NewEvent[]): Promise<void>;
  /** Newest first. */
  list(query: EventQuery): Promise<G1tEvent[]>;
}