@agent-relay/factory 0.1.39 → 0.1.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/orchestrator/factory.d.ts.map +1 -1
- package/dist/orchestrator/factory.js +87 -11
- package/dist/orchestrator/factory.js.map +1 -1
- package/dist/ports/state.d.ts +1 -0
- package/dist/ports/state.d.ts.map +1 -1
- package/dist/state/file-state-store.d.ts +1 -0
- package/dist/state/file-state-store.d.ts.map +1 -1
- package/dist/state/file-state-store.js +18 -0
- package/dist/state/file-state-store.js.map +1 -1
- package/dist/state/in-memory-state-store.d.ts +1 -0
- package/dist/state/in-memory-state-store.d.ts.map +1 -1
- package/dist/state/in-memory-state-store.js +12 -0
- package/dist/state/in-memory-state-store.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/orchestrator/factory.ts"],"names":[],"mappings":"AAIA,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAI1E,OAAO,KAAK,EAMV,WAAW,EASX,WAAW,EAKZ,MAAM,UAAU,CAAA;AAiCjB,OAAO,KAAK,EACV,cAAc,EACd,OAAO,EACP,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,mBAAmB,EAEnB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EAGnB,QAAQ,EACR,eAAe,EACf,WAAW,EAGX,cAAc,EAEf,MAAM,UAAU,CAAA;AA4BjB,KAAK,YAAY,GAAG,cAAc,GAAG,YAAY,GAAG,YAAY,GAAG,oBAAoB,GAAG,OAAO,CAAA;AACjG,KAAK,QAAQ,GAAG,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAA;AAoFtD,KAAK,iBAAiB,GAAG;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC7B,CAAA;AA8FD,eAAO,MAAM,mCAAmC,iDAAiD,CAAA;AACjG,eAAO,MAAM,kCAAkC,gDAAgD,CAAA;AAQ/F,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAEjF;AAED,qBAAa,WAAY,YAAW,OAAO;;gBA+J7B,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY;IAkIhD,uBAAuB,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAiEvD,KAAK,CAAC,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsHpD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwIrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA8mBxB,OAAO,CAAC,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,eAAe,CAAC;IAkoBlE,OAAO,CAAC,IAAI,GAAE,qBAA0B,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAyDrE,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;IAOxD,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,eAAe,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,cAAc,CAAC;IAsT7H,MAAM,IAAI,aAAa;IAiBvB,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,IAAI;
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/orchestrator/factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -2326,7 +2326,7 @@ export class FactoryLoop {
|
|
|
2326
2326
|
const batch = await this.#batch();
|
|
2327
2327
|
const agents = [];
|
|
2328
2328
|
let hasNonterminalDurableLifecycle = false;
|
|
2329
|
-
const durableLifecycles = await this.#state.listDispatchLifecycles(this.#workspaceId);
|
|
2329
|
+
const durableLifecycles = await this.#deduplicateQueuedGithubLifecycleAliases(await this.#state.listDispatchLifecycles(this.#workspaceId));
|
|
2330
2330
|
this.#logger.info?.('[factory] durable startup adoption loaded', {
|
|
2331
2331
|
lifecycles: durableLifecycles.length,
|
|
2332
2332
|
});
|
|
@@ -2418,6 +2418,64 @@ export class FactoryLoop {
|
|
|
2418
2418
|
this.#logger.warn?.('[factory] failed to re-adopt durable in-flight agents', { error });
|
|
2419
2419
|
}
|
|
2420
2420
|
}
|
|
2421
|
+
async #deduplicateQueuedGithubLifecycleAliases(lifecycles) {
|
|
2422
|
+
const groups = new Map();
|
|
2423
|
+
for (const entry of lifecycles) {
|
|
2424
|
+
if (isTerminalDispatchLifecycle(entry[1]))
|
|
2425
|
+
continue;
|
|
2426
|
+
const identity = githubIssueRefIdentity(entry[1].issue);
|
|
2427
|
+
if (!identity)
|
|
2428
|
+
continue;
|
|
2429
|
+
const group = groups.get(identity) ?? [];
|
|
2430
|
+
group.push(entry);
|
|
2431
|
+
groups.set(identity, group);
|
|
2432
|
+
}
|
|
2433
|
+
const clearedKeys = new Set();
|
|
2434
|
+
for (const [identity, group] of groups) {
|
|
2435
|
+
if (group.length < 2)
|
|
2436
|
+
continue;
|
|
2437
|
+
const active = group.filter(([, lifecycle]) => lifecycle.phase !== 'queued');
|
|
2438
|
+
// Two independently active aliases may each own useful work. Preserve
|
|
2439
|
+
// both for operator reconciliation instead of guessing which branch wins.
|
|
2440
|
+
if (active.length > 1) {
|
|
2441
|
+
this.#increment('dispatchLifecycleGithubAliasConflicts');
|
|
2442
|
+
this.#logger.warn?.('[factory] retained conflicting active GitHub lifecycle aliases', {
|
|
2443
|
+
identity,
|
|
2444
|
+
count: group.length,
|
|
2445
|
+
});
|
|
2446
|
+
continue;
|
|
2447
|
+
}
|
|
2448
|
+
const nowMs = this.#clock.now();
|
|
2449
|
+
const ownedElsewhere = group.some(([, lifecycle]) => lifecycle.lease &&
|
|
2450
|
+
lifecycle.lease.owner !== this.#dispatchLifecycleOwner &&
|
|
2451
|
+
lifecycle.lease.leaseUntilMs > nowMs);
|
|
2452
|
+
if (ownedElsewhere) {
|
|
2453
|
+
this.#increment('dispatchLifecycleGithubAliasDedupeDeferred');
|
|
2454
|
+
continue;
|
|
2455
|
+
}
|
|
2456
|
+
const winner = active[0] ?? [...group].sort(compareQueuedGithubLifecycleAliases)[0];
|
|
2457
|
+
for (const [key, lifecycle] of group) {
|
|
2458
|
+
if (key === winner[0] || lifecycle.phase !== 'queued')
|
|
2459
|
+
continue;
|
|
2460
|
+
const cleared = await this.#state.clearQueuedDispatchLifecycle(this.#workspaceId, key, lifecycle.lease);
|
|
2461
|
+
if (!cleared) {
|
|
2462
|
+
this.#increment('dispatchLifecycleGithubAliasDedupeDeferred');
|
|
2463
|
+
continue;
|
|
2464
|
+
}
|
|
2465
|
+
this.#dispatchLifecycleEpochs.delete(key);
|
|
2466
|
+
const timer = this.#dispatchLifecycleRetryTimers.get(key);
|
|
2467
|
+
if (timer)
|
|
2468
|
+
clearTimeout(timer);
|
|
2469
|
+
this.#dispatchLifecycleRetryTimers.delete(key);
|
|
2470
|
+
this.#dispatchLifecycleCapacityWaitLogged.delete(key);
|
|
2471
|
+
clearedKeys.add(key);
|
|
2472
|
+
this.#increment('dispatchLifecycleGithubAliasesCollapsed');
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
return clearedKeys.size > 0
|
|
2476
|
+
? lifecycles.filter(([key]) => !clearedKeys.has(key))
|
|
2477
|
+
: lifecycles;
|
|
2478
|
+
}
|
|
2421
2479
|
async #drainAgentExitsInFlight(names, timeoutMs) {
|
|
2422
2480
|
const drain = async () => {
|
|
2423
2481
|
for (;;) {
|
|
@@ -10982,24 +11040,42 @@ const normalizeGithubIssueCommentWatch = (watch) => ({
|
|
|
10982
11040
|
processedCommentIds: [...new Set(watch.processedCommentIds ?? [])],
|
|
10983
11041
|
});
|
|
10984
11042
|
const githubIssueReadCandidatePaths = (path) => {
|
|
11043
|
+
const candidates = [];
|
|
10985
11044
|
if (path.endsWith('/')) {
|
|
10986
|
-
|
|
11045
|
+
candidates.push(`${path}meta.json`, `${path}metadata.json`);
|
|
10987
11046
|
}
|
|
10988
|
-
if (path.endsWith('/meta.json')) {
|
|
10989
|
-
|
|
11047
|
+
else if (path.endsWith('/meta.json')) {
|
|
11048
|
+
candidates.push(path, path.replace(/\/meta\.json$/u, '/metadata.json'));
|
|
10990
11049
|
}
|
|
10991
|
-
if (path.endsWith('/metadata.json')) {
|
|
10992
|
-
|
|
11050
|
+
else if (path.endsWith('/metadata.json')) {
|
|
11051
|
+
candidates.push(path, path.replace(/\/metadata\.json$/u, '/meta.json'));
|
|
10993
11052
|
}
|
|
10994
|
-
if (githubIssuePathParts(path)) {
|
|
10995
|
-
|
|
11053
|
+
else if (githubIssuePathParts(path)) {
|
|
11054
|
+
candidates.push(path);
|
|
10996
11055
|
}
|
|
10997
|
-
if (githubIssueDirectoryPathParts(path)) {
|
|
11056
|
+
else if (githubIssueDirectoryPathParts(path)) {
|
|
10998
11057
|
// meta.json is the canonical relayfile GitHub issue basename. metadata.json
|
|
10999
11058
|
// remains a legacy read fallback for older local mount-state snapshots.
|
|
11000
|
-
|
|
11059
|
+
candidates.push(`${path}/meta.json`, `${path}/metadata.json`);
|
|
11060
|
+
}
|
|
11061
|
+
else {
|
|
11062
|
+
candidates.push(path);
|
|
11063
|
+
}
|
|
11064
|
+
// Title-derived directories are mutable aliases. A renamed issue may leave
|
|
11065
|
+
// a durable lifecycle pointing at its old slug, while the adapter continues
|
|
11066
|
+
// to expose the stable public by-id aliases. Always include both supported
|
|
11067
|
+
// repository layouts so recovery never hot-loops on an obsolete title path.
|
|
11068
|
+
const parts = githubIssuePathParts(path) ?? githubIssueDirectoryPathParts(path);
|
|
11069
|
+
if (parts) {
|
|
11070
|
+
candidates.push(`${GITHUB_ISSUE_ROOT}/${parts.owner}__${parts.repo}/issues/by-id/${parts.number}.json`, `${GITHUB_ISSUE_ROOT}/${parts.owner}/${parts.repo}/issues/by-id/${parts.number}.json`);
|
|
11001
11071
|
}
|
|
11002
|
-
return [
|
|
11072
|
+
return [...new Set(candidates)];
|
|
11073
|
+
};
|
|
11074
|
+
const compareQueuedGithubLifecycleAliases = (left, right) => {
|
|
11075
|
+
const stablePath = (lifecycle) => lifecycle.issue.path.includes('/issues/by-id/') ? 0 : 1;
|
|
11076
|
+
return stablePath(left[1]) - stablePath(right[1]) ||
|
|
11077
|
+
(right[1].updatedAtMs ?? 0) - (left[1].updatedAtMs ?? 0) ||
|
|
11078
|
+
left[0].localeCompare(right[0]);
|
|
11003
11079
|
};
|
|
11004
11080
|
const githubIssueDirectoryPathParts = (path) => {
|
|
11005
11081
|
const match = path.match(/^\/github\/repos\/(?:([^/]+)\/([^/]+)|([A-Za-z0-9-]+)__([^/]+))\/issues\/(\d+)(?:__([^/]+))?$/u);
|