@khalilgharbaoui/opencode-claude-code-plugin 0.61.2 → 0.62.1

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/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/claude-code-language-model.ts
2
- import { join as join19 } from "path";
2
+ import { join as join20 } from "path";
3
3
 
4
4
  // src/ids.ts
5
5
  import { randomInt } from "crypto";
@@ -906,6 +906,44 @@ function recordUsageReading(account, window, reading, now = Date.now()) {
906
906
  cache = { path: file, usage: kept };
907
907
  return writeStore(file, kept, store.known) ? entry : null;
908
908
  }
909
+ function usageReadingsFromObservation(observation, previous, now = Date.now()) {
910
+ const out = [];
911
+ const windows = observation.windows ?? {};
912
+ const limiting = observation.window;
913
+ if (limiting && observation.status) {
914
+ const own = windows[limiting];
915
+ out.push([
916
+ limiting,
917
+ {
918
+ utilization: finite(observation.utilization) ? observation.utilization : own && finite(own.utilization) ? own.utilization : null,
919
+ resetsAt: finite(observation.resetsAt) ? observation.resetsAt : own?.resetsAt,
920
+ status: observation.status
921
+ }
922
+ ]);
923
+ }
924
+ for (const [window, own] of Object.entries(windows)) {
925
+ if (window === limiting || !finite(own.utilization)) continue;
926
+ const before = previous(window);
927
+ const stillRefused = before !== void 0 && before.status === "rejected" && isReadingCurrent(before, now) && own.utilization >= 1;
928
+ out.push([window, { utilization: own.utilization, resetsAt: own.resetsAt, status: stillRefused ? "rejected" : "allowed" }]);
929
+ }
930
+ return out;
931
+ }
932
+ function recordRateLimitObservation(account, observation, now = Date.now()) {
933
+ if (!NAME.test(account)) return false;
934
+ const file = accountUsageStorePath();
935
+ const store = parseStore(file, now);
936
+ const merged = store.usage;
937
+ const windows = merged.get(account) ?? /* @__PURE__ */ new Map();
938
+ const previous = (window) => windows.get(window) ?? cached(now).get(account)?.get(window);
939
+ const readings = usageReadingsFromObservation(observation, previous, now).filter(([window]) => NAME.test(window));
940
+ if (readings.length === 0) return false;
941
+ for (const [window, reading] of readings) windows.set(window, applyReading(previous(window), reading, now));
942
+ merged.set(account, windows);
943
+ const kept = bounded(merged, now);
944
+ cache = { path: file, usage: kept };
945
+ return writeStore(file, kept, store.known);
946
+ }
909
947
  function markUsageNoted(account, window, thresholds, now = Date.now()) {
910
948
  if (!NAME.test(account) || !NAME.test(window) || thresholds.length === 0) return false;
911
949
  const file = accountUsageStorePath();
@@ -992,6 +1030,18 @@ function str(value) {
992
1030
  function num(value) {
993
1031
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
994
1032
  }
1033
+ function parseUnifiedWindows(value) {
1034
+ if (!isRecord(value)) return void 0;
1035
+ const out = {};
1036
+ for (const [window, raw] of Object.entries(value)) {
1037
+ if (!isRecord(raw)) continue;
1038
+ const utilization = num(raw.utilization);
1039
+ if (utilization === void 0 || utilization < 0) continue;
1040
+ const resetsAt = num(raw.resetsAt);
1041
+ out[window] = resetsAt === void 0 ? { utilization } : { utilization, resetsAt };
1042
+ }
1043
+ return Object.keys(out).length > 0 ? out : void 0;
1044
+ }
995
1045
  var RATE_LIMIT_MARKER = "\u258C **rate limit:**";
996
1046
  var RATE_LIMIT_ACTION = "Enable extra usage or add credits on the account, wait for the window to reset, switch account, org or plan, or authenticate with an API key.";
997
1047
  var OVERAGE_DISABLED_REASONS = {
@@ -1020,6 +1070,7 @@ function parseRateLimitEvent(msg) {
1020
1070
  if (msg.type !== "rate_limit_event") return null;
1021
1071
  const info = msg.rate_limit_info;
1022
1072
  if (!isRecord(info)) return null;
1073
+ const windows = parseUnifiedWindows(info.unifiedWindows);
1023
1074
  return {
1024
1075
  status: str(info.status),
1025
1076
  rateLimitType: str(info.rateLimitType),
@@ -1028,7 +1079,8 @@ function parseRateLimitEvent(msg) {
1028
1079
  isUsingOverage: info.isUsingOverage === true,
1029
1080
  overageStatus: str(info.overageStatus),
1030
1081
  overageResetsAt: num(info.overageResetsAt),
1031
- overageDisabledReason: str(info.overageDisabledReason)
1082
+ overageDisabledReason: str(info.overageDisabledReason),
1083
+ ...windows ? { windows } : {}
1032
1084
  };
1033
1085
  }
1034
1086
  function resetsAtToMs(resetsAt) {
@@ -7804,6 +7856,71 @@ async function requestSideQuestion(activeProcess, question, options) {
7804
7856
  });
7805
7857
  }
7806
7858
 
7859
+ // src/session-event-relay.ts
7860
+ var RELAY_KEY = /* @__PURE__ */ Symbol.for("@khalilgharbaoui/opencode-claude-code-plugin/session-event-relay");
7861
+ function relayState() {
7862
+ const holder = globalThis;
7863
+ let state = holder[RELAY_KEY];
7864
+ if (!state) {
7865
+ state = { members: /* @__PURE__ */ new Set(), followers: 0 };
7866
+ holder[RELAY_KEY] = state;
7867
+ }
7868
+ return state;
7869
+ }
7870
+ function safely(action) {
7871
+ try {
7872
+ action();
7873
+ } catch {
7874
+ }
7875
+ }
7876
+ var ownMember;
7877
+ var ownFollowers = 0;
7878
+ var ownServed = false;
7879
+ function join10() {
7880
+ if (!ownMember) return;
7881
+ const state = relayState();
7882
+ if (state.members.has(ownMember)) return;
7883
+ state.members.add(ownMember);
7884
+ if (state.followers > 0) safely(() => ownMember?.feedOpened());
7885
+ }
7886
+ function leave() {
7887
+ if (!ownMember) return;
7888
+ if (relayState().members.delete(ownMember)) safely(() => ownMember?.feedClosed());
7889
+ }
7890
+ function defineOwnRelayMember(member) {
7891
+ ownMember = member;
7892
+ if (ownServed) join10();
7893
+ }
7894
+ function noteRelayMemberServing() {
7895
+ ownServed = true;
7896
+ join10();
7897
+ }
7898
+ function openRelayFollower() {
7899
+ const state = relayState();
7900
+ join10();
7901
+ ownFollowers += 1;
7902
+ state.followers += 1;
7903
+ if (state.followers === 1) {
7904
+ for (const member of state.members) safely(() => member.feedOpened());
7905
+ }
7906
+ let closed = false;
7907
+ return () => {
7908
+ if (closed) return;
7909
+ closed = true;
7910
+ ownFollowers = Math.max(0, ownFollowers - 1);
7911
+ state.followers = Math.max(0, state.followers - 1);
7912
+ if (state.followers === 0) {
7913
+ for (const member of state.members) safely(() => member.feedClosed());
7914
+ }
7915
+ if (ownFollowers === 0 && !ownServed) leave();
7916
+ };
7917
+ }
7918
+ function relaySessionEvent(event) {
7919
+ const members = relayState().members;
7920
+ if (ownMember && !members.has(ownMember)) safely(() => ownMember?.handle(event));
7921
+ for (const member of [...members]) safely(() => member.handle(event));
7922
+ }
7923
+
7807
7924
  // src/session-manager.ts
7808
7925
  function findActiveProcessBySessionId(sessionID) {
7809
7926
  let found;
@@ -8030,6 +8147,7 @@ function processBelongsToAnotherAccount(active, cliPath, configDir) {
8030
8147
  function setActiveProcess(key, ap) {
8031
8148
  cancelIdleProcessEviction(key);
8032
8149
  activeProcesses.set(key, ap);
8150
+ noteRelayMemberServing();
8033
8151
  }
8034
8152
  function noteInteractiveProcessExit(sessionKey2, ap, code) {
8035
8153
  if (activeProcesses.get(sessionKey2) !== ap) return;
@@ -8324,8 +8442,7 @@ function spawnClaudeProcess(cliPath, cliArgs, cwd, sessionKey2, proxyServer, mcp
8324
8442
  settleTurn(ap);
8325
8443
  lineEmitter.emit("close");
8326
8444
  });
8327
- cancelIdleProcessEviction(sessionKey2);
8328
- activeProcesses.set(sessionKey2, ap);
8445
+ setActiveProcess(sessionKey2, ap);
8329
8446
  proc.on("error", (err) => {
8330
8447
  log.error("claude process error", { sessionKey: sessionKey2, error: err.message });
8331
8448
  });
@@ -10063,20 +10180,20 @@ async function fetchPlanUsage(cliPath, options = {}) {
10063
10180
  // src/turn-history.ts
10064
10181
  import { mkdirSync as mkdirSync7, readFileSync as readFileSync7, renameSync as renameSync6, statSync as statSync6, writeFileSync as writeFileSync7 } from "fs";
10065
10182
  import { homedir as homedir11 } from "os";
10066
- import { join as join11 } from "path";
10183
+ import { join as join12 } from "path";
10067
10184
 
10068
10185
  // src/turn-progress-store.ts
10069
10186
  import { mkdirSync as mkdirSync6, readFileSync as readFileSync6, renameSync as renameSync5, statSync as statSync5, writeFileSync as writeFileSync6 } from "fs";
10070
10187
  import { homedir as homedir10 } from "os";
10071
- import { join as join10 } from "path";
10188
+ import { join as join11 } from "path";
10072
10189
  var MAX_TURN_PROGRESS = 64;
10073
10190
  var TURN_PROGRESS_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
10074
10191
  var TAG = /^[0-9a-f]{8}$/;
10075
10192
  var pathOverride4 = null;
10076
10193
  function turnProgressStorePath() {
10077
10194
  if (pathOverride4) return pathOverride4;
10078
- const stateRoot = process.env.XDG_STATE_HOME || join10(homedir10(), ".local", "state");
10079
- return join10(stateRoot, "opencode-claude-code-plugin", "turn-progress.json");
10195
+ const stateRoot = process.env.XDG_STATE_HOME || join11(homedir10(), ".local", "state");
10196
+ return join11(stateRoot, "opencode-claude-code-plugin", "turn-progress.json");
10080
10197
  }
10081
10198
  function isProgress(value) {
10082
10199
  const record = value;
@@ -10106,7 +10223,7 @@ function recordTurnProgress(tag, progress, now = Date.now()) {
10106
10223
  merged.set(tag, { ...record, out: Math.round(record.out) });
10107
10224
  const kept = [...merged.entries()].slice(-MAX_TURN_PROGRESS);
10108
10225
  try {
10109
- mkdirSync6(join10(file, ".."), { recursive: true, mode: 448 });
10226
+ mkdirSync6(join11(file, ".."), { recursive: true, mode: 448 });
10110
10227
  const tmp = `${file}.${process.pid}.tmp`;
10111
10228
  writeFileSync6(tmp, JSON.stringify({ version: 1, turns: Object.fromEntries(kept) }), { mode: 384 });
10112
10229
  renameSync5(tmp, file);
@@ -10124,8 +10241,8 @@ var SESSION_TAG = /^[0-9a-f]{8}$/;
10124
10241
  var pathOverride5 = null;
10125
10242
  function turnHistoryStorePath() {
10126
10243
  if (pathOverride5) return pathOverride5;
10127
- const stateRoot = process.env.XDG_STATE_HOME || join11(homedir11(), ".local", "state");
10128
- return join11(stateRoot, "opencode-claude-code-plugin", "turn-history.json");
10244
+ const stateRoot = process.env.XDG_STATE_HOME || join12(homedir11(), ".local", "state");
10245
+ return join12(stateRoot, "opencode-claude-code-plugin", "turn-history.json");
10129
10246
  }
10130
10247
  function turnHistoryKey(agent, model) {
10131
10248
  return `${agent || "main"}/${model}`;
@@ -10309,7 +10426,7 @@ function recordTurnSample(key, sample) {
10309
10426
  merged.set(key, samples);
10310
10427
  const kept = bounded2(merged);
10311
10428
  try {
10312
- mkdirSync7(join11(file, ".."), { recursive: true, mode: 448 });
10429
+ mkdirSync7(join12(file, ".."), { recursive: true, mode: 448 });
10313
10430
  const tmp = `${file}.${process.pid}.tmp`;
10314
10431
  writeFileSync7(tmp, JSON.stringify({ version: 1, turns: Object.fromEntries(kept) }), { mode: 384 });
10315
10432
  renameSync6(tmp, file);
@@ -12733,7 +12850,7 @@ import { EventEmitter as EventEmitter4 } from "events";
12733
12850
  import { randomUUID as randomUUID5 } from "crypto";
12734
12851
  import { existsSync as existsSync4, writeFileSync as writeFileSync9 } from "fs";
12735
12852
  import { unlink as unlink2 } from "fs/promises";
12736
- import { join as join16 } from "path";
12853
+ import { join as join17 } from "path";
12737
12854
 
12738
12855
  // src/claude-session-bun.ts
12739
12856
  import * as os6 from "os";
@@ -13915,7 +14032,7 @@ ${text2}`
13915
14032
  }
13916
14033
  function stageImage(data, extension) {
13917
14034
  try {
13918
- const file = join16(pluginTmpDir(), `attachment-${randomUUID5()}.${extension}`);
14035
+ const file = join17(pluginTmpDir(), `attachment-${randomUUID5()}.${extension}`);
13919
14036
  writeFileSync9(file, data, { mode: 384, flag: "wx" });
13920
14037
  return file;
13921
14038
  } catch (err) {
@@ -14399,15 +14516,15 @@ function spawnInteractiveProcess(opts) {
14399
14516
  // src/spawn-record-store.ts
14400
14517
  import { mkdirSync as mkdirSync9, readFileSync as readFileSync11, renameSync as renameSync7, statSync as statSync10, writeFileSync as writeFileSync10 } from "fs";
14401
14518
  import { homedir as homedir14 } from "os";
14402
- import { join as join17 } from "path";
14519
+ import { join as join18 } from "path";
14403
14520
  var MAX_SPAWN_RECORDS = 256;
14404
14521
  var SPAWN_RECORD_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
14405
14522
  var pathOverride6 = null;
14406
14523
  var lastWritten = /* @__PURE__ */ new Map();
14407
14524
  function spawnRecordStorePath() {
14408
14525
  if (pathOverride6) return pathOverride6;
14409
- const stateRoot = process.env.XDG_STATE_HOME || join17(homedir14(), ".local", "state");
14410
- return join17(stateRoot, "opencode-claude-code-plugin", "session-spawns.json");
14526
+ const stateRoot = process.env.XDG_STATE_HOME || join18(homedir14(), ".local", "state");
14527
+ return join18(stateRoot, "opencode-claude-code-plugin", "session-spawns.json");
14411
14528
  }
14412
14529
  function isRecord5(value) {
14413
14530
  const record = value;
@@ -14459,7 +14576,7 @@ ${record.agent ?? ""}`;
14459
14576
  const cutoff = now - SPAWN_RECORD_MAX_AGE_MS;
14460
14577
  const kept = [...merged.entries()].filter(([, entry]) => entry.at >= cutoff).sort((a, b) => a[1].at - b[1].at).slice(-MAX_SPAWN_RECORDS);
14461
14578
  try {
14462
- mkdirSync9(join17(file, ".."), { recursive: true, mode: 448 });
14579
+ mkdirSync9(join18(file, ".."), { recursive: true, mode: 448 });
14463
14580
  const tmp = `${file}.${process.pid}.tmp`;
14464
14581
  writeFileSync10(tmp, JSON.stringify({ version: 1, sessions: Object.fromEntries(kept) }), {
14465
14582
  mode: 384
@@ -14537,7 +14654,7 @@ function dedupe2(dirs) {
14537
14654
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync11 } from "fs";
14538
14655
  import { homedir as homedir15 } from "os";
14539
14656
  import { randomUUID as randomUUID7 } from "crypto";
14540
- import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as join18 } from "path";
14657
+ import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as join19 } from "path";
14541
14658
  function readPromptFileIfPresent(path15) {
14542
14659
  try {
14543
14660
  const content = readFileSync12(path15, "utf8").trim();
@@ -14549,7 +14666,7 @@ function readPromptFileIfPresent(path15) {
14549
14666
  function nearestWorkspaceAgentsPrompt(cwd) {
14550
14667
  let dir = cwd;
14551
14668
  while (true) {
14552
- const content = readPromptFileIfPresent(join18(dir, "AGENTS.md"));
14669
+ const content = readPromptFileIfPresent(join19(dir, "AGENTS.md"));
14553
14670
  if (content) return content;
14554
14671
  const parent = dirname6(dir);
14555
14672
  if (parent === dir) return void 0;
@@ -14701,8 +14818,8 @@ ${options.compressionSummary.trim()}`
14701
14818
  for (const s of extraSystemContent) {
14702
14819
  if (s.trim()) parts.push(s.trim());
14703
14820
  }
14704
- const configRoot = process.env.XDG_CONFIG_HOME ?? join18(homedir15(), ".config");
14705
- const globalAgents = readPromptFileIfPresent(join18(configRoot, "opencode", "AGENTS.md"));
14821
+ const configRoot = process.env.XDG_CONFIG_HOME ?? join19(homedir15(), ".config");
14822
+ const globalAgents = readPromptFileIfPresent(join19(configRoot, "opencode", "AGENTS.md"));
14706
14823
  const workspaceAgents = nearestWorkspaceAgentsPrompt(cwd);
14707
14824
  const forwarded = extraSystemContent.join("\n\n");
14708
14825
  const pushGlobal = !!globalAgents && !forwarded.includes(globalAgents);
@@ -14718,7 +14835,7 @@ ${options.compressionSummary.trim()}`
14718
14835
  if (includeMultiStepHint) parts.push(MULTI_STEP_TASK_HINT);
14719
14836
  const content = parts.join("\n\n");
14720
14837
  if (!content) return void 0;
14721
- const path15 = join18(pluginTmpDir(), `opencode-cc-sys-${randomUUID7()}.md`);
14838
+ const path15 = join19(pluginTmpDir(), `opencode-cc-sys-${randomUUID7()}.md`);
14722
14839
  try {
14723
14840
  writeFileSync11(path15, content, { encoding: "utf8", mode: 384 });
14724
14841
  return path15;
@@ -16544,11 +16661,18 @@ function createLineHandler(state, ctx) {
16544
16661
  };
16545
16662
  rememberAccountLimit(ctx.sourceAccount, state.accountLimitHit);
16546
16663
  }
16547
- if (info?.rateLimitType && info.status) {
16548
- recordUsageReading(ctx.usageAccount, info.rateLimitType, {
16549
- utilization: info.utilization ?? null,
16664
+ if (info) {
16665
+ recordRateLimitObservation(ctx.usageAccount, {
16666
+ window: info.rateLimitType,
16667
+ status: info.status,
16668
+ utilization: info.utilization,
16550
16669
  resetsAt: resetsAtToMs(info.resetsAt),
16551
- status: info.status
16670
+ windows: info.windows ? Object.fromEntries(
16671
+ Object.entries(info.windows).map(([window, own]) => [
16672
+ window,
16673
+ { utilization: own.utilization, resetsAt: resetsAtToMs(own.resetsAt) }
16674
+ ])
16675
+ ) : void 0
16552
16676
  });
16553
16677
  }
16554
16678
  const note = reportRateLimitEvent(msg);
@@ -18555,7 +18679,7 @@ var ClaudeCodeLanguageModel = class {
18555
18679
  let replayReason = "no-session-for-key";
18556
18680
  if (this.config.resumeAfterRestart !== false && includeHistoryContext && !compactionMode && !forkFromClaudeSessionId && failoverAnswer?.kind !== "switch") {
18557
18681
  const configDir = resolveConfigDir(this.config.configDir);
18558
- const transcriptPath2 = (id, dir) => join19(dir ?? configDir, "projects", encodeCwd(cwd), `${id}.jsonl`);
18682
+ const transcriptPath2 = (id, dir) => join20(dir ?? configDir, "projects", encodeCwd(cwd), `${id}.jsonl`);
18559
18683
  const resumePoint = findResumePoint({
18560
18684
  sessionKey: sk,
18561
18685
  prompt: options.prompt,
@@ -20230,7 +20354,7 @@ import {
20230
20354
  writeFileSync as writeFileSync12
20231
20355
  } from "fs";
20232
20356
  import { homedir as homedir16 } from "os";
20233
- import { dirname as dirname7, join as join20, resolve as resolve6 } from "path";
20357
+ import { dirname as dirname7, join as join21, resolve as resolve6 } from "path";
20234
20358
  import { fileURLToPath as fileURLToPath4 } from "url";
20235
20359
  var STALE_PACKAGE_NAME = "opencode-claude-code-plugin";
20236
20360
  var SUSPECT_DESCRIPTION_TOKEN = "Claude Code";
@@ -20238,14 +20362,14 @@ var alreadyRan = false;
20238
20362
  function candidateCacheRoots() {
20239
20363
  const xdg = process.env.XDG_CACHE_HOME;
20240
20364
  return [
20241
- xdg ? join20(xdg, "opencode") : null,
20242
- join20(homedir16(), ".cache", "opencode"),
20243
- join20(homedir16(), "Library", "Caches", "opencode")
20365
+ xdg ? join21(xdg, "opencode") : null,
20366
+ join21(homedir16(), ".cache", "opencode"),
20367
+ join21(homedir16(), "Library", "Caches", "opencode")
20244
20368
  ].filter((p) => Boolean(p));
20245
20369
  }
20246
20370
  function userOpencodeJsonPath() {
20247
- const xdgConfig = process.env.XDG_CONFIG_HOME ?? join20(homedir16(), ".config");
20248
- return join20(xdgConfig, "opencode", "opencode.json");
20371
+ const xdgConfig = process.env.XDG_CONFIG_HOME ?? join21(homedir16(), ".config");
20372
+ return join21(xdgConfig, "opencode", "opencode.json");
20249
20373
  }
20250
20374
  function userIntendsToUseUnscoped() {
20251
20375
  const cfg = userOpencodeJsonPath();
@@ -20272,15 +20396,15 @@ function ourLoadedDir() {
20272
20396
  function ourVersion(dir) {
20273
20397
  if (!dir) return null;
20274
20398
  try {
20275
- const pkg = JSON.parse(readFileSync14(join20(dir, "package.json"), "utf8"));
20399
+ const pkg = JSON.parse(readFileSync14(join21(dir, "package.json"), "utf8"));
20276
20400
  return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
20277
20401
  } catch {
20278
20402
  return null;
20279
20403
  }
20280
20404
  }
20281
20405
  function markerPath() {
20282
- const stateRoot = process.env.XDG_STATE_HOME ?? join20(homedir16(), ".local", "state");
20283
- return join20(stateRoot, "opencode-claude-code-plugin", "cleanup-stale.json");
20406
+ const stateRoot = process.env.XDG_STATE_HOME ?? join21(homedir16(), ".local", "state");
20407
+ return join21(stateRoot, "opencode-claude-code-plugin", "cleanup-stale.json");
20284
20408
  }
20285
20409
  function markerVersion() {
20286
20410
  try {
@@ -20329,7 +20453,7 @@ function cleanupStaleUnscopedInstall() {
20329
20453
  }
20330
20454
  function cleanupOne(cacheRoot, ourDir) {
20331
20455
  if (!existsSync5(cacheRoot)) return;
20332
- const stalePath = join20(cacheRoot, "node_modules", STALE_PACKAGE_NAME);
20456
+ const stalePath = join21(cacheRoot, "node_modules", STALE_PACKAGE_NAME);
20333
20457
  if (!existsSync5(stalePath)) return;
20334
20458
  let realStalePath = stalePath;
20335
20459
  try {
@@ -20337,7 +20461,7 @@ function cleanupOne(cacheRoot, ourDir) {
20337
20461
  } catch {
20338
20462
  }
20339
20463
  if (ourDir && realStalePath === ourDir) return;
20340
- const pkgJsonPath = join20(stalePath, "package.json");
20464
+ const pkgJsonPath = join21(stalePath, "package.json");
20341
20465
  if (!existsSync5(pkgJsonPath)) return;
20342
20466
  let pkg = {};
20343
20467
  try {
@@ -20357,7 +20481,7 @@ function cleanupOne(cacheRoot, ourDir) {
20357
20481
  });
20358
20482
  return;
20359
20483
  }
20360
- const cachePkgJson = join20(cacheRoot, "package.json");
20484
+ const cachePkgJson = join21(cacheRoot, "package.json");
20361
20485
  if (!existsSync5(cachePkgJson)) return;
20362
20486
  try {
20363
20487
  const cfg = JSON.parse(readFileSync14(cachePkgJson, "utf8"));
@@ -20763,22 +20887,37 @@ function stoppedSessionIdV2(event) {
20763
20887
  const id = event.data?.sessionID;
20764
20888
  return typeof id === "string" && id.length > 0 ? id : void 0;
20765
20889
  }
20890
+ function handleSessionEventHere(event) {
20891
+ noteSessionRunEvent(event);
20892
+ const deleted = deletedSessionIdV2(event);
20893
+ if (deleted) {
20894
+ const released = deleteActiveProcessesForSession(deleted);
20895
+ if (released.length > 0) {
20896
+ log.info("released claude state for deleted session", { sessionID: deleted, released });
20897
+ }
20898
+ return;
20899
+ }
20900
+ const stopped = stoppedSessionIdV2(event);
20901
+ if (stopped) releaseParkedProxyCallsForSession(stopped);
20902
+ }
20903
+ var closeOwnFeed;
20904
+ defineOwnRelayMember({
20905
+ handle: (event) => handleSessionEventHere(event),
20906
+ feedOpened: () => {
20907
+ closeOwnFeed ??= openSessionRunEventFeed();
20908
+ },
20909
+ feedClosed: () => {
20910
+ const close = closeOwnFeed;
20911
+ closeOwnFeed = void 0;
20912
+ close?.();
20913
+ }
20914
+ });
20766
20915
  async function followSessionEvents(subscribe, signal) {
20767
- const closeFeed = openSessionRunEventFeed();
20916
+ const closeFollower = openRelayFollower();
20768
20917
  try {
20769
20918
  for await (const event of subscribe({ signal })) {
20770
20919
  if (signal.aborted) break;
20771
- noteSessionRunEvent(event);
20772
- const deleted = deletedSessionIdV2(event);
20773
- if (deleted) {
20774
- const released = deleteActiveProcessesForSession(deleted);
20775
- if (released.length > 0) {
20776
- log.info("released claude state for deleted session", { sessionID: deleted, released });
20777
- }
20778
- continue;
20779
- }
20780
- const stopped = stoppedSessionIdV2(event);
20781
- if (stopped) releaseParkedProxyCallsForSession(stopped);
20920
+ relaySessionEvent(event);
20782
20921
  }
20783
20922
  } catch (err) {
20784
20923
  if (!signal.aborted) {
@@ -20788,7 +20927,7 @@ async function followSessionEvents(subscribe, signal) {
20788
20927
  );
20789
20928
  }
20790
20929
  } finally {
20791
- closeFeed();
20930
+ closeFollower();
20792
20931
  }
20793
20932
  }
20794
20933
  var noticeEmitters = /* @__PURE__ */ new Set();