@gaia-ai/conductor 0.11.1 → 0.11.2
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.
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/** The global install target on npm (the meta package). */
|
|
2
|
+
export declare const GAIA_PACKAGE = "@gaia-ai/gaia";
|
|
3
|
+
/** The npm registry endpoint for the latest published version. */
|
|
4
|
+
export declare const REGISTRY_LATEST_URL = "https://registry.npmjs.org/@gaia-ai/gaia/latest";
|
|
5
|
+
/**
|
|
6
|
+
* The sentinel returned when the installed version cannot be resolved (the
|
|
7
|
+
* package.json walk failed). Never a real published release, so callers treat
|
|
8
|
+
* it as "unknown" and suppress the update notice rather than nagging.
|
|
9
|
+
*/
|
|
10
|
+
export declare const UNKNOWN_VERSION = "0.0.0";
|
|
11
|
+
/**
|
|
12
|
+
* The currently installed CLI version. Walks up from this module to the nearest
|
|
13
|
+
* @gaia-ai/conductor package.json so it resolves both from the compiled
|
|
14
|
+
* dist/src/cli/version-check.js and from a vitest src run. Same release tag
|
|
15
|
+
* across packages ⇒ == @gaia-ai/gaia. Memoized — the version cannot change
|
|
16
|
+
* within a process, so the walk runs at most once (finding #6).
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveCliVersion(): string;
|
|
19
|
+
/**
|
|
20
|
+
* Fetch the latest published version of @gaia-ai/gaia from the npm registry.
|
|
21
|
+
* Bounded by an AbortController timeout; NEVER throws — any failure (network,
|
|
22
|
+
* non-2xx, timeout, malformed JSON, missing field) resolves to null so the
|
|
23
|
+
* caller can treat the check as best-effort (AC-4). fetchImpl is injectable so
|
|
24
|
+
* tests run without network.
|
|
25
|
+
*/
|
|
26
|
+
export declare function fetchLatestVersion(fetchImpl?: typeof fetch, timeoutMs?: number): Promise<string | null>;
|
|
27
|
+
/**
|
|
28
|
+
* A human-readable "update available" notice when `latest` is strictly newer
|
|
29
|
+
* than `current`, else null (already current or ahead — AC-5). Pure.
|
|
30
|
+
*/
|
|
31
|
+
export declare function updateNotice(current: string, latest: string): string | null;
|
|
32
|
+
/** Spawns a command, inheriting stdio, resolving to its exit code. */
|
|
33
|
+
export type SpawnUpdate = (cmd: string, args: string[]) => Promise<number>;
|
|
34
|
+
/** Spawns a command, capturing stdout, resolving to its exit code + stdout. */
|
|
35
|
+
export type SpawnCapture = (cmd: string, args: string[]) => Promise<{
|
|
36
|
+
code: number;
|
|
37
|
+
stdout: string;
|
|
38
|
+
}>;
|
|
39
|
+
/**
|
|
40
|
+
* Upgrade the globally installed gaia CLI to the latest published version via
|
|
41
|
+
* `npm install -g @gaia-ai/gaia@latest`. Reports the actual global version
|
|
42
|
+
* before and after the install (queried from npm, not from a separate registry
|
|
43
|
+
* fetch — finding #2), so the caller reports the real change: `before` is null
|
|
44
|
+
* when gaia was not installed globally, and no "upgraded" claim is made unless
|
|
45
|
+
* npm actually changed the on-disk version. On install failure `after` mirrors
|
|
46
|
+
* `before` and the post-install query is skipped. spawnImpl/captureImpl are
|
|
47
|
+
* injectable for tests.
|
|
48
|
+
*/
|
|
49
|
+
export declare function runUpdate(spawnImpl?: SpawnUpdate, captureImpl?: SpawnCapture): Promise<{
|
|
50
|
+
ok: boolean;
|
|
51
|
+
before: string | null;
|
|
52
|
+
after: string | null;
|
|
53
|
+
}>;
|
|
54
|
+
/**
|
|
55
|
+
* Print the installed gaia version line (AC-2), synchronously, and return it.
|
|
56
|
+
* Never blocks on the registry — the caller kicks off the newer-version check
|
|
57
|
+
* separately (see fetchUpdateNotice) so start is not stalled waiting on npm.
|
|
58
|
+
*/
|
|
59
|
+
export declare function printVersionLine(out?: (s: string) => void): string;
|
|
60
|
+
/**
|
|
61
|
+
* Best-effort "update available" notice for the given installed version
|
|
62
|
+
* (AC-3/AC-5). Fetches the latest published version (fail-silent → null on any
|
|
63
|
+
* error, AC-4) and compares. Returns the notice string or null. fetchImpl is
|
|
64
|
+
* injectable for tests.
|
|
65
|
+
*/
|
|
66
|
+
export declare function fetchUpdateNotice(current: string, fetchImpl?: typeof fetch): Promise<string | null>;
|
|
67
|
+
/**
|
|
68
|
+
* Print the installed gaia version (AC-2) and, best-effort, a newer-version
|
|
69
|
+
* notice (AC-3/AC-5). The registry check is fail-silent (AC-4): an offline
|
|
70
|
+
* registry prints only the version line. out/fetchImpl are injectable for tests.
|
|
71
|
+
*/
|
|
72
|
+
export declare function printStartVersionBanner(out?: (s: string) => void, fetchImpl?: typeof fetch): Promise<void>;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import semver from 'semver';
|
|
6
|
+
/** The global install target on npm (the meta package). */
|
|
7
|
+
export const GAIA_PACKAGE = '@gaia-ai/gaia';
|
|
8
|
+
/** The npm registry endpoint for the latest published version. */
|
|
9
|
+
export const REGISTRY_LATEST_URL = 'https://registry.npmjs.org/@gaia-ai/gaia/latest';
|
|
10
|
+
/**
|
|
11
|
+
* The sentinel returned when the installed version cannot be resolved (the
|
|
12
|
+
* package.json walk failed). Never a real published release, so callers treat
|
|
13
|
+
* it as "unknown" and suppress the update notice rather than nagging.
|
|
14
|
+
*/
|
|
15
|
+
export const UNKNOWN_VERSION = '0.0.0';
|
|
16
|
+
let cachedCliVersion;
|
|
17
|
+
/**
|
|
18
|
+
* The currently installed CLI version. Walks up from this module to the nearest
|
|
19
|
+
* @gaia-ai/conductor package.json so it resolves both from the compiled
|
|
20
|
+
* dist/src/cli/version-check.js and from a vitest src run. Same release tag
|
|
21
|
+
* across packages ⇒ == @gaia-ai/gaia. Memoized — the version cannot change
|
|
22
|
+
* within a process, so the walk runs at most once (finding #6).
|
|
23
|
+
*/
|
|
24
|
+
export function resolveCliVersion() {
|
|
25
|
+
if (cachedCliVersion !== undefined)
|
|
26
|
+
return cachedCliVersion;
|
|
27
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
for (let i = 0; i < 6; i++) {
|
|
29
|
+
try {
|
|
30
|
+
const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
|
|
31
|
+
if (pkg.name === '@gaia-ai/conductor') {
|
|
32
|
+
cachedCliVersion = pkg.version ?? UNKNOWN_VERSION;
|
|
33
|
+
return cachedCliVersion;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// no package.json here — keep walking up
|
|
38
|
+
}
|
|
39
|
+
dir = dirname(dir);
|
|
40
|
+
}
|
|
41
|
+
cachedCliVersion = UNKNOWN_VERSION;
|
|
42
|
+
return cachedCliVersion;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Fetch the latest published version of @gaia-ai/gaia from the npm registry.
|
|
46
|
+
* Bounded by an AbortController timeout; NEVER throws — any failure (network,
|
|
47
|
+
* non-2xx, timeout, malformed JSON, missing field) resolves to null so the
|
|
48
|
+
* caller can treat the check as best-effort (AC-4). fetchImpl is injectable so
|
|
49
|
+
* tests run without network.
|
|
50
|
+
*/
|
|
51
|
+
export async function fetchLatestVersion(fetchImpl = globalThis.fetch, timeoutMs = 1500) {
|
|
52
|
+
const controller = new AbortController();
|
|
53
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
54
|
+
try {
|
|
55
|
+
const res = await fetchImpl(REGISTRY_LATEST_URL, {
|
|
56
|
+
signal: controller.signal,
|
|
57
|
+
headers: { accept: 'application/json' },
|
|
58
|
+
});
|
|
59
|
+
if (!res.ok)
|
|
60
|
+
return null;
|
|
61
|
+
const body = (await res.json());
|
|
62
|
+
return typeof body.version === 'string' ? body.version : null;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
clearTimeout(timer);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* A human-readable "update available" notice when `latest` is strictly newer
|
|
73
|
+
* than `current`, else null (already current or ahead — AC-5). Pure.
|
|
74
|
+
*/
|
|
75
|
+
export function updateNotice(current, latest) {
|
|
76
|
+
// Unknown installed version ⇒ suppress the notice (finding #5): otherwise a
|
|
77
|
+
// failed package.json walk yields a perpetual bogus "0.0.0 → x.y.z" nag.
|
|
78
|
+
if (current === UNKNOWN_VERSION)
|
|
79
|
+
return null;
|
|
80
|
+
if (!semver.valid(current) || !semver.valid(latest))
|
|
81
|
+
return null;
|
|
82
|
+
if (!semver.gt(latest, current))
|
|
83
|
+
return null;
|
|
84
|
+
// Two distinct steps, apt-style: first get the newer CODE, then migrate the
|
|
85
|
+
// CONFIG. There is no `gaia update` command — the CLI is a global npm package,
|
|
86
|
+
// so code is updated via npm; `gaia upgrade` then migrates the config shape.
|
|
87
|
+
return (`A new gaia version is available: ${current} → ${latest}\n` +
|
|
88
|
+
'Run `npm install -g @gaia-ai/gaia@latest` to update the CLI, ' +
|
|
89
|
+
'then `gaia upgrade` to migrate your config.');
|
|
90
|
+
}
|
|
91
|
+
const defaultSpawn = (cmd, args) => new Promise((resolve) => {
|
|
92
|
+
const child = spawn(cmd, args, { stdio: 'inherit', shell: false });
|
|
93
|
+
child.on('error', () => resolve(1));
|
|
94
|
+
child.on('close', (code) => resolve(code ?? 1));
|
|
95
|
+
});
|
|
96
|
+
const defaultCapture = (cmd, args) => new Promise((resolve) => {
|
|
97
|
+
let stdout = '';
|
|
98
|
+
const child = spawn(cmd, args, {
|
|
99
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
100
|
+
shell: false,
|
|
101
|
+
});
|
|
102
|
+
child.stdout?.on('data', (chunk) => {
|
|
103
|
+
stdout += String(chunk);
|
|
104
|
+
});
|
|
105
|
+
child.on('error', () => resolve({ code: 1, stdout }));
|
|
106
|
+
child.on('close', (code) => resolve({ code: code ?? 1, stdout }));
|
|
107
|
+
});
|
|
108
|
+
/**
|
|
109
|
+
* The version of the globally installed @gaia-ai/gaia, read from
|
|
110
|
+
* `npm ls -g @gaia-ai/gaia --json`, or null when it is not installed globally /
|
|
111
|
+
* the output cannot be parsed. This reflects what npm actually has on disk —
|
|
112
|
+
* independent of the (possibly dev-shim) CLI running this process.
|
|
113
|
+
*/
|
|
114
|
+
async function queryGlobalVersion(captureImpl) {
|
|
115
|
+
try {
|
|
116
|
+
const { stdout } = await captureImpl('npm', [
|
|
117
|
+
'ls',
|
|
118
|
+
'-g',
|
|
119
|
+
GAIA_PACKAGE,
|
|
120
|
+
'--json',
|
|
121
|
+
'--depth',
|
|
122
|
+
'0',
|
|
123
|
+
]);
|
|
124
|
+
const parsed = JSON.parse(stdout);
|
|
125
|
+
const v = parsed.dependencies?.[GAIA_PACKAGE]?.version;
|
|
126
|
+
return typeof v === 'string' ? v : null;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Upgrade the globally installed gaia CLI to the latest published version via
|
|
134
|
+
* `npm install -g @gaia-ai/gaia@latest`. Reports the actual global version
|
|
135
|
+
* before and after the install (queried from npm, not from a separate registry
|
|
136
|
+
* fetch — finding #2), so the caller reports the real change: `before` is null
|
|
137
|
+
* when gaia was not installed globally, and no "upgraded" claim is made unless
|
|
138
|
+
* npm actually changed the on-disk version. On install failure `after` mirrors
|
|
139
|
+
* `before` and the post-install query is skipped. spawnImpl/captureImpl are
|
|
140
|
+
* injectable for tests.
|
|
141
|
+
*/
|
|
142
|
+
export async function runUpdate(spawnImpl = defaultSpawn, captureImpl = defaultCapture) {
|
|
143
|
+
const before = await queryGlobalVersion(captureImpl);
|
|
144
|
+
const code = await spawnImpl('npm', [
|
|
145
|
+
'install',
|
|
146
|
+
'-g',
|
|
147
|
+
`${GAIA_PACKAGE}@latest`,
|
|
148
|
+
]);
|
|
149
|
+
if (code !== 0)
|
|
150
|
+
return { ok: false, before, after: before };
|
|
151
|
+
const after = await queryGlobalVersion(captureImpl);
|
|
152
|
+
return { ok: true, before, after };
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Print the installed gaia version line (AC-2), synchronously, and return it.
|
|
156
|
+
* Never blocks on the registry — the caller kicks off the newer-version check
|
|
157
|
+
* separately (see fetchUpdateNotice) so start is not stalled waiting on npm.
|
|
158
|
+
*/
|
|
159
|
+
export function printVersionLine(out = console.log) {
|
|
160
|
+
const current = resolveCliVersion();
|
|
161
|
+
out(`gaia v${current}`);
|
|
162
|
+
return current;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Best-effort "update available" notice for the given installed version
|
|
166
|
+
* (AC-3/AC-5). Fetches the latest published version (fail-silent → null on any
|
|
167
|
+
* error, AC-4) and compares. Returns the notice string or null. fetchImpl is
|
|
168
|
+
* injectable for tests.
|
|
169
|
+
*/
|
|
170
|
+
export async function fetchUpdateNotice(current, fetchImpl = globalThis.fetch) {
|
|
171
|
+
const latest = await fetchLatestVersion(fetchImpl);
|
|
172
|
+
if (latest === null)
|
|
173
|
+
return null;
|
|
174
|
+
return updateNotice(current, latest);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Print the installed gaia version (AC-2) and, best-effort, a newer-version
|
|
178
|
+
* notice (AC-3/AC-5). The registry check is fail-silent (AC-4): an offline
|
|
179
|
+
* registry prints only the version line. out/fetchImpl are injectable for tests.
|
|
180
|
+
*/
|
|
181
|
+
export async function printStartVersionBanner(out = console.log, fetchImpl = globalThis.fetch) {
|
|
182
|
+
const current = printVersionLine(out);
|
|
183
|
+
const notice = await fetchUpdateNotice(current, fetchImpl);
|
|
184
|
+
if (notice !== null)
|
|
185
|
+
out(notice);
|
|
186
|
+
}
|
|
@@ -71,23 +71,25 @@ export declare class Conductor {
|
|
|
71
71
|
*/
|
|
72
72
|
private finalizeDoneRuns;
|
|
73
73
|
/**
|
|
74
|
-
* Reconcile
|
|
74
|
+
* Reconcile closed tickets against their herdr worktrees and tear down any
|
|
75
75
|
* whose workspace still lingers (GAIA-89). Driven by the durable `cleaned_up`
|
|
76
|
-
* flag via {@link GaiaRemote.fetchUncleanedTickets}: every ticket
|
|
77
|
-
*
|
|
78
|
-
*
|
|
76
|
+
* flag via {@link GaiaRemote.fetchUncleanedTickets}: every ticket the server
|
|
77
|
+
* has already closed but not yet cleaned. The SAME reconciliation runs on
|
|
78
|
+
* every tick AND standalone as `gaia conductor reap`, and the query is
|
|
79
79
|
* scoped to THIS conductor (GAIA-121) — so it catches the orphans a
|
|
80
80
|
* live-tick-only path structurally cannot (the conductor was down when the
|
|
81
|
-
* ticket
|
|
81
|
+
* ticket closed, or crashed mid-cleanup) for its OWN tickets. A foreign
|
|
82
82
|
* (non-gaia) worktree has no gaia ticket, so it is never on the work list; a
|
|
83
83
|
* ticket assigned to another conductor is filtered out at the query — both are
|
|
84
84
|
* left untouched with no host enumeration.
|
|
85
85
|
*
|
|
86
|
-
*
|
|
87
|
-
* is
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
86
|
+
* The conductor is structurally UNABLE to close a ticket (GAIA-451): closing
|
|
87
|
+
* is a server-side projection of terminality written by
|
|
88
|
+
* `GaiaTicket::preSave()` on any save of a terminal, unclosed ticket, so it
|
|
89
|
+
* holds for every write path and cannot be withheld by a teardown hiccup —
|
|
90
|
+
* the reap reasons about `cleaned_up` alone. `cleaned_up` is withheld unless
|
|
91
|
+
* the teardown is ACCOUNTED FOR (GAIA-141 RC-2), which `removeWorktree`
|
|
92
|
+
* reports as one of three outcomes (GAIA-293):
|
|
91
93
|
* - `removed` — gone because this host tore it down → flag cleaned;
|
|
92
94
|
* - `already_absent` — nothing was there to tear down. A FINISHED teardown,
|
|
93
95
|
* not a failure: it is recorded in this log AND on the run record, then
|
|
@@ -330,23 +330,25 @@ export class Conductor {
|
|
|
330
330
|
}
|
|
331
331
|
}
|
|
332
332
|
/**
|
|
333
|
-
* Reconcile
|
|
333
|
+
* Reconcile closed tickets against their herdr worktrees and tear down any
|
|
334
334
|
* whose workspace still lingers (GAIA-89). Driven by the durable `cleaned_up`
|
|
335
|
-
* flag via {@link GaiaRemote.fetchUncleanedTickets}: every ticket
|
|
336
|
-
*
|
|
337
|
-
*
|
|
335
|
+
* flag via {@link GaiaRemote.fetchUncleanedTickets}: every ticket the server
|
|
336
|
+
* has already closed but not yet cleaned. The SAME reconciliation runs on
|
|
337
|
+
* every tick AND standalone as `gaia conductor reap`, and the query is
|
|
338
338
|
* scoped to THIS conductor (GAIA-121) — so it catches the orphans a
|
|
339
339
|
* live-tick-only path structurally cannot (the conductor was down when the
|
|
340
|
-
* ticket
|
|
340
|
+
* ticket closed, or crashed mid-cleanup) for its OWN tickets. A foreign
|
|
341
341
|
* (non-gaia) worktree has no gaia ticket, so it is never on the work list; a
|
|
342
342
|
* ticket assigned to another conductor is filtered out at the query — both are
|
|
343
343
|
* left untouched with no host enumeration.
|
|
344
344
|
*
|
|
345
|
-
*
|
|
346
|
-
* is
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
345
|
+
* The conductor is structurally UNABLE to close a ticket (GAIA-451): closing
|
|
346
|
+
* is a server-side projection of terminality written by
|
|
347
|
+
* `GaiaTicket::preSave()` on any save of a terminal, unclosed ticket, so it
|
|
348
|
+
* holds for every write path and cannot be withheld by a teardown hiccup —
|
|
349
|
+
* the reap reasons about `cleaned_up` alone. `cleaned_up` is withheld unless
|
|
350
|
+
* the teardown is ACCOUNTED FOR (GAIA-141 RC-2), which `removeWorktree`
|
|
351
|
+
* reports as one of three outcomes (GAIA-293):
|
|
350
352
|
* - `removed` — gone because this host tore it down → flag cleaned;
|
|
351
353
|
* - `already_absent` — nothing was there to tear down. A FINISHED teardown,
|
|
352
354
|
* not a failure: it is recorded in this log AND on the run record, then
|
|
@@ -371,13 +373,6 @@ export class Conductor {
|
|
|
371
373
|
const tickets = await this.remote.fetchUncleanedTickets(this.id);
|
|
372
374
|
for (const t of tickets) {
|
|
373
375
|
try {
|
|
374
|
-
// Lifecycle: close a done+unclosed ticket at once, decoupled from the
|
|
375
|
-
// infra teardown below — a done ticket whose conductor was down was
|
|
376
|
-
// never closed, and withholding the close on a teardown hiccup would
|
|
377
|
-
// make a finished ticket look unfinished (the pre-GAIA-89 defect).
|
|
378
|
-
if (t.state === 'done' && !t.closed) {
|
|
379
|
-
await this.remote.closeTicket(t.ticketUuid);
|
|
380
|
-
}
|
|
381
376
|
// Infra teardown. The `after_done` hook runs in the worktree regardless
|
|
382
377
|
// of executor kind (a non-persistent gitWorkspace still has an on-disk
|
|
383
378
|
// worktree); only the workspace removal is gated on the persistent
|
|
@@ -116,12 +116,14 @@ export interface RunMetrics {
|
|
|
116
116
|
user_prompt_words: number;
|
|
117
117
|
}
|
|
118
118
|
/**
|
|
119
|
-
* A
|
|
119
|
+
* A closed ticket whose worktree has not yet been torn down — the
|
|
120
120
|
* conductor's teardown work list, driven by the durable `cleaned_up` flag
|
|
121
|
-
* (GAIA-89).
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
121
|
+
* (GAIA-89). Since GAIA-451 the server closes every terminal ticket on its own
|
|
122
|
+
* save, so "finished" collapses to `closed = 1`; `cleaned_up=0` (or never
|
|
123
|
+
* written at all) means the herdr worktree still needs reclaiming. The
|
|
124
|
+
* reconciliation is NOT scoped to a conductor's machine_id, so it also
|
|
125
|
+
* surfaces tickets whose conductor was down at close or whose `conductor_id`
|
|
126
|
+
* was reassigned.
|
|
125
127
|
*/
|
|
126
128
|
export interface UncleanTicket {
|
|
127
129
|
ticketUuid: string;
|
|
@@ -132,10 +134,6 @@ export interface UncleanTicket {
|
|
|
132
134
|
* `worktree_path`), or '' when unresolved. The cwd the teardown runs in.
|
|
133
135
|
*/
|
|
134
136
|
worktreePath: string;
|
|
135
|
-
/** Workflow state (e.g. `coding`, `done`). */
|
|
136
|
-
state: string;
|
|
137
|
-
/** Whether the ticket's lifecycle has already been closed out. */
|
|
138
|
-
closed: boolean;
|
|
139
137
|
/**
|
|
140
138
|
* UUID of the ticket's latest run — the one {@link worktreePath} came from —
|
|
141
139
|
* or '' when the ticket has no run with a path. The record teardown notes are
|
|
@@ -215,22 +213,19 @@ export interface GaiaRemote {
|
|
|
215
213
|
*/
|
|
216
214
|
finalizeRun(uuid: string, log: string, metrics?: RunMetrics): Promise<void>;
|
|
217
215
|
/**
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
216
|
+
* Closed tickets (closed=1) whose worktree is not yet torn down
|
|
217
|
+
* (cleaned_up=0, or never written at all) — the conductor's teardown work
|
|
218
|
+
* list (GAIA-89). Since GAIA-451 the server closes every terminal ticket on
|
|
219
|
+
* its own save, so this asks one question — closed but not cleaned up —
|
|
220
|
+
* with no workflow-state reasoning left in it. Driven by the durable
|
|
221
|
+
* `cleaned_up` flag AND scoped to the reaping conductor (GAIA-121): only
|
|
222
|
+
* tickets assigned to `conductorId` are loaded, so every ticket on the list
|
|
223
|
+
* is unambiguously this conductor's — a missing worktree means "already torn
|
|
224
|
+
* down on this host", not "belongs to another host". The same query backs
|
|
225
|
+
* the live tick and the standalone `gaia conductor reap`. Empty once every
|
|
226
|
+
* closed ticket this conductor owns is cleaned.
|
|
226
227
|
*/
|
|
227
228
|
fetchUncleanedTickets(conductorId: string): Promise<UncleanTicket[]>;
|
|
228
|
-
/**
|
|
229
|
-
* Close a ticket: set closed=true + closed_date. Ticket-lifecycle only, and
|
|
230
|
-
* decoupled from teardown — a done ticket is closed even if its worktree
|
|
231
|
-
* teardown later fails. No state change (the ticket is already done).
|
|
232
|
-
*/
|
|
233
|
-
closeTicket(uuid: string): Promise<void>;
|
|
234
229
|
/**
|
|
235
230
|
* Mark a ticket's worktree torn down: set cleaned_up=true so it drops off the
|
|
236
231
|
* {@link fetchUncleanedTickets} work list. Written ONLY after a verified
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gaia-ai/conductor",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.2",
|
|
4
4
|
"description": "GAIA conductor engine + CLI: registers, claims tickets via JSON:API, dispatches agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"directory": "gaia-cli/conductor"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@gaia-ai/core": "^0.11.
|
|
31
|
+
"@gaia-ai/core": "^0.11.2",
|
|
32
32
|
"@dropsh/plugin-oauth2": "^0.6.1",
|
|
33
33
|
"@dropsh/plugin-jsonapi-schema": "^0.6.1",
|
|
34
34
|
"commander": "^12.1.0",
|