gitd-client 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/gitd.d.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  import { type Transport } from "@connectrpc/connect";
2
- import type { AuditEntry, AuditOptions, CheckoutOptions, Description, Info, PrepareOptions, Probe, Published, UpdateOptions, Workspace } from "./types.js";
2
+ import { Credentials } from "./credentials.js";
3
+ import { Publishing } from "./publishing.js";
4
+ import type { PublishOptions } from "./publishing-types.js";
5
+ import type { AuditEntry, AuditOptions, Changes, CheckoutOptions, CompareOptions, Comparison, Conflict, Description, Diff, DiffOptions, Info, PrepareOptions, Probe, Published, Side, WorkspaceEvent, UpdateOptions, WarmLayer, Workspace } from "./types.js";
3
6
  export interface GitdOptions {
4
7
  /** gitd's Unix socket; default $GITD_SOCKET, then /run/gitd/gitd.sock. */
5
8
  socket?: string;
@@ -7,10 +10,15 @@ export interface GitdOptions {
7
10
  transport?: Transport;
8
11
  }
9
12
  /**
10
- * A gitd on its Unix socket. No call takes a credential: gitd reads and publishes with the
11
- * ones it keeps.
13
+ * A gitd on its Unix socket. No call on workspaces takes a credential: gitd reads and
14
+ * publishes with the ones it keeps, which a platform manages through `credentials`, and
15
+ * publishing follows the rules it sets through `publishing`.
12
16
  */
13
17
  export declare class Gitd {
18
+ /** The credentials gitd keeps, and connecting GitHub. */
19
+ readonly credentials: Credentials;
20
+ /** The rules publishing follows, per repository prefix. */
21
+ readonly publishing: Publishing;
14
22
  private readonly workspaces;
15
23
  private readonly repositories;
16
24
  private readonly server;
@@ -27,10 +35,31 @@ export declare class Gitd {
27
35
  checkout(path: string, commit: string, options?: CheckoutOptions): Promise<Workspace>;
28
36
  /** What a workspace is on disk, without the network. */
29
37
  describe(path: string): Promise<Description>;
30
- /** Pushes what was committed in a workspace to a new branch, with the token gitd keeps. */
31
- publish(path: string, branch: string): Promise<Published>;
38
+ /**
39
+ * Pushes what was committed in a workspace to a new branch, with the credential gitd
40
+ * keeps, and opens its pull request when the publishing settings or the options say so.
41
+ */
42
+ publish(path: string, branch: string, options?: PublishOptions): Promise<Published>;
32
43
  /** The audit log: every publish, done or refused, newest first. */
33
44
  audit(options?: AuditOptions): Promise<AuditEntry[]>;
45
+ /** What was changed in a workspace since gitd put it on its commit, committed or not. */
46
+ changes(path: string, includeIgnored?: boolean): Promise<Changes>;
47
+ /** The unified diff of a workspace's changes, of some files or all, cut short at a size. */
48
+ diff(path: string, options?: DiffOptions): Promise<Diff>;
49
+ /** How two works of one repository differ, from first to second. */
50
+ compare(first: Side, second: Side, options?: CompareOptions): Promise<Comparison>;
51
+ /** Which pairs of works do not merge cleanly; a workspace stands for what it committed. */
52
+ conflicts(sides: Side[], url?: string): Promise<Conflict[]>;
53
+ /** What happens to the workspaces at paths, or to every one, as it happens. */
54
+ watch(paths?: string[], signal?: AbortSignal): AsyncGenerator<WorkspaceEvent>;
55
+ /**
56
+ * Seals what was installed in an overlay workspace as the warm layer `name` of its
57
+ * repository, for workspaces made later at the same commit to stand on. The layer is
58
+ * moved, not copied: the workspace is removed.
59
+ */
60
+ seal(path: string, name: string): Promise<WarmLayer>;
61
+ /** The warm layers of a repository. */
62
+ warmLayers(url: string): Promise<WarmLayer[]>;
34
63
  /** Deletes a workspace; its pool stays. */
35
64
  remove(path: string): Promise<void>;
36
65
  }
package/dist/gitd.js CHANGED
@@ -1,15 +1,26 @@
1
1
  import { timestampFromDate } from "@bufbuild/protobuf/wkt";
2
2
  import { createClient } from "@connectrpc/connect";
3
3
  import { createConnectTransport } from "@connectrpc/connect-node";
4
- import { RepositoryService, ServerService, WorkspaceService } from "./gen/gitd/v1/gitd_pb.js";
4
+ import { ConnectionService, PublishingService, RepositoryService, ServerService, WorkspaceService, } from "./gen/gitd/v1/gitd_pb.js";
5
5
  import { call, drain } from "./calls.js";
6
- import { accessName, pushedOf, revisionOf, strategyName, strategyProto, toAuditEntry, toWorkspace, } from "./convert.js";
6
+ import { sideProto, toEvent, toSide } from "./compare-convert.js";
7
+ import { toWarmLayer } from "./warm-convert.js";
8
+ import { refusal } from "./errors.js";
9
+ import { Credentials } from "./credentials.js";
10
+ import { pullRequestOptionsProto } from "./publishing-convert.js";
11
+ import { Publishing } from "./publishing.js";
12
+ import { accessName, publishedOf, revisionOf, strategyName, strategyProto, toAuditEntry, toChangedFiles, toChanges, toWorkspace, } from "./convert.js";
7
13
  const defaultSocket = "/run/gitd/gitd.sock";
8
14
  /**
9
- * A gitd on its Unix socket. No call takes a credential: gitd reads and publishes with the
10
- * ones it keeps.
15
+ * A gitd on its Unix socket. No call on workspaces takes a credential: gitd reads and
16
+ * publishes with the ones it keeps, which a platform manages through `credentials`, and
17
+ * publishing follows the rules it sets through `publishing`.
11
18
  */
12
19
  export class Gitd {
20
+ /** The credentials gitd keeps, and connecting GitHub. */
21
+ credentials;
22
+ /** The rules publishing follows, per repository prefix. */
23
+ publishing;
13
24
  workspaces;
14
25
  repositories;
15
26
  server;
@@ -18,6 +29,8 @@ export class Gitd {
18
29
  this.workspaces = createClient(WorkspaceService, transport);
19
30
  this.repositories = createClient(RepositoryService, transport);
20
31
  this.server = createClient(ServerService, transport);
32
+ this.credentials = new Credentials(createClient(ConnectionService, transport));
33
+ this.publishing = new Publishing(createClient(PublishingService, transport));
21
34
  }
22
35
  /** Which gitd answers, and how it makes workspaces here and why. */
23
36
  async info() {
@@ -52,6 +65,7 @@ export class Gitd {
52
65
  withSubmodules: options.submodules ?? false,
53
66
  fullHistory: options.fullHistory ?? false,
54
67
  strategy: strategyProto(options.strategy),
68
+ warm: options.warm ?? "",
55
69
  };
56
70
  const stream = this.workspaces.prepare(request, { signal: options.signal });
57
71
  return toWorkspace(options.path, await drain(stream, options.onProgress));
@@ -86,10 +100,24 @@ export class Gitd {
86
100
  lfsPatterns: answer.lfsPatterns,
87
101
  };
88
102
  }
89
- /** Pushes what was committed in a workspace to a new branch, with the token gitd keeps. */
90
- async publish(path, branch) {
91
- const answer = await call(() => this.workspaces.publish({ path, branch }));
92
- return { branch: answer.branch, repositories: pushedOf(answer.repository, answer.submodules) };
103
+ /**
104
+ * Pushes what was committed in a workspace to a new branch, with the credential gitd
105
+ * keeps, and opens its pull request when the publishing settings or the options say so.
106
+ */
107
+ async publish(path, branch, options = {}) {
108
+ const answer = await call(() => this.workspaces.publish({
109
+ path,
110
+ branch,
111
+ requestedBy: options.requestedBy ?? "",
112
+ pullRequest: pullRequestOptionsProto(options.pullRequest),
113
+ provenance: options.provenance && {
114
+ agent: options.provenance.agent ?? "",
115
+ model: options.provenance.model ?? "",
116
+ session: options.provenance.session ?? "",
117
+ taskUrl: options.provenance.taskUrl ?? "",
118
+ },
119
+ }));
120
+ return publishedOf(answer);
93
121
  }
94
122
  /** The audit log: every publish, done or refused, newest first. */
95
123
  async audit(options = {}) {
@@ -101,6 +129,69 @@ export class Gitd {
101
129
  const answer = await call(() => this.server.audit(request));
102
130
  return answer.entries.map(toAuditEntry);
103
131
  }
132
+ /** What was changed in a workspace since gitd put it on its commit, committed or not. */
133
+ async changes(path, includeIgnored = false) {
134
+ return toChanges(await call(() => this.workspaces.changes({ path, includeIgnored })));
135
+ }
136
+ /** The unified diff of a workspace's changes, of some files or all, cut short at a size. */
137
+ async diff(path, options = {}) {
138
+ const answer = await call(() => this.workspaces.diff({
139
+ path,
140
+ files: options.files ?? [],
141
+ maxBytes: BigInt(options.maxBytes ?? 0),
142
+ includeIgnored: options.includeIgnored ?? false,
143
+ }));
144
+ return { base: answer.base, diff: answer.diff, truncated: answer.truncated };
145
+ }
146
+ /** How two works of one repository differ, from first to second. */
147
+ async compare(first, second, options = {}) {
148
+ const answer = await call(() => this.workspaces.compare({
149
+ first: sideProto(first),
150
+ second: sideProto(second),
151
+ url: options.url ?? "",
152
+ withDiff: options.withDiff ?? false,
153
+ maxBytes: BigInt(options.maxBytes ?? 0),
154
+ includeIgnored: options.includeIgnored ?? false,
155
+ }));
156
+ return { files: toChangedFiles(answer.files), diff: answer.diff, truncated: answer.truncated };
157
+ }
158
+ /** Which pairs of works do not merge cleanly; a workspace stands for what it committed. */
159
+ async conflicts(sides, url = "") {
160
+ const answer = await call(() => this.workspaces.conflicts({ sides: sides.map(sideProto), url }));
161
+ return answer.conflicts.map((conflict) => ({
162
+ first: toSide(conflict.first),
163
+ second: toSide(conflict.second),
164
+ paths: conflict.paths,
165
+ }));
166
+ }
167
+ /** What happens to the workspaces at paths, or to every one, as it happens. */
168
+ async *watch(paths = [], signal) {
169
+ try {
170
+ for await (const event of this.workspaces.watch({ paths }, { signal })) {
171
+ yield toEvent(event);
172
+ }
173
+ }
174
+ catch (error) {
175
+ if (signal?.aborted) {
176
+ return;
177
+ }
178
+ throw refusal(error);
179
+ }
180
+ }
181
+ /**
182
+ * Seals what was installed in an overlay workspace as the warm layer `name` of its
183
+ * repository, for workspaces made later at the same commit to stand on. The layer is
184
+ * moved, not copied: the workspace is removed.
185
+ */
186
+ async seal(path, name) {
187
+ const answer = await call(() => this.workspaces.seal({ path, name }));
188
+ return toWarmLayer(answer.warm);
189
+ }
190
+ /** The warm layers of a repository. */
191
+ async warmLayers(url) {
192
+ const answer = await call(() => this.workspaces.listWarm({ url }));
193
+ return answer.warm.map(toWarmLayer);
194
+ }
104
195
  /** Deletes a workspace; its pool stays. */
105
196
  async remove(path) {
106
197
  await call(() => this.workspaces.remove({ path }));
package/dist/index.d.ts CHANGED
@@ -1,4 +1,8 @@
1
1
  export { Gitd, type GitdOptions } from "./gitd.js";
2
2
  export { GitdError } from "./errors.js";
3
+ export { Credentials } from "./credentials.js";
4
+ export { Publishing } from "./publishing.js";
3
5
  export type * from "./types.js";
6
+ export type * from "./credential-types.js";
7
+ export type * from "./publishing-types.js";
4
8
  export * as proto from "./gen/gitd/v1/gitd_pb.js";
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
1
  export { Gitd } from "./gitd.js";
2
2
  export { GitdError } from "./errors.js";
3
+ export { Credentials } from "./credentials.js";
4
+ export { Publishing } from "./publishing.js";
3
5
  export * as proto from "./gen/gitd/v1/gitd_pb.js";
@@ -0,0 +1,8 @@
1
+ import type { MessageInitShape } from "@bufbuild/protobuf";
2
+ import { type Preset as PresetMessage, type PresetSchema, type PublishSettings as PublishSettingsMessage, type PublishSettingsSchema, type PullRequestOptionsSchema } from "./gen/gitd/v1/gitd_pb.js";
3
+ import type { Preset, PublishSettings, PullRequestOptions } from "./publishing-types.js";
4
+ export declare function toPublishSettings(settings: PublishSettingsMessage | undefined): PublishSettings;
5
+ export declare function publishSettingsProto(settings: PublishSettings): MessageInitShape<typeof PublishSettingsSchema>;
6
+ export declare function pullRequestOptionsProto(options: PullRequestOptions | undefined): MessageInitShape<typeof PullRequestOptionsSchema> | undefined;
7
+ export declare function toPreset(preset: PresetMessage | undefined): Preset;
8
+ export declare function presetProto(preset: Preset): MessageInitShape<typeof PresetSchema>;
@@ -0,0 +1,74 @@
1
+ import { Preset_Origin, PullRequestSettings_Open, } from "./gen/gitd/v1/gitd_pb.js";
2
+ export function toPublishSettings(settings) {
3
+ const pullRequests = settings?.pullRequests;
4
+ return {
5
+ urlPrefix: settings?.urlPrefix ?? "",
6
+ preset: settings?.preset || undefined,
7
+ protectedPaths: settings?.protectedPaths ?? [],
8
+ keptPaths: settings?.keptPaths ?? [],
9
+ allowedPaths: settings?.allowedPaths ?? [],
10
+ maxChangedFiles: settings?.maxChangedFiles,
11
+ branchPrefix: settings?.branchPrefix ?? "",
12
+ pullRequests: pullRequests && {
13
+ opening: pullRequests.open === PullRequestSettings_Open.ALWAYS ? "always" : "when_asked",
14
+ draft: pullRequests.draft,
15
+ labels: pullRequests.labels,
16
+ requestReviewFromRequester: pullRequests.requestReviewFromRequester,
17
+ },
18
+ fromFile: settings?.fromFile ?? false,
19
+ };
20
+ }
21
+ export function publishSettingsProto(settings) {
22
+ const pullRequests = settings.pullRequests;
23
+ return {
24
+ urlPrefix: settings.urlPrefix,
25
+ preset: settings.preset ?? "",
26
+ protectedPaths: settings.protectedPaths ?? [],
27
+ keptPaths: settings.keptPaths ?? [],
28
+ allowedPaths: settings.allowedPaths ?? [],
29
+ maxChangedFiles: settings.maxChangedFiles,
30
+ branchPrefix: settings.branchPrefix ?? "",
31
+ pullRequests: pullRequests && {
32
+ open: pullRequests.opening === "always" ? PullRequestSettings_Open.ALWAYS : PullRequestSettings_Open.WHEN_ASKED,
33
+ draft: pullRequests.draft ?? false,
34
+ labels: pullRequests.labels ?? [],
35
+ requestReviewFromRequester: pullRequests.requestReviewFromRequester ?? false,
36
+ },
37
+ };
38
+ }
39
+ export function pullRequestOptionsProto(options) {
40
+ return (options && {
41
+ open: options.open ?? false,
42
+ title: options.title ?? "",
43
+ body: options.body ?? "",
44
+ base: options.base ?? "",
45
+ draft: options.draft,
46
+ });
47
+ }
48
+ export function toPreset(preset) {
49
+ return {
50
+ name: preset?.name ?? "",
51
+ protectedPaths: preset?.protectedPaths ?? [],
52
+ keptPaths: preset?.keptPaths ?? [],
53
+ maxChangedFiles: preset?.maxChangedFiles,
54
+ origin: originName(preset?.origin ?? Preset_Origin.UNSPECIFIED),
55
+ };
56
+ }
57
+ export function presetProto(preset) {
58
+ return {
59
+ name: preset.name,
60
+ protectedPaths: preset.protectedPaths ?? [],
61
+ keptPaths: preset.keptPaths ?? [],
62
+ maxChangedFiles: preset.maxChangedFiles,
63
+ };
64
+ }
65
+ function originName(origin) {
66
+ switch (origin) {
67
+ case Preset_Origin.BUILT_IN:
68
+ return "built_in";
69
+ case Preset_Origin.FILE:
70
+ return "file";
71
+ default:
72
+ return "api";
73
+ }
74
+ }
@@ -0,0 +1,70 @@
1
+ /** When publishes open pull requests: only when a publish asks, or always. */
2
+ export type Opening = "when_asked" | "always";
3
+ /** How publishes open pull requests. */
4
+ export interface PullRequestSettings {
5
+ opening: Opening;
6
+ draft?: boolean;
7
+ labels?: string[];
8
+ /** Ask the person a publish names as requester to review it. */
9
+ requestReviewFromRequester?: boolean;
10
+ }
11
+ /** The rules of the repositories whose address starts with urlPrefix ("" for every one). */
12
+ export interface PublishSettings {
13
+ urlPrefix: string;
14
+ /** The name of a preset whose rules these take; `recommended` is gitd's own. */
15
+ preset?: string;
16
+ /** Paths a publish may not change, as git's glob pathspecs, e.g. `.github/workflows/**`. */
17
+ protectedPaths?: string[];
18
+ /** Paths a publish may change but not delete or rename away. */
19
+ keptPaths?: string[];
20
+ /** Paths these settings' own rules leave free, e.g. `.gitmodules` under `recommended`. */
21
+ allowedPaths?: string[];
22
+ maxChangedFiles?: number;
23
+ /** What every published branch must start with, e.g. `agents/`. */
24
+ branchPrefix?: string;
25
+ pullRequests?: PullRequestSettings;
26
+ /** Declared in gitd.toml: shown, never changed through the API. */
27
+ fromFile?: boolean;
28
+ }
29
+ /** Where a preset comes from: gitd's own, gitd.toml, or the API. */
30
+ export type PresetOrigin = "built_in" | "file" | "api";
31
+ /** A named set of rules settings take; one named `recommended` replaces gitd's own. */
32
+ export interface Preset {
33
+ name: string;
34
+ protectedPaths?: string[];
35
+ keptPaths?: string[];
36
+ maxChangedFiles?: number;
37
+ /** Read from gitd, never sent. */
38
+ origin?: PresetOrigin;
39
+ }
40
+ /** A publish's own say on its pull request. */
41
+ export interface PullRequestOptions {
42
+ /** Open one even when the settings open them only when asked. */
43
+ open?: boolean;
44
+ /** Default: the newest commit's subject. */
45
+ title?: string;
46
+ /** Text that comes before what gitd checked. */
47
+ body?: string;
48
+ /** The branch it merges into; default: the repository's default branch. */
49
+ base?: string;
50
+ draft?: boolean;
51
+ }
52
+ /** Where a publish's work came from, as the platform says; gitd records it as told. */
53
+ export interface Provenance {
54
+ agent?: string;
55
+ model?: string;
56
+ session?: string;
57
+ /** An https address: an issue, a ticket. */
58
+ taskUrl?: string;
59
+ }
60
+ export interface PublishOptions {
61
+ /** Who asked for the work, as their account on the host. */
62
+ requestedBy?: string;
63
+ pullRequest?: PullRequestOptions;
64
+ provenance?: Provenance;
65
+ }
66
+ /** A pull request gitd opened. */
67
+ export interface OpenedPullRequest {
68
+ url: string;
69
+ number: number;
70
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ import type { Client } from "@connectrpc/connect";
2
+ import type { PublishingService } from "./gen/gitd/v1/gitd_pb.js";
3
+ import type { Preset, PublishSettings } from "./publishing-types.js";
4
+ /**
5
+ * The rules publishing follows, per repository prefix, as `gitd.publishing`: for a
6
+ * platform's own pages, never for an agent.
7
+ */
8
+ export declare class Publishing {
9
+ private readonly publishing;
10
+ constructor(publishing: Client<typeof PublishingService>);
11
+ /** Every setting, gitd.toml's included. */
12
+ settings(): Promise<PublishSettings[]>;
13
+ /** Keeps the settings of a prefix, replacing those it had, as gitd checked them. */
14
+ set(settings: PublishSettings): Promise<PublishSettings>;
15
+ /** Forgets the settings of a prefix set through the API. */
16
+ remove(urlPrefix: string): Promise<void>;
17
+ /** Every preset as it applies: gitd's own, gitd.toml's and those set through the API. */
18
+ presets(): Promise<Preset[]>;
19
+ /** Keeps a preset, replacing one of the same name; `recommended` replaces gitd's own. */
20
+ setPreset(preset: Preset): Promise<Preset>;
21
+ /** Forgets a preset set through the API; refused while settings take it. */
22
+ removePreset(name: string): Promise<void>;
23
+ }
@@ -0,0 +1,40 @@
1
+ import { call } from "./calls.js";
2
+ import { presetProto, publishSettingsProto, toPreset, toPublishSettings } from "./publishing-convert.js";
3
+ /**
4
+ * The rules publishing follows, per repository prefix, as `gitd.publishing`: for a
5
+ * platform's own pages, never for an agent.
6
+ */
7
+ export class Publishing {
8
+ publishing;
9
+ constructor(publishing) {
10
+ this.publishing = publishing;
11
+ }
12
+ /** Every setting, gitd.toml's included. */
13
+ async settings() {
14
+ const answer = await call(() => this.publishing.getSettings({}));
15
+ return answer.settings.map(toPublishSettings);
16
+ }
17
+ /** Keeps the settings of a prefix, replacing those it had, as gitd checked them. */
18
+ async set(settings) {
19
+ const answer = await call(() => this.publishing.setSettings({ settings: publishSettingsProto(settings) }));
20
+ return toPublishSettings(answer.settings);
21
+ }
22
+ /** Forgets the settings of a prefix set through the API. */
23
+ async remove(urlPrefix) {
24
+ await call(() => this.publishing.removeSettings({ urlPrefix }));
25
+ }
26
+ /** Every preset as it applies: gitd's own, gitd.toml's and those set through the API. */
27
+ async presets() {
28
+ const answer = await call(() => this.publishing.listPresets({}));
29
+ return answer.presets.map(toPreset);
30
+ }
31
+ /** Keeps a preset, replacing one of the same name; `recommended` replaces gitd's own. */
32
+ async setPreset(preset) {
33
+ const answer = await call(() => this.publishing.setPreset({ preset: presetProto(preset) }));
34
+ return toPreset(answer.preset);
35
+ }
36
+ /** Forgets a preset set through the API; refused while settings take it. */
37
+ async removePreset(name) {
38
+ await call(() => this.publishing.removePreset({ name }));
39
+ }
40
+ }
package/dist/types.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Progress } from "./gen/gitd/v1/gitd_pb.js";
2
+ import type { OpenedPullRequest, Provenance } from "./publishing-types.js";
2
3
  /** How a workspace was made: a layer on a shared template, a block clone, or every file written. */
3
4
  export type StrategyName = "overlay" | "reflink" | "copy";
4
5
  /** Where a workspace ended up. */
@@ -8,7 +9,7 @@ export interface Workspace {
8
9
  /** The branch it follows; empty when detached at a commit. */
9
10
  branch: string;
10
11
  strategy: StrategyName;
11
- /** An overlay workspace's template (lower) and its own layer (upper, work). */
12
+ /** An overlay workspace's template (lower), its own layer (upper, work), and its warm layer. */
12
13
  layers?: Layers;
13
14
  /** Submodules that could not be checked out, and why. */
14
15
  pendingSubmodules: PendingSubmodule[];
@@ -19,6 +20,21 @@ export interface Layers {
19
20
  lower: string;
20
21
  upper: string;
21
22
  work: string;
23
+ /** The warm layer between the template and its own, when it stands on one; else empty. */
24
+ warm: string;
25
+ }
26
+ /** A layer sealed from a workspace — what installing its dependencies wrote — for later ones to stand on. */
27
+ export interface WarmLayer {
28
+ url: string;
29
+ name: string;
30
+ /** Workspaces stand on it at this commit only. */
31
+ commit: string;
32
+ sealedAt: Date;
33
+ sealedFrom: string;
34
+ /** Files it changes that git does not ignore, e.g. a lock file rewritten. */
35
+ changedFiles: number;
36
+ /** Workspaces standing on it now. */
37
+ users: number;
22
38
  }
23
39
  export interface PendingSubmodule {
24
40
  path: string;
@@ -43,10 +59,20 @@ export interface Submodule {
43
59
  commit: string;
44
60
  checkedOut: boolean;
45
61
  }
46
- /** What a publish pushed: the workspace's repository first, then each submodule. */
62
+ /** Why gitd refused something: its reason (POLICY_REFUSED, AUTH_REQUIRED, …) and what was said. */
63
+ export interface Refusal {
64
+ reason: string;
65
+ said: string;
66
+ }
67
+ /**
68
+ * What a publish pushed: the workspace's repository first, then each submodule; the pull
69
+ * request it opened, or why it could not, the branch being published either way.
70
+ */
47
71
  export interface Published {
48
72
  branch: string;
49
73
  repositories: PublishedRepository[];
74
+ pullRequest?: OpenedPullRequest;
75
+ pullRequestRefused?: Refusal;
50
76
  }
51
77
  export interface PublishedRepository {
52
78
  url: string;
@@ -56,6 +82,70 @@ export interface PublishedRepository {
56
82
  /** The subjects of the new commits, newest first. */
57
83
  subjects: string[];
58
84
  }
85
+ /** How a file changed. */
86
+ export type ChangeKind = "added" | "modified" | "deleted";
87
+ /** A file changed, relative to the workspace, with its lines; a binary one counts none. */
88
+ export interface ChangedFile {
89
+ path: string;
90
+ kind: ChangeKind;
91
+ addedLines: number;
92
+ removedLines: number;
93
+ binary: boolean;
94
+ }
95
+ /** What was changed in a workspace since gitd put it on `base`, committed or not. */
96
+ export interface Changes {
97
+ base: string;
98
+ /** Read from the agent's own layer, with no git run in the workspace. */
99
+ fromLayer: boolean;
100
+ files: ChangedFile[];
101
+ }
102
+ /** The unified diff of a workspace's changes. */
103
+ export interface Diff {
104
+ base: string;
105
+ diff: string;
106
+ /** Cut short at maxBytes. */
107
+ truncated: boolean;
108
+ }
109
+ export interface DiffOptions {
110
+ /** Only these files, relative to the workspace. */
111
+ files?: string[];
112
+ /** At most this many bytes: 512 KiB by default, never more than 8 MiB. */
113
+ maxBytes?: number;
114
+ includeIgnored?: boolean;
115
+ }
116
+ /** One work: a workspace by its path, or a branch gitd published or its pool holds. */
117
+ export type Side = {
118
+ workspace: string;
119
+ } | {
120
+ branch: string;
121
+ };
122
+ export interface CompareOptions {
123
+ /** The repository, when both sides are branches. */
124
+ url?: string;
125
+ withDiff?: boolean;
126
+ maxBytes?: number;
127
+ includeIgnored?: boolean;
128
+ }
129
+ /** How two works differ, from the first to the second. */
130
+ export interface Comparison {
131
+ files: ChangedFile[];
132
+ diff: string;
133
+ truncated: boolean;
134
+ }
135
+ /** Two works that do not merge cleanly, and the files they conflict on. */
136
+ export interface Conflict {
137
+ first: Side;
138
+ second: Side;
139
+ paths: string[];
140
+ }
141
+ /** What happened to a workspace. */
142
+ export interface WorkspaceEvent {
143
+ kind: "made" | "changed" | "published" | "refused" | "removed";
144
+ path: string;
145
+ time: Date;
146
+ branch: string;
147
+ detail: string;
148
+ }
59
149
  /** Which gitd answers, and how it makes workspaces on its machine. */
60
150
  export interface Info {
61
151
  version: string;
@@ -76,7 +166,15 @@ export interface Probe {
76
166
  /** Why it cannot be read, when denied. */
77
167
  denied?: string;
78
168
  }
79
- /** One publish, done or refused, as the audit log keeps it. */
169
+ /** A change to the credentials or publishing settings, as the audit log keeps it. */
170
+ export interface ConfigurationChange {
171
+ /** connection_added, connection_removed, settings_set or settings_removed. */
172
+ action: string;
173
+ /** The credential's id, or the settings' prefix. */
174
+ subject: string;
175
+ urlPrefix: string;
176
+ }
177
+ /** One publish, done or refused, or one change to credentials or settings, as the audit log keeps it. */
80
178
  export interface AuditEntry {
81
179
  time: Date;
82
180
  /** The workspace's path, as the caller gave it. */
@@ -87,10 +185,13 @@ export interface AuditEntry {
87
185
  /** What was pushed, the workspace's repository first; empty when refused. */
88
186
  repositories: PublishedRepository[];
89
187
  /** Why it was refused, when it was. */
90
- refused?: {
91
- reason: string;
92
- said: string;
93
- };
188
+ refused?: Refusal;
189
+ /** Who asked for the work, as the publish said. */
190
+ requestedBy: string;
191
+ pullRequest?: OpenedPullRequest;
192
+ pullRequestRefused?: Refusal;
193
+ change?: ConfigurationChange;
194
+ provenance?: Provenance;
94
195
  }
95
196
  export interface AuditOptions {
96
197
  /** Only the publishes from this time on. */
@@ -115,6 +216,11 @@ export interface PrepareOptions extends Progressing {
115
216
  fullHistory?: boolean;
116
217
  /** A preference; gitd falls back to copy when it cannot run here. */
117
218
  strategy?: StrategyName;
219
+ /**
220
+ * A warm layer to stand on, its dependencies installed already: the workspace is then made
221
+ * by overlay, at the commit the layer was sealed at, or not at all.
222
+ */
223
+ warm?: string;
118
224
  }
119
225
  export interface UpdateOptions extends Progressing {
120
226
  /** The branch to follow; default: the one it follows. */
@@ -0,0 +1,4 @@
1
+ import type { WarmLayer as WarmLayerMessage } from "./gen/gitd/v1/gitd_pb.js";
2
+ import type { WarmLayer } from "./types.js";
3
+ /** A warm layer as gitd answers it, read as this client's. */
4
+ export declare function toWarmLayer(warm: WarmLayerMessage | undefined): WarmLayer;
@@ -0,0 +1,12 @@
1
+ /** A warm layer as gitd answers it, read as this client's. */
2
+ export function toWarmLayer(warm) {
3
+ return {
4
+ url: warm?.url ?? "",
5
+ name: warm?.name ?? "",
6
+ commit: warm?.commit ?? "",
7
+ sealedAt: new Date(Number(warm?.sealedAt ?? 0n) * 1000),
8
+ sealedFrom: warm?.sealedFrom ?? "",
9
+ changedFiles: warm?.changedFiles ?? 0,
10
+ users: warm?.users ?? 0,
11
+ };
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitd-client",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Client for gitd: instant, secretless git checkouts for agent sandboxes",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {