@h-rig/transport-plugin 0.0.6-alpha.158

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,923 @@
1
+ // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __returnValue = (v) => v;
4
+ function __exportSetter(name, newValue) {
5
+ this[name] = __returnValue.bind(null, newValue);
6
+ }
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, {
10
+ get: all[name],
11
+ enumerable: true,
12
+ configurable: true,
13
+ set: __exportSetter.bind(all, name)
14
+ });
15
+ };
16
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
+
18
+ // packages/transport-plugin/relay-registry/src/client.ts
19
+ import { Effect, Queue, Stream } from "effect";
20
+ function registryUrl(baseUrl, pathname) {
21
+ const base = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
22
+ return new URL(pathname.replace(/^\/+/, ""), base);
23
+ }
24
+ function registryWsUrl(baseUrl, pathname) {
25
+ const url = registryUrl(baseUrl, pathname);
26
+ url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
27
+ return url;
28
+ }
29
+ async function parseResponseJson(response) {
30
+ const text = await response.text();
31
+ const data = text ? JSON.parse(text) : null;
32
+ if (!response.ok) {
33
+ const message = data && typeof data === "object" && "error" in data ? String(data.error) : response.statusText;
34
+ throw new Error(`registry request failed (${response.status}): ${message}`);
35
+ }
36
+ return data;
37
+ }
38
+ function workerProjectionFrame(frame) {
39
+ return typeof frame === "object" && frame !== null && "type" in frame && frame.type === "projection" ? frame : { type: "projection", projection: frame };
40
+ }
41
+ function connectWorkerProjection(first, runId, options) {
42
+ const cfg = typeof first === "string" ? { baseUrl: options?.baseUrl ?? "", namespaceKey: first, runId: runId ?? "", ...options?.WebSocket ? { WebSocket: options.WebSocket } : {} } : first;
43
+ if (!cfg.baseUrl)
44
+ throw new Error("baseUrl is required for worker projection websocket");
45
+ if (!cfg.runId)
46
+ throw new Error("runId is required for worker projection websocket");
47
+ const WebSocketCtor = cfg.WebSocket ?? WebSocket;
48
+ const url = registryWsUrl(cfg.baseUrl, "worker");
49
+ url.searchParams.set("namespaceKey", cfg.namespaceKey);
50
+ url.searchParams.set("runId", cfg.runId);
51
+ const ws = new WebSocketCtor(url);
52
+ const pending = [];
53
+ let closed = false;
54
+ const ready = new Promise((resolve, reject) => {
55
+ ws.addEventListener("open", () => {
56
+ resolve();
57
+ while (pending.length && ws.readyState === WebSocketCtor.OPEN)
58
+ ws.send(JSON.stringify(pending.shift()));
59
+ }, { once: true });
60
+ ws.addEventListener("error", () => {
61
+ closed = true;
62
+ pending.length = 0;
63
+ reject(new Error("worker projection websocket error"));
64
+ }, { once: true });
65
+ });
66
+ ready.catch(() => {
67
+ return;
68
+ });
69
+ return {
70
+ ready,
71
+ push(frame) {
72
+ if (closed)
73
+ return;
74
+ const encoded = workerProjectionFrame(frame);
75
+ if (ws.readyState === WebSocketCtor.OPEN) {
76
+ ws.send(JSON.stringify(encoded));
77
+ return;
78
+ }
79
+ pending.push(encoded);
80
+ },
81
+ close() {
82
+ closed = true;
83
+ pending.length = 0;
84
+ try {
85
+ ws.close();
86
+ } catch {}
87
+ }
88
+ };
89
+ }
90
+ function subscribeDiscovery(namespaceKey, repo, options) {
91
+ return Stream.callback((queue) => Effect.sync(() => {
92
+ const WebSocketCtor = options.WebSocket ?? WebSocket;
93
+ const url = registryWsUrl(options.baseUrl, "ws");
94
+ url.searchParams.set("namespaceKey", namespaceKey);
95
+ if (repo)
96
+ url.searchParams.set("repo", repo);
97
+ const ws = new WebSocketCtor(url);
98
+ const entries = new Map;
99
+ const snapshot = (sentAt) => ({
100
+ type: "registry.snapshot",
101
+ namespaceKey,
102
+ sentAt,
103
+ entries: Array.from(entries.values())
104
+ });
105
+ ws.addEventListener("message", (event) => {
106
+ try {
107
+ const text = typeof event.data === "string" ? event.data : String(event.data);
108
+ const frame = JSON.parse(text);
109
+ if (frame?.type === "registry.snapshot") {
110
+ entries.clear();
111
+ for (const entry of frame.entries)
112
+ entries.set(entry.roomId, entry);
113
+ Queue.offerUnsafe(queue, frame);
114
+ return;
115
+ }
116
+ if (frame?.type !== "registry.delta")
117
+ return;
118
+ if (frame.action === "remove") {
119
+ entries.delete(frame.roomId);
120
+ } else if (frame.entry) {
121
+ entries.set(frame.entry.roomId, frame.entry);
122
+ }
123
+ Queue.offerUnsafe(queue, snapshot(frame.sentAt));
124
+ } catch {}
125
+ });
126
+ ws.addEventListener("error", () => {});
127
+ return ws;
128
+ }).pipe(Effect.flatMap((ws) => Effect.addFinalizer(() => Effect.sync(() => ws.close())))), { bufferSize: 1, strategy: "sliding" });
129
+ }
130
+ function createRegistryClient(options) {
131
+ const requestFetch = options.fetch ?? fetch;
132
+ const headers = { "content-type": "application/json" };
133
+ async function post(pathname, body) {
134
+ const response = await requestFetch(registryUrl(options.baseUrl, pathname), {
135
+ method: "POST",
136
+ headers,
137
+ body: JSON.stringify(body)
138
+ });
139
+ return parseResponseJson(response);
140
+ }
141
+ return {
142
+ async registerRoom(room) {
143
+ const response = await post("register", room);
144
+ return response.entry;
145
+ },
146
+ async heartbeatRoom(roomId, status, projection) {
147
+ const body = projection === undefined ? { roomId, namespaceKey: options.namespaceKey, status } : { roomId, namespaceKey: options.namespaceKey, status, projection };
148
+ const response = await post("heartbeat", body);
149
+ return response.entry;
150
+ },
151
+ async ingestProjection(input) {
152
+ const response = await post("projection", {
153
+ ...input,
154
+ namespaceKey: input.namespaceKey ?? options.namespaceKey
155
+ });
156
+ return response.entry;
157
+ },
158
+ async listRoomsByOwner(filter) {
159
+ const namespaceKey = filter.namespaceKey ?? options.namespaceKey;
160
+ const url = registryUrl(options.baseUrl, "list");
161
+ url.searchParams.set("namespaceKey", namespaceKey);
162
+ if (filter.selectedRepo)
163
+ url.searchParams.set("repo", filter.selectedRepo);
164
+ const response = await requestFetch(url);
165
+ return (await parseResponseJson(response)).entries;
166
+ },
167
+ async removeRoom(roomId) {
168
+ const response = await post("remove", { roomId, namespaceKey: options.namespaceKey });
169
+ return response.removed;
170
+ }
171
+ };
172
+ }
173
+ var init_client = () => {};
174
+
175
+ // packages/transport-plugin/relay-registry/src/schema.ts
176
+ import { RunStatus as ContractRunStatus, Schema } from "@rig/contracts";
177
+ function isRegistryStatus(value) {
178
+ return typeof value === "string" && REGISTRY_STATUS_SET.has(value);
179
+ }
180
+ function coerceRegistryStatus(value, fallback) {
181
+ if (value === "starting")
182
+ return "preparing";
183
+ if (value === "waiting-input")
184
+ return "waiting-user-input";
185
+ return isRegistryStatus(value) ? value : fallback;
186
+ }
187
+ var RegistryOwner, REGISTRY_STATUS_ALIASES, REGISTRY_STATUS_VALUES, RegistryStatus, REGISTRY_STATUS_SET, RegistryEntry, RegisterRequest, HeartbeatRequest, ProjectionIngestRequest, RemoveRequest, ListedRegistryEntry, ListResponse, RegisterResponse, HeartbeatResponse, ProjectionIngestResponse, RemoveResponse, RegistrySnapshotFrame, RegistryDeltaFrame, WorkerProjectionFrame;
188
+ var init_schema = __esm(() => {
189
+ RegistryOwner = Schema.Struct({
190
+ githubUserId: Schema.String,
191
+ login: Schema.String,
192
+ namespaceKey: Schema.String
193
+ });
194
+ REGISTRY_STATUS_ALIASES = ["starting", "waiting-input"];
195
+ REGISTRY_STATUS_VALUES = [
196
+ ...ContractRunStatus.members.map((member) => member.literal),
197
+ ...REGISTRY_STATUS_ALIASES
198
+ ];
199
+ RegistryStatus = Schema.Literals(REGISTRY_STATUS_VALUES);
200
+ REGISTRY_STATUS_SET = new Set(REGISTRY_STATUS_VALUES);
201
+ RegistryEntry = Schema.Struct({
202
+ roomId: Schema.String,
203
+ owner: RegistryOwner,
204
+ repo: Schema.String,
205
+ title: Schema.String,
206
+ status: RegistryStatus,
207
+ joinLink: Schema.String,
208
+ webLink: Schema.String,
209
+ relayUrl: Schema.String,
210
+ startedAt: Schema.String,
211
+ cwd: Schema.optional(Schema.String),
212
+ sessionPath: Schema.optional(Schema.String),
213
+ heartbeatAt: Schema.String,
214
+ pid: Schema.optional(Schema.Number),
215
+ projection: Schema.optional(Schema.Unknown)
216
+ });
217
+ RegisterRequest = Schema.Struct({
218
+ roomId: Schema.String,
219
+ owner: RegistryOwner,
220
+ repo: Schema.String,
221
+ title: Schema.String,
222
+ status: RegistryStatus,
223
+ joinLink: Schema.String,
224
+ webLink: Schema.String,
225
+ relayUrl: Schema.String,
226
+ startedAt: Schema.String,
227
+ cwd: Schema.optional(Schema.String),
228
+ sessionPath: Schema.optional(Schema.String),
229
+ pid: Schema.optional(Schema.Number),
230
+ projection: Schema.optional(Schema.Unknown)
231
+ });
232
+ HeartbeatRequest = Schema.Struct({
233
+ roomId: Schema.String,
234
+ namespaceKey: Schema.String,
235
+ status: RegistryStatus,
236
+ projection: Schema.optional(Schema.Unknown)
237
+ });
238
+ ProjectionIngestRequest = Schema.Struct({
239
+ namespaceKey: Schema.String,
240
+ roomId: Schema.optional(Schema.String),
241
+ owner: Schema.optional(RegistryOwner),
242
+ repo: Schema.optional(Schema.String),
243
+ projection: Schema.Unknown
244
+ });
245
+ RemoveRequest = Schema.Struct({
246
+ namespaceKey: Schema.String,
247
+ roomId: Schema.String
248
+ });
249
+ ListedRegistryEntry = Schema.Struct({
250
+ roomId: Schema.String,
251
+ owner: RegistryOwner,
252
+ repo: Schema.String,
253
+ title: Schema.String,
254
+ status: RegistryStatus,
255
+ joinLink: Schema.String,
256
+ webLink: Schema.String,
257
+ relayUrl: Schema.String,
258
+ startedAt: Schema.String,
259
+ heartbeatAt: Schema.String,
260
+ cwd: Schema.optional(Schema.String),
261
+ sessionPath: Schema.optional(Schema.String),
262
+ pid: Schema.optional(Schema.Number),
263
+ projection: Schema.optional(Schema.Unknown),
264
+ stale: Schema.Boolean
265
+ });
266
+ ListResponse = Schema.Struct({
267
+ entries: Schema.Array(ListedRegistryEntry)
268
+ });
269
+ RegisterResponse = Schema.Struct({
270
+ entry: RegistryEntry
271
+ });
272
+ HeartbeatResponse = Schema.Struct({
273
+ entry: RegistryEntry
274
+ });
275
+ ProjectionIngestResponse = Schema.Struct({
276
+ entry: RegistryEntry
277
+ });
278
+ RemoveResponse = Schema.Struct({
279
+ removed: Schema.Boolean
280
+ });
281
+ RegistrySnapshotFrame = Schema.Struct({
282
+ type: Schema.Literal("registry.snapshot"),
283
+ namespaceKey: Schema.String,
284
+ sentAt: Schema.String,
285
+ entries: Schema.Array(ListedRegistryEntry)
286
+ });
287
+ RegistryDeltaFrame = Schema.Struct({
288
+ type: Schema.Literal("registry.delta"),
289
+ namespaceKey: Schema.String,
290
+ sentAt: Schema.String,
291
+ action: Schema.Literals(["upsert", "remove"]),
292
+ roomId: Schema.String,
293
+ entry: Schema.optional(ListedRegistryEntry)
294
+ });
295
+ WorkerProjectionFrame = Schema.Struct({
296
+ type: Schema.Literal("projection"),
297
+ projection: Schema.Unknown
298
+ });
299
+ });
300
+
301
+ // packages/transport-plugin/src/relay-registry.ts
302
+ var exports_relay_registry = {};
303
+ __export(exports_relay_registry, {
304
+ subscribeDiscovery: () => subscribeDiscovery,
305
+ createRegistryClient: () => createRegistryClient,
306
+ connectWorkerProjection: () => connectWorkerProjection,
307
+ coerceRegistryStatus: () => coerceRegistryStatus
308
+ });
309
+ var init_relay_registry = __esm(() => {
310
+ init_client();
311
+ init_schema();
312
+ });
313
+
314
+ // packages/transport-plugin/src/discovery.ts
315
+ var exports_discovery = {};
316
+ __export(exports_discovery, {
317
+ runDiscoveryStream: () => runDiscoveryStream,
318
+ registrySnapshotStream: () => registrySnapshotStream,
319
+ registryBaseUrl: () => registryBaseUrl,
320
+ matchesRun: () => matchesRun,
321
+ listActiveRunCollab: () => listActiveRunCollab,
322
+ defaultListActiveCollabSessions: () => defaultListActiveCollabSessions,
323
+ collabFromRegistryEntry: () => collabFromRegistryEntry,
324
+ attachViaRelay: () => attachViaRelay
325
+ });
326
+ import { Effect as Effect2, Option, Stream as Stream2, Duration } from "effect";
327
+ import { resolveOwnerNamespaceKey, resolveRegistryBaseUrl } from "@rig/core/remote-config";
328
+ function registryBaseUrl(projectRoot = process.cwd(), env = process.env) {
329
+ return resolveRegistryBaseUrl(projectRoot, env);
330
+ }
331
+ function collabFromRegistryEntry(entry) {
332
+ return {
333
+ sessionId: entry.roomId,
334
+ title: entry.title,
335
+ sessionPath: entry.sessionPath ?? (entry.projection && typeof entry.projection === "object" && "sessionPath" in entry.projection && typeof entry.projection.sessionPath === "string" ? entry.projection.sessionPath : ""),
336
+ cwd: entry.cwd ?? (entry.projection && typeof entry.projection === "object" && "worktreePath" in entry.projection && typeof entry.projection.worktreePath === "string" ? entry.projection.worktreePath : ""),
337
+ joinLink: entry.joinLink ?? "",
338
+ webLink: entry.webLink ?? "",
339
+ relayUrl: entry.relayUrl ?? "",
340
+ owner: entry.owner,
341
+ selectedRepo: entry.repo,
342
+ startedAt: entry.startedAt,
343
+ updatedAt: entry.heartbeatAt,
344
+ ...entry.pid === undefined ? {} : { pid: entry.pid },
345
+ stale: entry.stale,
346
+ registryStatus: entry.status,
347
+ registryProjection: entry.projection
348
+ };
349
+ }
350
+ function namespaceKeyFor(projectRoot, filter = {}) {
351
+ return filter.namespaceKey ?? resolveOwnerNamespaceKey(projectRoot) ?? "anonymous";
352
+ }
353
+ async function listActiveRunCollab(projectRoot, filter) {
354
+ return defaultListActiveCollabSessions(projectRoot, filter);
355
+ }
356
+ async function defaultListActiveCollabSessions(projectRoot, filter) {
357
+ const namespaceKey = namespaceKeyFor(projectRoot, filter);
358
+ if (!namespaceKey)
359
+ return [];
360
+ try {
361
+ const client = createRegistryClient({ baseUrl: registryBaseUrl(projectRoot), namespaceKey });
362
+ return (await client.listRoomsByOwner({ ...filter, namespaceKey })).map(collabFromRegistryEntry);
363
+ } catch {
364
+ return [];
365
+ }
366
+ }
367
+ function matchesRun(collab, runId, taskId) {
368
+ if (collab.sessionId === runId)
369
+ return true;
370
+ return Boolean(taskId && collab.title?.includes(taskId));
371
+ }
372
+ function runDiscoveryStream(projectRoot) {
373
+ const namespaceKey = namespaceKeyFor(projectRoot);
374
+ if (!namespaceKey)
375
+ return Stream2.never;
376
+ return subscribeDiscovery(namespaceKey, null, { baseUrl: registryBaseUrl(projectRoot) }).pipe(Stream2.map(() => {
377
+ return;
378
+ }));
379
+ }
380
+ function registrySnapshotStream(projectRoot, filter = {}) {
381
+ const namespaceKey = namespaceKeyFor(projectRoot, filter);
382
+ if (!namespaceKey)
383
+ return Stream2.never;
384
+ return subscribeDiscovery(namespaceKey, filter.selectedRepo ?? null, { baseUrl: registryBaseUrl(projectRoot) });
385
+ }
386
+ async function attachViaRelay(input, deps = {}) {
387
+ const timeoutMs = input.timeoutMs ?? DEFAULT_ATTACH_TIMEOUT_MS;
388
+ const root = input.projectRoot ?? process.cwd();
389
+ const listActive = deps.listActiveCollabSessions ?? ((filter) => defaultListActiveCollabSessions(root, filter));
390
+ const checkOnce = async () => {
391
+ const live = await listActive(input.identityFilter);
392
+ const exact = live.find((collab) => collab.sessionId === input.runId && !collab.stale);
393
+ const match = exact ?? live.find((collab) => matchesRun(collab, input.runId, input.taskId) && !collab.stale);
394
+ if (!match)
395
+ return null;
396
+ return { sessionPath: match.sessionPath ?? null, joinLink: match.joinLink ?? null, collabSessionId: match.sessionId ?? null };
397
+ };
398
+ const immediate = await checkOnce();
399
+ if (immediate)
400
+ return immediate;
401
+ const events = deps.discoveryStream ? deps.discoveryStream(root) : runDiscoveryStream(root);
402
+ return await Effect2.runPromise(events.pipe(Stream2.mapEffect(() => Effect2.promise(checkOnce)), Stream2.filter((m) => m !== null), Stream2.runHead, Effect2.timeout(Duration.millis(timeoutMs)), Effect2.map(Option.getOrNull), Effect2.catch(() => Effect2.succeed(null))));
403
+ }
404
+ var DEFAULT_ATTACH_TIMEOUT_MS = 15000;
405
+ var init_discovery = __esm(() => {
406
+ init_relay_registry();
407
+ });
408
+
409
+ // packages/transport-plugin/src/identity-env.ts
410
+ import { existsSync, readFileSync } from "fs";
411
+ import { resolve } from "path";
412
+ function stringField(value) {
413
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
414
+ }
415
+ function githubUserId(value) {
416
+ if (typeof value === "number" && Number.isInteger(value))
417
+ return String(value);
418
+ return stringField(value);
419
+ }
420
+ function readJsonRecord(path) {
421
+ if (!existsSync(path))
422
+ return null;
423
+ try {
424
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
425
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
426
+ } catch {
427
+ return null;
428
+ }
429
+ }
430
+ function resolveTransportIdentityEnv(workspaceRoot) {
431
+ const stateDir = resolve(workspaceRoot, ".rig", "state");
432
+ const auth = readJsonRecord(resolve(stateDir, "github-auth.json"));
433
+ const connection = readJsonRecord(resolve(stateDir, "connection.json"));
434
+ const projectLink = readJsonRecord(resolve(stateDir, "project-link.json"));
435
+ const values = {};
436
+ const selectedRepo = stringField(auth?.selectedRepo) ?? stringField(connection?.project) ?? stringField(projectLink?.repoSlug);
437
+ const userId = githubUserId(auth?.userId);
438
+ const login = stringField(auth?.login);
439
+ const namespaceKey = stringField(auth?.userNamespaceKey);
440
+ if (selectedRepo)
441
+ values.RIG_SELECTED_REPO = selectedRepo;
442
+ if (userId)
443
+ values.RIG_GITHUB_USER_ID = userId;
444
+ if (login)
445
+ values.RIG_GITHUB_LOGIN = login;
446
+ if (namespaceKey)
447
+ values.RIG_GITHUB_NAMESPACE_KEY = namespaceKey;
448
+ return values;
449
+ }
450
+ var init_identity_env = () => {};
451
+
452
+ // packages/transport-plugin/src/dispatch.ts
453
+ var exports_dispatch = {};
454
+ __export(exports_dispatch, {
455
+ spawnRunProcess: () => spawnRunProcess,
456
+ sessionIdFromDispatchSnapshot: () => sessionIdFromDispatchSnapshot,
457
+ resolveRigRunBin: () => resolveRigRunBin,
458
+ resolveDispatchTransportPlacement: () => resolveDispatchTransportPlacement2,
459
+ dispatchRun: () => dispatchRun,
460
+ createPlacementRunTransport: () => createPlacementRunTransport
461
+ });
462
+ import { randomUUID } from "crypto";
463
+ import { spawn as nodeSpawn } from "child_process";
464
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
465
+ import { dirname, resolve as resolve2 } from "path";
466
+ import { fileURLToPath } from "url";
467
+ import { resolveOwnerNamespaceKey as resolveOwnerNamespaceKey2, resolveRegistryBaseUrl as resolveRegistryBaseUrl2, resolveDispatchTransportPlacement } from "@rig/core/remote-config";
468
+ import {
469
+ REMOTE_RIG_RUN_COMMAND,
470
+ REMOTE_RESOLVED_RIG_RUN_COMMAND,
471
+ buildRemoteRigRunResolutionShell,
472
+ buildRigRunLaunchArgs,
473
+ readGithubAuthStateBase64,
474
+ resolveLocalDispatchRigRunBin,
475
+ resolveRemoteCheckoutPlan,
476
+ resolveRunGithubAuthMaterialization
477
+ } from "@rig/core/run-provisioning";
478
+ import { Duration as Duration2, Effect as Effect3, Option as Option2, Stream as Stream3 } from "effect";
479
+ import { resolveDispatchTransportPlacement as resolveDispatchTransportPlacement2 } from "@rig/core/remote-config";
480
+ function sessionIdFromSessionFile(sessionPath) {
481
+ if (!sessionPath)
482
+ return null;
483
+ const file = sessionPath.split(/[\\/]/).pop() ?? "";
484
+ const match = file.match(/_([0-9a-fA-F][0-9a-fA-F-]{7,})\.jsonl$/);
485
+ return match?.[1] ?? null;
486
+ }
487
+ function dispatchLogPath(projectRoot, source, runId) {
488
+ return resolve2(projectRoot, ".rig", "logs", `${source}-dispatch-${runId}.log`);
489
+ }
490
+ function resolveRigRunBin() {
491
+ return resolveLocalDispatchRigRunBin({
492
+ importMetaUrl: import.meta.url,
493
+ sourceRigRunPath: resolve2(dirname(fileURLToPath(import.meta.url)), "../../../rig-host/bin/rig-run.ts")
494
+ });
495
+ }
496
+ function shellQuote(value) {
497
+ return `'${value.replace(/'/g, "'\\''")}'`;
498
+ }
499
+ function remoteRuntimeEnvPayload(env) {
500
+ const lines = REMOTE_RUNTIME_ENV_KEYS.flatMap((key) => {
501
+ const value = env[key]?.trim();
502
+ return value ? [`export ${key}=${shellQuote(value)}`] : [];
503
+ });
504
+ return lines.length > 0 ? Buffer.from(`${lines.join(`
505
+ `)}
506
+ `, "utf8").toString("base64") : "";
507
+ }
508
+ function dispatchChildEnv(env, identityEnv, authMaterialization) {
509
+ const childEnv = { ...env };
510
+ for (const key of DISPATCH_TOKEN_ENV_KEYS)
511
+ delete childEnv[key];
512
+ for (const [key, value] of Object.entries(identityEnv)) {
513
+ if (value !== undefined)
514
+ childEnv[key] = value;
515
+ }
516
+ childEnv.RIG_GITHUB_AUTH_STATE_FILE ??= authMaterialization.operatorAuthPath;
517
+ childEnv.RIG_STATE_DIR ??= authMaterialization.operatorStateDir;
518
+ return childEnv;
519
+ }
520
+ function rigRunShellInvocation(input, runId, command = REMOTE_RIG_RUN_COMMAND) {
521
+ return [
522
+ command,
523
+ ...buildRigRunLaunchArgs(input, runId, "$CHECKOUT").map((arg) => arg === "$CHECKOUT" ? '"$CHECKOUT"' : shellQuote(arg))
524
+ ].join(" ");
525
+ }
526
+ function isRecord(value) {
527
+ return value !== null && typeof value === "object";
528
+ }
529
+ function isDispatchTransportPlacement(value) {
530
+ if (!isRecord(value))
531
+ return false;
532
+ if (value.kind === "local")
533
+ return value.sshTarget === null;
534
+ return value.kind === "remote" && typeof value.sshTarget === "string" && value.sshTarget.trim().length > 0;
535
+ }
536
+ function placementResolverFromOptions(options) {
537
+ if (!isRecord(options))
538
+ return;
539
+ const placement = options.placement;
540
+ if (typeof placement === "function")
541
+ return placement;
542
+ if (isDispatchTransportPlacement(placement))
543
+ return () => placement;
544
+ return;
545
+ }
546
+ function stringField2(value) {
547
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
548
+ }
549
+ function readJsonRecord2(path) {
550
+ if (!existsSync2(path))
551
+ return null;
552
+ try {
553
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
554
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
555
+ } catch {
556
+ return null;
557
+ }
558
+ }
559
+ function readProjectSlug(projectRoot) {
560
+ const connection = readJsonRecord2(resolve2(projectRoot, ".rig", "state", "connection.json"));
561
+ return stringField2(connection?.project) ?? null;
562
+ }
563
+ function resolveGitDir(projectRoot) {
564
+ const dotGit = resolve2(projectRoot, ".git");
565
+ if (existsSync2(resolve2(dotGit, "HEAD")))
566
+ return dotGit;
567
+ try {
568
+ const match = /^gitdir:\s*(.+)$/m.exec(readFileSync2(dotGit, "utf8"));
569
+ return match ? resolve2(projectRoot, match[1].trim()) : null;
570
+ } catch {
571
+ return null;
572
+ }
573
+ }
574
+ function readGitDirFile(gitDir, relativePath) {
575
+ try {
576
+ return readFileSync2(resolve2(gitDir, relativePath), "utf8").trim();
577
+ } catch {
578
+ return null;
579
+ }
580
+ }
581
+ function resolveCommonGitDir(gitDir) {
582
+ const commonDir = readGitDirFile(gitDir, "commondir");
583
+ return commonDir ? resolve2(gitDir, commonDir) : null;
584
+ }
585
+ function resolveProjectHeadCommit(projectRoot) {
586
+ const gitDir = resolveGitDir(projectRoot);
587
+ if (!gitDir)
588
+ return null;
589
+ const head = readGitDirFile(gitDir, "HEAD");
590
+ if (!head)
591
+ return null;
592
+ if (/^[0-9a-f]{40}$/i.test(head))
593
+ return head;
594
+ const ref = head.startsWith("ref:") ? head.slice(4).trim() : "";
595
+ if (!ref)
596
+ return null;
597
+ const lookupDirs = [gitDir, resolveCommonGitDir(gitDir)].filter((dir) => Boolean(dir));
598
+ for (const dir of lookupDirs) {
599
+ const looseRef = readGitDirFile(dir, ref);
600
+ if (looseRef && /^[0-9a-f]{40}$/i.test(looseRef))
601
+ return looseRef;
602
+ }
603
+ for (const dir of lookupDirs) {
604
+ const packedRefs = readGitDirFile(dir, "packed-refs");
605
+ const packed = packedRefs?.split(/\r?\n/).map((line) => line.trim()).filter((line) => line && !line.startsWith("#") && !line.startsWith("^")).map((line) => line.split(/\s+/)).find(([sha, name]) => name === ref && /^[0-9a-f]{40}$/i.test(sha ?? ""))?.[0];
606
+ if (packed)
607
+ return packed;
608
+ }
609
+ return null;
610
+ }
611
+ async function spawnRunProcess(input, deps = {}) {
612
+ const runId = (deps.uuid ?? randomUUID)();
613
+ const env = deps.env ?? process.env;
614
+ const identityEnv = resolveTransportIdentityEnv(input.projectRoot);
615
+ const authMaterialization = resolveRunGithubAuthMaterialization(input.projectRoot);
616
+ const placement = (deps.resolvePlacement ?? resolveDispatchTransportPlacement)(input.projectRoot, env);
617
+ if (placement.kind === "remote") {
618
+ const selected = placement.selected;
619
+ const sshTarget = placement.sshTarget;
620
+ const namespaceKey = identityEnv.RIG_GITHUB_NAMESPACE_KEY ?? resolveOwnerNamespaceKey2(input.projectRoot, env) ?? "";
621
+ const sh = shellQuote;
622
+ const projectSlug = readProjectSlug(input.projectRoot);
623
+ const checkoutPlan = resolveRemoteCheckoutPlan({ selectedCheckout: selected?.checkout ?? null, projectSlug });
624
+ const checkoutExpr = checkoutPlan.checkoutPathKind === "literal" ? sh(checkoutPlan.checkoutPath) : `"$HOME/${checkoutPlan.checkoutPath}"`;
625
+ const identityAssignments = Object.entries(identityEnv).flatMap(([k, v]) => v ? [`${k}=${sh(v)}`] : []);
626
+ if (namespaceKey && !identityEnv.RIG_GITHUB_NAMESPACE_KEY)
627
+ identityAssignments.push(`RIG_GITHUB_NAMESPACE_KEY=${sh(namespaceKey)}`);
628
+ const registryBaseUrl2 = resolveRegistryBaseUrl2(input.projectRoot, env);
629
+ const runtimeEnvB64 = remoteRuntimeEnvPayload(env);
630
+ const remoteAuthState = `"${authMaterialization.remoteAuthPath}"`;
631
+ const remoteStateDir = `"${authMaterialization.remoteStateDir}"`;
632
+ const runInvocation = [
633
+ ...identityAssignments,
634
+ `RIG_REGISTRY_URL=${sh(registryBaseUrl2)}`,
635
+ `RIG_GITHUB_AUTH_STATE_FILE=${remoteAuthState}`,
636
+ `RIG_STATE_DIR=${remoteStateDir}`,
637
+ rigRunShellInvocation(input, runId, REMOTE_RESOLVED_RIG_RUN_COMMAND)
638
+ ].filter(Boolean).join(" ");
639
+ const authStateB64 = readGithubAuthStateBase64(authMaterialization.operatorAuthPath);
640
+ const operatorHead = resolveProjectHeadCommit(input.projectRoot);
641
+ if (!operatorHead)
642
+ throw new Error(`remote dispatch cannot resolve operator git HEAD for ${input.projectRoot}`);
643
+ const gitCredentialHelper = `#!/usr/bin/env bun
644
+ import { readFileSync } from "node:fs";
645
+ try {
646
+ const path = process.env.RIG_GITHUB_AUTH_STATE_FILE;
647
+ if (!path) process.exit(0);
648
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
649
+ const token = typeof parsed.token === "string" ? parsed.token.trim() : "";
650
+ if (token) process.stdout.write(\`username=x-access-token\\npassword=${"${token}"}\\n\`);
651
+ } catch {
652
+ process.exit(0);
653
+ }
654
+ `;
655
+ const provisionAndRun = [
656
+ "set -e",
657
+ "IFS= read -r __RIG_GH_AUTH_B64 || true",
658
+ "IFS= read -r __RIG_RUNTIME_ENV_B64 || true",
659
+ "__RIG_AUTH_FILE=$(mktemp)",
660
+ "__RIG_RUNTIME_ENV_FILE=$(mktemp)",
661
+ "__RIG_GIT_HELPER=$(mktemp)",
662
+ `trap 'rm -f "$__RIG_AUTH_FILE" "$__RIG_RUNTIME_ENV_FILE" "$__RIG_GIT_HELPER"' EXIT`,
663
+ `if [ -n "$__RIG_GH_AUTH_B64" ]; then printf %s "$__RIG_GH_AUTH_B64" | base64 -d > "$__RIG_AUTH_FILE" && chmod 600 "$__RIG_AUTH_FILE"; fi`,
664
+ `if [ -n "$__RIG_RUNTIME_ENV_B64" ]; then printf %s "$__RIG_RUNTIME_ENV_B64" | base64 -d > "$__RIG_RUNTIME_ENV_FILE" && chmod 600 "$__RIG_RUNTIME_ENV_FILE" && . "$__RIG_RUNTIME_ENV_FILE"; fi`,
665
+ `printf %s ${sh(gitCredentialHelper)} > "$__RIG_GIT_HELPER"`,
666
+ 'chmod 700 "$__RIG_GIT_HELPER"',
667
+ 'git_with_auth() { RIG_GITHUB_AUTH_STATE_FILE="$__RIG_AUTH_FILE" git -c credential.helper="!$__RIG_GIT_HELPER" "$@"; }',
668
+ `CHECKOUT=${checkoutExpr}`,
669
+ checkoutPlan.originUrl ? `[ -d "$CHECKOUT/.git" ] || git_with_auth clone ${sh(checkoutPlan.originUrl)} "$CHECKOUT"` : `[ -d "$CHECKOUT/.git" ] || { echo "rig: remote checkout $CHECKOUT missing and no origin to clone" >&2; exit 1; }`,
670
+ `cd "$CHECKOUT"`,
671
+ `git_with_auth fetch origin ${sh(operatorHead)} --quiet || git_with_auth fetch origin --prune --quiet`,
672
+ `git cat-file -e ${sh(`${operatorHead}^{commit}`)} || { echo "rig: operator commit ${operatorHead} is unavailable on remote checkout" >&2; exit 1; }`,
673
+ `git checkout --detach ${sh(operatorHead)} --quiet`,
674
+ `git reset --hard ${sh(operatorHead)} --quiet`,
675
+ "bun install --silent || bun install",
676
+ `mkdir -p "$CHECKOUT/.rig/state"`,
677
+ `if [ -s "$__RIG_AUTH_FILE" ]; then cp "$__RIG_AUTH_FILE" "$CHECKOUT/.rig/state/github-auth.json" && chmod 600 "$CHECKOUT/.rig/state/github-auth.json"; fi`,
678
+ ...buildRemoteRigRunResolutionShell(`https://${DEFAULT_RIG_BACKBONE_HOST}/install`),
679
+ runInvocation
680
+ ].join("; ");
681
+ const dispatchLogDir2 = resolve2(input.projectRoot, ".rig", "logs");
682
+ mkdirSync(dispatchLogDir2, { recursive: true });
683
+ const remoteDispatchLogPath = dispatchLogPath(input.projectRoot, placement.kind, runId);
684
+ await new Promise((resolveDone, rejectDone) => {
685
+ const sshArgs = ["-o", "ConnectTimeout=20", ...selected && selected.port !== 22 ? ["-p", String(selected.port)] : [], sshTarget, `bash -lc ${sh(provisionAndRun)}`];
686
+ const child = (deps.spawn ?? nodeSpawn)("ssh", sshArgs, {
687
+ cwd: input.projectRoot,
688
+ env: dispatchChildEnv(env, identityEnv, authMaterialization),
689
+ stdio: ["pipe", "pipe", "pipe"]
690
+ });
691
+ try {
692
+ child.stdin?.write(`${authStateB64}
693
+ ${runtimeEnvB64}
694
+ `);
695
+ child.stdin?.end();
696
+ } catch {}
697
+ let out = "";
698
+ child.stdout?.on("data", (chunk) => {
699
+ out += String(chunk);
700
+ });
701
+ child.stderr?.on("data", (chunk) => {
702
+ out += String(chunk);
703
+ });
704
+ const timer = setTimeout(() => {
705
+ try {
706
+ child.kill();
707
+ } catch {}
708
+ try {
709
+ writeFileSync(remoteDispatchLogPath, out);
710
+ } catch {}
711
+ rejectDone(new Error(`remote dispatch for task ${input.taskId} did not confirm within 180s (see ${remoteDispatchLogPath})`));
712
+ }, DEFAULT_REMOTE_DISPATCH_TIMEOUT_MS);
713
+ child.on("error", (error) => {
714
+ clearTimeout(timer);
715
+ rejectDone(error);
716
+ });
717
+ child.on("close", (code) => {
718
+ clearTimeout(timer);
719
+ try {
720
+ writeFileSync(remoteDispatchLogPath, out);
721
+ } catch {}
722
+ if (code === 0) {
723
+ resolveDone();
724
+ return;
725
+ }
726
+ const detail = out.trim().split(`
727
+ `).slice(-8).join(`
728
+ `);
729
+ rejectDone(new Error(`remote dispatch for task ${input.taskId} exited ${code ?? "null"} (see ${remoteDispatchLogPath})${detail ? `:
730
+ ${detail}` : ""}`));
731
+ });
732
+ });
733
+ return { runId };
734
+ }
735
+ const dispatchLogDir = resolve2(input.projectRoot, ".rig", "logs");
736
+ mkdirSync(dispatchLogDir, { recursive: true });
737
+ const localDispatchLogPath = dispatchLogPath(input.projectRoot, "local", runId);
738
+ const command = (deps.resolveRigRunBin ?? resolveRigRunBin)();
739
+ const args = buildRigRunLaunchArgs(input, runId, input.projectRoot);
740
+ await new Promise((resolveDone, rejectDone) => {
741
+ const child = (deps.spawn ?? nodeSpawn)(command, args, {
742
+ cwd: input.projectRoot,
743
+ env: dispatchChildEnv(env, identityEnv, authMaterialization),
744
+ stdio: ["ignore", "pipe", "pipe"]
745
+ });
746
+ let out = "";
747
+ child.stdout?.on("data", (chunk) => {
748
+ out += String(chunk);
749
+ });
750
+ child.stderr?.on("data", (chunk) => {
751
+ out += String(chunk);
752
+ });
753
+ child.on("error", (error) => {
754
+ try {
755
+ writeFileSync(localDispatchLogPath, out);
756
+ } catch {}
757
+ rejectDone(error);
758
+ });
759
+ child.on("close", (code) => {
760
+ try {
761
+ writeFileSync(localDispatchLogPath, out);
762
+ } catch {}
763
+ if (code === 0) {
764
+ resolveDone();
765
+ return;
766
+ }
767
+ const detail = out.trim().split(`
768
+ `).slice(-8).join(`
769
+ `);
770
+ rejectDone(new Error(`local dispatch for task ${input.taskId} exited ${code ?? "null"} (see ${localDispatchLogPath})${detail ? `:
771
+ ${detail}` : ""}`));
772
+ });
773
+ });
774
+ return { runId };
775
+ }
776
+ function entryProjection(entry) {
777
+ return entry.projection && typeof entry.projection === "object" ? entry.projection : {};
778
+ }
779
+ function textContainsHandle(value, handle) {
780
+ return Boolean(value && value.includes(handle));
781
+ }
782
+ function sessionIdFromDispatchSnapshot(snapshot, dispatchHandle) {
783
+ for (const entry of snapshot.entries) {
784
+ const projection = entryProjection(entry);
785
+ const sessionPath = stringField2(projection.sessionPath) ?? entry.sessionPath ?? null;
786
+ const cwd = stringField2(projection.cwd) ?? stringField2(projection.collabCwd) ?? entry.cwd ?? stringField2(projection.worktreePath) ?? null;
787
+ const handleField = stringField2(projection.dispatchHandle);
788
+ if (handleField !== dispatchHandle && !textContainsHandle(sessionPath, dispatchHandle) && !textContainsHandle(cwd, dispatchHandle))
789
+ continue;
790
+ return stringField2(projection.runId) ?? sessionIdFromSessionFile(sessionPath) ?? entry.roomId;
791
+ }
792
+ return null;
793
+ }
794
+ async function waitForSessionId(projectRoot, handle, logPath, source, deps) {
795
+ const timeoutMs = source === "remote" ? deps.remoteSessionTimeoutMs ?? DEFAULT_REMOTE_DISPATCH_TIMEOUT_MS : deps.localSessionTimeoutMs ?? DEFAULT_LOCAL_SESSION_TIMEOUT_MS;
796
+ const found = await Effect3.runPromise((deps.discoverySnapshots ?? registrySnapshotStream)(projectRoot).pipe(Stream3.map((snapshot) => sessionIdFromDispatchSnapshot(snapshot, handle)), Stream3.filter((sessionId) => sessionId !== null), Stream3.runHead, Effect3.timeout(Duration2.millis(timeoutMs)), Effect3.map(Option2.getOrNull), Effect3.catch(() => Effect3.succeed(null))));
797
+ if (found)
798
+ return found;
799
+ throw new Error(`dispatch for handle ${handle} timed out before an OMP session id appeared (see ${logPath})`);
800
+ }
801
+ async function dispatchRun(input, deps = {}) {
802
+ const env = deps.env ?? process.env;
803
+ const placement = (deps.resolvePlacement ?? resolveDispatchTransportPlacement)(input.projectRoot, env);
804
+ const handle = (deps.uuid ?? randomUUID)();
805
+ const inner = await (deps.spawnRunProcess ?? spawnRunProcess)(input, { ...deps, uuid: () => handle, resolvePlacement: () => placement });
806
+ const dispatchHandle = inner.runId;
807
+ const logPath = dispatchLogPath(input.projectRoot, placement.kind, dispatchHandle);
808
+ return { runId: await waitForSessionId(input.projectRoot, dispatchHandle, logPath, placement.kind, deps) };
809
+ }
810
+ function createPlacementRunTransport(deps = {}) {
811
+ return {
812
+ async dispatch(task, options) {
813
+ const resolvePlacement = placementResolverFromOptions(options);
814
+ const { runId } = await dispatchRun(task, resolvePlacement ? { ...deps, resolvePlacement } : deps);
815
+ return runId;
816
+ }
817
+ };
818
+ }
819
+ var DEFAULT_REMOTE_DISPATCH_TIMEOUT_MS = 180000, DEFAULT_LOCAL_SESSION_TIMEOUT_MS = 120000, DISPATCH_TOKEN_ENV_KEYS, REMOTE_RUNTIME_ENV_KEYS;
820
+ var init_dispatch = __esm(() => {
821
+ init_identity_env();
822
+ init_discovery();
823
+ init_plugin();
824
+ DISPATCH_TOKEN_ENV_KEYS = [
825
+ "RIG_GITHUB_TOKEN",
826
+ "RIG_GITHUB_SELECTED_TOKEN",
827
+ "GH_TOKEN",
828
+ "GITHUB_TOKEN"
829
+ ];
830
+ REMOTE_RUNTIME_ENV_KEYS = [
831
+ "ANTHROPIC_API_KEY",
832
+ "OPENAI_API_KEY",
833
+ "OPENROUTER_API_KEY"
834
+ ];
835
+ });
836
+
837
+ // packages/transport-plugin/src/plugin.ts
838
+ import { definePlugin } from "@rig/core/config";
839
+ import { defineCapability } from "@rig/core/capability";
840
+ import {
841
+ RUN_DISPATCH,
842
+ RUN_DISCOVERY,
843
+ PLACEMENT_RUN_TRANSPORT,
844
+ RUN_REGISTRY_BACKBONE
845
+ } from "@rig/contracts";
846
+ import { registerBackboneDefaults } from "@rig/core/remote-config";
847
+ function createTransportPlugin() {
848
+ return transportPlugin;
849
+ }
850
+ var TRANSPORT_PLUGIN_NAME = "@rig/transport-plugin", DEFAULT_RIG_BACKBONE_HOST = "where.rig-does.work", DEFAULT_RIG_RELAY_URL, DEFAULT_RIG_REGISTRY_URL, DEFAULT_RIG_SSH_TARGET = "ubuntu@100.125.210.33", RUN_DISCOVERY_CAPABILITY_ID = "rig.runs.discovery", RunDiscoveryCap, RunDispatchCap, PlacementRunTransportCap, RunRegistryBackboneCap, transportPlugin, plugin_default;
851
+ var init_plugin = __esm(() => {
852
+ DEFAULT_RIG_RELAY_URL = `wss://${DEFAULT_RIG_BACKBONE_HOST}`;
853
+ DEFAULT_RIG_REGISTRY_URL = `https://${DEFAULT_RIG_BACKBONE_HOST}/registry`;
854
+ registerBackboneDefaults({
855
+ relayUrl: DEFAULT_RIG_RELAY_URL,
856
+ registryBaseUrl: DEFAULT_RIG_REGISTRY_URL,
857
+ sshTarget: DEFAULT_RIG_SSH_TARGET
858
+ });
859
+ RunDiscoveryCap = defineCapability(RUN_DISCOVERY);
860
+ RunDispatchCap = defineCapability(RUN_DISPATCH);
861
+ PlacementRunTransportCap = defineCapability(PLACEMENT_RUN_TRANSPORT);
862
+ RunRegistryBackboneCap = defineCapability(RUN_REGISTRY_BACKBONE);
863
+ transportPlugin = definePlugin({
864
+ name: TRANSPORT_PLUGIN_NAME,
865
+ version: "0.0.0-alpha.1",
866
+ contributes: {
867
+ capabilities: [
868
+ RunDiscoveryCap.provide(async () => {
869
+ const discovery = await Promise.resolve().then(() => (init_discovery(), exports_discovery));
870
+ return {
871
+ listActiveRunCollab: discovery.listActiveRunCollab,
872
+ runDiscoveryStream: discovery.runDiscoveryStream,
873
+ attachViaRelay: discovery.attachViaRelay
874
+ };
875
+ }, {
876
+ title: "Run discovery (relay-registry merge)",
877
+ description: "The unified active-run list: local FS-watch + remote registry SSE, plus relay attach."
878
+ }),
879
+ RunDispatchCap.provide(async () => {
880
+ const dispatch = await Promise.resolve().then(() => (init_dispatch(), exports_dispatch));
881
+ return { dispatchRun: (input) => dispatch.dispatchRun(input) };
882
+ }, {
883
+ title: "Run dispatch (placement-aware)",
884
+ description: "Dispatch a run resolving local vs remote/fleet placement at dispatch time."
885
+ }),
886
+ PlacementRunTransportCap.provide(async () => {
887
+ const { createPlacementRunTransport: createPlacementRunTransport2 } = await Promise.resolve().then(() => (init_dispatch(), exports_dispatch));
888
+ return createPlacementRunTransport2();
889
+ }, {
890
+ title: "Placement run transport",
891
+ description: "The placement-aware TransportCapability instance passed to adopt() in run-worker sessions."
892
+ }),
893
+ RunRegistryBackboneCap.provide(async () => {
894
+ const registry = await Promise.resolve().then(() => (init_relay_registry(), exports_relay_registry));
895
+ return {
896
+ createRegistryClient: registry.createRegistryClient,
897
+ connectWorkerProjection: registry.connectWorkerProjection,
898
+ coerceRegistryStatus: registry.coerceRegistryStatus
899
+ };
900
+ }, {
901
+ title: "Run registry backbone",
902
+ description: "Transport-owned relay-registry client for run-worker room registration, heartbeat, and live projection."
903
+ })
904
+ ],
905
+ config: { defaults: () => ({ runtime: { server: { host: DEFAULT_RIG_BACKBONE_HOST, sshTarget: DEFAULT_RIG_SSH_TARGET } } }) }
906
+ }
907
+ });
908
+ plugin_default = transportPlugin;
909
+ });
910
+ init_plugin();
911
+
912
+ export {
913
+ transportPlugin,
914
+ plugin_default as default,
915
+ createTransportPlugin,
916
+ TRANSPORT_PLUGIN_NAME,
917
+ RUN_DISCOVERY_CAPABILITY_ID,
918
+ RUN_DISCOVERY,
919
+ DEFAULT_RIG_SSH_TARGET,
920
+ DEFAULT_RIG_RELAY_URL,
921
+ DEFAULT_RIG_REGISTRY_URL,
922
+ DEFAULT_RIG_BACKBONE_HOST
923
+ };