@gaia-ai/addon-herdr 0.6.1 → 0.6.3
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/src/workspace.d.ts +36 -5
- package/dist/src/workspace.js +56 -21
- package/package.json +4 -4
package/dist/src/workspace.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { EnsuredWorkspace, GaiaWorkspace, WorkspacePlugin } from '@gaia-ai/conductor/contract';
|
|
2
2
|
import type { ConductorLogger } from '@gaia-ai/core';
|
|
3
3
|
import type { AgentLaunchHost } from './agent-host.js';
|
|
4
|
-
import type
|
|
4
|
+
import { type PaneSpec } from './config.js';
|
|
5
5
|
import { type RootGitExec } from './root-anchor.js';
|
|
6
6
|
export type HerdrExec = (args: string[]) => Promise<string>;
|
|
7
7
|
export type GitExec = (args: string[]) => Promise<string>;
|
|
@@ -10,13 +10,35 @@ export type GitExec = (args: string[]) => Promise<string>;
|
|
|
10
10
|
* (GAIA-139): `command` launches a tool in the main pane (e.g. `spiceedit`) so
|
|
11
11
|
* the human lands in an editor instead of a bare shell; `panes[]` are optional
|
|
12
12
|
* splits off it. Same shape as the executor's per-state layout minus `tabLabel`
|
|
13
|
-
* — there is only ONE open layout, not a per-ticket-state map.
|
|
14
|
-
*
|
|
13
|
+
* — there is only ONE open layout, not a per-ticket-state map.
|
|
14
|
+
*
|
|
15
|
+
* GAIA-234: `{identifier}`, `{branch}` and `{worktreePath}` expand in `command`
|
|
16
|
+
* **and** in every `panes[].command`. The root command is rendered here, by
|
|
17
|
+
* `ensure`, before the finished layout reaches `applyPaneLayout` — that shared
|
|
18
|
+
* helper types its root command VERBATIM on purpose, because its other caller
|
|
19
|
+
* (the executor) pre-assembles `KEY='value' <agent>` env prefixes whose values
|
|
20
|
+
* may legitimately contain braces (spec D2).
|
|
21
|
+
*
|
|
22
|
+
* Unset → {@link DEFAULT_OPEN_LAYOUT}, the ticket deep link. `{}` → the bare
|
|
23
|
+
* empty tab (`applyPaneLayout` issues no calls for an empty layout).
|
|
15
24
|
*/
|
|
16
25
|
export interface OpenLayout {
|
|
17
26
|
command?: string;
|
|
18
27
|
panes?: PaneSpec[];
|
|
19
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* The shipped default open layout (GAIA-234): a fresh worktree's initial pane
|
|
31
|
+
* renders the ticket it belongs to instead of an anonymous shell prompt.
|
|
32
|
+
*
|
|
33
|
+
* It lives in **code, not config**, because a default each repo has to opt into
|
|
34
|
+
* would leave the defect in place for every other consumer of this addon; the
|
|
35
|
+
* addon already ships opinionated defaults of this kind (`BUILTIN_DEFAULTS` in
|
|
36
|
+
* `./config.js`), and `gaia ui` is a command of the very host that ships it.
|
|
37
|
+
*
|
|
38
|
+
* `open: {}` is the documented opt-out back to the pre-GAIA-234 bare tab, so
|
|
39
|
+
* the default is not a one-way door.
|
|
40
|
+
*/
|
|
41
|
+
export declare const DEFAULT_OPEN_LAYOUT: OpenLayout;
|
|
20
42
|
export interface HerdrWorkspaceOptions {
|
|
21
43
|
/** Main clone (a git repo): herdr `--cwd` target + worktree base. */
|
|
22
44
|
root: string;
|
|
@@ -30,7 +52,8 @@ export interface HerdrWorkspaceOptions {
|
|
|
30
52
|
baseBranch?: string;
|
|
31
53
|
/**
|
|
32
54
|
* Startup layout for the initial pane, applied on a FRESH worktree open only
|
|
33
|
-
* (GAIA-139). Unset →
|
|
55
|
+
* (GAIA-139). Unset → {@link DEFAULT_OPEN_LAYOUT} (`gaia ui --ticket <ID>`,
|
|
56
|
+
* GAIA-234); `{}` → the bare empty tab is left unchanged.
|
|
34
57
|
*/
|
|
35
58
|
open?: OpenLayout;
|
|
36
59
|
/** Overrideable herdr exec fn — defaults to the real `herdr` binary. */
|
|
@@ -68,7 +91,13 @@ export declare class HerdrWorkspace implements GaiaWorkspace {
|
|
|
68
91
|
* Returns the ref when it exists, else undefined so the caller falls back.
|
|
69
92
|
*/
|
|
70
93
|
private verifyRemoteRef;
|
|
71
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Ensure the branch's worktree + herdr workspace exist. `identifier` is the
|
|
96
|
+
* ticket's human id: it is NOT used to locate the worktree (the branch is),
|
|
97
|
+
* but it IS the value the open layout's `{identifier}` renders to (GAIA-234),
|
|
98
|
+
* which is why it is taken as-passed rather than parsed back out of `branch`.
|
|
99
|
+
*/
|
|
100
|
+
ensure(identifier: string, branch?: string, baseRefOverride?: string): Promise<EnsuredWorkspace>;
|
|
72
101
|
}
|
|
73
102
|
export declare function herdrWorkspace(opts?: {
|
|
74
103
|
/**
|
|
@@ -81,5 +110,7 @@ export declare function herdrWorkspace(opts?: {
|
|
|
81
110
|
open?: OpenLayout;
|
|
82
111
|
/** Overrideable git exec for root derivation (tests). */
|
|
83
112
|
execGit?: RootGitExec;
|
|
113
|
+
/** Overrideable herdr exec (tests) — sibling of `execGit`. */
|
|
114
|
+
execHerdr?: HerdrExec;
|
|
84
115
|
}): WorkspacePlugin;
|
|
85
116
|
export default herdrWorkspace;
|
package/dist/src/workspace.js
CHANGED
|
@@ -2,8 +2,24 @@ import { resolve } from 'node:path';
|
|
|
2
2
|
import { loadInstructions } from '@gaia-ai/addon-workspace-git';
|
|
3
3
|
import { exec } from '@gaia-ai/core';
|
|
4
4
|
import { herdrAgentHost } from './agents.js';
|
|
5
|
+
import { renderTemplate } from './config.js';
|
|
5
6
|
import { applyPaneLayout, isRecord, parseJson } from './pane-layout.js';
|
|
6
7
|
import { deriveHerdrRoot } from './root-anchor.js';
|
|
8
|
+
/**
|
|
9
|
+
* The shipped default open layout (GAIA-234): a fresh worktree's initial pane
|
|
10
|
+
* renders the ticket it belongs to instead of an anonymous shell prompt.
|
|
11
|
+
*
|
|
12
|
+
* It lives in **code, not config**, because a default each repo has to opt into
|
|
13
|
+
* would leave the defect in place for every other consumer of this addon; the
|
|
14
|
+
* addon already ships opinionated defaults of this kind (`BUILTIN_DEFAULTS` in
|
|
15
|
+
* `./config.js`), and `gaia ui` is a command of the very host that ships it.
|
|
16
|
+
*
|
|
17
|
+
* `open: {}` is the documented opt-out back to the pre-GAIA-234 bare tab, so
|
|
18
|
+
* the default is not a one-way door.
|
|
19
|
+
*/
|
|
20
|
+
export const DEFAULT_OPEN_LAYOUT = {
|
|
21
|
+
command: 'gaia ui --ticket {identifier}',
|
|
22
|
+
};
|
|
7
23
|
const defaultExec = (args) => exec('herdr', args);
|
|
8
24
|
const defaultGitExec = (args) => exec('git', args);
|
|
9
25
|
const noopLogger = {
|
|
@@ -82,7 +98,8 @@ export class HerdrWorkspace {
|
|
|
82
98
|
this.execGit = options.execGit ?? defaultGitExec;
|
|
83
99
|
this.root = resolve(options.root);
|
|
84
100
|
this.worktreeDir = options.worktreeDir ?? '.gaia-worktrees';
|
|
85
|
-
|
|
101
|
+
// `??`, not `||`: an explicit `open: {}` must survive as the opt-out.
|
|
102
|
+
this.open = options.open ?? DEFAULT_OPEN_LAYOUT;
|
|
86
103
|
this.logger = options.logger ?? noopLogger;
|
|
87
104
|
this.agentHost = herdrAgentHost(this.execHerdr);
|
|
88
105
|
}
|
|
@@ -150,7 +167,13 @@ export class HerdrWorkspace {
|
|
|
150
167
|
return undefined;
|
|
151
168
|
}
|
|
152
169
|
}
|
|
153
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Ensure the branch's worktree + herdr workspace exist. `identifier` is the
|
|
172
|
+
* ticket's human id: it is NOT used to locate the worktree (the branch is),
|
|
173
|
+
* but it IS the value the open layout's `{identifier}` renders to (GAIA-234),
|
|
174
|
+
* which is why it is taken as-passed rather than parsed back out of `branch`.
|
|
175
|
+
*/
|
|
176
|
+
async ensure(identifier, branch, baseRefOverride) {
|
|
154
177
|
if (branch === undefined) {
|
|
155
178
|
throw new Error('herdr workspace requires a branch name');
|
|
156
179
|
}
|
|
@@ -214,26 +237,33 @@ export class HerdrWorkspace {
|
|
|
214
237
|
'--json',
|
|
215
238
|
]);
|
|
216
239
|
const path = parseWorktreePath(createOutput, 'worktree create');
|
|
217
|
-
// GAIA-139: on a FRESH create, apply the
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
// root pane's cwd is already
|
|
221
|
-
// `fetchBaseRef` pattern above: a
|
|
222
|
-
//
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
240
|
+
// GAIA-139: on a FRESH create, apply the open layout to the initial root
|
|
241
|
+
// pane — by default (GAIA-234) the ticket's `gaia ui` deep link, so the tab
|
|
242
|
+
// shows the ticket instead of a bare shell. The pane's cwd is the worktree
|
|
243
|
+
// checkout, passed explicitly on the splits (the root pane's cwd is already
|
|
244
|
+
// the checkout). Best-effort — mirrors the `fetchBaseRef` pattern above: a
|
|
245
|
+
// broken layout is logged and swallowed so a startup-command failure can
|
|
246
|
+
// NEVER wedge worktree creation / run dispatch.
|
|
247
|
+
try {
|
|
248
|
+
const rootPaneId = parseWorktreeRootPane(createOutput);
|
|
249
|
+
if (rootPaneId) {
|
|
250
|
+
// Render the ROOT command here (spec D2). `applyPaneLayout` types its
|
|
251
|
+
// root command verbatim for the executor's brace-bearing env-prefixed
|
|
252
|
+
// agent command, so templating it there would corrupt that; the split
|
|
253
|
+
// commands it already renders from the same `vars`.
|
|
254
|
+
const vars = { identifier, branch, worktreePath: path };
|
|
255
|
+
const layout = {
|
|
256
|
+
...this.open,
|
|
257
|
+
...(this.open.command !== undefined
|
|
258
|
+
? { command: renderTemplate(this.open.command, vars) }
|
|
259
|
+
: {}),
|
|
260
|
+
};
|
|
261
|
+
await applyPaneLayout(this.execHerdr, rootPaneId, layout, path, vars);
|
|
235
262
|
}
|
|
236
263
|
}
|
|
264
|
+
catch (err) {
|
|
265
|
+
this.logger.warn({ branch, worktree: path, err: String(err) }, 'herdr open-layout failed (best-effort, ignored)');
|
|
266
|
+
}
|
|
237
267
|
// The `after_create` hook is run by the executor (GAIA-84), not here — the
|
|
238
268
|
// workspace only reports that it created a fresh worktree.
|
|
239
269
|
return { path, instructions: loadInstructions(path), created: true };
|
|
@@ -244,7 +274,10 @@ export function herdrWorkspace(opts = {}) {
|
|
|
244
274
|
kind: 'workspace',
|
|
245
275
|
id: 'herdr',
|
|
246
276
|
requiredModules: [],
|
|
247
|
-
|
|
277
|
+
// GAIA-234: `deps` carries the conductor logger, so the best-effort
|
|
278
|
+
// open-layout failure is actually logged instead of vanishing into the noop
|
|
279
|
+
// logger. Optional per the contract — absent, the noop default stays.
|
|
280
|
+
async createWorkspace(config, deps) {
|
|
248
281
|
const root = await deriveHerdrRoot(config.config_path, {
|
|
249
282
|
...(opts.root !== undefined ? { override: opts.root } : {}),
|
|
250
283
|
...(opts.execGit ? { execGit: opts.execGit } : {}),
|
|
@@ -254,6 +287,8 @@ export function herdrWorkspace(opts = {}) {
|
|
|
254
287
|
...(opts.worktreeDir ? { worktreeDir: opts.worktreeDir } : {}),
|
|
255
288
|
...(opts.baseBranch ? { baseBranch: opts.baseBranch } : {}),
|
|
256
289
|
...(opts.open ? { open: opts.open } : {}),
|
|
290
|
+
...(opts.execHerdr ? { execHerdr: opts.execHerdr } : {}),
|
|
291
|
+
...(deps?.logger ? { logger: deps.logger } : {}),
|
|
257
292
|
});
|
|
258
293
|
},
|
|
259
294
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gaia-ai/addon-herdr",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "GAIA herdr integration: spawn executor + per-ticket worktree workspace.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
"directory": "gaia-cli/addons/herdr"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@gaia-ai/addon-workspace-git": "^0.6.
|
|
23
|
+
"@gaia-ai/addon-workspace-git": "^0.6.3"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@gaia-ai/conductor": "^0.6.
|
|
27
|
-
"@gaia-ai/core": "^0.6.
|
|
26
|
+
"@gaia-ai/conductor": "^0.6.3",
|
|
27
|
+
"@gaia-ai/core": "^0.6.3"
|
|
28
28
|
}
|
|
29
29
|
}
|