@straiffi/archon 1.0.10 → 1.0.12
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/client/assets/index-BhQzJS4j.css +2 -0
- package/dist/client/assets/{index-C1cEAh5V.js → index-vramqRal.js} +86 -86
- package/dist/client/index.html +2 -2
- package/dist/server/index.js +122 -9
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/index-DIk6btSD.css +0 -2
package/dist/client/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>Archon</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-vramqRal.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BhQzJS4j.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
package/dist/server/index.js
CHANGED
|
@@ -866,7 +866,75 @@ const getBundleReviewState = (projectId, tickets) => {
|
|
|
866
866
|
can_re_review: reviewState.can_re_review,
|
|
867
867
|
};
|
|
868
868
|
};
|
|
869
|
-
const BUNDLE_PULL_REQUEST_SYNC_TTL_MS =
|
|
869
|
+
const BUNDLE_PULL_REQUEST_SYNC_TTL_MS = 60 * 1000;
|
|
870
|
+
const BUNDLE_PULL_REQUEST_DISCOVERY_MISS_COOLDOWN_MS = 10 * 60 * 1000;
|
|
871
|
+
const BUNDLE_PULL_REQUEST_DISCOVERY_ERROR_COOLDOWN_MS = 2 * 60 * 1000;
|
|
872
|
+
const BUNDLE_PULL_REQUEST_SYNC_ERROR_COOLDOWN_MS = 2 * 60 * 1000;
|
|
873
|
+
const MAX_BACKGROUND_PULL_REQUEST_SYNCS_PER_PROJECT_REFRESH = 2;
|
|
874
|
+
// Avoid repeated open-triggered discovery hits when a bundle has no PR yet or GitHub is temporarily unavailable.
|
|
875
|
+
const bundlePullRequestDiscoveryInFlight = new Map();
|
|
876
|
+
const bundlePullRequestDiscoveryMissTimestamps = new Map();
|
|
877
|
+
const bundlePullRequestDiscoveryErrorTimestamps = new Map();
|
|
878
|
+
const bundlePullRequestSyncInFlight = new Map();
|
|
879
|
+
const bundlePullRequestSyncErrorTimestamps = new Map();
|
|
880
|
+
const getBundlePullRequestDiscoveryKey = (projectId, bundleId) => `${projectId}:${bundleId}`;
|
|
881
|
+
const isBundlePullRequestDiscoveryCoolingDown = (timestamps, key, cooldownMs) => {
|
|
882
|
+
const lastAttemptAt = timestamps.get(key);
|
|
883
|
+
if (lastAttemptAt === undefined) {
|
|
884
|
+
return false;
|
|
885
|
+
}
|
|
886
|
+
if (Date.now() - lastAttemptAt < cooldownMs) {
|
|
887
|
+
return true;
|
|
888
|
+
}
|
|
889
|
+
timestamps.delete(key);
|
|
890
|
+
return false;
|
|
891
|
+
};
|
|
892
|
+
const shouldDiscoverBundlePullRequestOnOpen = (project, bundle) => {
|
|
893
|
+
if (!getGitHubConnectionConfig(project.id) || isProjectRootBundle(bundle) || getBundlePullRequestRecord(bundle.id, project.id)) {
|
|
894
|
+
return false;
|
|
895
|
+
}
|
|
896
|
+
const tickets = listBundleTickets(project.id, bundle.id);
|
|
897
|
+
if (tickets.length === 0 || !tickets.some(ticket => ticket.state !== 'plan')) {
|
|
898
|
+
return false;
|
|
899
|
+
}
|
|
900
|
+
if (tickets.some(ticket => ticket.agent_status === 'running')) {
|
|
901
|
+
return false;
|
|
902
|
+
}
|
|
903
|
+
if (!hasGitHubRemoteBranch(project.repo_path, bundle.branch)) {
|
|
904
|
+
return false;
|
|
905
|
+
}
|
|
906
|
+
const key = getBundlePullRequestDiscoveryKey(project.id, bundle.id);
|
|
907
|
+
if (bundlePullRequestDiscoveryInFlight.has(key)) {
|
|
908
|
+
return false;
|
|
909
|
+
}
|
|
910
|
+
return !isBundlePullRequestDiscoveryCoolingDown(bundlePullRequestDiscoveryMissTimestamps, key, BUNDLE_PULL_REQUEST_DISCOVERY_MISS_COOLDOWN_MS) && !isBundlePullRequestDiscoveryCoolingDown(bundlePullRequestDiscoveryErrorTimestamps, key, BUNDLE_PULL_REQUEST_DISCOVERY_ERROR_COOLDOWN_MS);
|
|
911
|
+
};
|
|
912
|
+
const startBundlePullRequestDiscoveryIfNeeded = (project, bundle) => {
|
|
913
|
+
if (!shouldDiscoverBundlePullRequestOnOpen(project, bundle)) {
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
const key = getBundlePullRequestDiscoveryKey(project.id, bundle.id);
|
|
917
|
+
const task = (async () => {
|
|
918
|
+
try {
|
|
919
|
+
const discoveredPullRequest = await discoverOpenBundlePullRequest(project, bundle);
|
|
920
|
+
if (!discoveredPullRequest) {
|
|
921
|
+
bundlePullRequestDiscoveryMissTimestamps.set(key, Date.now());
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
924
|
+
bundlePullRequestDiscoveryMissTimestamps.delete(key);
|
|
925
|
+
bundlePullRequestDiscoveryErrorTimestamps.delete(key);
|
|
926
|
+
reconcileBundleTicketsAfterPullRequestSync(project.id, bundle.id);
|
|
927
|
+
}
|
|
928
|
+
catch (error) {
|
|
929
|
+
bundlePullRequestDiscoveryErrorTimestamps.set(key, Date.now());
|
|
930
|
+
console.warn(`[integrations] github pr discovery failed project=${project.id} bundle=${bundle.id}`, error);
|
|
931
|
+
}
|
|
932
|
+
finally {
|
|
933
|
+
bundlePullRequestDiscoveryInFlight.delete(key);
|
|
934
|
+
}
|
|
935
|
+
})();
|
|
936
|
+
bundlePullRequestDiscoveryInFlight.set(key, task);
|
|
937
|
+
};
|
|
870
938
|
const serializeBundleRow = (projectId, bundle) => {
|
|
871
939
|
if (!bundle) {
|
|
872
940
|
return null;
|
|
@@ -921,6 +989,7 @@ const discoverOpenBundlePullRequest = async (project, bundle) => {
|
|
|
921
989
|
};
|
|
922
990
|
const syncTrackedBundlePullRequestIfNeeded = async (project, bundle, options = {}) => {
|
|
923
991
|
const force = options.force ?? false;
|
|
992
|
+
const rethrow = options.rethrow ?? false;
|
|
924
993
|
const githubConfig = getGitHubConnectionConfig(project.id);
|
|
925
994
|
const existingRecord = getBundlePullRequestRecord(bundle.id, project.id);
|
|
926
995
|
if (!githubConfig || !existingRecord) {
|
|
@@ -936,9 +1005,49 @@ const syncTrackedBundlePullRequestIfNeeded = async (project, bundle, options = {
|
|
|
936
1005
|
}
|
|
937
1006
|
catch (error) {
|
|
938
1007
|
console.warn(`[integrations] github pr sync failed project=${project.id} bundle=${bundle.id} pr=${existingRecord.number}`, error);
|
|
1008
|
+
if (rethrow) {
|
|
1009
|
+
throw error;
|
|
1010
|
+
}
|
|
939
1011
|
return existingRecord;
|
|
940
1012
|
}
|
|
941
1013
|
};
|
|
1014
|
+
const shouldStartTrackedBundlePullRequestSync = (project, bundle, options = {}) => {
|
|
1015
|
+
const force = options.force ?? false;
|
|
1016
|
+
const existingRecord = getBundlePullRequestRecord(bundle.id, project.id);
|
|
1017
|
+
if (!getGitHubConnectionConfig(project.id) || !existingRecord) {
|
|
1018
|
+
return false;
|
|
1019
|
+
}
|
|
1020
|
+
if (!force && !shouldSyncBundlePullRequest(existingRecord, BUNDLE_PULL_REQUEST_SYNC_TTL_MS)) {
|
|
1021
|
+
return false;
|
|
1022
|
+
}
|
|
1023
|
+
const key = getBundlePullRequestDiscoveryKey(project.id, bundle.id);
|
|
1024
|
+
if (bundlePullRequestSyncInFlight.has(key)) {
|
|
1025
|
+
return false;
|
|
1026
|
+
}
|
|
1027
|
+
return force || !isBundlePullRequestDiscoveryCoolingDown(bundlePullRequestSyncErrorTimestamps, key, BUNDLE_PULL_REQUEST_SYNC_ERROR_COOLDOWN_MS);
|
|
1028
|
+
};
|
|
1029
|
+
const startTrackedBundlePullRequestSyncIfNeeded = (project, bundle, options = {}) => {
|
|
1030
|
+
if (!shouldStartTrackedBundlePullRequestSync(project, bundle, options)) {
|
|
1031
|
+
return false;
|
|
1032
|
+
}
|
|
1033
|
+
const key = getBundlePullRequestDiscoveryKey(project.id, bundle.id);
|
|
1034
|
+
const task = (async () => {
|
|
1035
|
+
try {
|
|
1036
|
+
await syncTrackedBundlePullRequestIfNeeded(project, bundle, { ...options, rethrow: true });
|
|
1037
|
+
bundlePullRequestSyncErrorTimestamps.delete(key);
|
|
1038
|
+
reconcileBundleTicketsAfterPullRequestSync(project.id, bundle.id);
|
|
1039
|
+
}
|
|
1040
|
+
catch (error) {
|
|
1041
|
+
bundlePullRequestSyncErrorTimestamps.set(key, Date.now());
|
|
1042
|
+
console.warn(`[integrations] github pr background sync failed project=${project.id} bundle=${bundle.id}`, error);
|
|
1043
|
+
}
|
|
1044
|
+
finally {
|
|
1045
|
+
bundlePullRequestSyncInFlight.delete(key);
|
|
1046
|
+
}
|
|
1047
|
+
})();
|
|
1048
|
+
bundlePullRequestSyncInFlight.set(key, task);
|
|
1049
|
+
return true;
|
|
1050
|
+
};
|
|
942
1051
|
const listBundleTicketIds = (projectId, bundleId) => {
|
|
943
1052
|
const rows = db.prepare('SELECT id FROM tickets WHERE project_id = ? AND worktree_bundle_id = ? ORDER BY updated_at DESC, id DESC').all(projectId, bundleId);
|
|
944
1053
|
return rows.map(row => row.id);
|
|
@@ -996,11 +1105,15 @@ const reconcileBundleTicketsAfterPullRequestSync = (projectId, bundleId) => {
|
|
|
996
1105
|
}
|
|
997
1106
|
};
|
|
998
1107
|
const syncProjectBundlePullRequestsIfNeeded = async (project, bundles, options = {}) => {
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1108
|
+
let startedCount = 0;
|
|
1109
|
+
for (const bundle of bundles) {
|
|
1110
|
+
if (startedCount >= MAX_BACKGROUND_PULL_REQUEST_SYNCS_PER_PROJECT_REFRESH) {
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
if (startTrackedBundlePullRequestSyncIfNeeded(project, bundle, options)) {
|
|
1114
|
+
startedCount += 1;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1004
1117
|
};
|
|
1005
1118
|
const startProjectBundlePullRequestSyncIfNeeded = (project, bundles, options = {}) => {
|
|
1006
1119
|
void syncProjectBundlePullRequestsIfNeeded(project, bundles, options).catch(error => {
|
|
@@ -1993,9 +2106,8 @@ app.get('/tickets/:id', async (req, res) => {
|
|
|
1993
2106
|
const project = getProjectById(ticket.project_id);
|
|
1994
2107
|
const bundle = project ? getBundle(ticket.worktree_bundle_id, project.id) : null;
|
|
1995
2108
|
if (project && bundle) {
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
ticket = getTicket(req.params.id);
|
|
2109
|
+
startTrackedBundlePullRequestSyncIfNeeded(project, bundle);
|
|
2110
|
+
startBundlePullRequestDiscoveryIfNeeded(project, bundle);
|
|
1999
2111
|
}
|
|
2000
2112
|
}
|
|
2001
2113
|
return res.json(ticket);
|
|
@@ -2103,6 +2215,7 @@ app.get('/bundles/:id/conversation', (req, res) => {
|
|
|
2103
2215
|
if (!bundle) {
|
|
2104
2216
|
return res.status(404).json({ error: 'Bundle not found' });
|
|
2105
2217
|
}
|
|
2218
|
+
startBundlePullRequestDiscoveryIfNeeded(result.project, bundle);
|
|
2106
2219
|
const payload = serializeBundleConversationDetails(result.project, bundle);
|
|
2107
2220
|
res.json(payload);
|
|
2108
2221
|
});
|