@straiffi/archon 1.0.9 → 1.0.11

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.
@@ -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-7j74CLel.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-DIk6btSD.css">
8
+ <script type="module" crossorigin src="/assets/index-Dgewr5ST.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-BhQzJS4j.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
@@ -867,6 +867,70 @@ const getBundleReviewState = (projectId, tickets) => {
867
867
  };
868
868
  };
869
869
  const BUNDLE_PULL_REQUEST_SYNC_TTL_MS = 15 * 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
+ // Avoid repeated open-triggered discovery hits when a bundle has no PR yet or GitHub is temporarily unavailable.
873
+ const bundlePullRequestDiscoveryInFlight = new Map();
874
+ const bundlePullRequestDiscoveryMissTimestamps = new Map();
875
+ const bundlePullRequestDiscoveryErrorTimestamps = new Map();
876
+ const getBundlePullRequestDiscoveryKey = (projectId, bundleId) => `${projectId}:${bundleId}`;
877
+ const isBundlePullRequestDiscoveryCoolingDown = (timestamps, key, cooldownMs) => {
878
+ const lastAttemptAt = timestamps.get(key);
879
+ if (lastAttemptAt === undefined) {
880
+ return false;
881
+ }
882
+ if (Date.now() - lastAttemptAt < cooldownMs) {
883
+ return true;
884
+ }
885
+ timestamps.delete(key);
886
+ return false;
887
+ };
888
+ const shouldDiscoverBundlePullRequestOnOpen = (project, bundle) => {
889
+ if (!getGitHubConnectionConfig(project.id) || isProjectRootBundle(bundle) || getBundlePullRequestRecord(bundle.id, project.id)) {
890
+ return false;
891
+ }
892
+ const tickets = listBundleTickets(project.id, bundle.id);
893
+ if (tickets.length === 0 || !tickets.some(ticket => ticket.state !== 'plan')) {
894
+ return false;
895
+ }
896
+ if (tickets.some(ticket => ticket.agent_status === 'running')) {
897
+ return false;
898
+ }
899
+ if (!hasGitHubRemoteBranch(project.repo_path, bundle.branch)) {
900
+ return false;
901
+ }
902
+ const key = getBundlePullRequestDiscoveryKey(project.id, bundle.id);
903
+ if (bundlePullRequestDiscoveryInFlight.has(key)) {
904
+ return false;
905
+ }
906
+ return !isBundlePullRequestDiscoveryCoolingDown(bundlePullRequestDiscoveryMissTimestamps, key, BUNDLE_PULL_REQUEST_DISCOVERY_MISS_COOLDOWN_MS) && !isBundlePullRequestDiscoveryCoolingDown(bundlePullRequestDiscoveryErrorTimestamps, key, BUNDLE_PULL_REQUEST_DISCOVERY_ERROR_COOLDOWN_MS);
907
+ };
908
+ const startBundlePullRequestDiscoveryIfNeeded = (project, bundle) => {
909
+ if (!shouldDiscoverBundlePullRequestOnOpen(project, bundle)) {
910
+ return;
911
+ }
912
+ const key = getBundlePullRequestDiscoveryKey(project.id, bundle.id);
913
+ const task = (async () => {
914
+ try {
915
+ const discoveredPullRequest = await discoverOpenBundlePullRequest(project, bundle);
916
+ if (!discoveredPullRequest) {
917
+ bundlePullRequestDiscoveryMissTimestamps.set(key, Date.now());
918
+ return;
919
+ }
920
+ bundlePullRequestDiscoveryMissTimestamps.delete(key);
921
+ bundlePullRequestDiscoveryErrorTimestamps.delete(key);
922
+ reconcileBundleTicketsAfterPullRequestSync(project.id, bundle.id);
923
+ }
924
+ catch (error) {
925
+ bundlePullRequestDiscoveryErrorTimestamps.set(key, Date.now());
926
+ console.warn(`[integrations] github pr discovery failed project=${project.id} bundle=${bundle.id}`, error);
927
+ }
928
+ finally {
929
+ bundlePullRequestDiscoveryInFlight.delete(key);
930
+ }
931
+ })();
932
+ bundlePullRequestDiscoveryInFlight.set(key, task);
933
+ };
870
934
  const serializeBundleRow = (projectId, bundle) => {
871
935
  if (!bundle) {
872
936
  return null;
@@ -1995,6 +2059,7 @@ app.get('/tickets/:id', async (req, res) => {
1995
2059
  if (project && bundle) {
1996
2060
  await syncTrackedBundlePullRequestIfNeeded(project, bundle);
1997
2061
  reconcileBundleTicketsAfterPullRequestSync(project.id, bundle.id);
2062
+ startBundlePullRequestDiscoveryIfNeeded(project, bundle);
1998
2063
  ticket = getTicket(req.params.id);
1999
2064
  }
2000
2065
  }
@@ -2103,6 +2168,7 @@ app.get('/bundles/:id/conversation', (req, res) => {
2103
2168
  if (!bundle) {
2104
2169
  return res.status(404).json({ error: 'Bundle not found' });
2105
2170
  }
2171
+ startBundlePullRequestDiscoveryIfNeeded(result.project, bundle);
2106
2172
  const payload = serializeBundleConversationDetails(result.project, bundle);
2107
2173
  res.json(payload);
2108
2174
  });