flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/packages/contracts/src/events.ts

230 lines10,476 bytesCodeBlame

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 attempts1/**
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
Sidebar: the panels really slide4 * feeds timelines, webhooks and workflows.
Initial g1t: services, event bus, intents and attempts5 *
6 * The envelope follows CloudEvents: `type` says what happened, `subject`
7 * says to what, `data` is the type-specific payload.
8 */
Agents as a team: lifecycle, merge queue, billing and a new shell9
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look10import type { RepoRole } from "./access";
Agents as a team: lifecycle, merge queue, billing and a new shell11import type { Verdict } from "./work";
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look12
13/** The payload of the `repo.collaborator_*` events. */
14export type RepoCollaboratorData = {
15 repoId: string;
16 namespace: string;
17 name: string;
18 username: string;
19 role: RepoRole | null;
20 previousRole: RepoRole | null;
21};
Initial g1t: services, event bus, intents and attempts22export type EventPayloads = {
23 "repo.created": { repoId: string; namespace: string; name: string; isPrivate: boolean };
Issues and pull requests replace intents and attempts24 "repo.forked": { repoId: string; sourceRepoId: string; pullId: string };
Events service in Rust, with RFC 3339 times and accurate push events25 /**
Search across all of g1t, Explore, and a command palette26 * A repository's description, topics or visibility changed.
27 * `visibilityChanged` says whether it went public or private, which
28 * `repo.visibility_changed` also announces on its own.
29 */
30 "repo.updated": { repoId: string; namespace: string; name: string; isPrivate: boolean; visibilityChanged: boolean };
31 "repo.visibility_changed": { repoId: string; isPrivate: boolean };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look32 /**
33 * A repository's name changed within its workspace `namespace`, from
34 * `from` to `to`, keeping its id. A path change like `repo.transferred`:
35 * services move rows kept under its path to its *current* path (see
36 * `repoMove`, `currentMovedPath`).
37 */
38 "repo.renamed": { repoId: string; namespace: string; from: string; to: string };
39 /**
40 * A repository was deleted. It is hidden and git refuses it, but it can
41 * be restored until `purgeAfter`: services stop what runs for it and hide
42 * it, and keep their rows until `repo.purged`.
43 */
44 "repo.deleted": { repoId: string; namespace: string; name: string; isPrivate: boolean; purgeAfter: string };
45 /** A deleted repository is back, as it was. Services start again what they stopped. */
46 "repo.restored": { repoId: string; namespace: string; name: string; isPrivate: boolean };
47 /**
48 * A deleted repository is gone for good, its git data with it. Services
49 * drop every row they keep for it, except a workspace's history (ledgers,
50 * invoices, the audit log).
51 */
52 "repo.purged": { repoId: string; namespace: string; name: string };
53 /**
54 * A repository was archived (read-only: pushes, merges, agents and
55 * workflows refused; issues and pull requests locked; deployments keep
56 * serving), or unarchived.
57 */
58 "repo.archived": { repoId: string; namespace: string; name: string; archived: true };
59 "repo.unarchived": { repoId: string; namespace: string; name: string; archived: false };
60 /** The default branch is now `to`; `renamed` when `from` was renamed to it. */
61 "repo.default_branch_changed": { repoId: string; from: string; to: string; renamed: boolean };
62 /** A branch was renamed. Pull requests from it follow. */
63 "branch.renamed": { repoId: string; from: string; to: string; defaultBranch: boolean };
Search across all of g1t, Explore, and a command palette64 /** An account was made, or changed what its profile shows. Ask identity for the profile. */
65 "user.updated": { username: string };
66 /** A workspace was made, or its name, description or icon changed. */
67 "workspace.updated": { workspaceId: string; slug: string };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look68 /** Someone, or g1t staff, made an invite. Never the code or the address. */
69 "invite.created": { inviteId: string; inviterId: string | null; workspaceId: string | null; bound: boolean };
70 /** An invite was used: by a new account, or by an account joining a workspace. */
71 "invite.redeemed": {
72 inviteId: string;
73 userId: string;
74 inviterId: string | null;
75 workspaceId: string | null;
76 createdAccount: boolean;
77 };
78 /** Someone asked for access while registration is invite-only. The address is not in the event. */
79 "waitlist.requested": { entryId: string };
Search across all of g1t, Explore, and a command palette80 /**
Events service in Rust, with RFC 3339 times and accurate push events81 * One branch moved by a push. `ref` is the full ref, `after` the commit it
82 * points to now, and `defaultBranch` whether it is the default branch.
83 */
84 "git.push": { repoId: string; ref: string; after: string; defaultBranch: boolean };
Issues and pull requests replace intents and attempts85 "issue.opened": { issueId: string; repoId: string; number: number; title: string };
86 "issue.updated": { issueId: string; repoId: string; number: number };
Agents as a team: lifecycle, merge queue, billing and a new shell87 /** The people an issue is assigned to changed; `assignees` is the new set. */
88 "issue.assigned": { issueId: string; repoId: string; number: number; assignees: string[] };
Issues and pull requests replace intents and attempts89 /** `resolvedBy` is the number of the pull request whose merge closed it. */
90 "issue.closed": {
91 issueId: string;
92 repoId: string;
93 number: number;
94 reason: "completed" | "not_planned";
95 resolvedBy?: number;
96 };
97 "issue.reopened": { issueId: string; repoId: string; number: number };
98 /** `issue` is the number of the issue the pull request is for. */
99 "pull.opened": { pullId: string; repoId: string; number: number; issue?: number; agent: string };
100 "pull.ready": { pullId: string; repoId: string; number: number; issue?: number };
Acceptance checks in sandboxes, line comments and review verdicts101 /** A push moved the head of a pull request that is ready for review. */
102 "pull.updated": { pullId: string; repoId: string; number: number; issue?: number; commit: string };
Agents as a team: lifecycle, merge queue, billing and a new shell103 /** A merge was asked for while the pull request was behind; it has to catch up first. */
104 "pull.merge_requested": { pullId: string; repoId: string; number: number; issue?: number };
Issues and pull requests replace intents and attempts105 "pull.closed": { pullId: string; repoId: string; number: number; issue?: number };
Agents and memory, checks and conflicts, profiles, slug renames, custom domains106 /**
107 * The pull request's head or its target moved and the files both changed
108 * overlap: a sandbox should find out whether it still merges cleanly.
109 * `commit` is its head.
110 */
111 "pull.mergecheck": { pullId: string; repoId: string; number: number; issue?: number; commit: string };
112 /** Whether the pull request merges cleanly was settled. */
113 "pull.mergeability": { pullId: string; repoId: string; number: number; issue?: number };
Agents asked while not at work are woken to answer114 /** Another agent asked the agent on a pull request, which was not at work, a question or handed it work. */
115 "agent.asked": { pullId: string; repoId: string; number: number; issue?: number };
Issues and pull requests replace intents and attempts116 "pull.merged": { pullId: string; repoId: string; number: number; issue?: number; commit: string };
Acceptance checks in sandboxes, line comments and review verdicts117 /** A run of the acceptance checks finished. `commit` is what was checked. */
118 "checks.completed": {
119 pullId: string;
120 repoId: string;
121 number: number;
122 status: "passed" | "failed" | "errored";
123 commit: string;
124 };
Agents as a team: lifecycle, merge queue, billing and a new shell125 /** A g1t agent finished reviewing a pull request; no verdict if it could not. */
126 "review.completed": {
127 pullId: string;
128 repoId: string;
129 number: number;
130 verdict?: "approve" | "request_changes";
131 };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look132 /** A person was given a role on one repository directly, had it changed, or lost it. `role` is null once removed. */
133 "repo.collaborator_added": RepoCollaboratorData;
134 "repo.collaborator_removed": RepoCollaboratorData;
135 "repo.collaborator_role_changed": RepoCollaboratorData;
Agents as a team: lifecycle, merge queue, billing and a new shell136 /** A repository's merge queue gained, lost or settled an entry. */
137 "queue.changed": { repoId: string };
What happened across an outcome, as a feed beside its graph138 /** `number` is the issue or pull request commented on. */
Agents as a team: lifecycle, merge queue, billing and a new shell139 "comment.created": {
140 commentId: string;
141 repoId: string;
142 number: number;
143 /** Set when the comment is on a pull request. */
144 pullId?: string;
145 /** Set when the comment is a review. */
146 verdict?: Verdict;
147 };
Issues and pull requests replace intents and attempts148 "session.appended": { pullId: string; repoId: string; number: number; count: number };
Agents and memory, checks and conflicts, profiles, slug renames, custom domains149 /**
150 * A workspace's slug changed from `from` to `to`. Services that store a
151 * slug move their rows to the workspace's *current* slug (see
152 * `currentWorkspaceSlug`), so a repeated or late delivery after a second
153 * rename still lands in the right place.
154 */
155 "workspace.renamed": { workspaceId: string; from: string; to: string };
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API156 /**
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look157 * A repository moved from workspace `from` to `to`, keeping its id and
158 * name. Services that store its path or its workspace's slug move those
159 * rows to its *current* path (ask repos `path_by_id`), so a repeated or
160 * late delivery after a second transfer still lands in the right place.
161 */
162 "repo.transferred": { repoId: string; name: string; from: string; to: string };
163 /**
164 * A workspace is gone. Services drop what they keep for it alone; ledgers,
165 * invoices and the audit log stay under its slug, which is never reused.
166 */
167 "workspace.deleted": { workspaceId: string; slug: string };
168 /**
Agents get guardrails, run credentials, an audit log, a context hub, repository instructions and mentions; security upkeep; snake_case API169 * A memory was added, changed, reviewed or forgotten. No text: ask the
170 * work service for it by id. `repoId` is the project's, or null for the
171 * workspace's memory. `status` is `deleted` once forgotten.
172 */
173 "memory.changed": { memoryId: string; workspace: string; status: "candidate" | "kept" | "dismissed" | "deleted" };
Invite-only launch: sign in with GitHub, repository access and lifecycle, many emails, a new look174 /**
175 * A sandbox was stopped because it looked like it was mining: CPU pinned
176 * with little I/O and no progress, or a miner seen by name. For g1t's
177 * staff, in sudo; published with no `repoId` so it never reaches a
178 * repository's timeline or webhooks. `metrics` is what the sandbox
179 * measured (`Verdict` in crates/runner abuse.rs), or null if it could
180 * not say.
181 */
182 "abuse.flagged": {
183 workspace: string;
184 repo: string | null;
185 /** The agent run, when the sandbox had one. */
186 run: string | null;
187 /** What the sandbox was for: agent, checks, queue, actions, deploy... */
188 kind: string;
189 sandbox: string;
190 metrics: Record<string, unknown> | null;
191 };
Initial g1t: services, event bus, intents and attempts192};
193
194export type EventType = keyof EventPayloads;
195
196export type G1tEvent<T extends EventType = EventType> = {
197 [K in T]: {
198 id: string;
199 type: K;
200 /** The service that published it. */
201 source: string;
Events service in Rust, with RFC 3339 times and accurate push events202 /** RFC 3339. */
203 time: string;
Initial g1t: services, event bus, intents and attempts204 /** The repo the event concerns, used to scope timelines and deliveries. */
205 repoId: string | null;
206 /** The user or agent that caused it, if any. */
207 actor: string | null;
208 data: EventPayloads[K];
209 };
210}[T];
211
212/** What a publisher supplies; the bus fills in `id` and `time`. */
213export type NewEvent<T extends EventType = EventType> = {
214 [K in T]: Omit<G1tEvent<K>, "id" | "time">;
215}[T];
216
217export type EventQuery = {
218 repoId?: string;
219 types?: EventType[];
220 /** Return events older than this event id. */
221 before?: string;
222 limit?: number;
223};
224
225/** The event bus and its durable log. */
226export interface EventsApi {
227 publish(events: NewEvent[]): Promise<void>;
228 /** Newest first. */
229 list(query: EventQuery): Promise<G1tEvent[]>;
230}