agents-relay 2.0.4 → 2.0.5
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 +1 -1
- package/dist/relayd.js +11 -38
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -160,7 +160,7 @@ reconcile leases and launches ready tasks without waiting inside the runtime sch
|
|
|
160
160
|
|
|
161
161
|
`agents-relayd` without `--pr`/`--id` runs in workspace mode by default: it discovers nested Git repositories under `~/Workspace`, keeps only GitHub `origin` remotes, and aggregates their managed PR jobs into one dashboard and worker pool. Pass `--workspace PATH` to use another root. `--repo OWNER/REPO` remains the single-repository pool mode.
|
|
162
162
|
|
|
163
|
-
For automation, Agents Relay can use GitHub App installation authentication via `AGENTS_RELAY_GITHUB_APP_ID`, `AGENTS_RELAY_GITHUB_APP_INSTALLATION_ID`, and `AGENTS_RELAY_GITHUB_APP_PRIVATE_KEY_FILE` (or matching CLI flags). Webhook mode is
|
|
163
|
+
For automation, Agents Relay can use GitHub App installation authentication via `AGENTS_RELAY_GITHUB_APP_ID`, `AGENTS_RELAY_GITHUB_APP_INSTALLATION_ID`, and `AGENTS_RELAY_GITHUB_APP_PRIVATE_KEY_FILE` (or matching CLI flags). Webhook mode is local-first: targeted webhook reconciliation is primary, dashboard auto-refresh reads the disposable in-process view restored from SQLite RelayStore state, and the broad watchdog drops to a 30-minute fallback. No separate persisted dashboard Job cache is maintained. See [docs/github-app-rate-limit.md](docs/github-app-rate-limit.md).
|
|
164
164
|
|
|
165
165
|
V1 assumes one active runner/daemon per job. Use a distributed atomic lease before running multiple reconcilers. Do not put secrets, credentials, private prompts, or large private payloads in the PR-body Job marker or PR-comment Task markers; store only summaries and artifact references.
|
|
166
166
|
|
package/dist/relayd.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { once } from 'node:events';
|
|
3
|
-
import {
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { ChatGptAdapter, CodexAdapter } from './adapters.js';
|
|
@@ -134,17 +134,18 @@ export async function runDaemon(argv) {
|
|
|
134
134
|
projectionWriters.set(key, projected.projection);
|
|
135
135
|
return projected;
|
|
136
136
|
};
|
|
137
|
-
const makeReconciler = (store, maxConcurrent) => new Reconciler(store, { owner: `relayd-${process.pid}`, maxConcurrent, leaseMs: Number(value(argv, '--lease-ms', '300000')), adapters: [new CodexAdapter(value(argv, '--codex', 'codex')), new ChatGptAdapter()], continuations: [new CodexThreadContinuation(value(argv, '--codex', 'codex')), new CommandContinuation(), new WebhookContinuation()], planner: runtimePlanner(argv), usageSnapshotProvider: () => usageRegistry.snapshot(), runtimeSummaryProvider: () => ({ chatgptRunning: summarizeRuntime(cachedOverviews.map(item => item.job)).workers.chatgpt }), decisionEngine: new LayaCliDecisionEngine(), decisionMode: decisionMode(), decisionAuditStore, eventBus: bus, reviewer: runtimeReviewer(), projectPathForJob: async (job) => resolveRepositoryProjectPath(repositoryPaths.get(job.repository) ?? await resolveManagedProjectPath(job.repository, explicitProjectPath, workspaceRoot), job.projectPath) });
|
|
138
137
|
if (repositories.length === 0)
|
|
139
138
|
throw new Error(`No Git repositories with GitHub origins found under ${normalized.workspaceRoot ?? defaultWorkspaceRoot()}`);
|
|
140
|
-
const
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
139
|
+
const localSnapshots = await discoverLocalRelayStoreSnapshots(join(homedir(), '.agents-relay', 'stores'));
|
|
140
|
+
const knownRepositories = new Set(repositories);
|
|
141
|
+
cachedOverviews = dashboardManagedJobs(localSnapshots.flatMap(snapshot => {
|
|
142
|
+
if (!snapshot.facts)
|
|
143
|
+
return [];
|
|
144
|
+
return snapshot.jobs.filter(job => knownRepositories.has(job.repository)).map(job => ({
|
|
145
|
+
job, githubState: snapshot.facts.state, draft: false, mergedAt: null, closedAt: null, publication: null,
|
|
146
|
+
}));
|
|
147
|
+
}));
|
|
148
|
+
const makeReconciler = (store, maxConcurrent) => new Reconciler(store, { owner: `relayd-${process.pid}`, maxConcurrent, leaseMs: Number(value(argv, '--lease-ms', '300000')), adapters: [new CodexAdapter(value(argv, '--codex', 'codex')), new ChatGptAdapter()], continuations: [new CodexThreadContinuation(value(argv, '--codex', 'codex')), new CommandContinuation(), new WebhookContinuation()], planner: runtimePlanner(argv), usageSnapshotProvider: () => usageRegistry.snapshot(), runtimeSummaryProvider: () => ({ chatgptRunning: summarizeRuntime(cachedOverviews.map(item => item.job)).workers.chatgpt }), decisionEngine: new LayaCliDecisionEngine(), decisionMode: decisionMode(), decisionAuditStore, eventBus: bus, reviewer: runtimeReviewer(), projectPathForJob: async (job) => resolveRepositoryProjectPath(repositoryPaths.get(job.repository) ?? await resolveManagedProjectPath(job.repository, explicitProjectPath, workspaceRoot), job.projectPath) });
|
|
148
149
|
const refreshAll = async (full = false) => {
|
|
149
150
|
if (client.rateLimitStatus().limited)
|
|
150
151
|
return cachedOverviews;
|
|
@@ -157,11 +158,6 @@ export async function runDaemon(argv) {
|
|
|
157
158
|
const scanned = new Set(scanRepositories);
|
|
158
159
|
const merged = dashboardManagedJobs([...cachedOverviews.filter(item => !scanned.has(item.job.repository)), ...refreshed]);
|
|
159
160
|
cachedOverviews = await overlayOperationalOverviews(merged, (repository, prNumber) => runtimeStore(repository, prNumber));
|
|
160
|
-
try {
|
|
161
|
-
await mkdir(cacheDirectory, { recursive: true });
|
|
162
|
-
await writeFile(cacheFile, JSON.stringify(cachedOverviews), 'utf8');
|
|
163
|
-
}
|
|
164
|
-
catch { /* cache is best effort */ }
|
|
165
161
|
return cachedOverviews;
|
|
166
162
|
}
|
|
167
163
|
catch (error) {
|
|
@@ -175,13 +171,6 @@ export async function runDaemon(argv) {
|
|
|
175
171
|
cachedOverviews = await overlayOperationalOverviews(cachedOverviews, (repository, prNumber) => runtimeStore(repository, prNumber));
|
|
176
172
|
return cachedOverviews;
|
|
177
173
|
};
|
|
178
|
-
const persistCache = async () => {
|
|
179
|
-
try {
|
|
180
|
-
await mkdir(cacheDirectory, { recursive: true });
|
|
181
|
-
await writeFile(cacheFile, JSON.stringify(cachedOverviews), 'utf8');
|
|
182
|
-
}
|
|
183
|
-
catch { /* cache is best effort */ }
|
|
184
|
-
};
|
|
185
174
|
const pullRequestRefreshFlights = new Map();
|
|
186
175
|
const pullRequestRefreshCache = new Map();
|
|
187
176
|
const incrementTrigger = (counts, trigger) => { counts[trigger] = (counts[trigger] ?? 0) + 1; };
|
|
@@ -209,7 +198,6 @@ export async function runDaemon(argv) {
|
|
|
209
198
|
cachedOverviews = cachedOverviews.filter(item => item.job.repository !== repository || item.job.prNumber !== prNumber);
|
|
210
199
|
cachedOverviews.push(...operational);
|
|
211
200
|
cachedOverviews = dashboardManagedJobs(cachedOverviews);
|
|
212
|
-
await persistCache();
|
|
213
201
|
const operationalSnapshot = { ...snapshot, overviews: operational };
|
|
214
202
|
pullRequestRefreshCache.set(key, { snapshot: operationalSnapshot, completedAt: Date.now() });
|
|
215
203
|
return operationalSnapshot;
|
|
@@ -384,21 +372,6 @@ export async function runDaemon(argv) {
|
|
|
384
372
|
store.close(); server.close(() => process.exit(0)); }); };
|
|
385
373
|
process.once('SIGINT', stop);
|
|
386
374
|
process.once('SIGTERM', stop);
|
|
387
|
-
const localSnapshots = await discoverLocalRelayStoreSnapshots(join(homedir(), '.agents-relay', 'stores'));
|
|
388
|
-
const knownRepositories = new Set(repositories);
|
|
389
|
-
const localOverviews = localSnapshots.flatMap(snapshot => {
|
|
390
|
-
if (!snapshot.facts)
|
|
391
|
-
return [];
|
|
392
|
-
return snapshot.jobs.filter(job => knownRepositories.has(job.repository)).map(job => ({
|
|
393
|
-
job, githubState: snapshot.facts.state, draft: false, mergedAt: null, closedAt: null, publication: null,
|
|
394
|
-
}));
|
|
395
|
-
});
|
|
396
|
-
const byJob = new Map();
|
|
397
|
-
for (const item of cachedOverviews)
|
|
398
|
-
byJob.set(item.job.repository + '#' + item.job.prNumber + ':' + item.job.id, item);
|
|
399
|
-
for (const item of localOverviews)
|
|
400
|
-
byJob.set(item.job.repository + '#' + item.job.prNumber + ':' + item.job.id, item);
|
|
401
|
-
cachedOverviews = dashboardManagedJobs([...byJob.values()]);
|
|
402
375
|
await pool.reconcileKnown(cachedOverviews);
|
|
403
376
|
await scheduleHeartbeatSafely();
|
|
404
377
|
await flushProjectionsSafely();
|