@gaia-ai/gaia 0.2.0 → 0.4.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.
Files changed (52) hide show
  1. package/bin/gaia +1 -1
  2. package/dist/src/plugins-barrel.d.ts +1 -0
  3. package/dist/src/plugins-barrel.js +1 -0
  4. package/package.json +10 -16
  5. package/dist/src/cli/gaia.d.ts +0 -24
  6. package/dist/src/cli/gaia.js +0 -572
  7. package/dist/src/cli/init.d.ts +0 -74
  8. package/dist/src/cli/init.js +0 -220
  9. package/dist/src/cli/local-registry.d.ts +0 -14
  10. package/dist/src/cli/local-registry.js +0 -56
  11. package/dist/src/config.d.ts +0 -13
  12. package/dist/src/config.js +0 -186
  13. package/dist/src/core/conductor-id.d.ts +0 -1
  14. package/dist/src/core/conductor-id.js +0 -8
  15. package/dist/src/core/conductor.d.ts +0 -47
  16. package/dist/src/core/conductor.js +0 -287
  17. package/dist/src/core/exec.d.ts +0 -33
  18. package/dist/src/core/exec.js +0 -65
  19. package/dist/src/core/logger.d.ts +0 -31
  20. package/dist/src/core/logger.js +0 -36
  21. package/dist/src/core/slug.d.ts +0 -9
  22. package/dist/src/core/slug.js +0 -18
  23. package/dist/src/index.d.ts +0 -16
  24. package/dist/src/index.js +0 -9
  25. package/dist/src/plugin-api.d.ts +0 -7
  26. package/dist/src/plugin-api.js +0 -3
  27. package/dist/src/plugins/agent/agent.d.ts +0 -20
  28. package/dist/src/plugins/agent/agent.js +0 -1
  29. package/dist/src/plugins/auth/basic.d.ts +0 -11
  30. package/dist/src/plugins/auth/basic.js +0 -35
  31. package/dist/src/plugins/executor/executor.d.ts +0 -61
  32. package/dist/src/plugins/executor/executor.js +0 -1
  33. package/dist/src/plugins/plugins.d.ts +0 -38
  34. package/dist/src/plugins/plugins.js +0 -16
  35. package/dist/src/plugins/registry-exports.d.ts +0 -6
  36. package/dist/src/plugins/registry-exports.js +0 -6
  37. package/dist/src/plugins/remote/drupal.d.ts +0 -47
  38. package/dist/src/plugins/remote/drupal.js +0 -337
  39. package/dist/src/plugins/remote/fake.d.ts +0 -81
  40. package/dist/src/plugins/remote/fake.js +0 -203
  41. package/dist/src/plugins/remote/remote.d.ts +0 -143
  42. package/dist/src/plugins/remote/remote.js +0 -1
  43. package/dist/src/plugins/workspace/fake.d.ts +0 -9
  44. package/dist/src/plugins/workspace/fake.js +0 -19
  45. package/dist/src/plugins/workspace/git.d.ts +0 -53
  46. package/dist/src/plugins/workspace/git.js +0 -113
  47. package/dist/src/plugins/workspace/instructions.d.ts +0 -6
  48. package/dist/src/plugins/workspace/instructions.js +0 -16
  49. package/dist/src/plugins/workspace/workspace.d.ts +0 -33
  50. package/dist/src/plugins/workspace/workspace.js +0 -1
  51. package/dist/src/types.d.ts +0 -51
  52. package/dist/src/types.js +0 -1
@@ -1,38 +0,0 @@
1
- import type { DropSHPlugin } from 'dropsh/plugin';
2
- import type { ConductorFileConfig } from '../types.js';
3
- import type { GaiaAgent } from './agent/agent.js';
4
- import type { GaiaExecutor } from './executor/executor.js';
5
- import type { GaiaRemote } from './remote/remote.js';
6
- import type { GaiaWorkspace } from './workspace/workspace.js';
7
- export interface RemotePlugin extends DropSHPlugin {
8
- readonly kind: 'remote';
9
- readonly id: string;
10
- readonly requiredModules: string[];
11
- createRemote(config: ConductorFileConfig): Promise<GaiaRemote>;
12
- }
13
- export interface ExecutorPlugin extends DropSHPlugin {
14
- readonly kind: 'executor';
15
- readonly id: string;
16
- readonly requiredModules: string[];
17
- createExecutor(config: ConductorFileConfig): Promise<GaiaExecutor>;
18
- }
19
- export interface WorkspacePlugin extends DropSHPlugin {
20
- readonly kind: 'workspace';
21
- readonly id: string;
22
- readonly requiredModules: string[];
23
- createWorkspace(config: ConductorFileConfig): Promise<GaiaWorkspace>;
24
- }
25
- export interface AgentPlugin extends DropSHPlugin {
26
- readonly kind: 'agent';
27
- readonly id: string;
28
- readonly requiredModules: string[];
29
- createAgent(config: ConductorFileConfig): Promise<GaiaAgent>;
30
- }
31
- /** Resolves the remote from its named config slot. */
32
- export declare function selectRemote(config: ConductorFileConfig): Promise<GaiaRemote>;
33
- /** Resolves the executor from its named config slot. */
34
- export declare function selectExecutor(config: ConductorFileConfig): Promise<GaiaExecutor>;
35
- /** Resolves the workspace from its named config slot. */
36
- export declare function selectWorkspace(config: ConductorFileConfig): Promise<GaiaWorkspace>;
37
- /** Resolves the agent from its named config slot. */
38
- export declare function selectAgent(config: ConductorFileConfig): Promise<GaiaAgent>;
@@ -1,16 +0,0 @@
1
- /** Resolves the remote from its named config slot. */
2
- export async function selectRemote(config) {
3
- return config.remote.createRemote(config);
4
- }
5
- /** Resolves the executor from its named config slot. */
6
- export async function selectExecutor(config) {
7
- return config.executor.createExecutor(config);
8
- }
9
- /** Resolves the workspace from its named config slot. */
10
- export async function selectWorkspace(config) {
11
- return config.workspace.createWorkspace(config);
12
- }
13
- /** Resolves the agent from its named config slot. */
14
- export async function selectAgent(config) {
15
- return config.agent.createAgent(config);
16
- }
@@ -1,6 +0,0 @@
1
- export { basicAuthProvider } from './auth/basic.js';
2
- export { selectAgent, selectExecutor, selectRemote, selectWorkspace, } from './plugins.js';
3
- export { DrupalGaiaRemote, drupalRemote } from './remote/drupal.js';
4
- export { FakeGaiaRemote, fakeRemote } from './remote/fake.js';
5
- export { FakeWorkspace, fakeWorkspace } from './workspace/fake.js';
6
- export { GitWorkspace, gitWorkspace } from './workspace/git.js';
@@ -1,6 +0,0 @@
1
- export { basicAuthProvider } from './auth/basic.js';
2
- export { selectAgent, selectExecutor, selectRemote, selectWorkspace, } from './plugins.js';
3
- export { DrupalGaiaRemote, drupalRemote } from './remote/drupal.js';
4
- export { FakeGaiaRemote, fakeRemote } from './remote/fake.js';
5
- export { FakeWorkspace, fakeWorkspace } from './workspace/fake.js';
6
- export { GitWorkspace, gitWorkspace } from './workspace/git.js';
@@ -1,47 +0,0 @@
1
- import type { JsonApiClient } from 'dropsh/plugin';
2
- import type { RemotePlugin } from '../plugins.js';
3
- import type { ActiveRun, ClaimedRun, ClaimOptions, ConductorRegistration, ConductorStatus, FinalizableRun, FinalizableTicket, GaiaRemote, RunWriteAttributes, Ticket, TicketComment } from './remote.js';
4
- interface JsonApiResource {
5
- type?: string;
6
- id?: string;
7
- attributes?: Record<string, unknown>;
8
- }
9
- /**
10
- * Extracts gaia_comment resources from a JSON:API `included` array into
11
- * conductor-facing TicketComments. JSON:API renames the comment entity's `type`
12
- * field to `gaia_comment_type` (the bare `type` is the reserved resource type),
13
- * and serialises the text_long `body` as `{value, format, processed}`. Resources
14
- * of other types are ignored; the server already returns them created-ASC.
15
- */
16
- export declare function parseTicketComments(included: JsonApiResource[] | undefined): TicketComment[];
17
- export declare class DrupalGaiaRemote implements GaiaRemote {
18
- private readonly api;
19
- constructor(api: JsonApiClient);
20
- fetchActiveRuns(id: string): Promise<ActiveRun[]>;
21
- activeRunCount(id: string): Promise<number>;
22
- claimNext(c: ClaimOptions): Promise<ClaimedRun | null>;
23
- getTicket(uuid: string): Promise<Ticket>;
24
- getRunWorktree(uuid: string): Promise<string>;
25
- getRunTicketIdentifier(uuid: string): Promise<string>;
26
- getRunTicketBranchName(uuid: string): Promise<string>;
27
- registerConductor(reg: ConductorRegistration): Promise<string>;
28
- heartbeat(reg: ConductorRegistration, load: number, lease?: number): Promise<string>;
29
- getConductorStatus(id: string): Promise<string | null>;
30
- setConductorStatus(id: string, status: string): Promise<void>;
31
- listConductors(owner?: 'me'): Promise<ConductorStatus[]>;
32
- markRunning(uuid: string, attrs?: RunWriteAttributes): Promise<void>;
33
- fetchFinalizableRuns(id: string): Promise<FinalizableRun[]>;
34
- finalizeRun(uuid: string, log: string): Promise<void>;
35
- fetchFinalizableTickets(id: string): Promise<FinalizableTicket[]>;
36
- closeTicket(uuid: string): Promise<void>;
37
- /**
38
- * Absolute worktree path of the ticket's latest run (highest run id with a
39
- * non-empty worktree_path), or '' when none — the cwd the cleanup command
40
- * runs in. The conductor persists worktree_path on markRunning, so a done
41
- * ticket's run carries the path even after the run closed.
42
- */
43
- private latestRunWorktree;
44
- private projectUuid;
45
- }
46
- export declare function drupalRemote(): RemotePlugin;
47
- export {};
@@ -1,337 +0,0 @@
1
- import { resolveAuth } from 'dropsh';
2
- import { createHttpClient, createJsonApiClient } from 'dropsh/plugin';
3
- const ACTIVE = ['claimed', 'running'];
4
- /**
5
- * Extracts gaia_comment resources from a JSON:API `included` array into
6
- * conductor-facing TicketComments. JSON:API renames the comment entity's `type`
7
- * field to `gaia_comment_type` (the bare `type` is the reserved resource type),
8
- * and serialises the text_long `body` as `{value, format, processed}`. Resources
9
- * of other types are ignored; the server already returns them created-ASC.
10
- */
11
- export function parseTicketComments(included) {
12
- if (!Array.isArray(included)) {
13
- return [];
14
- }
15
- const comments = [];
16
- for (const res of included) {
17
- if (res?.type !== 'gaia_comment--gaia_comment') {
18
- continue;
19
- }
20
- const attrs = res.attributes ?? {};
21
- const body = attrs.body;
22
- const value = typeof body === 'string'
23
- ? body
24
- : typeof body?.value === 'string'
25
- ? body.value
26
- : '';
27
- comments.push({
28
- type: typeof attrs.gaia_comment_type === 'string'
29
- ? attrs.gaia_comment_type
30
- : 'comment',
31
- body: value,
32
- created: typeof attrs.created === 'string' ? attrs.created : '',
33
- });
34
- }
35
- return comments;
36
- }
37
- export class DrupalGaiaRemote {
38
- api;
39
- constructor(api) {
40
- this.api = api;
41
- }
42
- async fetchActiveRuns(id) {
43
- // The conductor identity `id` is the machine_id (hash of hostname+path).
44
- // gaia_run links to its owning conductor via the `conductor_id` entity-ref;
45
- // filter on the related conductor's `machine_id` (nested relationship filter).
46
- const rows = await this.api
47
- .collection('gaia_run')
48
- .where('conductor_id.machine_id', '=', id)
49
- .whereIn('state', ACTIVE)
50
- .fields(['state', 'state_at_start', 'worktree_path'])
51
- .page(100)
52
- .list();
53
- return Promise.all(rows.map(async (r) => ({
54
- runUuid: r.id,
55
- ticketUuid: r.rel('ticket_id') ?? '',
56
- ticketIdentifier: await this.getRunTicketIdentifier(r.id),
57
- branchName: await this.getRunTicketBranchName(r.id),
58
- state: r.attr('state') ?? '',
59
- stateAtStart: r.attr('state_at_start') ?? '',
60
- worktreePath: r.attr('worktree_path') ?? '',
61
- })));
62
- }
63
- async activeRunCount(id) {
64
- // Filter on the related conductor's `machine_id` (nested relationship filter).
65
- return this.api
66
- .collection('gaia_run')
67
- .where('conductor_id.machine_id', '=', id)
68
- .whereIn('state', ACTIVE)
69
- .fields(['drupal_internal__id'])
70
- .page(100)
71
- .count();
72
- }
73
- async claimNext(c) {
74
- const res = (await this.api.post('gaia/claim-next', {
75
- data: {
76
- attributes: {
77
- lease_seconds: c.leaseSeconds,
78
- // Server (`ConductorResolverTrait`) narrows to the caller's conductor
79
- // by the `machine_id` attribute; `c.conductorId` IS the machine_id.
80
- machine_id: c.conductorId,
81
- },
82
- },
83
- }));
84
- if (!res?.data) {
85
- return null;
86
- }
87
- const d = res.data;
88
- const rawId = d.attributes?.drupal_internal__id;
89
- if (rawId === undefined || rawId === null) {
90
- throw new Error(`claimNext: missing drupal_internal__id on run ${d.id}`);
91
- }
92
- return {
93
- runUuid: d.id,
94
- runId: Number(rawId),
95
- ticketUuid: d.relationships?.ticket_id?.data?.id ?? '',
96
- stateAtStart: String(d.attributes?.state_at_start ?? ''),
97
- // handler_id was dropped; the handler is the work the run does, i.e. the
98
- // ticket state the run started in.
99
- handler: String(d.attributes?.state_at_start ?? ''),
100
- };
101
- }
102
- async getTicket(uuid) {
103
- // `?include=comments` sideloads the ticket's comments in one request so the
104
- // conductor can render them into the dispatch prompt (review→coding bounce
105
- // must carry the review summary to the coder). `comments` is a computed
106
- // entity_reference field (CommentsItemList, ordered created ASC), so the
107
- // included resources arrive oldest-first. We use the raw client here rather
108
- // than `resource()` because `resource()` discards the `included` array.
109
- const doc = (await this.api.get(`gaia_ticket/gaia_ticket/${uuid}?include=comments`));
110
- const attrs = doc.data?.attributes ?? {};
111
- const issueUrl = typeof attrs.origin === 'string' ? attrs.origin : undefined;
112
- return {
113
- uuid: doc.data?.id ?? uuid,
114
- identifier: typeof attrs.identifier === 'string' ? attrs.identifier : uuid,
115
- title: typeof attrs.title === 'string' ? attrs.title : '',
116
- state: typeof attrs.state === 'string' ? attrs.state : '',
117
- branchName: typeof attrs.branch_name === 'string' ? attrs.branch_name : '',
118
- ...(typeof attrs.base_branch === 'string' && attrs.base_branch !== ''
119
- ? { baseBranch: attrs.base_branch }
120
- : {}),
121
- comments: parseTicketComments(doc.included),
122
- ...(issueUrl ? { issueUrl } : {}),
123
- };
124
- }
125
- async getRunWorktree(uuid) {
126
- const r = await this.api.resource('gaia_run', uuid);
127
- return r.attr('worktree_path') ?? '';
128
- }
129
- async getRunTicketIdentifier(uuid) {
130
- const run = await this.api.resource('gaia_run', uuid);
131
- const ticketUuid = run.rel('ticket_id');
132
- if (!ticketUuid) {
133
- return '';
134
- }
135
- const ticket = await this.api.resource('gaia_ticket', ticketUuid);
136
- return ticket.attr('identifier') ?? '';
137
- }
138
- async getRunTicketBranchName(uuid) {
139
- const run = await this.api.resource('gaia_run', uuid);
140
- const ticketUuid = run.rel('ticket_id');
141
- if (!ticketUuid) {
142
- return '';
143
- }
144
- const ticket = await this.api.resource('gaia_ticket', ticketUuid);
145
- return ticket.attr('branch_name') ?? '';
146
- }
147
- async registerConductor(reg) {
148
- const r = await this.api.upsert('gaia_conductor', { path: 'machine_id', value: reg.id }, {
149
- attributes: {
150
- machine_id: reg.id,
151
- status: 'online',
152
- workspace_root: reg.workspace,
153
- label: reg.label,
154
- states: reg.states,
155
- max_parallel: reg.max_parallel,
156
- },
157
- relationships: {
158
- owner_user_id: {
159
- data: { type: 'user--user', id: await this.api.me() },
160
- },
161
- project_id: {
162
- data: {
163
- type: 'gaia_project--gaia_project',
164
- id: await this.projectUuid(reg.project),
165
- },
166
- },
167
- },
168
- });
169
- return r.id; // drupal uuid
170
- }
171
- async heartbeat(reg, load, lease = 300) {
172
- // Server-side upsert by machine_id (see HeartbeatResource): never 404s,
173
- // heals a vanished registration, and returns the resulting status. Sending
174
- // the full registration lets the server recreate the entity when missing.
175
- const res = (await this.api.post('gaia/heartbeat', {
176
- data: {
177
- attributes: {
178
- machine_id: reg.id,
179
- project: reg.project,
180
- states: reg.states,
181
- workspace_root: reg.workspace,
182
- label: reg.label,
183
- max_parallel: reg.max_parallel,
184
- current_load: load,
185
- lease_seconds: lease,
186
- },
187
- },
188
- }));
189
- const status = res?.data?.attributes?.status;
190
- return typeof status === 'string' ? status : 'online';
191
- }
192
- async getConductorStatus(id) {
193
- const c = await this.api
194
- .collection('gaia_conductor')
195
- .where('machine_id', '=', id)
196
- .fields(['status'])
197
- .first();
198
- return c ? (c.attr('status') ?? null) : null;
199
- }
200
- async setConductorStatus(id, status) {
201
- const c = await this.api
202
- .collection('gaia_conductor')
203
- .where('machine_id', '=', id)
204
- .first();
205
- if (c) {
206
- await this.api.update('gaia_conductor', c.id, { attributes: { status } });
207
- }
208
- }
209
- async listConductors(owner) {
210
- let col = this.api.collection('gaia_conductor');
211
- if (owner === 'me') {
212
- col = col.where('owner_user_id.id', '=', await this.api.me());
213
- }
214
- const rows = await col.page(200).list();
215
- return rows.map((r) => ({
216
- id: r.attr('machine_id') ?? r.id,
217
- project: '',
218
- label: r.attr('label') ?? '',
219
- status: r.attr('status') ?? '',
220
- lastSeen: r.attr('last_seen') ?? 0,
221
- load: r.attr('current_load') ?? 0,
222
- }));
223
- }
224
- async markRunning(uuid, attrs) {
225
- const t = Math.floor(Date.now() / 1000);
226
- await this.api.update('gaia_run', uuid, {
227
- attributes: {
228
- state: 'running',
229
- heartbeat: t,
230
- ...(attrs?.worktree_path ? { worktree_path: attrs.worktree_path } : {}),
231
- },
232
- });
233
- }
234
- async fetchFinalizableRuns(id) {
235
- const rows = await this.api
236
- .collection('gaia_run')
237
- .where('conductor_id.machine_id', '=', id)
238
- .where('state', '=', 'done')
239
- .where('closed', '=', '0')
240
- .fields(['worktree_path'])
241
- .page(100)
242
- .list();
243
- return rows.map((r) => ({
244
- runUuid: r.id,
245
- worktreePath: r.attr('worktree_path') ?? '',
246
- }));
247
- }
248
- async finalizeRun(uuid, log) {
249
- const t = Math.floor(Date.now() / 1000);
250
- await this.api.update('gaia_run', uuid, {
251
- attributes: {
252
- closed: true,
253
- closed_date: t,
254
- ...(log ? { log } : {}),
255
- },
256
- }); // NO state — the run is already done.
257
- }
258
- async fetchFinalizableTickets(id) {
259
- // Symmetric to fetchFinalizableRuns, on the ticket axis: this conductor's
260
- // tickets that reached done but were never closed. Nested relationship
261
- // filter on the owning conductor's machine_id (`id` IS the machine_id).
262
- const rows = await this.api
263
- .collection('gaia_ticket')
264
- .where('conductor_id.machine_id', '=', id)
265
- .where('state', '=', 'done')
266
- .where('closed', '=', '0')
267
- .fields(['branch_name'])
268
- .page(100)
269
- .list();
270
- return Promise.all(rows.map(async (r) => ({
271
- ticketUuid: r.id,
272
- branchName: r.attr('branch_name') ?? '',
273
- worktreePath: await this.latestRunWorktree(r.id),
274
- })));
275
- }
276
- async closeTicket(uuid) {
277
- const t = Math.floor(Date.now() / 1000);
278
- await this.api.update('gaia_ticket', uuid, {
279
- attributes: { closed: true, closed_date: t },
280
- }); // NO state — the ticket is already done.
281
- }
282
- /**
283
- * Absolute worktree path of the ticket's latest run (highest run id with a
284
- * non-empty worktree_path), or '' when none — the cwd the cleanup command
285
- * runs in. The conductor persists worktree_path on markRunning, so a done
286
- * ticket's run carries the path even after the run closed.
287
- */
288
- async latestRunWorktree(ticketUuid) {
289
- const rows = await this.api
290
- .collection('gaia_run')
291
- .where('ticket_id.id', '=', ticketUuid)
292
- .fields(['worktree_path', 'drupal_internal__id'])
293
- .sort('-drupal_internal__id')
294
- .page(100)
295
- .list();
296
- for (const r of rows) {
297
- const path = r.attr('worktree_path');
298
- if (path) {
299
- return path;
300
- }
301
- }
302
- return '';
303
- }
304
- async projectUuid(name) {
305
- const p = await this.api
306
- .collection('gaia_project')
307
- .where('name', '=', name)
308
- .first();
309
- if (!p) {
310
- throw new Error(`gaia project "${name}" not found`);
311
- }
312
- return p.id;
313
- }
314
- }
315
- export function drupalRemote() {
316
- return {
317
- kind: 'remote',
318
- id: 'drupal',
319
- requiredModules: [],
320
- async createRemote(config) {
321
- const http = createHttpClient();
322
- const auth = await resolveAuth({
323
- baseUrl: config.site.base_url,
324
- plugins: config.plugins ?? [],
325
- http,
326
- now: Date.now,
327
- // stateDir omitted → dropsh defaultStateDir() (~/.config/dropsh)
328
- });
329
- return new DrupalGaiaRemote(createJsonApiClient({
330
- baseUrl: config.site.base_url,
331
- prefix: config.site.jsonapi_prefix,
332
- http,
333
- auth: auth,
334
- }));
335
- },
336
- };
337
- }
@@ -1,81 +0,0 @@
1
- import type { RemotePlugin } from '../plugins.js';
2
- import type { ActiveRun, ClaimedRun, ClaimOptions, ConductorRegistration, ConductorStatus, FinalizableRun, FinalizableTicket, GaiaRemote, RunWriteAttributes, Ticket, TicketComment } from './remote.js';
3
- export interface FakeSeedRun {
4
- runUuid: string;
5
- /** Numeric (drupal_internal__id) run id. Defaults to a stable 1-based counter when omitted. */
6
- id?: number;
7
- ticketUuid: string;
8
- stateAtStart: string;
9
- /** Override the initial state (defaults to stateAtStart). */
10
- state?: string;
11
- handler?: string;
12
- worktreePath?: string;
13
- closed?: boolean;
14
- }
15
- export interface FakeSeedTicket {
16
- identifier: string;
17
- title: string;
18
- state: string;
19
- branchName?: string;
20
- /** Computed base branch (parent branch / project default / 'main'). */
21
- baseBranch?: string;
22
- url?: string;
23
- workflow?: string;
24
- comments?: TicketComment[];
25
- /** Whether the ticket is already closed (excluded from the cleanup query). */
26
- closed?: boolean;
27
- }
28
- export interface FakeRemoteSeed {
29
- runs?: FakeSeedRun[];
30
- tickets?: Record<string, FakeSeedTicket>;
31
- }
32
- export interface MarkRunningCall {
33
- runUuid: string;
34
- attrs?: {
35
- worktree_path?: string;
36
- };
37
- }
38
- export interface FinalizeRunCall {
39
- runUuid: string;
40
- log: string;
41
- }
42
- export declare class FakeGaiaRemote implements GaiaRemote {
43
- readonly calls: {
44
- markRunning: MarkRunningCall[];
45
- finalizeRun: FinalizeRunCall[];
46
- closeTicket: string[];
47
- };
48
- /**
49
- * Override for reconcile tests: when set, `fetchActiveRuns` returns this
50
- * list verbatim instead of deriving it from the internal runs map.
51
- */
52
- activeRuns: ActiveRun[] | null;
53
- private readonly runs;
54
- private readonly queue;
55
- private readonly tickets;
56
- private conductorStatus;
57
- /** Stable counter for assigning numeric ids to unseeded runs. */
58
- private runIdCounter;
59
- constructor(seed?: FakeRemoteSeed);
60
- registerConductor(_reg: ConductorRegistration): Promise<string>;
61
- heartbeat(): Promise<string>;
62
- getConductorStatus(_conductorId: string): Promise<string | null>;
63
- setConductorStatus(_conductorId: string, status: 'offline' | 'online'): Promise<void>;
64
- listConductors(_owner?: 'me'): Promise<ConductorStatus[]>;
65
- activeRunCount(_conductorId: string): Promise<number>;
66
- fetchActiveRuns(_conductorId: string): Promise<ActiveRun[]>;
67
- claimNext(_claim: ClaimOptions): Promise<ClaimedRun | null>;
68
- getTicket(ticketUuid: string): Promise<Ticket>;
69
- getRunWorktree(runUuid: string): Promise<string>;
70
- getRunTicketIdentifier(runUuid: string): Promise<string>;
71
- getRunTicketBranchName(runUuid: string): Promise<string>;
72
- markRunning(runUuid: string, attrs?: RunWriteAttributes): Promise<void>;
73
- fetchFinalizableRuns(_conductorId: string): Promise<FinalizableRun[]>;
74
- finalizeRun(runUuid: string, log: string): Promise<void>;
75
- fetchFinalizableTickets(_conductorId: string): Promise<FinalizableTicket[]>;
76
- closeTicket(uuid: string): Promise<void>;
77
- /** Worktree path of the ticket's most recently seeded run, or '' when none. */
78
- private latestRunWorktree;
79
- private internalActiveRuns;
80
- }
81
- export declare function fakeRemote(seed?: FakeRemoteSeed): RemotePlugin;