repowisestage 0.0.80 → 0.0.81

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.
Files changed (2) hide show
  1. package/dist/bin/repowise.js +121 -72
  2. package/package.json +1 -1
@@ -3172,6 +3172,8 @@ init_config_dir();
3172
3172
  import { readFile as readFile14, writeFile as writeFile16, mkdir as mkdir16, stat as fsStat } from "fs/promises";
3173
3173
  import { join as join42, dirname as dirname18 } from "path";
3174
3174
  import { fileURLToPath as fileURLToPath3 } from "url";
3175
+ import { execFile as execFile9 } from "child_process";
3176
+ import { promisify as promisify7 } from "util";
3175
3177
  import lockfile5 from "proper-lockfile";
3176
3178
 
3177
3179
  // ../../packages/shared/dist/lib/ai-tools.js
@@ -10986,6 +10988,7 @@ async function fetchProducerGraph(apiUrl, authToken, repoId, fetchImpl = fetch)
10986
10988
  // ../listener/dist/typed-resolution/hooks.js
10987
10989
  function buildTypedResolutionHooks(options) {
10988
10990
  const producer = options.producer ?? "repowise-listener/0.0.0";
10991
+ const inFlightProducers = /* @__PURE__ */ new Set();
10989
10992
  async function resolveToken() {
10990
10993
  try {
10991
10994
  return await options.getAuthToken();
@@ -11040,85 +11043,93 @@ function buildTypedResolutionHooks(options) {
11040
11043
  }
11041
11044
  },
11042
11045
  async onGraphReady(repoId, commitSha, localPath) {
11043
- const apiUrl = options.repoApiUrls.get(repoId);
11044
- if (!apiUrl)
11046
+ const inFlightKey = `${repoId} ${commitSha}`;
11047
+ if (inFlightProducers.has(inFlightKey))
11045
11048
  return;
11046
- const token = await resolveToken();
11047
- if (!token)
11048
- return;
11049
- const graph = await fetchProducerGraph(apiUrl, token, repoId);
11050
- const shaMatches = graph !== null && (graph.commitSha === commitSha || graph.commitSha.startsWith(commitSha) || commitSha.startsWith(graph.commitSha));
11051
- if (!graph || !shaMatches) {
11052
- console.warn(`[typed-resolution] graph.ready for ${repoId}@${commitSha.slice(0, 12)} but fetched graph is ${graph ? `at ${graph.commitSha.slice(0, 12)}` : "missing"} \u2014 skipping`);
11053
- return;
11054
- }
11055
- const receivers = graph.unresolvedReceivers ?? [];
11056
- const snapshot = {
11057
- resolvedCount: 0,
11058
- remainingReceivers: receivers.length,
11059
- // Until the first receiver completes, session spawn + server
11060
- // indexing is the activity signal that keeps the wait alive.
11061
- indexingActive: true
11062
- };
11063
- const reporter = createStatusReporter({
11064
- apiUrl,
11065
- repoId,
11066
- commitSha: graph.commitSha,
11067
- getAuthToken: options.getAuthToken,
11068
- ...options.getAuthTokenForceRefresh ? { getAuthTokenForceRefresh: options.getAuthTokenForceRefresh } : {},
11069
- getSnapshot: () => ({ ...snapshot })
11070
- });
11071
- reporter.start();
11072
- let prepared = null;
11049
+ inFlightProducers.add(inFlightKey);
11073
11050
  try {
11074
- if (receivers.length === 0) {
11075
- await reporter.reportCompleted();
11051
+ const apiUrl = options.repoApiUrls.get(repoId);
11052
+ if (!apiUrl)
11076
11053
  return;
11077
- }
11078
- prepared = await prepareCommittedTree(localPath, graph.commitSha);
11079
- if (!prepared) {
11080
- await reporter.reportCrashed();
11054
+ const token = await resolveToken();
11055
+ if (!token)
11056
+ return;
11057
+ const graph = await fetchProducerGraph(apiUrl, token, repoId);
11058
+ const shaMatches = graph !== null && (graph.commitSha === commitSha || graph.commitSha.startsWith(commitSha) || commitSha.startsWith(graph.commitSha));
11059
+ if (!graph || !shaMatches) {
11060
+ console.warn(`[typed-resolution] graph.ready for ${repoId}@${commitSha.slice(0, 12)} but fetched graph is ${graph ? `at ${graph.commitSha.slice(0, 12)}` : "missing"} \u2014 skipping`);
11081
11061
  return;
11082
11062
  }
11083
- const buildResult = await ensureIndexable(prepared.indexRoot, "swift", {
11084
- onActivity: () => {
11085
- snapshot.indexingActive = true;
11086
- }
11087
- });
11088
- if (!buildResult.ready) {
11089
- console.warn(`[typed-resolution] swift build unavailable for ${repoId}: ${buildResult.reason ?? "unknown"} \u2014 continuing without it`);
11090
- }
11091
- const lspOverrides = options.getLspOverrides?.();
11092
- const result = await runProducerCycle({
11063
+ const receivers = graph.unresolvedReceivers ?? [];
11064
+ const snapshot = {
11065
+ resolvedCount: 0,
11066
+ remainingReceivers: receivers.length,
11067
+ // Until the first receiver completes, session spawn + server
11068
+ // indexing is the activity signal that keeps the wait alive.
11069
+ indexingActive: true
11070
+ };
11071
+ const reporter = createStatusReporter({
11093
11072
  apiUrl,
11094
- authToken: token,
11095
11073
  repoId,
11096
- repoRoot: prepared.indexRoot,
11097
- graph,
11098
- workspaces: options.workspaces,
11099
- producer,
11100
- ...lspOverrides ? { lspOverrides } : {},
11101
- onReceiverProcessed: (processed, total, resolvedCount) => {
11102
- snapshot.resolvedCount = resolvedCount;
11103
- snapshot.remainingReceivers = Math.max(0, total - processed);
11104
- snapshot.indexingActive = false;
11105
- }
11074
+ commitSha: graph.commitSha,
11075
+ getAuthToken: options.getAuthToken,
11076
+ ...options.getAuthTokenForceRefresh ? { getAuthTokenForceRefresh: options.getAuthTokenForceRefresh } : {},
11077
+ getSnapshot: () => ({ ...snapshot })
11106
11078
  });
11107
- if (result) {
11108
- await reporter.reportCompleted();
11109
- } else {
11110
- await reporter.reportCrashed();
11111
- }
11112
- } catch (err) {
11113
- console.warn(`[typed-resolution] graph.ready producer failed for ${repoId}: ${err instanceof Error ? err.message : String(err)}`);
11114
- await reporter.reportCrashed().catch(() => void 0);
11115
- } finally {
11116
- reporter.stop();
11117
- if (prepared) {
11118
- await prepared.cleanup().catch((cleanupErr) => {
11119
- console.warn(`[typed-resolution] worktree cleanup failed: ${cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr)}`);
11079
+ reporter.start();
11080
+ let prepared = null;
11081
+ try {
11082
+ if (receivers.length === 0) {
11083
+ await reporter.reportCompleted();
11084
+ return;
11085
+ }
11086
+ prepared = await prepareCommittedTree(localPath, graph.commitSha);
11087
+ if (!prepared) {
11088
+ await reporter.reportCrashed();
11089
+ return;
11090
+ }
11091
+ const buildResult = await ensureIndexable(prepared.indexRoot, "swift", {
11092
+ onActivity: () => {
11093
+ snapshot.indexingActive = true;
11094
+ }
11120
11095
  });
11096
+ if (!buildResult.ready) {
11097
+ console.warn(`[typed-resolution] swift build unavailable for ${repoId}: ${buildResult.reason ?? "unknown"} \u2014 continuing without it`);
11098
+ }
11099
+ const lspOverrides = options.getLspOverrides?.();
11100
+ const result = await runProducerCycle({
11101
+ apiUrl,
11102
+ authToken: token,
11103
+ repoId,
11104
+ repoRoot: prepared.indexRoot,
11105
+ graph,
11106
+ workspaces: options.workspaces,
11107
+ producer,
11108
+ ...lspOverrides ? { lspOverrides } : {},
11109
+ onReceiverProcessed: (processed, total, resolvedCount) => {
11110
+ snapshot.resolvedCount = resolvedCount;
11111
+ snapshot.remainingReceivers = Math.max(0, total - processed);
11112
+ snapshot.indexingActive = false;
11113
+ }
11114
+ });
11115
+ if (result) {
11116
+ await reporter.reportCompleted();
11117
+ } else {
11118
+ await reporter.reportCrashed();
11119
+ }
11120
+ } catch (err) {
11121
+ console.warn(`[typed-resolution] graph.ready producer failed for ${repoId}: ${err instanceof Error ? err.message : String(err)}`);
11122
+ await reporter.reportCrashed().catch(() => void 0);
11123
+ } finally {
11124
+ reporter.stop();
11125
+ if (prepared) {
11126
+ await prepared.cleanup().catch((cleanupErr) => {
11127
+ console.warn(`[typed-resolution] worktree cleanup failed: ${cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr)}`);
11128
+ });
11129
+ }
11121
11130
  }
11131
+ } finally {
11132
+ inFlightProducers.delete(inFlightKey);
11122
11133
  }
11123
11134
  },
11124
11135
  async onSidecarMerged(repoId, commitSha) {
@@ -11142,6 +11153,16 @@ function buildTypedResolutionHooks(options) {
11142
11153
 
11143
11154
  // ../listener/dist/main.js
11144
11155
  var TWENTY_FOUR_HOURS_MS = 24 * 60 * 60 * 1e3;
11156
+ var execFileAsync4 = promisify7(execFile9);
11157
+ async function resolveHeadSha(localPath) {
11158
+ try {
11159
+ const { stdout } = await execFileAsync4("git", ["-C", localPath, "rev-parse", "HEAD"]);
11160
+ const sha = stdout.trim();
11161
+ return /^[0-9a-f]{7,40}$/.test(sha) ? sha : null;
11162
+ } catch {
11163
+ return null;
11164
+ }
11165
+ }
11145
11166
  var STALE_CHECK_COOLDOWN_MS = 60 * 60 * 1e3;
11146
11167
  var CRASH_LOOP_WINDOW_MS = 3e4;
11147
11168
  var CRASH_LOOP_THRESHOLD = 3;
@@ -11536,16 +11557,24 @@ async function handleCatchUp(offlineState, pollClient, repoIds, state, repoLocal
11536
11557
  lastSyncCommitSha: null
11537
11558
  // unknown from catch-up, but timestamp prevents re-download
11538
11559
  };
11560
+ const onGraphReady = typedResolutionHooks?.onGraphReady;
11561
+ if (onGraphReady) {
11562
+ void resolveHeadSha(localPath).then((headSha) => headSha ? onGraphReady(repoId, headSha, localPath) : void 0).catch((err) => {
11563
+ console.warn(`[catch-up] typed-resolution producer failed for ${repoId}: ${err instanceof Error ? err.message : String(err)}`);
11564
+ });
11565
+ }
11539
11566
  }
11540
11567
  }
11541
11568
  await saveState(state);
11542
- notifyBackOnline(syncCount);
11569
+ if (!offlineState.fromRestart)
11570
+ notifyBackOnline(syncCount);
11543
11571
  } else {
11544
11572
  const sinceTimestamp = offlineState.offlineSince;
11545
11573
  const response = await pollClient.poll(repoIds, sinceTimestamp);
11546
11574
  const updateCount = await processNotifications(response.notifications, state, repoLocalPaths, apiUrl, lspWorkspaces, typedResolutionHooks);
11547
11575
  await saveState(state);
11548
- notifyBackOnline(updateCount);
11576
+ if (!offlineState.fromRestart)
11577
+ notifyBackOnline(updateCount);
11549
11578
  }
11550
11579
  }
11551
11580
  async function checkStaleContext(repos, state, groups) {
@@ -11808,13 +11837,20 @@ async function startListener() {
11808
11837
  const apiUrl = repo.apiUrl ?? config2.defaultApiUrl;
11809
11838
  let group = groupMap.get(apiUrl);
11810
11839
  if (!group) {
11840
+ const persistedOfflineSince = state.offlineCursors?.[apiUrl] ?? null;
11811
11841
  group = {
11812
11842
  apiUrl,
11813
11843
  pollClient: new PollClient(apiUrl),
11814
11844
  backoff: new BackoffCalculator(),
11815
11845
  repoIds: [],
11816
11846
  repoLocalPaths: /* @__PURE__ */ new Map(),
11817
- offline: { isOffline: false, offlineSince: null, attemptCount: 0, nextRetryAt: 0 }
11847
+ offline: {
11848
+ isOffline: persistedOfflineSince !== null,
11849
+ offlineSince: persistedOfflineSince,
11850
+ attemptCount: 0,
11851
+ nextRetryAt: 0,
11852
+ fromRestart: persistedOfflineSince !== null
11853
+ }
11818
11854
  };
11819
11855
  groupMap.set(apiUrl, group);
11820
11856
  }
@@ -12233,7 +12269,12 @@ async function startListener() {
12233
12269
  group.offline.offlineSince = null;
12234
12270
  group.offline.attemptCount = 0;
12235
12271
  group.offline.nextRetryAt = 0;
12272
+ group.offline.fromRestart = false;
12236
12273
  group.backoff.reset();
12274
+ if (state.offlineCursors?.[group.apiUrl]) {
12275
+ delete state.offlineCursors[group.apiUrl];
12276
+ await saveState(state);
12277
+ }
12237
12278
  } else if (response.notifications.length > 0) {
12238
12279
  await processNotifications(response.notifications, state, group.repoLocalPaths, group.apiUrl, mcpRuntime?.lspWorkspaces, typedResolutionHooks);
12239
12280
  await saveState(state);
@@ -12274,11 +12315,19 @@ async function startListener() {
12274
12315
  group.offline.isOffline = true;
12275
12316
  group.offline.offlineSince = (/* @__PURE__ */ new Date()).toISOString();
12276
12317
  group.offline.attemptCount = 0;
12318
+ group.offline.fromRestart = false;
12277
12319
  if (!connectionLostNotified) {
12278
12320
  notifyConnectionLost();
12279
12321
  connectionLostNotified = true;
12280
12322
  }
12281
12323
  }
12324
+ if (group.offline.offlineSince) {
12325
+ state.offlineCursors = {
12326
+ ...state.offlineCursors,
12327
+ [group.apiUrl]: group.offline.offlineSince
12328
+ };
12329
+ await saveState(state);
12330
+ }
12282
12331
  group.offline.attemptCount++;
12283
12332
  const delay3 = group.backoff.nextDelay();
12284
12333
  group.offline.nextRetryAt = Date.now() + delay3;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "repowisestage",
3
- "version": "0.0.80",
3
+ "version": "0.0.81",
4
4
  "type": "module",
5
5
  "description": "AI-optimized codebase context generator",
6
6
  "bin": {