@agent-relay/factory 0.0.0 → 0.1.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.
Files changed (235) hide show
  1. package/README.md +182 -23
  2. package/bin/factory.mjs +7 -0
  3. package/dist/cli/fleet.d.ts +81 -0
  4. package/dist/cli/fleet.d.ts.map +1 -0
  5. package/dist/cli/fleet.js +571 -0
  6. package/dist/cli/fleet.js.map +1 -0
  7. package/dist/config/schema.d.ts +1313 -0
  8. package/dist/config/schema.d.ts.map +1 -0
  9. package/dist/config/schema.js +320 -0
  10. package/dist/config/schema.js.map +1 -0
  11. package/dist/constants/linear.d.ts +6 -0
  12. package/dist/constants/linear.d.ts.map +1 -0
  13. package/dist/constants/linear.js +21 -0
  14. package/dist/constants/linear.js.map +1 -0
  15. package/dist/constants/slack.d.ts +3 -0
  16. package/dist/constants/slack.d.ts.map +1 -0
  17. package/dist/constants/slack.js +3 -0
  18. package/dist/constants/slack.js.map +1 -0
  19. package/dist/dispatch/templates.d.ts +52 -0
  20. package/dist/dispatch/templates.d.ts.map +1 -0
  21. package/dist/dispatch/templates.js +118 -0
  22. package/dist/dispatch/templates.js.map +1 -0
  23. package/dist/fleet/create-fleet.d.ts +14 -0
  24. package/dist/fleet/create-fleet.d.ts.map +1 -0
  25. package/dist/fleet/create-fleet.js +15 -0
  26. package/dist/fleet/create-fleet.js.map +1 -0
  27. package/dist/fleet/ensure-relay-broker.d.ts +24 -0
  28. package/dist/fleet/ensure-relay-broker.d.ts.map +1 -0
  29. package/dist/fleet/ensure-relay-broker.js +56 -0
  30. package/dist/fleet/ensure-relay-broker.js.map +1 -0
  31. package/dist/fleet/internal-fleet-client.d.ts +90 -0
  32. package/dist/fleet/internal-fleet-client.d.ts.map +1 -0
  33. package/dist/fleet/internal-fleet-client.js +602 -0
  34. package/dist/fleet/internal-fleet-client.js.map +1 -0
  35. package/dist/fleet/relay-fleet-client.d.ts +105 -0
  36. package/dist/fleet/relay-fleet-client.d.ts.map +1 -0
  37. package/dist/fleet/relay-fleet-client.js +509 -0
  38. package/dist/fleet/relay-fleet-client.js.map +1 -0
  39. package/dist/github/index.d.ts +5 -0
  40. package/dist/github/index.d.ts.map +1 -0
  41. package/dist/github/index.js +3 -0
  42. package/dist/github/index.js.map +1 -0
  43. package/dist/github/merge-gate.d.ts +47 -0
  44. package/dist/github/merge-gate.d.ts.map +1 -0
  45. package/dist/github/merge-gate.js +147 -0
  46. package/dist/github/merge-gate.js.map +1 -0
  47. package/dist/github/probe-closer.d.ts +15 -0
  48. package/dist/github/probe-closer.d.ts.map +1 -0
  49. package/dist/github/probe-closer.js +67 -0
  50. package/dist/github/probe-closer.js.map +1 -0
  51. package/dist/index.d.ts +36 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +20 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/issue-key-match.d.ts +3 -0
  56. package/dist/issue-key-match.d.ts.map +1 -0
  57. package/dist/issue-key-match.js +22 -0
  58. package/dist/issue-key-match.js.map +1 -0
  59. package/dist/linear/state-resolver.d.ts +26 -0
  60. package/dist/linear/state-resolver.d.ts.map +1 -0
  61. package/dist/linear/state-resolver.js +285 -0
  62. package/dist/linear/state-resolver.js.map +1 -0
  63. package/dist/mount/local-mount-preflight.d.ts +9 -0
  64. package/dist/mount/local-mount-preflight.d.ts.map +1 -0
  65. package/dist/mount/local-mount-preflight.js +149 -0
  66. package/dist/mount/local-mount-preflight.js.map +1 -0
  67. package/dist/mount/relayfile-binary.d.ts +9 -0
  68. package/dist/mount/relayfile-binary.d.ts.map +1 -0
  69. package/dist/mount/relayfile-binary.js +177 -0
  70. package/dist/mount/relayfile-binary.js.map +1 -0
  71. package/dist/mount/relayfile-cloud-mount-client.d.ts +123 -0
  72. package/dist/mount/relayfile-cloud-mount-client.d.ts.map +1 -0
  73. package/dist/mount/relayfile-cloud-mount-client.js +427 -0
  74. package/dist/mount/relayfile-cloud-mount-client.js.map +1 -0
  75. package/dist/node/factory-node.d.ts +59 -0
  76. package/dist/node/factory-node.d.ts.map +1 -0
  77. package/dist/node/factory-node.js +351 -0
  78. package/dist/node/factory-node.js.map +1 -0
  79. package/dist/node/factory.node.d.ts +3 -0
  80. package/dist/node/factory.node.d.ts.map +1 -0
  81. package/dist/node/factory.node.js +5 -0
  82. package/dist/node/factory.node.js.map +1 -0
  83. package/dist/orchestrator/batch-tracker.d.ts +42 -0
  84. package/dist/orchestrator/batch-tracker.d.ts.map +1 -0
  85. package/dist/orchestrator/batch-tracker.js +125 -0
  86. package/dist/orchestrator/batch-tracker.js.map +1 -0
  87. package/dist/orchestrator/factory.d.ts +58 -0
  88. package/dist/orchestrator/factory.d.ts.map +1 -0
  89. package/dist/orchestrator/factory.js +4372 -0
  90. package/dist/orchestrator/factory.js.map +1 -0
  91. package/dist/orchestrator/index.d.ts +5 -0
  92. package/dist/orchestrator/index.d.ts.map +1 -0
  93. package/dist/orchestrator/index.js +4 -0
  94. package/dist/orchestrator/index.js.map +1 -0
  95. package/dist/orchestrator/process-identity.d.ts +23 -0
  96. package/dist/orchestrator/process-identity.d.ts.map +1 -0
  97. package/dist/orchestrator/process-identity.js +122 -0
  98. package/dist/orchestrator/process-identity.js.map +1 -0
  99. package/dist/orchestrator/reaper.d.ts +60 -0
  100. package/dist/orchestrator/reaper.d.ts.map +1 -0
  101. package/dist/orchestrator/reaper.js +293 -0
  102. package/dist/orchestrator/reaper.js.map +1 -0
  103. package/dist/ports/fleet.d.ts +101 -0
  104. package/dist/ports/fleet.d.ts.map +1 -0
  105. package/dist/ports/fleet.js +2 -0
  106. package/dist/ports/fleet.js.map +1 -0
  107. package/dist/ports/index.d.ts +5 -0
  108. package/dist/ports/index.d.ts.map +1 -0
  109. package/dist/ports/index.js +2 -0
  110. package/dist/ports/index.js.map +1 -0
  111. package/dist/ports/mount.d.ts +56 -0
  112. package/dist/ports/mount.d.ts.map +1 -0
  113. package/dist/ports/mount.js +2 -0
  114. package/dist/ports/mount.js.map +1 -0
  115. package/dist/ports/state.d.ts +61 -0
  116. package/dist/ports/state.d.ts.map +1 -0
  117. package/dist/ports/state.js +2 -0
  118. package/dist/ports/state.js.map +1 -0
  119. package/dist/ports/system.d.ts +15 -0
  120. package/dist/ports/system.d.ts.map +1 -0
  121. package/dist/ports/system.js +2 -0
  122. package/dist/ports/system.js.map +1 -0
  123. package/dist/ports/writeback.d.ts +25 -0
  124. package/dist/ports/writeback.d.ts.map +1 -0
  125. package/dist/ports/writeback.js +2 -0
  126. package/dist/ports/writeback.js.map +1 -0
  127. package/dist/safety/factory-scope.d.ts +16 -0
  128. package/dist/safety/factory-scope.d.ts.map +1 -0
  129. package/dist/safety/factory-scope.js +107 -0
  130. package/dist/safety/factory-scope.js.map +1 -0
  131. package/dist/state/in-memory-state-store.d.ts +31 -0
  132. package/dist/state/in-memory-state-store.d.ts.map +1 -0
  133. package/dist/state/in-memory-state-store.js +115 -0
  134. package/dist/state/in-memory-state-store.js.map +1 -0
  135. package/dist/state/index.d.ts +3 -0
  136. package/dist/state/index.d.ts.map +1 -0
  137. package/dist/state/index.js +2 -0
  138. package/dist/state/index.js.map +1 -0
  139. package/dist/state/store.d.ts +29 -0
  140. package/dist/state/store.d.ts.map +1 -0
  141. package/dist/state/store.js +26 -0
  142. package/dist/state/store.js.map +1 -0
  143. package/dist/subscriptions/common.d.ts +7 -0
  144. package/dist/subscriptions/common.d.ts.map +1 -0
  145. package/dist/subscriptions/common.js +59 -0
  146. package/dist/subscriptions/common.js.map +1 -0
  147. package/dist/subscriptions/event-client.d.ts +40 -0
  148. package/dist/subscriptions/event-client.d.ts.map +1 -0
  149. package/dist/subscriptions/event-client.js +234 -0
  150. package/dist/subscriptions/event-client.js.map +1 -0
  151. package/dist/subscriptions/globs.d.ts +5 -0
  152. package/dist/subscriptions/globs.d.ts.map +1 -0
  153. package/dist/subscriptions/globs.js +50 -0
  154. package/dist/subscriptions/globs.js.map +1 -0
  155. package/dist/subscriptions/index.d.ts +8 -0
  156. package/dist/subscriptions/index.d.ts.map +1 -0
  157. package/dist/subscriptions/index.js +5 -0
  158. package/dist/subscriptions/index.js.map +1 -0
  159. package/dist/subscriptions/linear-filter.d.ts +26 -0
  160. package/dist/subscriptions/linear-filter.d.ts.map +1 -0
  161. package/dist/subscriptions/linear-filter.js +143 -0
  162. package/dist/subscriptions/linear-filter.js.map +1 -0
  163. package/dist/subscriptions/specs.d.ts +44 -0
  164. package/dist/subscriptions/specs.d.ts.map +1 -0
  165. package/dist/subscriptions/specs.js +195 -0
  166. package/dist/subscriptions/specs.js.map +1 -0
  167. package/dist/testing/fakes.d.ts +114 -0
  168. package/dist/testing/fakes.d.ts.map +1 -0
  169. package/dist/testing/fakes.js +219 -0
  170. package/dist/testing/fakes.js.map +1 -0
  171. package/dist/testing/index.d.ts +2 -0
  172. package/dist/testing/index.d.ts.map +1 -0
  173. package/dist/testing/index.js +2 -0
  174. package/dist/testing/index.js.map +1 -0
  175. package/dist/triage/heuristic.d.ts +42 -0
  176. package/dist/triage/heuristic.d.ts.map +1 -0
  177. package/dist/triage/heuristic.js +326 -0
  178. package/dist/triage/heuristic.js.map +1 -0
  179. package/dist/triage/index.d.ts +7 -0
  180. package/dist/triage/index.d.ts.map +1 -0
  181. package/dist/triage/index.js +5 -0
  182. package/dist/triage/index.js.map +1 -0
  183. package/dist/triage/llm.d.ts +11 -0
  184. package/dist/triage/llm.d.ts.map +1 -0
  185. package/dist/triage/llm.js +48 -0
  186. package/dist/triage/llm.js.map +1 -0
  187. package/dist/triage/schema.d.ts +344 -0
  188. package/dist/triage/schema.d.ts.map +1 -0
  189. package/dist/triage/schema.js +37 -0
  190. package/dist/triage/schema.js.map +1 -0
  191. package/dist/triage/tiered.d.ts +8 -0
  192. package/dist/triage/tiered.d.ts.map +1 -0
  193. package/dist/triage/tiered.js +47 -0
  194. package/dist/triage/tiered.js.map +1 -0
  195. package/dist/types.d.ts +212 -0
  196. package/dist/types.d.ts.map +1 -0
  197. package/dist/types.js +2 -0
  198. package/dist/types.js.map +1 -0
  199. package/dist/webhook/handler.d.ts +22 -0
  200. package/dist/webhook/handler.d.ts.map +1 -0
  201. package/dist/webhook/handler.js +57 -0
  202. package/dist/webhook/handler.js.map +1 -0
  203. package/dist/webhook/index.d.ts +5 -0
  204. package/dist/webhook/index.d.ts.map +1 -0
  205. package/dist/webhook/index.js +3 -0
  206. package/dist/webhook/index.js.map +1 -0
  207. package/dist/webhook/registrar.d.ts +16 -0
  208. package/dist/webhook/registrar.d.ts.map +1 -0
  209. package/dist/webhook/registrar.js +50 -0
  210. package/dist/webhook/registrar.js.map +1 -0
  211. package/dist/writeback/github.d.ts +6 -0
  212. package/dist/writeback/github.d.ts.map +1 -0
  213. package/dist/writeback/github.js +48 -0
  214. package/dist/writeback/github.js.map +1 -0
  215. package/dist/writeback/index.d.ts +6 -0
  216. package/dist/writeback/index.d.ts.map +1 -0
  217. package/dist/writeback/index.js +4 -0
  218. package/dist/writeback/index.js.map +1 -0
  219. package/dist/writeback/linear.d.ts +41 -0
  220. package/dist/writeback/linear.d.ts.map +1 -0
  221. package/dist/writeback/linear.js +286 -0
  222. package/dist/writeback/linear.js.map +1 -0
  223. package/dist/writeback/shared.d.ts +7 -0
  224. package/dist/writeback/shared.d.ts.map +1 -0
  225. package/dist/writeback/shared.js +29 -0
  226. package/dist/writeback/shared.js.map +1 -0
  227. package/dist/writeback/slack.d.ts +16 -0
  228. package/dist/writeback/slack.d.ts.map +1 -0
  229. package/dist/writeback/slack.js +104 -0
  230. package/dist/writeback/slack.js.map +1 -0
  231. package/package.json +54 -9
  232. package/scripts/com.agentrelay.factory-canary.plist.example +53 -0
  233. package/scripts/factory-canary.sh +89 -0
  234. package/index.d.ts +0 -2
  235. package/index.js +0 -7
@@ -0,0 +1,351 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import { hostname } from 'node:os';
4
+ import { basename, dirname, join, resolve, sep } from 'node:path';
5
+ import { spawn as spawnProcess } from 'node:child_process';
6
+ import { action, defineNode } from '@agent-relay/fleet';
7
+ import { z } from 'zod';
8
+ import { loadFactoryConfig, NodeConfigSchema } from '../config/schema.js';
9
+ import { buildRelayMcpHarnessConfig, capabilityCli, resolveAgentRelayMcpCommand, } from '../fleet/internal-fleet-client.js';
10
+ export const FACTORY_NODE_CONFIG_ENV = 'FACTORY_NODE_CONFIG';
11
+ export const AGENT_RELAY_FACTORY_NODE_CONFIG_ENV = 'AGENT_RELAY_FACTORY_NODE_CONFIG';
12
+ export const DEFAULT_FACTORY_NODE_CONFIG_PATH = 'factory.node.json';
13
+ const factoryNodeCapabilities = ['spawn:claude', 'spawn:codex', 'workflow:run'];
14
+ const knownFactoryNodeCapabilities = new Set(factoryNodeCapabilities);
15
+ const requireForResolve = createRequire(import.meta.url);
16
+ const restartPolicySchema = z.object({
17
+ enabled: z.boolean().optional(),
18
+ max_restarts: z.number().int().min(0).optional(),
19
+ cooldown_ms: z.number().int().min(0).optional(),
20
+ max_consecutive_failures: z.number().int().min(0).optional(),
21
+ }).passthrough();
22
+ const spawnCapabilityInputSchema = z.object({
23
+ name: z.string().min(1).optional(),
24
+ agent: z.string().min(1).optional(),
25
+ repo: z.string().min(1).optional(),
26
+ clone_path: z.string().min(1).optional(),
27
+ clonePath: z.string().min(1).optional(),
28
+ cwd: z.string().min(1).optional(),
29
+ task: z.string().optional(),
30
+ model: z.string().min(1).optional(),
31
+ session_ref: z.string().min(1).optional(),
32
+ sessionRef: z.string().min(1).optional(),
33
+ invocationId: z.string().min(1).optional(),
34
+ invocation_id: z.string().min(1).optional(),
35
+ channels: z.array(z.string().min(1)).optional(),
36
+ channel: z.string().min(1).optional(),
37
+ args: z.array(z.string()).optional(),
38
+ restart_policy: restartPolicySchema.optional(),
39
+ restartPolicy: restartPolicySchema.optional(),
40
+ skip_relay_prompt: z.boolean().optional(),
41
+ }).passthrough().transform((input) => ({
42
+ ...input,
43
+ name: input.name ?? input.agent,
44
+ clonePath: input.clonePath ?? input.clone_path,
45
+ sessionRef: input.sessionRef ?? input.session_ref,
46
+ invocationId: input.invocationId ?? input.invocation_id,
47
+ channels: input.channels ?? (input.channel ? [input.channel] : undefined),
48
+ restartPolicy: input.restartPolicy ?? input.restart_policy,
49
+ }));
50
+ const workflowCapabilityInputSchema = z.object({
51
+ name: z.string().min(1).optional(),
52
+ agent: z.string().min(1).optional(),
53
+ repo: z.string().min(1).optional(),
54
+ clone_path: z.string().min(1).optional(),
55
+ clonePath: z.string().min(1).optional(),
56
+ cwd: z.string().min(1).optional(),
57
+ workflow: z.string().min(1),
58
+ inputs: z.record(z.unknown()).default({}),
59
+ invocationId: z.string().min(1).optional(),
60
+ invocation_id: z.string().min(1).optional(),
61
+ }).passthrough().transform((input) => ({
62
+ ...input,
63
+ name: input.name ?? input.agent,
64
+ clonePath: input.clonePath ?? input.clone_path,
65
+ invocationId: input.invocationId ?? input.invocation_id,
66
+ }));
67
+ export function createFactoryNodeDefinition(options) {
68
+ const config = options.config;
69
+ const capabilities = normalizeCapabilities(config.capabilities);
70
+ const metadata = nodeCapabilityMetadata(config);
71
+ const handlers = {};
72
+ for (const capability of capabilities) {
73
+ if (capability === 'workflow:run') {
74
+ handlers[capability] = action({
75
+ input: workflowCapabilityInputSchema,
76
+ metadata: { ...metadata, handler: 'relayflows' },
77
+ }, async (input, ctx) => runWorkflowCapability(input, ctx, {
78
+ config,
79
+ workflowRunner: options.workflowRunner ?? runRelayflowsWorkflow,
80
+ }));
81
+ continue;
82
+ }
83
+ handlers[capability] = action({
84
+ input: spawnCapabilityInputSchema,
85
+ metadata: { ...metadata, handler: 'harness', cli: capabilityCli[capability] },
86
+ }, async (input, ctx) => runSpawnCapability(capability, input, ctx, {
87
+ config,
88
+ resolveAgentRelayMcpCommand: options.resolveAgentRelayMcpCommand ?? resolveAgentRelayMcpCommand,
89
+ }));
90
+ }
91
+ return defineNode({
92
+ name: options.name ?? defaultFactoryNodeName(),
93
+ ...(options.maxAgents !== undefined ? { maxAgents: options.maxAgents } : {}),
94
+ capabilities: handlers,
95
+ tags: options.tags ?? defaultFactoryNodeTags(config),
96
+ version: options.version ?? 'factory-node-v1',
97
+ });
98
+ }
99
+ export function readFactoryNodeConfigSync(configPath = resolveFactoryNodeConfigPath()) {
100
+ const raw = readFileSync(configPath, 'utf8');
101
+ const parsed = JSON.parse(raw);
102
+ return parseFactoryNodeConfig(parsed);
103
+ }
104
+ export function resolveFactoryNodeConfigPath(env = process.env) {
105
+ return resolve(env[AGENT_RELAY_FACTORY_NODE_CONFIG_ENV] ??
106
+ env[FACTORY_NODE_CONFIG_ENV] ??
107
+ env.FACTORY_CONFIG ??
108
+ DEFAULT_FACTORY_NODE_CONFIG_PATH);
109
+ }
110
+ export function parseFactoryNodeConfig(input) {
111
+ const record = asRecord(input);
112
+ if ('nodeConfig' in record) {
113
+ return NodeConfigSchema.parse(record.nodeConfig);
114
+ }
115
+ if ('factoryConfig' in record || 'workspaceConfig' in record || 'repos' in record) {
116
+ return loadFactoryConfig(input).nodeConfig;
117
+ }
118
+ return NodeConfigSchema.parse(input);
119
+ }
120
+ /**
121
+ * Builds the `inventory.sync` payload a node emits on reconnect so the cloud can
122
+ * reconcile live agents against the node's advertised clone paths (AC3/AC5).
123
+ *
124
+ * Provisional surface: the wire-level reconnect/drain handshake is owned by the
125
+ * installed `agent-relay` sidecar, not this package — the sidecar calls this
126
+ * builder via the default node export to produce the reconcile payload. It is
127
+ * exported (and unit-proven) here so the payload shape stays pinned to NodeConfig
128
+ * even though no in-package handler invokes it directly.
129
+ */
130
+ export function factoryNodeInventorySync(config, agents) {
131
+ return {
132
+ type: 'inventory.sync',
133
+ workspaceId: config.workspaceId,
134
+ clonePaths: { ...config.clonePaths },
135
+ agents: agents.map((agent) => ({ ...agent })),
136
+ };
137
+ }
138
+ async function runSpawnCapability(capability, input, ctx, deps) {
139
+ if (!input.name) {
140
+ throw new Error(`${capability} requires name or agent`);
141
+ }
142
+ const cwd = resolveCheckoutPath(deps.config, input);
143
+ const cli = capabilityCli[capability];
144
+ const command = deps.resolveAgentRelayMcpCommand?.();
145
+ const spawnInput = {
146
+ name: input.name,
147
+ cli,
148
+ args: input.args,
149
+ channels: input.channels,
150
+ task: input.task,
151
+ model: input.model,
152
+ cwd,
153
+ continueFrom: input.sessionRef,
154
+ restartPolicy: input.restartPolicy,
155
+ };
156
+ const harnessConfig = command ? buildRelayMcpHarnessConfig(spawnInput, command) : undefined;
157
+ const agent = {
158
+ name: input.name,
159
+ runtime: 'pty',
160
+ cli,
161
+ ...(input.model ? { model: input.model } : {}),
162
+ ...(input.args && input.args.length > 0 ? { args: input.args } : {}),
163
+ ...(input.channels ? { channels: input.channels } : {}),
164
+ cwd,
165
+ ...(input.sessionRef ? { session_id: input.sessionRef } : {}),
166
+ ...(input.restartPolicy ? { restart_policy: input.restartPolicy } : {}),
167
+ ...(harnessConfig ? { harness_config: harnessConfig } : {}),
168
+ };
169
+ const output = await ctx.spawnAgent({
170
+ agent,
171
+ ...(input.task !== undefined ? { initialTask: input.task } : {}),
172
+ skipRelayPrompt: input.skip_relay_prompt ?? false,
173
+ invocationId: input.invocationId ?? ctx.invocationId,
174
+ });
175
+ return {
176
+ name: input.name,
177
+ capability,
178
+ cwd,
179
+ invocationId: input.invocationId ?? ctx.invocationId,
180
+ agent: output,
181
+ };
182
+ }
183
+ async function runWorkflowCapability(input, ctx, deps) {
184
+ const cwd = resolveCheckoutPath(deps.config, input);
185
+ const result = await deps.workflowRunner({
186
+ workflow: input.workflow,
187
+ cwd,
188
+ inputs: input.inputs,
189
+ invocationId: input.invocationId ?? ctx.invocationId,
190
+ });
191
+ return {
192
+ name: input.name ?? input.workflow,
193
+ capability: 'workflow:run',
194
+ workflow: input.workflow,
195
+ invocationId: input.invocationId ?? ctx.invocationId,
196
+ ...result,
197
+ cwd,
198
+ };
199
+ }
200
+ export async function runRelayflowsWorkflow(input) {
201
+ const { command, args } = resolveRelayflowsInvocation(input.workflow);
202
+ const childEnv = {
203
+ ...process.env,
204
+ RELAYFLOWS_INPUTS_JSON: JSON.stringify(input.inputs),
205
+ FACTORY_WORKFLOW_INPUTS_JSON: JSON.stringify(input.inputs),
206
+ ...(input.invocationId ? { RELAY_INVOCATION_ID: input.invocationId } : {}),
207
+ };
208
+ return await new Promise((resolvePromise, reject) => {
209
+ const child = spawnProcess(command, args, {
210
+ cwd: input.cwd,
211
+ env: childEnv,
212
+ stdio: ['ignore', 'pipe', 'pipe'],
213
+ });
214
+ let stdout = '';
215
+ let stderr = '';
216
+ child.stdout?.setEncoding('utf8');
217
+ child.stderr?.setEncoding('utf8');
218
+ child.stdout?.on('data', (chunk) => {
219
+ stdout += chunk;
220
+ });
221
+ child.stderr?.on('data', (chunk) => {
222
+ stderr += chunk;
223
+ });
224
+ child.on('error', reject);
225
+ child.on('close', (code) => {
226
+ const exitCode = code ?? 1;
227
+ const result = { command, args, cwd: input.cwd, exitCode, stdout, stderr };
228
+ if (exitCode === 0) {
229
+ resolvePromise(result);
230
+ return;
231
+ }
232
+ reject(new Error(`relayflows run ${input.workflow} failed with exit code ${exitCode}${stderr ? `: ${stderr.trim()}` : ''}`));
233
+ });
234
+ });
235
+ }
236
+ function resolveRelayflowsInvocation(workflow) {
237
+ if (process.env.RELAYFLOWS_BIN) {
238
+ return { command: process.env.RELAYFLOWS_BIN, args: ['run', workflow] };
239
+ }
240
+ try {
241
+ const packageJsonPath = requireForResolve.resolve('@relayflows/cli/package.json');
242
+ return { command: process.execPath, args: [join(dirname(packageJsonPath), 'dist', 'cli.js'), 'run', workflow] };
243
+ }
244
+ catch {
245
+ return { command: 'relayflows', args: ['run', workflow] };
246
+ }
247
+ }
248
+ function resolveCheckoutPath(config, input) {
249
+ const clonePaths = config.clonePaths;
250
+ const configuredPaths = new Set(Object.values(clonePaths).map((path) => resolve(path)));
251
+ const explicitPath = input.clonePath ?? input.cwd;
252
+ if (explicitPath) {
253
+ const resolved = resolve(explicitPath);
254
+ // Only honor a cloud-supplied path when it is advertised: it must be one of
255
+ // the configured clonePaths, or live under the configured cloneRoot. Empty
256
+ // clonePaths must NOT be treated as "allow all" — that would let the cloud
257
+ // direct spawns into arbitrary local directories (see F4).
258
+ if (configuredPaths.has(resolved) || isWithinCloneRoot(config, resolved)) {
259
+ return resolved;
260
+ }
261
+ throw new Error(`checkout path is not advertised by this node: ${explicitPath}`);
262
+ }
263
+ const repo = input.repo ?? repoFromInputs(input.inputs);
264
+ if (repo) {
265
+ const mapped = checkoutForRepo(config, repo);
266
+ if (mapped)
267
+ return mapped;
268
+ }
269
+ const paths = Object.values(clonePaths);
270
+ if (paths.length === 1) {
271
+ return resolve(paths[0]);
272
+ }
273
+ throw new Error(repo
274
+ ? `no checkout path configured for repo ${repo}`
275
+ : 'spawn requires repo, clonePath, cwd, or a NodeConfig with exactly one clonePath');
276
+ }
277
+ function isWithinCloneRoot(config, resolvedPath) {
278
+ if (!config.cloneRoot)
279
+ return false;
280
+ const root = resolve(config.cloneRoot);
281
+ if (resolvedPath === root)
282
+ return true;
283
+ const prefix = root.endsWith(sep) ? root : root + sep;
284
+ return resolvedPath.startsWith(prefix);
285
+ }
286
+ function checkoutForRepo(config, repo) {
287
+ const candidates = new Set([
288
+ repo,
289
+ repo.replace(/^\/+|\/+$/gu, ''),
290
+ basename(repo),
291
+ ]);
292
+ for (const [key, clonePath] of Object.entries(config.clonePaths)) {
293
+ if (candidates.has(key) || candidates.has(basename(key))) {
294
+ return resolve(clonePath);
295
+ }
296
+ }
297
+ if (config.cloneRoot) {
298
+ return resolve(join(config.cloneRoot, basename(repo)));
299
+ }
300
+ return undefined;
301
+ }
302
+ function repoFromInputs(inputs) {
303
+ if (!inputs)
304
+ return undefined;
305
+ for (const key of ['repo', 'repository', 'repoLabel', 'repo_label']) {
306
+ const value = inputs[key];
307
+ if (typeof value === 'string' && value.trim()) {
308
+ return value.trim();
309
+ }
310
+ }
311
+ return undefined;
312
+ }
313
+ function normalizeCapabilities(capabilities) {
314
+ const normalized = capabilities
315
+ .map((capability) => capability.trim())
316
+ .filter((capability) => knownFactoryNodeCapabilities.has(capability));
317
+ const unique = [...new Set(normalized)];
318
+ if (unique.length === 0) {
319
+ throw new Error('NodeConfig.capabilities must include at least one factory node capability');
320
+ }
321
+ return unique;
322
+ }
323
+ function nodeCapabilityMetadata(config) {
324
+ return {
325
+ factoryNode: true,
326
+ ...(config.workspaceId ? { workspaceId: config.workspaceId } : {}),
327
+ cloneRoot: config.cloneRoot ?? null,
328
+ clonePaths: jsonRecord(config.clonePaths),
329
+ dryRun: config.dryRun,
330
+ };
331
+ }
332
+ function jsonRecord(input) {
333
+ return Object.fromEntries(Object.entries(input).map(([key, value]) => [key, value]));
334
+ }
335
+ function defaultFactoryNodeTags(config) {
336
+ return [
337
+ 'factory',
338
+ ...(config.workspaceId ? [`workspace:${config.workspaceId}`] : []),
339
+ ...Object.keys(config.clonePaths).map((repo) => `repo:${repo}`),
340
+ ];
341
+ }
342
+ function defaultFactoryNodeName() {
343
+ return process.env.AGENT_RELAY_NODE_NAME || process.env.FACTORY_NODE_NAME || `factory-${hostname()}`;
344
+ }
345
+ function asRecord(value) {
346
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
347
+ return value;
348
+ }
349
+ throw new Error('factory node config must be a JSON object');
350
+ }
351
+ //# sourceMappingURL=factory-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory-node.js","sourceRoot":"","sources":["../../src/node/factory-node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("@agent-relay/fleet").FleetNodeDefinition;
2
+ export default _default;
3
+ //# sourceMappingURL=factory.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.node.d.ts","sourceRoot":"","sources":["../../src/node/factory.node.ts"],"names":[],"mappings":";AAEA,wBAEE"}
@@ -0,0 +1,5 @@
1
+ import { createFactoryNodeDefinition, readFactoryNodeConfigSync } from './factory-node.js';
2
+ export default createFactoryNodeDefinition({
3
+ config: readFactoryNodeConfigSync(),
4
+ });
5
+ //# sourceMappingURL=factory.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.node.js","sourceRoot":"","sources":["../../src/node/factory.node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAA;AAEvF,eAAe,2BAA2B,CAAC;IACzC,MAAM,EAAE,yBAAyB,EAAE;CACpC,CAAC,CAAA"}
@@ -0,0 +1,42 @@
1
+ import type { AgentSpec, SpawnResult } from '../ports/index.js';
2
+ import type { DispatchResult, IssueRef, TriageDecision } from '../types.js';
3
+ export interface TrackedAgent {
4
+ spec: AgentSpec;
5
+ result?: SpawnResult;
6
+ sessionRef?: string;
7
+ }
8
+ export interface InFlightIssue {
9
+ issue: IssueRef;
10
+ decision: TriageDecision;
11
+ dryRun: boolean;
12
+ agents: Map<string, TrackedAgent>;
13
+ invocationIds: Set<string>;
14
+ result?: DispatchResult;
15
+ }
16
+ export interface QueuedIssue {
17
+ issue: IssueRef;
18
+ decision: TriageDecision;
19
+ dryRun: boolean;
20
+ }
21
+ export declare class BatchTracker {
22
+ #private;
23
+ constructor(batchSize: number);
24
+ get size(): number;
25
+ get inFlight(): InFlightIssue[];
26
+ get queued(): QueuedIssue[];
27
+ getIssue(issue: IssueRef): InFlightIssue | undefined;
28
+ getIssueByAgent(name: string): InFlightIssue | undefined;
29
+ isInFlight(issue: IssueRef): boolean;
30
+ isQueued(issue: IssueRef): boolean;
31
+ canStart(): boolean;
32
+ start(decision: TriageDecision, dryRun: boolean): InFlightIssue | undefined;
33
+ queue(decision: TriageDecision, dryRun: boolean): boolean;
34
+ complete(issue: IssueRef): QueuedIssue | undefined;
35
+ abandon(issue: IssueRef): void;
36
+ invocationIdFor(issue: IssueRef, spec: AgentSpec): string;
37
+ shouldSpawn(record: InFlightIssue, invocationId: string): boolean;
38
+ recordSpawn(record: InFlightIssue, spec: AgentSpec, invocationId: string, result: SpawnResult): void;
39
+ recordDryRun(record: InFlightIssue, spec: AgentSpec, invocationId: string): void;
40
+ }
41
+ export declare const issueKey: (issue: IssueRef) => string;
42
+ //# sourceMappingURL=batch-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-tracker.d.ts","sourceRoot":"","sources":["../../src/orchestrator/batch-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAExE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAA;IACf,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,QAAQ,CAAA;IACf,QAAQ,EAAE,cAAc,CAAA;IACxB,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACjC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC1B,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,QAAQ,CAAA;IACf,QAAQ,EAAE,cAAc,CAAA;IACxB,MAAM,EAAE,OAAO,CAAA;CAChB;AAYD,qBAAa,YAAY;;gBAMX,SAAS,EAAE,MAAM;IAI7B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,QAAQ,IAAI,aAAa,EAAE,CAE9B;IAED,IAAI,MAAM,IAAI,WAAW,EAAE,CAE1B;IAED,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,aAAa,GAAG,SAAS;IAIpD,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIxD,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAIpC,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAIlC,QAAQ,IAAI,OAAO;IAInB,KAAK,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,GAAG,aAAa,GAAG,SAAS;IAwB3E,KAAK,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO;IAUzD,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,WAAW,GAAG,SAAS;IAsBlD,OAAO,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAY9B,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM;IAIzD,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO;IAIjE,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI;IAUpG,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;CASjF;AAED,eAAO,MAAM,QAAQ,GAAI,OAAO,QAAQ,KAAG,MAAoD,CAAA"}
@@ -0,0 +1,125 @@
1
+ const stableHash = (input) => {
2
+ let hash = 0x811c9dc5;
3
+ for (let index = 0; index < input.length; index += 1) {
4
+ hash ^= input.charCodeAt(index);
5
+ hash = Math.imul(hash, 0x01000193);
6
+ }
7
+ return (hash >>> 0).toString(36);
8
+ };
9
+ export class BatchTracker {
10
+ #limit;
11
+ #inFlight = new Map();
12
+ #queued = new Map();
13
+ #invocationIds = new Set();
14
+ constructor(batchSize) {
15
+ this.#limit = Math.max(1, Math.min(5, Math.trunc(batchSize)));
16
+ }
17
+ get size() {
18
+ return this.#inFlight.size;
19
+ }
20
+ get inFlight() {
21
+ return [...this.#inFlight.values()];
22
+ }
23
+ get queued() {
24
+ return [...this.#queued.values()];
25
+ }
26
+ getIssue(issue) {
27
+ return this.#inFlight.get(issueKey(issue));
28
+ }
29
+ getIssueByAgent(name) {
30
+ return this.inFlight.find((record) => record.agents.has(name));
31
+ }
32
+ isInFlight(issue) {
33
+ return this.#inFlight.has(issueKey(issue));
34
+ }
35
+ isQueued(issue) {
36
+ return this.#queued.has(issueKey(issue));
37
+ }
38
+ canStart() {
39
+ return this.#inFlight.size < this.#limit;
40
+ }
41
+ start(decision, dryRun) {
42
+ const key = issueKey(decision.issue);
43
+ const existing = this.#inFlight.get(key);
44
+ if (existing) {
45
+ return existing;
46
+ }
47
+ if (!this.canStart()) {
48
+ this.queue(decision, dryRun);
49
+ return undefined;
50
+ }
51
+ const record = {
52
+ issue: decision.issue,
53
+ decision,
54
+ dryRun,
55
+ agents: new Map(),
56
+ invocationIds: new Set(),
57
+ };
58
+ this.#inFlight.set(key, record);
59
+ this.#queued.delete(key);
60
+ return record;
61
+ }
62
+ queue(decision, dryRun) {
63
+ const key = issueKey(decision.issue);
64
+ if (this.#inFlight.has(key) || this.#queued.has(key)) {
65
+ return false;
66
+ }
67
+ this.#queued.set(key, { issue: decision.issue, decision, dryRun });
68
+ return true;
69
+ }
70
+ complete(issue) {
71
+ const key = issueKey(issue);
72
+ const record = this.#inFlight.get(key);
73
+ if (record) {
74
+ for (const invocationId of record.invocationIds) {
75
+ this.#invocationIds.delete(invocationId);
76
+ }
77
+ }
78
+ this.#inFlight.delete(key);
79
+ if (!this.canStart()) {
80
+ return undefined;
81
+ }
82
+ const next = this.#queued.values().next().value;
83
+ if (next) {
84
+ this.#queued.delete(issueKey(next.issue));
85
+ }
86
+ return next;
87
+ }
88
+ abandon(issue) {
89
+ const key = issueKey(issue);
90
+ const record = this.#inFlight.get(key);
91
+ if (record) {
92
+ for (const invocationId of record.invocationIds) {
93
+ this.#invocationIds.delete(invocationId);
94
+ }
95
+ }
96
+ this.#inFlight.delete(key);
97
+ this.#queued.delete(key);
98
+ }
99
+ invocationIdFor(issue, spec) {
100
+ return spec.invocationId ?? `factory:${issue.key}:${stableHash(`${issue.uuid}:${spec.role}:${spec.name}:${spec.repo}`)}`;
101
+ }
102
+ shouldSpawn(record, invocationId) {
103
+ return !record.invocationIds.has(invocationId) && !this.#invocationIds.has(invocationId);
104
+ }
105
+ recordSpawn(record, spec, invocationId, result) {
106
+ record.invocationIds.add(invocationId);
107
+ this.#invocationIds.add(invocationId);
108
+ record.agents.set(result.name, {
109
+ spec: { ...spec, invocationId },
110
+ result,
111
+ sessionRef: result.sessionRef ?? spec.sessionRef,
112
+ });
113
+ }
114
+ recordDryRun(record, spec, invocationId) {
115
+ record.invocationIds.add(invocationId);
116
+ this.#invocationIds.add(invocationId);
117
+ record.agents.set(spec.name, {
118
+ spec: { ...spec, invocationId },
119
+ result: { name: spec.name, sessionRef: spec.sessionRef },
120
+ sessionRef: spec.sessionRef,
121
+ });
122
+ }
123
+ }
124
+ export const issueKey = (issue) => `${issue.key}:${issue.uuid}:${issue.path}`;
125
+ //# sourceMappingURL=batch-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch-tracker.js","sourceRoot":"","sources":["../../src/orchestrator/batch-tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import { type FactoryConfig } from '../config/schema.js';
2
+ import type { ChangeEvent, MountClient } from '../ports/index.js';
3
+ import type { DispatchResult, Factory, FactoryEventPayload, FactoryPorts, FactoryStatus, FactoryStartOptions, FactoryLoopRunOptions, FactoryLoopHeartbeat, FactoryLoopLiveness, IterationReport, LinearIssue, TriageDecision } from '../types.js';
4
+ type FactoryEvent = 'issue-queued' | 'dispatched' | 'issue-done' | 'writeback-verified' | 'error';
5
+ type Listener = (payload: FactoryEventPayload) => void;
6
+ type GithubIssueSource = {
7
+ owner: string;
8
+ repoName: string;
9
+ repo: string;
10
+ number: number;
11
+ title: string;
12
+ body: string;
13
+ url: string;
14
+ state: string;
15
+ labels: string[];
16
+ path: string;
17
+ raw: Record<string, unknown>;
18
+ };
19
+ export declare const LIVE_GITHUB_ISSUE_GLOB = "/github/repos/**";
20
+ export declare const DEFAULT_FACTORY_LOOP_HEARTBEAT_PATH = "/tmp/factory-run/factory-loop-heartbeat.json";
21
+ export declare const DEFAULT_FACTORY_LOOP_REGISTRY_PATH = "/tmp/factory-run/factory-loop-registry.json";
22
+ export declare function createFactory(config: FactoryConfig, ports: FactoryPorts): Factory;
23
+ export declare class FactoryLoop implements Factory {
24
+ #private;
25
+ constructor(config: FactoryConfig, ports: FactoryPorts);
26
+ start(opts?: FactoryStartOptions): Promise<void>;
27
+ stop(): Promise<void>;
28
+ dispose(): Promise<void>;
29
+ runOnce(opts?: {
30
+ dryRun?: boolean;
31
+ }): Promise<IterationReport>;
32
+ runLoop(opts?: FactoryLoopRunOptions): Promise<IterationReport[]>;
33
+ triageIssue(issue: LinearIssue): Promise<TriageDecision>;
34
+ dispatch(decision: TriageDecision, opts?: {
35
+ dryRun?: boolean;
36
+ }): Promise<DispatchResult>;
37
+ status(): FactoryStatus;
38
+ on(event: FactoryEvent, listener: Listener): () => void;
39
+ }
40
+ export declare function parseLinearIssue(path: string, content: unknown): LinearIssue;
41
+ export declare function readLinearIssueWithCanonicalFallback(mount: Pick<MountClient, 'readFile'>, path: string): Promise<LinearIssue>;
42
+ export declare function parseGithubIssue(path: string, content: unknown): GithubIssueSource;
43
+ export declare function readFactoryLoopHeartbeat(path?: string): Promise<FactoryLoopHeartbeat | undefined>;
44
+ export declare function checkFactoryLoopLiveness(heartbeat: FactoryLoopHeartbeat | undefined, opts?: {
45
+ nowMs?: number;
46
+ staleMs?: number;
47
+ }): FactoryLoopLiveness;
48
+ export declare function isRealLinearIssue(issue: LinearIssue): boolean;
49
+ export declare const githubIssuePathParts: (path: string) => {
50
+ owner: string;
51
+ repo: string;
52
+ number: number;
53
+ slug?: string;
54
+ } | undefined;
55
+ export declare const keyFromPath: (path: string) => string;
56
+ export declare const changeEventPath: (event: ChangeEvent) => string | undefined;
57
+ export {};
58
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/orchestrator/factory.ts"],"names":[],"mappings":"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"}