@agent-relay/factory 0.1.19 → 0.1.21
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/README.md +42 -0
- package/dist/cli/fleet.d.ts +4 -0
- package/dist/cli/fleet.d.ts.map +1 -1
- package/dist/cli/fleet.js +186 -23
- package/dist/cli/fleet.js.map +1 -1
- package/dist/config/local-clone-paths.d.ts +18 -0
- package/dist/config/local-clone-paths.d.ts.map +1 -0
- package/dist/config/local-clone-paths.js +188 -0
- package/dist/config/local-clone-paths.js.map +1 -0
- package/dist/config/schema.d.ts +84 -2
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +71 -5
- package/dist/config/schema.js.map +1 -1
- package/dist/dispatch/templates.d.ts +18 -0
- package/dist/dispatch/templates.d.ts.map +1 -1
- package/dist/dispatch/templates.js +45 -11
- package/dist/dispatch/templates.js.map +1 -1
- package/dist/fleet/internal-fleet-client.d.ts +4 -0
- package/dist/fleet/internal-fleet-client.d.ts.map +1 -1
- package/dist/fleet/internal-fleet-client.js +4 -1
- package/dist/fleet/internal-fleet-client.js.map +1 -1
- package/dist/fleet/relay-fleet-client.d.ts +4 -0
- package/dist/fleet/relay-fleet-client.d.ts.map +1 -1
- package/dist/fleet/relay-fleet-client.js +14 -3
- package/dist/fleet/relay-fleet-client.js.map +1 -1
- package/dist/logging.d.ts +17 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +347 -0
- package/dist/logging.js.map +1 -0
- package/dist/mount/relayfile-cloud-mount-client.js +10 -0
- package/dist/mount/relayfile-cloud-mount-client.js.map +1 -1
- package/dist/mount/relayfile-github-connection-write.d.ts.map +1 -1
- package/dist/mount/relayfile-github-connection-write.js +19 -7
- package/dist/mount/relayfile-github-connection-write.js.map +1 -1
- package/dist/orchestrator/batch-tracker.d.ts +3 -0
- package/dist/orchestrator/batch-tracker.d.ts.map +1 -1
- package/dist/orchestrator/batch-tracker.js +28 -0
- package/dist/orchestrator/batch-tracker.js.map +1 -1
- package/dist/orchestrator/factory.d.ts +2 -1
- package/dist/orchestrator/factory.d.ts.map +1 -1
- package/dist/orchestrator/factory.js +3295 -321
- package/dist/orchestrator/factory.js.map +1 -1
- package/dist/orchestrator/reaper.d.ts.map +1 -1
- package/dist/orchestrator/reaper.js +6 -4
- package/dist/orchestrator/reaper.js.map +1 -1
- package/dist/ports/fleet.d.ts +25 -0
- package/dist/ports/fleet.d.ts.map +1 -1
- package/dist/ports/mount.d.ts +7 -1
- package/dist/ports/mount.d.ts.map +1 -1
- package/dist/ports/state.d.ts +120 -0
- package/dist/ports/state.d.ts.map +1 -1
- package/dist/ports/writeback.d.ts +2 -0
- package/dist/ports/writeback.d.ts.map +1 -1
- package/dist/state/file-state-store.d.ts +33 -2
- package/dist/state/file-state-store.d.ts.map +1 -1
- package/dist/state/file-state-store.js +520 -10
- package/dist/state/file-state-store.js.map +1 -1
- package/dist/state/in-memory-state-store.d.ts +31 -1
- package/dist/state/in-memory-state-store.d.ts.map +1 -1
- package/dist/state/in-memory-state-store.js +245 -0
- package/dist/state/in-memory-state-store.js.map +1 -1
- package/dist/testing/fakes.d.ts +7 -0
- package/dist/testing/fakes.d.ts.map +1 -1
- package/dist/testing/fakes.js +1 -0
- package/dist/testing/fakes.js.map +1 -1
- package/dist/triage/agent-names.d.ts +13 -0
- package/dist/triage/agent-names.d.ts.map +1 -0
- package/dist/triage/agent-names.js +54 -0
- package/dist/triage/agent-names.js.map +1 -0
- package/dist/triage/heuristic.d.ts.map +1 -1
- package/dist/triage/heuristic.js +16 -23
- package/dist/triage/heuristic.js.map +1 -1
- package/dist/triage/llm.d.ts.map +1 -1
- package/dist/triage/llm.js +3 -2
- package/dist/triage/llm.js.map +1 -1
- package/dist/triage/schema.d.ts +26 -26
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/writeback/github.d.ts +1 -0
- package/dist/writeback/github.d.ts.map +1 -1
- package/dist/writeback/github.js +11 -0
- package/dist/writeback/github.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { realpath, stat } from 'node:fs/promises';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { loadFactoryConfig } from './schema.js';
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
/**
|
|
8
|
+
* Parse a factory config, then apply the environment-dependent conveniences
|
|
9
|
+
* that are appropriate only for a local CLI run.
|
|
10
|
+
*/
|
|
11
|
+
export async function resolveLocalFactoryConfig(input, options = {}) {
|
|
12
|
+
const config = loadFactoryConfig(input).factoryConfig;
|
|
13
|
+
const git = options.git ?? runGit;
|
|
14
|
+
let resolved = config;
|
|
15
|
+
if (options.inferFromCwd !== false) {
|
|
16
|
+
const repoName = cwdInferenceRepoName(input);
|
|
17
|
+
if (repoName !== undefined) {
|
|
18
|
+
const repo = config.repos.byLabel[repoName];
|
|
19
|
+
if (!repo || !isQualifiedRepo(repo)) {
|
|
20
|
+
throw new Error(`[factory] cannot infer clonePath from cwd: resolved route for repos.names[0] must be owner/name (received ${JSON.stringify(repo ?? repoName)})`);
|
|
21
|
+
}
|
|
22
|
+
const checkoutRoot = await gitCheckoutRoot(options.cwd ?? process.cwd(), git, repo);
|
|
23
|
+
await assertMatchingGithubRemote(checkoutRoot, repo, git);
|
|
24
|
+
const clonePaths = { ...config.clonePaths, [repo]: checkoutRoot };
|
|
25
|
+
resolved = {
|
|
26
|
+
...config,
|
|
27
|
+
clonePaths,
|
|
28
|
+
repos: { ...config.repos, clonePaths },
|
|
29
|
+
};
|
|
30
|
+
options.logger?.info?.(`[factory] clonePath inferred from cwd: ${checkoutRoot}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (options.validateConfiguredCheckouts) {
|
|
34
|
+
await validateClonePaths(resolved.clonePaths, git);
|
|
35
|
+
}
|
|
36
|
+
return resolved;
|
|
37
|
+
}
|
|
38
|
+
async function gitCheckoutRoot(cwd, git, repo) {
|
|
39
|
+
let root;
|
|
40
|
+
try {
|
|
41
|
+
root = (await git(cwd, ['rev-parse', '--show-toplevel'])).trim();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw new Error(`[factory] cannot infer clonePath for ${repo}: cwd is not inside a git checkout: ${resolve(cwd)}; configure cloneRoot or clonePaths explicitly`);
|
|
45
|
+
}
|
|
46
|
+
if (!root) {
|
|
47
|
+
throw new Error(`[factory] cannot infer clonePath for ${repo}: git returned no checkout root for cwd ${resolve(cwd)}; configure cloneRoot or clonePaths explicitly`);
|
|
48
|
+
}
|
|
49
|
+
return resolve(root);
|
|
50
|
+
}
|
|
51
|
+
async function assertMatchingGithubRemote(checkoutRoot, expectedRepo, git) {
|
|
52
|
+
const remoteNames = (await git(checkoutRoot, ['remote']))
|
|
53
|
+
.split(/\r?\n/u)
|
|
54
|
+
.map((name) => name.trim())
|
|
55
|
+
.filter(Boolean);
|
|
56
|
+
if (remoteNames.length === 0) {
|
|
57
|
+
throw new Error(`[factory] cannot infer clonePath for ${expectedRepo}: git checkout ${checkoutRoot} has no remotes; add a matching GitHub remote or configure cloneRoot/clonePaths explicitly`);
|
|
58
|
+
}
|
|
59
|
+
const remoteUrls = [];
|
|
60
|
+
for (const remote of remoteNames) {
|
|
61
|
+
try {
|
|
62
|
+
remoteUrls.push(...(await git(checkoutRoot, ['remote', 'get-url', '--all', remote]))
|
|
63
|
+
.split(/\r?\n/u)
|
|
64
|
+
.map((url) => url.trim())
|
|
65
|
+
.filter(Boolean));
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// A concurrently removed/broken remote is treated like an unparseable
|
|
69
|
+
// remote below, yielding one actionable config error.
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const parsedRepos = remoteUrls
|
|
73
|
+
.map(githubRepoFromRemoteUrl)
|
|
74
|
+
.filter((repo) => repo !== undefined);
|
|
75
|
+
if (parsedRepos.some((repo) => repo.toLowerCase() === expectedRepo.toLowerCase()))
|
|
76
|
+
return;
|
|
77
|
+
const found = [...new Set(parsedRepos)];
|
|
78
|
+
const detail = found.length > 0
|
|
79
|
+
? `found GitHub remote${found.length === 1 ? '' : 's'} for ${found.join(', ')}`
|
|
80
|
+
: 'found no parseable GitHub remote URLs';
|
|
81
|
+
throw new Error(`[factory] cannot infer clonePath for ${expectedRepo}: ${detail} in ${checkoutRoot}; add a matching remote or configure cloneRoot/clonePaths explicitly`);
|
|
82
|
+
}
|
|
83
|
+
export function githubRepoFromRemoteUrl(remoteUrl) {
|
|
84
|
+
const value = remoteUrl.trim().replace(/^git\+/u, '');
|
|
85
|
+
let host;
|
|
86
|
+
let pathname;
|
|
87
|
+
try {
|
|
88
|
+
const url = new URL(value);
|
|
89
|
+
host = url.hostname;
|
|
90
|
+
pathname = url.pathname;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
const scp = /^(?:[^@/\s]+@)?([^:/\s]+):(.+)$/u.exec(value);
|
|
94
|
+
if (scp) {
|
|
95
|
+
host = scp[1];
|
|
96
|
+
pathname = scp[2];
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const hostPath = /^([^/\s]+)\/(.+)$/u.exec(value);
|
|
100
|
+
if (!hostPath)
|
|
101
|
+
return undefined;
|
|
102
|
+
host = hostPath[1];
|
|
103
|
+
pathname = hostPath[2];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (!['github.com', 'www.github.com'].includes(host.toLowerCase()))
|
|
107
|
+
return undefined;
|
|
108
|
+
const parts = pathname
|
|
109
|
+
.replace(/^\/+|\/+$/gu, '')
|
|
110
|
+
.replace(/\.git$/iu, '')
|
|
111
|
+
.split('/')
|
|
112
|
+
.filter(Boolean);
|
|
113
|
+
if (parts.length !== 2)
|
|
114
|
+
return undefined;
|
|
115
|
+
return `${parts[0]}/${parts[1]}`;
|
|
116
|
+
}
|
|
117
|
+
async function validateClonePaths(clonePaths, git) {
|
|
118
|
+
for (const [repo, clonePath] of Object.entries(clonePaths)) {
|
|
119
|
+
const path = resolve(clonePath);
|
|
120
|
+
let pathStat;
|
|
121
|
+
try {
|
|
122
|
+
pathStat = await stat(path);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
throw new Error(`[factory] clonePath for ${repo} does not exist: ${path}`);
|
|
126
|
+
}
|
|
127
|
+
if (!pathStat.isDirectory()) {
|
|
128
|
+
throw new Error(`[factory] clonePath for ${repo} is not a directory: ${path}`);
|
|
129
|
+
}
|
|
130
|
+
let checkoutRoot;
|
|
131
|
+
try {
|
|
132
|
+
checkoutRoot = (await git(path, ['rev-parse', '--show-toplevel'])).trim();
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
throw new Error(`[factory] clonePath for ${repo} is not a git checkout: ${path}`);
|
|
136
|
+
}
|
|
137
|
+
if (!checkoutRoot) {
|
|
138
|
+
throw new Error(`[factory] clonePath for ${repo} is not a git checkout: ${path}`);
|
|
139
|
+
}
|
|
140
|
+
const [realPath, realRoot] = await Promise.all([realpath(path), realpath(resolve(checkoutRoot))]);
|
|
141
|
+
if (realPath !== realRoot) {
|
|
142
|
+
throw new Error(`[factory] clonePath for ${repo} points inside a git checkout (${path}); configure the checkout root ${resolve(checkoutRoot)}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async function runGit(cwd, args) {
|
|
147
|
+
const { stdout } = await execFileAsync('git', ['-C', cwd, ...args], {
|
|
148
|
+
encoding: 'utf8',
|
|
149
|
+
maxBuffer: 1024 * 1024,
|
|
150
|
+
});
|
|
151
|
+
return stdout;
|
|
152
|
+
}
|
|
153
|
+
function cwdInferenceRepoName(input) {
|
|
154
|
+
const inputRecord = record(input);
|
|
155
|
+
const factoryInput = record(inputRecord.factoryConfig ?? input);
|
|
156
|
+
if (hasOwn(factoryInput, 'workspaceConfig') || hasOwn(factoryInput, 'nodeConfig')) {
|
|
157
|
+
const workspace = record(factoryInput.workspaceConfig);
|
|
158
|
+
const node = record(factoryInput.nodeConfig);
|
|
159
|
+
const repos = record(workspace.repos);
|
|
160
|
+
if (hasClonePathConfig(workspace) || hasClonePathConfig(node) || hasClonePathConfig(repos))
|
|
161
|
+
return undefined;
|
|
162
|
+
return singleRepoName(repos.names);
|
|
163
|
+
}
|
|
164
|
+
const repos = record(factoryInput.repos);
|
|
165
|
+
if (hasClonePathConfig(factoryInput) || hasClonePathConfig(repos))
|
|
166
|
+
return undefined;
|
|
167
|
+
return singleRepoName(repos.names);
|
|
168
|
+
}
|
|
169
|
+
function hasClonePathConfig(value) {
|
|
170
|
+
return hasOwn(value, 'cloneRoot') || hasOwn(value, 'clonePaths');
|
|
171
|
+
}
|
|
172
|
+
function singleRepoName(value) {
|
|
173
|
+
return Array.isArray(value) && value.length === 1 && typeof value[0] === 'string'
|
|
174
|
+
? value[0]
|
|
175
|
+
: undefined;
|
|
176
|
+
}
|
|
177
|
+
function isQualifiedRepo(repo) {
|
|
178
|
+
return /^[^/\s]+\/[^/\s]+$/u.test(repo);
|
|
179
|
+
}
|
|
180
|
+
function record(value) {
|
|
181
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
182
|
+
? value
|
|
183
|
+
: {};
|
|
184
|
+
}
|
|
185
|
+
function hasOwn(value, key) {
|
|
186
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=local-clone-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-clone-paths.js","sourceRoot":"","sources":["../../src/config/local-clone-paths.ts"],"names":[],"mappings":"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"}
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -134,20 +134,36 @@ export declare const WorkspaceConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
134
134
|
triage?: string | undefined;
|
|
135
135
|
babysitter?: string | undefined;
|
|
136
136
|
}>>;
|
|
137
|
+
agentCapabilities: z.ZodDefault<z.ZodObject<{
|
|
138
|
+
implementer: z.ZodDefault<z.ZodEnum<["spawn:codex", "spawn:claude"]>>;
|
|
139
|
+
reviewer: z.ZodDefault<z.ZodEnum<["spawn:codex", "spawn:claude"]>>;
|
|
140
|
+
babysitter: z.ZodDefault<z.ZodEnum<["spawn:codex", "spawn:claude"]>>;
|
|
141
|
+
}, "strip", z.ZodTypeAny, {
|
|
142
|
+
implementer: "spawn:codex" | "spawn:claude";
|
|
143
|
+
reviewer: "spawn:codex" | "spawn:claude";
|
|
144
|
+
babysitter: "spawn:codex" | "spawn:claude";
|
|
145
|
+
}, {
|
|
146
|
+
implementer?: "spawn:codex" | "spawn:claude" | undefined;
|
|
147
|
+
reviewer?: "spawn:codex" | "spawn:claude" | undefined;
|
|
148
|
+
babysitter?: "spawn:codex" | "spawn:claude" | undefined;
|
|
149
|
+
}>>;
|
|
137
150
|
slack: z.ZodOptional<z.ZodObject<{
|
|
138
151
|
channel: z.ZodString;
|
|
139
152
|
style: z.ZodDefault<z.ZodLiteral<"threaded-summarized">>;
|
|
140
153
|
botUserId: z.ZodDefault<z.ZodString>;
|
|
154
|
+
stakeholderUserIds: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
141
155
|
staleAfterMs: z.ZodDefault<z.ZodNumber>;
|
|
142
156
|
}, "strip", z.ZodTypeAny, {
|
|
143
157
|
channel: string;
|
|
144
158
|
style: "threaded-summarized";
|
|
145
159
|
botUserId: string;
|
|
160
|
+
stakeholderUserIds: string[];
|
|
146
161
|
staleAfterMs: number;
|
|
147
162
|
}, {
|
|
148
163
|
channel: string;
|
|
149
164
|
style?: "threaded-summarized" | undefined;
|
|
150
165
|
botUserId?: string | undefined;
|
|
166
|
+
stakeholderUserIds?: string[] | undefined;
|
|
151
167
|
staleAfterMs?: number | undefined;
|
|
152
168
|
}>>;
|
|
153
169
|
issueSource: z.ZodOptional<z.ZodEnum<["linear", "github"]>>;
|
|
@@ -316,6 +332,11 @@ export declare const WorkspaceConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
316
332
|
reviewer?: string | undefined;
|
|
317
333
|
triage?: string | undefined;
|
|
318
334
|
};
|
|
335
|
+
agentCapabilities: {
|
|
336
|
+
implementer: "spawn:codex" | "spawn:claude";
|
|
337
|
+
reviewer: "spawn:codex" | "spawn:claude";
|
|
338
|
+
babysitter: "spawn:codex" | "spawn:claude";
|
|
339
|
+
};
|
|
319
340
|
linear: {
|
|
320
341
|
states: {
|
|
321
342
|
readyForAgent?: string | undefined;
|
|
@@ -352,6 +373,7 @@ export declare const WorkspaceConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
352
373
|
channel: string;
|
|
353
374
|
style: "threaded-summarized";
|
|
354
375
|
botUserId: string;
|
|
376
|
+
stakeholderUserIds: string[];
|
|
355
377
|
staleAfterMs: number;
|
|
356
378
|
} | undefined;
|
|
357
379
|
issueSource?: "linear" | "github" | undefined;
|
|
@@ -407,10 +429,16 @@ export declare const WorkspaceConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
407
429
|
triage?: string | undefined;
|
|
408
430
|
babysitter?: string | undefined;
|
|
409
431
|
} | undefined;
|
|
432
|
+
agentCapabilities?: {
|
|
433
|
+
implementer?: "spawn:codex" | "spawn:claude" | undefined;
|
|
434
|
+
reviewer?: "spawn:codex" | "spawn:claude" | undefined;
|
|
435
|
+
babysitter?: "spawn:codex" | "spawn:claude" | undefined;
|
|
436
|
+
} | undefined;
|
|
410
437
|
slack?: {
|
|
411
438
|
channel: string;
|
|
412
439
|
style?: "threaded-summarized" | undefined;
|
|
413
440
|
botUserId?: string | undefined;
|
|
441
|
+
stakeholderUserIds?: string[] | undefined;
|
|
414
442
|
staleAfterMs?: number | undefined;
|
|
415
443
|
} | undefined;
|
|
416
444
|
linear?: {
|
|
@@ -496,6 +524,11 @@ export declare const WorkspaceConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
496
524
|
reviewer?: string | undefined;
|
|
497
525
|
triage?: string | undefined;
|
|
498
526
|
};
|
|
527
|
+
agentCapabilities: {
|
|
528
|
+
implementer: "spawn:codex" | "spawn:claude";
|
|
529
|
+
reviewer: "spawn:codex" | "spawn:claude";
|
|
530
|
+
babysitter: "spawn:codex" | "spawn:claude";
|
|
531
|
+
};
|
|
499
532
|
linear: {
|
|
500
533
|
states: {
|
|
501
534
|
readyForAgent?: string | undefined;
|
|
@@ -532,6 +565,7 @@ export declare const WorkspaceConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
532
565
|
channel: string;
|
|
533
566
|
style: "threaded-summarized";
|
|
534
567
|
botUserId: string;
|
|
568
|
+
stakeholderUserIds: string[];
|
|
535
569
|
staleAfterMs: number;
|
|
536
570
|
} | undefined;
|
|
537
571
|
issueSource?: "linear" | "github" | undefined;
|
|
@@ -587,10 +621,16 @@ export declare const WorkspaceConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
587
621
|
triage?: string | undefined;
|
|
588
622
|
babysitter?: string | undefined;
|
|
589
623
|
} | undefined;
|
|
624
|
+
agentCapabilities?: {
|
|
625
|
+
implementer?: "spawn:codex" | "spawn:claude" | undefined;
|
|
626
|
+
reviewer?: "spawn:codex" | "spawn:claude" | undefined;
|
|
627
|
+
babysitter?: "spawn:codex" | "spawn:claude" | undefined;
|
|
628
|
+
} | undefined;
|
|
590
629
|
slack?: {
|
|
591
630
|
channel: string;
|
|
592
631
|
style?: "threaded-summarized" | undefined;
|
|
593
632
|
botUserId?: string | undefined;
|
|
633
|
+
stakeholderUserIds?: string[] | undefined;
|
|
594
634
|
staleAfterMs?: number | undefined;
|
|
595
635
|
} | undefined;
|
|
596
636
|
linear?: {
|
|
@@ -651,12 +691,12 @@ export declare const NodeConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
651
691
|
factoryLoopHeartbeatPath?: string | undefined;
|
|
652
692
|
factoryLoopRegistryPath?: string | undefined;
|
|
653
693
|
}>, {
|
|
694
|
+
cloneRoot: string | undefined;
|
|
695
|
+
clonePaths: Record<string, string>;
|
|
654
696
|
factoryLoopHeartbeatPath: string | undefined;
|
|
655
697
|
factoryLoopRegistryPath: string | undefined;
|
|
656
|
-
clonePaths: Record<string, string>;
|
|
657
698
|
capabilities: string[];
|
|
658
699
|
dryRun: boolean;
|
|
659
|
-
cloneRoot?: string | undefined;
|
|
660
700
|
workspaceId?: string | undefined;
|
|
661
701
|
}, {
|
|
662
702
|
cloneRoot?: string | undefined;
|
|
@@ -799,20 +839,36 @@ export declare const FactoryConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
799
839
|
triage?: string | undefined;
|
|
800
840
|
babysitter?: string | undefined;
|
|
801
841
|
}>>;
|
|
842
|
+
agentCapabilities: z.ZodDefault<z.ZodObject<{
|
|
843
|
+
implementer: z.ZodDefault<z.ZodEnum<["spawn:codex", "spawn:claude"]>>;
|
|
844
|
+
reviewer: z.ZodDefault<z.ZodEnum<["spawn:codex", "spawn:claude"]>>;
|
|
845
|
+
babysitter: z.ZodDefault<z.ZodEnum<["spawn:codex", "spawn:claude"]>>;
|
|
846
|
+
}, "strip", z.ZodTypeAny, {
|
|
847
|
+
implementer: "spawn:codex" | "spawn:claude";
|
|
848
|
+
reviewer: "spawn:codex" | "spawn:claude";
|
|
849
|
+
babysitter: "spawn:codex" | "spawn:claude";
|
|
850
|
+
}, {
|
|
851
|
+
implementer?: "spawn:codex" | "spawn:claude" | undefined;
|
|
852
|
+
reviewer?: "spawn:codex" | "spawn:claude" | undefined;
|
|
853
|
+
babysitter?: "spawn:codex" | "spawn:claude" | undefined;
|
|
854
|
+
}>>;
|
|
802
855
|
slack: z.ZodOptional<z.ZodObject<{
|
|
803
856
|
channel: z.ZodString;
|
|
804
857
|
style: z.ZodDefault<z.ZodLiteral<"threaded-summarized">>;
|
|
805
858
|
botUserId: z.ZodDefault<z.ZodString>;
|
|
859
|
+
stakeholderUserIds: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
806
860
|
staleAfterMs: z.ZodDefault<z.ZodNumber>;
|
|
807
861
|
}, "strip", z.ZodTypeAny, {
|
|
808
862
|
channel: string;
|
|
809
863
|
style: "threaded-summarized";
|
|
810
864
|
botUserId: string;
|
|
865
|
+
stakeholderUserIds: string[];
|
|
811
866
|
staleAfterMs: number;
|
|
812
867
|
}, {
|
|
813
868
|
channel: string;
|
|
814
869
|
style?: "threaded-summarized" | undefined;
|
|
815
870
|
botUserId?: string | undefined;
|
|
871
|
+
stakeholderUserIds?: string[] | undefined;
|
|
816
872
|
staleAfterMs?: number | undefined;
|
|
817
873
|
}>>;
|
|
818
874
|
issueSource: z.ZodOptional<z.ZodEnum<["linear", "github"]>>;
|
|
@@ -990,6 +1046,11 @@ export declare const FactoryConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
990
1046
|
reviewer?: string | undefined;
|
|
991
1047
|
triage?: string | undefined;
|
|
992
1048
|
};
|
|
1049
|
+
agentCapabilities: {
|
|
1050
|
+
implementer: "spawn:codex" | "spawn:claude";
|
|
1051
|
+
reviewer: "spawn:codex" | "spawn:claude";
|
|
1052
|
+
babysitter: "spawn:codex" | "spawn:claude";
|
|
1053
|
+
};
|
|
993
1054
|
linear: {
|
|
994
1055
|
states: {
|
|
995
1056
|
readyForAgent?: string | undefined;
|
|
@@ -1029,6 +1090,7 @@ export declare const FactoryConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
1029
1090
|
channel: string;
|
|
1030
1091
|
style: "threaded-summarized";
|
|
1031
1092
|
botUserId: string;
|
|
1093
|
+
stakeholderUserIds: string[];
|
|
1032
1094
|
staleAfterMs: number;
|
|
1033
1095
|
} | undefined;
|
|
1034
1096
|
issueSource?: "linear" | "github" | undefined;
|
|
@@ -1088,10 +1150,16 @@ export declare const FactoryConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
1088
1150
|
triage?: string | undefined;
|
|
1089
1151
|
babysitter?: string | undefined;
|
|
1090
1152
|
} | undefined;
|
|
1153
|
+
agentCapabilities?: {
|
|
1154
|
+
implementer?: "spawn:codex" | "spawn:claude" | undefined;
|
|
1155
|
+
reviewer?: "spawn:codex" | "spawn:claude" | undefined;
|
|
1156
|
+
babysitter?: "spawn:codex" | "spawn:claude" | undefined;
|
|
1157
|
+
} | undefined;
|
|
1091
1158
|
slack?: {
|
|
1092
1159
|
channel: string;
|
|
1093
1160
|
style?: "threaded-summarized" | undefined;
|
|
1094
1161
|
botUserId?: string | undefined;
|
|
1162
|
+
stakeholderUserIds?: string[] | undefined;
|
|
1095
1163
|
staleAfterMs?: number | undefined;
|
|
1096
1164
|
} | undefined;
|
|
1097
1165
|
linear?: {
|
|
@@ -1188,6 +1256,11 @@ export declare const FactoryConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
1188
1256
|
reviewer?: string | undefined;
|
|
1189
1257
|
triage?: string | undefined;
|
|
1190
1258
|
};
|
|
1259
|
+
agentCapabilities: {
|
|
1260
|
+
implementer: "spawn:codex" | "spawn:claude";
|
|
1261
|
+
reviewer: "spawn:codex" | "spawn:claude";
|
|
1262
|
+
babysitter: "spawn:codex" | "spawn:claude";
|
|
1263
|
+
};
|
|
1191
1264
|
linear: {
|
|
1192
1265
|
states: {
|
|
1193
1266
|
readyForAgent?: string | undefined;
|
|
@@ -1226,6 +1299,7 @@ export declare const FactoryConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
1226
1299
|
channel: string;
|
|
1227
1300
|
style: "threaded-summarized";
|
|
1228
1301
|
botUserId: string;
|
|
1302
|
+
stakeholderUserIds: string[];
|
|
1229
1303
|
staleAfterMs: number;
|
|
1230
1304
|
} | undefined;
|
|
1231
1305
|
issueSource?: "linear" | "github" | undefined;
|
|
@@ -1283,10 +1357,16 @@ export declare const FactoryConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
1283
1357
|
triage?: string | undefined;
|
|
1284
1358
|
babysitter?: string | undefined;
|
|
1285
1359
|
} | undefined;
|
|
1360
|
+
agentCapabilities?: {
|
|
1361
|
+
implementer?: "spawn:codex" | "spawn:claude" | undefined;
|
|
1362
|
+
reviewer?: "spawn:codex" | "spawn:claude" | undefined;
|
|
1363
|
+
babysitter?: "spawn:codex" | "spawn:claude" | undefined;
|
|
1364
|
+
} | undefined;
|
|
1286
1365
|
slack?: {
|
|
1287
1366
|
channel: string;
|
|
1288
1367
|
style?: "threaded-summarized" | undefined;
|
|
1289
1368
|
botUserId?: string | undefined;
|
|
1369
|
+
stakeholderUserIds?: string[] | undefined;
|
|
1290
1370
|
staleAfterMs?: number | undefined;
|
|
1291
1371
|
} | undefined;
|
|
1292
1372
|
linear?: {
|
|
@@ -1326,6 +1406,8 @@ export declare const FactoryConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
|
1326
1406
|
factoryLoopHeartbeatPath?: string | undefined;
|
|
1327
1407
|
factoryLoopRegistryPath?: string | undefined;
|
|
1328
1408
|
}>;
|
|
1409
|
+
/** Expand the shell-like home shorthand that Node's filesystem APIs do not. */
|
|
1410
|
+
export declare function expandLeadingTilde(value: string, field?: string): string;
|
|
1329
1411
|
export interface LoadedFactoryConfig {
|
|
1330
1412
|
workspaceConfig: WorkspaceConfig;
|
|
1331
1413
|
nodeConfig: NodeConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/config/schema.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join } from 'node:path';
|
|
1
3
|
import { z } from 'zod';
|
|
2
4
|
// The five workflow-state roles the factory drives an issue through. Each is
|
|
3
5
|
// configured either by name (config.linear.states.<role>, resolved to a
|
|
@@ -76,10 +78,28 @@ const modelsSchema = z.object({
|
|
|
76
78
|
// reviewer's unset (inherit) behavior.
|
|
77
79
|
babysitter: z.string().default('sonnet'),
|
|
78
80
|
}).default({});
|
|
81
|
+
// Which agent CLI backs each spawn role. `models.*` picks the model; this picks
|
|
82
|
+
// the CLI. Restricted to the two spawn capabilities actually wired into
|
|
83
|
+
// capabilityCli (internal-fleet-client.ts) — spawn:opencode / spawn:gemini would
|
|
84
|
+
// resolve to an undefined CLI and are intentionally excluded until mapped.
|
|
85
|
+
// Defaults preserve today's behavior (codex implements, claude reviews/babysits)
|
|
86
|
+
// so existing configs are unaffected unless a role is set explicitly. The map is
|
|
87
|
+
// named agentCapabilities rather than `capabilities` because the node config
|
|
88
|
+
// already owns a top-level `capabilities` (advertised node capability list).
|
|
89
|
+
const spawnCapabilitySchema = z.enum(['spawn:codex', 'spawn:claude']);
|
|
90
|
+
const agentCapabilitiesSchema = z.object({
|
|
91
|
+
implementer: spawnCapabilitySchema.default('spawn:codex'),
|
|
92
|
+
reviewer: spawnCapabilitySchema.default('spawn:claude'),
|
|
93
|
+
babysitter: spawnCapabilitySchema.default('spawn:claude'),
|
|
94
|
+
}).default({});
|
|
79
95
|
const slackSchema = z.object({
|
|
80
96
|
channel: z.string(),
|
|
81
97
|
style: z.literal('threaded-summarized').default('threaded-summarized'),
|
|
82
98
|
botUserId: z.string().default('U0B2596R7EZ'),
|
|
99
|
+
// Slack user IDs to mention when an agent needs a human decision. Keeping
|
|
100
|
+
// this explicit avoids guessing that a Linear assignee name is also a Slack
|
|
101
|
+
// identity, while still making parked questions immediately actionable.
|
|
102
|
+
stakeholderUserIds: z.array(z.string().min(1)).default([]),
|
|
83
103
|
staleAfterMs: z.number().int().min(1_000).default(10 * 60_000),
|
|
84
104
|
}).optional();
|
|
85
105
|
const babysitterSchema = z.object({
|
|
@@ -127,6 +147,7 @@ const WorkspaceConfigObjectSchema = z.object({
|
|
|
127
147
|
repos: workspaceReposSchema,
|
|
128
148
|
batchSize: z.number().int().min(1).max(5).default(5),
|
|
129
149
|
models: modelsSchema,
|
|
150
|
+
agentCapabilities: agentCapabilitiesSchema,
|
|
130
151
|
slack: slackSchema,
|
|
131
152
|
// Linear remains the default whenever its issue sub-root is connected. When
|
|
132
153
|
// omitted, the orchestrator probes that sub-root once and falls back to
|
|
@@ -191,17 +212,28 @@ function normalizeWorkspaceConfig(cfg) {
|
|
|
191
212
|
};
|
|
192
213
|
}
|
|
193
214
|
function normalizeNodeConfig(cfg) {
|
|
215
|
+
const cloneRoot = cfg.cloneRoot === undefined
|
|
216
|
+
? undefined
|
|
217
|
+
: expandLeadingTilde(cfg.cloneRoot, 'cloneRoot');
|
|
194
218
|
return {
|
|
195
219
|
...cfg,
|
|
220
|
+
cloneRoot,
|
|
221
|
+
clonePaths: expandClonePaths(cfg.clonePaths),
|
|
196
222
|
factoryLoopHeartbeatPath: cfg.factoryLoopHeartbeatPath,
|
|
197
223
|
factoryLoopRegistryPath: cfg.factoryLoopRegistryPath,
|
|
198
224
|
};
|
|
199
225
|
}
|
|
200
226
|
function normalizeFactoryConfig(cfg) {
|
|
201
|
-
const
|
|
227
|
+
const topLevelCloneRoot = cfg.cloneRoot === undefined
|
|
228
|
+
? undefined
|
|
229
|
+
: expandLeadingTilde(cfg.cloneRoot, 'cloneRoot');
|
|
230
|
+
const legacyCloneRoot = cfg.repos.cloneRoot === undefined
|
|
231
|
+
? undefined
|
|
232
|
+
: expandLeadingTilde(cfg.repos.cloneRoot, 'repos.cloneRoot');
|
|
233
|
+
const cloneRoot = topLevelCloneRoot ?? legacyCloneRoot;
|
|
202
234
|
const explicitClonePaths = {
|
|
203
|
-
...cfg.repos.clonePaths,
|
|
204
|
-
...cfg.clonePaths,
|
|
235
|
+
...expandClonePaths(cfg.repos.clonePaths, 'repos.clonePaths'),
|
|
236
|
+
...expandClonePaths(cfg.clonePaths),
|
|
205
237
|
};
|
|
206
238
|
const resolved = resolveRepos(cfg.repos, cloneRoot, explicitClonePaths);
|
|
207
239
|
const labels = resolveSubscriptionLabels(cfg.subscription.labels, cfg.repos.names ?? []);
|
|
@@ -244,13 +276,16 @@ function resolveRepos(repos, cloneRoot, explicitClonePaths = repos.clonePaths) {
|
|
|
244
276
|
// Explicit clonePaths entries win.
|
|
245
277
|
const derivedClonePaths = {};
|
|
246
278
|
if (cloneRoot) {
|
|
247
|
-
const root = cloneRoot.replace(/\/+$/u, '');
|
|
279
|
+
const root = expandLeadingTilde(cloneRoot, 'cloneRoot').replace(/\/+$/u, '');
|
|
248
280
|
for (const repo of Object.values(resolvedByLabel)) {
|
|
249
281
|
const repoName = repo.includes('/') ? repo.slice(repo.lastIndexOf('/') + 1) : repo;
|
|
250
282
|
derivedClonePaths[repo] = `${root}/${repoName}`;
|
|
251
283
|
}
|
|
252
284
|
}
|
|
253
|
-
const resolvedClonePaths = {
|
|
285
|
+
const resolvedClonePaths = {
|
|
286
|
+
...derivedClonePaths,
|
|
287
|
+
...expandClonePaths(explicitClonePaths),
|
|
288
|
+
};
|
|
254
289
|
return {
|
|
255
290
|
byLabel: resolvedByLabel,
|
|
256
291
|
byProject,
|
|
@@ -259,6 +294,23 @@ function resolveRepos(repos, cloneRoot, explicitClonePaths = repos.clonePaths) {
|
|
|
259
294
|
defaultRepo,
|
|
260
295
|
};
|
|
261
296
|
}
|
|
297
|
+
function expandClonePaths(clonePaths, field = 'clonePaths') {
|
|
298
|
+
return Object.fromEntries(Object.entries(clonePaths).map(([repo, clonePath]) => [
|
|
299
|
+
repo,
|
|
300
|
+
expandLeadingTilde(clonePath, `${field}[${JSON.stringify(repo)}]`),
|
|
301
|
+
]));
|
|
302
|
+
}
|
|
303
|
+
/** Expand the shell-like home shorthand that Node's filesystem APIs do not. */
|
|
304
|
+
export function expandLeadingTilde(value, field = 'path') {
|
|
305
|
+
if (value === '~')
|
|
306
|
+
return homedir();
|
|
307
|
+
if (value.startsWith('~/'))
|
|
308
|
+
return join(homedir(), value.slice(2));
|
|
309
|
+
if (value.startsWith('~')) {
|
|
310
|
+
throw new Error(`${field} does not support ~user expansion; use ~ or ~/ instead`);
|
|
311
|
+
}
|
|
312
|
+
return value;
|
|
313
|
+
}
|
|
262
314
|
function resolveSubscriptionLabels(labels, repoNames) {
|
|
263
315
|
return labels.length > 0 ? labels : repoNames;
|
|
264
316
|
}
|
|
@@ -296,6 +348,10 @@ function combineSplitConfigInput(workspaceInput, nodeInput) {
|
|
|
296
348
|
const node = asConfigRecord(nodeInput);
|
|
297
349
|
const workspaceRepos = asOptionalConfigRecord(workspace.repos);
|
|
298
350
|
assertCompatibleWorkspaceIds(workspace.workspaceId, node.workspaceId);
|
|
351
|
+
// Validate tilde syntax in both split halves before node-local values take
|
|
352
|
+
// precedence, so an overridden ~user path is never silently accepted.
|
|
353
|
+
validateClonePathSyntax(workspaceRepos, 'workspaceConfig.repos');
|
|
354
|
+
validateClonePathSyntax(node, 'nodeConfig');
|
|
299
355
|
return {
|
|
300
356
|
...workspace,
|
|
301
357
|
...node,
|
|
@@ -306,6 +362,16 @@ function combineSplitConfigInput(workspaceInput, nodeInput) {
|
|
|
306
362
|
},
|
|
307
363
|
};
|
|
308
364
|
}
|
|
365
|
+
function validateClonePathSyntax(input, field) {
|
|
366
|
+
if (typeof input.cloneRoot === 'string')
|
|
367
|
+
expandLeadingTilde(input.cloneRoot, `${field}.cloneRoot`);
|
|
368
|
+
const clonePaths = asOptionalConfigRecord(input.clonePaths);
|
|
369
|
+
for (const [repo, clonePath] of Object.entries(clonePaths)) {
|
|
370
|
+
if (typeof clonePath === 'string') {
|
|
371
|
+
expandLeadingTilde(clonePath, `${field}.clonePaths[${JSON.stringify(repo)}]`);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
309
375
|
function assertCompatibleWorkspaceIds(workspaceId, nodeWorkspaceId) {
|
|
310
376
|
if (typeof workspaceId === 'string' &&
|
|
311
377
|
typeof nodeWorkspaceId === 'string' &&
|