@funnycode/myclaude 0.1.89 → 0.1.90

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/myclaude.js CHANGED
@@ -4,8 +4,8 @@
4
4
  // MACRO - build-time constants (injected by build.ts)
5
5
  // MACRO injected by build script
6
6
  globalThis.MACRO = {
7
- VERSION: "0.1.89",
8
- BUILD_TIME: "2026-07-17T12:20:44.184Z",
7
+ VERSION: "0.1.90",
8
+ BUILD_TIME: "2026-07-17T18:18:41.746Z",
9
9
  PACKAGE_URL: "@funnycode/myclaude",
10
10
  NATIVE_PACKAGE_URL: "@funnycode/myclaude",
11
11
  VERSION_CHANGELOG: '',
@@ -117484,7 +117484,7 @@ var package_default;
117484
117484
  var init_package = __esm(() => {
117485
117485
  package_default = {
117486
117486
  name: "@funnycode/myclaude",
117487
- version: "0.1.89",
117487
+ version: "0.1.90",
117488
117488
  private: false,
117489
117489
  description: "An open-source AI coding assistant in your terminal - powered by Claude",
117490
117490
  license: "MIT",
@@ -117548,6 +117548,7 @@ var init_package = __esm(() => {
117548
117548
  "@opentelemetry/semantic-conventions": "1.40.0",
117549
117549
  ajv: "8.18.0",
117550
117550
  asciichart: "1.5.25",
117551
+ "async-mutex": "^0.5.0",
117551
117552
  "auto-bind": "5.0.1",
117552
117553
  axios: "1.14.0",
117553
117554
  "bidi-js": "1.0.3",
@@ -210289,27 +210290,50 @@ function createDumpPromptsFetch(agentIdOrSessionId) {
210289
210290
  const reader = cloned.body.getReader();
210290
210291
  const decoder = new TextDecoder;
210291
210292
  let buffer = "";
210293
+ const chunks = [];
210292
210294
  try {
210293
210295
  while (true) {
210294
210296
  const { done, value } = await reader.read();
210295
210297
  if (done)
210296
210298
  break;
210297
210299
  buffer += decoder.decode(value, { stream: true });
210300
+ const lastDoubleNewline = buffer.lastIndexOf(`
210301
+
210302
+ `);
210303
+ if (lastDoubleNewline !== -1) {
210304
+ const completeEvents = buffer.slice(0, lastDoubleNewline);
210305
+ buffer = buffer.slice(lastDoubleNewline + 2);
210306
+ for (const event of completeEvents.split(`
210307
+
210308
+ `)) {
210309
+ for (const line of event.split(`
210310
+ `)) {
210311
+ if (line.startsWith("data: ") && line !== "data: [DONE]") {
210312
+ try {
210313
+ chunks.push(jsonParse(line.slice(6)));
210314
+ } catch (err2) {
210315
+ logForDebugging(`dumpPrompts.SSE parse error: ${err2}`, { level: "error" });
210316
+ }
210317
+ }
210318
+ }
210319
+ }
210320
+ }
210298
210321
  }
210299
210322
  } finally {
210300
210323
  reader.releaseLock();
210301
210324
  }
210302
- const chunks = [];
210303
- for (const event of buffer.split(`
210325
+ if (buffer.trim()) {
210326
+ for (const event of buffer.split(`
210304
210327
 
210305
210328
  `)) {
210306
- for (const line of event.split(`
210329
+ for (const line of event.split(`
210307
210330
  `)) {
210308
- if (line.startsWith("data: ") && line !== "data: [DONE]") {
210309
- try {
210310
- chunks.push(jsonParse(line.slice(6)));
210311
- } catch (err2) {
210312
- logForDebugging(`dumpPrompts.SSE parse error: ${err2}`, { level: "error" });
210331
+ if (line.startsWith("data: ") && line !== "data: [DONE]") {
210332
+ try {
210333
+ chunks.push(jsonParse(line.slice(6)));
210334
+ } catch (err2) {
210335
+ logForDebugging(`dumpPrompts.SSE parse error: ${err2}`, { level: "error" });
210336
+ }
210313
210337
  }
210314
210338
  }
210315
210339
  }
@@ -300876,6 +300900,214 @@ var init_gracefulShutdown = __esm(() => {
300876
300900
  };
300877
300901
  });
300878
300902
 
300903
+ // node_modules/async-mutex/index.mjs
300904
+ class Semaphore {
300905
+ constructor(_value, _cancelError = E_CANCELED) {
300906
+ this._value = _value;
300907
+ this._cancelError = _cancelError;
300908
+ this._queue = [];
300909
+ this._weightedWaiters = [];
300910
+ }
300911
+ acquire(weight = 1, priority = 0) {
300912
+ if (weight <= 0)
300913
+ throw new Error(`invalid weight ${weight}: must be positive`);
300914
+ return new Promise((resolve28, reject2) => {
300915
+ const task = { resolve: resolve28, reject: reject2, weight, priority };
300916
+ const i3 = findIndexFromEnd(this._queue, (other) => priority <= other.priority);
300917
+ if (i3 === -1 && weight <= this._value) {
300918
+ this._dispatchItem(task);
300919
+ } else {
300920
+ this._queue.splice(i3 + 1, 0, task);
300921
+ }
300922
+ });
300923
+ }
300924
+ runExclusive(callback_1) {
300925
+ return __awaiter$2(this, arguments, undefined, function* (callback, weight = 1, priority = 0) {
300926
+ const [value, release] = yield this.acquire(weight, priority);
300927
+ try {
300928
+ return yield callback(value);
300929
+ } finally {
300930
+ release();
300931
+ }
300932
+ });
300933
+ }
300934
+ waitForUnlock(weight = 1, priority = 0) {
300935
+ if (weight <= 0)
300936
+ throw new Error(`invalid weight ${weight}: must be positive`);
300937
+ if (this._couldLockImmediately(weight, priority)) {
300938
+ return Promise.resolve();
300939
+ } else {
300940
+ return new Promise((resolve28) => {
300941
+ if (!this._weightedWaiters[weight - 1])
300942
+ this._weightedWaiters[weight - 1] = [];
300943
+ insertSorted(this._weightedWaiters[weight - 1], { resolve: resolve28, priority });
300944
+ });
300945
+ }
300946
+ }
300947
+ isLocked() {
300948
+ return this._value <= 0;
300949
+ }
300950
+ getValue() {
300951
+ return this._value;
300952
+ }
300953
+ setValue(value) {
300954
+ this._value = value;
300955
+ this._dispatchQueue();
300956
+ }
300957
+ release(weight = 1) {
300958
+ if (weight <= 0)
300959
+ throw new Error(`invalid weight ${weight}: must be positive`);
300960
+ this._value += weight;
300961
+ this._dispatchQueue();
300962
+ }
300963
+ cancel() {
300964
+ this._queue.forEach((entry) => entry.reject(this._cancelError));
300965
+ this._queue = [];
300966
+ }
300967
+ _dispatchQueue() {
300968
+ this._drainUnlockWaiters();
300969
+ while (this._queue.length > 0 && this._queue[0].weight <= this._value) {
300970
+ this._dispatchItem(this._queue.shift());
300971
+ this._drainUnlockWaiters();
300972
+ }
300973
+ }
300974
+ _dispatchItem(item) {
300975
+ const previousValue = this._value;
300976
+ this._value -= item.weight;
300977
+ item.resolve([previousValue, this._newReleaser(item.weight)]);
300978
+ }
300979
+ _newReleaser(weight) {
300980
+ let called = false;
300981
+ return () => {
300982
+ if (called)
300983
+ return;
300984
+ called = true;
300985
+ this.release(weight);
300986
+ };
300987
+ }
300988
+ _drainUnlockWaiters() {
300989
+ if (this._queue.length === 0) {
300990
+ for (let weight = this._value;weight > 0; weight--) {
300991
+ const waiters = this._weightedWaiters[weight - 1];
300992
+ if (!waiters)
300993
+ continue;
300994
+ waiters.forEach((waiter) => waiter.resolve());
300995
+ this._weightedWaiters[weight - 1] = [];
300996
+ }
300997
+ } else {
300998
+ const queuedPriority = this._queue[0].priority;
300999
+ for (let weight = this._value;weight > 0; weight--) {
301000
+ const waiters = this._weightedWaiters[weight - 1];
301001
+ if (!waiters)
301002
+ continue;
301003
+ const i3 = waiters.findIndex((waiter) => waiter.priority <= queuedPriority);
301004
+ (i3 === -1 ? waiters : waiters.splice(0, i3)).forEach((waiter) => waiter.resolve());
301005
+ }
301006
+ }
301007
+ }
301008
+ _couldLockImmediately(weight, priority) {
301009
+ return (this._queue.length === 0 || this._queue[0].priority < priority) && weight <= this._value;
301010
+ }
301011
+ }
301012
+ function insertSorted(a2, v2) {
301013
+ const i3 = findIndexFromEnd(a2, (other) => v2.priority <= other.priority);
301014
+ a2.splice(i3 + 1, 0, v2);
301015
+ }
301016
+ function findIndexFromEnd(a2, predicate) {
301017
+ for (let i3 = a2.length - 1;i3 >= 0; i3--) {
301018
+ if (predicate(a2[i3])) {
301019
+ return i3;
301020
+ }
301021
+ }
301022
+ return -1;
301023
+ }
301024
+
301025
+ class Mutex {
301026
+ constructor(cancelError) {
301027
+ this._semaphore = new Semaphore(1, cancelError);
301028
+ }
301029
+ acquire() {
301030
+ return __awaiter$1(this, arguments, undefined, function* (priority = 0) {
301031
+ const [, releaser] = yield this._semaphore.acquire(1, priority);
301032
+ return releaser;
301033
+ });
301034
+ }
301035
+ runExclusive(callback, priority = 0) {
301036
+ return this._semaphore.runExclusive(() => callback(), 1, priority);
301037
+ }
301038
+ isLocked() {
301039
+ return this._semaphore.isLocked();
301040
+ }
301041
+ waitForUnlock(priority = 0) {
301042
+ return this._semaphore.waitForUnlock(1, priority);
301043
+ }
301044
+ release() {
301045
+ if (this._semaphore.isLocked())
301046
+ this._semaphore.release();
301047
+ }
301048
+ cancel() {
301049
+ return this._semaphore.cancel();
301050
+ }
301051
+ }
301052
+ var E_TIMEOUT, E_ALREADY_LOCKED, E_CANCELED, __awaiter$2 = function(thisArg, _arguments, P2, generator) {
301053
+ function adopt(value) {
301054
+ return value instanceof P2 ? value : new P2(function(resolve28) {
301055
+ resolve28(value);
301056
+ });
301057
+ }
301058
+ return new (P2 || (P2 = Promise))(function(resolve28, reject2) {
301059
+ function fulfilled(value) {
301060
+ try {
301061
+ step(generator.next(value));
301062
+ } catch (e) {
301063
+ reject2(e);
301064
+ }
301065
+ }
301066
+ function rejected(value) {
301067
+ try {
301068
+ step(generator["throw"](value));
301069
+ } catch (e) {
301070
+ reject2(e);
301071
+ }
301072
+ }
301073
+ function step(result) {
301074
+ result.done ? resolve28(result.value) : adopt(result.value).then(fulfilled, rejected);
301075
+ }
301076
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
301077
+ });
301078
+ }, __awaiter$1 = function(thisArg, _arguments, P2, generator) {
301079
+ function adopt(value) {
301080
+ return value instanceof P2 ? value : new P2(function(resolve28) {
301081
+ resolve28(value);
301082
+ });
301083
+ }
301084
+ return new (P2 || (P2 = Promise))(function(resolve28, reject2) {
301085
+ function fulfilled(value) {
301086
+ try {
301087
+ step(generator.next(value));
301088
+ } catch (e) {
301089
+ reject2(e);
301090
+ }
301091
+ }
301092
+ function rejected(value) {
301093
+ try {
301094
+ step(generator["throw"](value));
301095
+ } catch (e) {
301096
+ reject2(e);
301097
+ }
301098
+ }
301099
+ function step(result) {
301100
+ result.done ? resolve28(result.value) : adopt(result.value).then(fulfilled, rejected);
301101
+ }
301102
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
301103
+ });
301104
+ };
301105
+ var init_async_mutex = __esm(() => {
301106
+ E_TIMEOUT = new Error("timeout while waiting for mutex to become available");
301107
+ E_ALREADY_LOCKED = new Error("mutex already locked");
301108
+ E_CANCELED = new Error("request for lock canceled");
301109
+ });
301110
+
300879
301111
  // src/services/api/grove.ts
300880
301112
  function memoizeWithTTL(fn, ttlMs) {
300881
301113
  let lastCachedAt = 0;
@@ -300891,6 +301123,9 @@ function memoizeWithTTL(fn, ttlMs) {
300891
301123
  const result = await memoized(...args);
300892
301124
  if (result && typeof result === "object" && "success" in result && result.success === true) {
300893
301125
  lastCachedAt = Date.now();
301126
+ } else if (result && typeof result === "object" && "success" in result && result.success === false) {
301127
+ originalClear();
301128
+ lastCachedAt = 0;
300894
301129
  }
300895
301130
  return result;
300896
301131
  } catch (error49) {
@@ -300972,13 +301207,12 @@ async function isQualifiedForGrove() {
300972
301207
  return cachedEntry.grove_enabled;
300973
301208
  }
300974
301209
  async function fetchAndStoreGroveConfig(accountId) {
300975
- let releaseLock;
300976
- const lockPromise = new Promise((resolve28) => {
300977
- releaseLock = resolve28;
300978
- });
300979
- const previous = groveConfigLocks.get(accountId) ?? Promise.resolve();
300980
- groveConfigLocks.set(accountId, lockPromise);
300981
- await previous;
301210
+ let mutex = groveConfigMutexes.get(accountId);
301211
+ if (!mutex) {
301212
+ mutex = new Mutex;
301213
+ groveConfigMutexes.set(accountId, mutex);
301214
+ }
301215
+ const release = await mutex.acquire();
300982
301216
  try {
300983
301217
  const result = await getGroveNoticeConfig();
300984
301218
  if (!result.success) {
@@ -301002,10 +301236,7 @@ async function fetchAndStoreGroveConfig(accountId) {
301002
301236
  } catch (err2) {
301003
301237
  logForDebugging(`Grove: Failed to fetch and store config: ${err2}`);
301004
301238
  } finally {
301005
- releaseLock();
301006
- if (groveConfigLocks.get(accountId) === lockPromise) {
301007
- groveConfigLocks.delete(accountId);
301008
- }
301239
+ release();
301009
301240
  }
301010
301241
  }
301011
301242
  function calculateShouldShowGrove(settingsResult, configResult, showIfAlreadyViewed) {
@@ -301059,7 +301290,7 @@ An update to our Consumer Terms and Privacy Policy will take effect on October 8
301059
301290
  }
301060
301291
  }
301061
301292
  }
301062
- var groveConfigLocks, GROVE_CACHE_EXPIRATION_MS, GROVE_API_TIMEOUT_MS, getGroveSettings, getGroveNoticeConfig;
301293
+ var groveConfigMutexes, GROVE_CACHE_EXPIRATION_MS, GROVE_API_TIMEOUT_MS, getGroveSettings, getGroveNoticeConfig;
301063
301294
  var init_grove = __esm(() => {
301064
301295
  init_axios2();
301065
301296
  init_memoize();
@@ -301071,7 +301302,8 @@ var init_grove = __esm(() => {
301071
301302
  init_config();
301072
301303
  init_http2();
301073
301304
  init_log3();
301074
- groveConfigLocks = new Map;
301305
+ init_async_mutex();
301306
+ groveConfigMutexes = new Map;
301075
301307
  GROVE_CACHE_EXPIRATION_MS = 24 * 60 * 60 * 1000;
301076
301308
  GROVE_API_TIMEOUT_MS = parseInt(process.env.GROVE_API_TIMEOUT_MS ?? "3000", 10);
301077
301309
  getGroveSettings = memoizeWithTTL(async () => {
@@ -342110,17 +342342,20 @@ async function appendSessionLogImpl(sessionId, entry, url3, headers) {
342110
342342
  logForDebugging(`Session 409: adopting server lastUuid=${serverLastUuid} from header, retrying entry ${entry.uuid}`);
342111
342343
  } else {
342112
342344
  const sequentialFetch = getOrCreateSequentialFetch(sessionId);
342113
- const logs2 = await sequentialFetch(sessionId, url3, headers);
342345
+ let logs2 = null;
342346
+ try {
342347
+ logs2 = await sequentialFetch(sessionId, url3, headers);
342348
+ } catch (fetchError) {
342349
+ logError2(new Error(`Session 409: fetch failed for session ${sessionId}, entry ${entry.uuid}: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`));
342350
+ logForDiagnosticsNoPII("error", "session_persist_409_fetch_fail");
342351
+ }
342114
342352
  const adoptedUuid = findLastUuid(logs2);
342115
342353
  if (adoptedUuid) {
342116
342354
  lastUuidMap.set(sessionId, adoptedUuid);
342117
342355
  logForDebugging(`Session 409: re-fetched ${logs2.length} entries, adopting lastUuid=${adoptedUuid}, retrying entry ${entry.uuid}`);
342118
342356
  } else {
342119
- const errorData = response.data;
342120
- const errorMessage2 = errorData.error?.message || "Concurrent modification detected";
342121
- logError2(new Error(`Session persistence conflict: UUID mismatch for session ${sessionId}, entry ${entry.uuid}. ${errorMessage2}`));
342122
- logForDiagnosticsNoPII("error", "session_persist_fail_concurrent_modification");
342123
- return false;
342357
+ logForDebugging(`Session 409: could not determine server state for session ${sessionId}, entry ${entry.uuid}`);
342358
+ logForDiagnosticsNoPII("warn", "session_persist_409_no_adopted_uuid");
342124
342359
  }
342125
342360
  }
342126
342361
  logForDiagnosticsNoPII("info", "session_persist_409_adopt_server_uuid");
@@ -342137,10 +342372,11 @@ async function appendSessionLogImpl(sessionId, entry, url3, headers) {
342137
342372
  attempt
342138
342373
  });
342139
342374
  } catch (error49) {
342140
- const axiosError = error49;
342141
- logError2(new Error(`Error persisting session log: ${axiosError.message}`));
342375
+ const errorMessage2 = error49 instanceof Error ? error49.message : String(error49);
342376
+ const axiosStatus = error49 && typeof error49 === "object" && "status" in error49 ? error49.status : undefined;
342377
+ logError2(new Error(`Error persisting session log: ${errorMessage2}`));
342142
342378
  logForDiagnosticsNoPII("error", "session_persist_fail_status", {
342143
- status: axiosError.status,
342379
+ status: axiosStatus,
342144
342380
  attempt
342145
342381
  });
342146
342382
  }
@@ -348844,7 +349080,7 @@ var require_semaphore = __commonJS((exports) => {
348844
349080
  exports.Semaphore = undefined;
348845
349081
  var ral_1 = require_ral();
348846
349082
 
348847
- class Semaphore {
349083
+ class Semaphore2 {
348848
349084
  constructor(capacity = 1) {
348849
349085
  if (capacity <= 0) {
348850
349086
  throw new Error("Capacity must be greater than 0");
@@ -348901,7 +349137,7 @@ var require_semaphore = __commonJS((exports) => {
348901
349137
  }
348902
349138
  }
348903
349139
  }
348904
- exports.Semaphore = Semaphore;
349140
+ exports.Semaphore = Semaphore2;
348905
349141
  });
348906
349142
 
348907
349143
  // node_modules/vscode-jsonrpc/lib/common/messageReader.js
@@ -453615,7 +453851,11 @@ async function fetchAndStorePassesEligibility() {
453615
453851
  logForDebugging("Passes: Reusing in-flight eligibility fetch");
453616
453852
  return fetchInProgress;
453617
453853
  }
453618
- fetchInProgress = (async () => {
453854
+ let resolvePromise;
453855
+ fetchInProgress = new Promise((resolve47) => {
453856
+ resolvePromise = resolve47;
453857
+ });
453858
+ (async () => {
453619
453859
  try {
453620
453860
  const response = await fetchReferralEligibility();
453621
453861
  const cacheEntry = {
@@ -453630,11 +453870,11 @@ async function fetchAndStorePassesEligibility() {
453630
453870
  }
453631
453871
  }));
453632
453872
  logForDebugging(`Passes eligibility cached for org ${orgId}: ${response.eligible}`);
453633
- return response;
453873
+ resolvePromise(response);
453634
453874
  } catch (error49) {
453635
453875
  logForDebugging("Failed to fetch and cache passes eligibility");
453636
453876
  logError2(error49);
453637
- return null;
453877
+ resolvePromise(null);
453638
453878
  } finally {
453639
453879
  fetchInProgress = null;
453640
453880
  }
package/dist/myclaude.mjs CHANGED
@@ -4,8 +4,8 @@
4
4
  // MACRO - build-time constants (injected by build.ts)
5
5
  // MACRO injected by build script
6
6
  globalThis.MACRO = {
7
- VERSION: "0.1.89",
8
- BUILD_TIME: "2026-07-17T12:20:44.184Z",
7
+ VERSION: "0.1.90",
8
+ BUILD_TIME: "2026-07-17T18:18:41.746Z",
9
9
  PACKAGE_URL: "@funnycode/myclaude",
10
10
  NATIVE_PACKAGE_URL: "@funnycode/myclaude",
11
11
  VERSION_CHANGELOG: '',
@@ -117484,7 +117484,7 @@ var package_default;
117484
117484
  var init_package = __esm(() => {
117485
117485
  package_default = {
117486
117486
  name: "@funnycode/myclaude",
117487
- version: "0.1.89",
117487
+ version: "0.1.90",
117488
117488
  private: false,
117489
117489
  description: "An open-source AI coding assistant in your terminal - powered by Claude",
117490
117490
  license: "MIT",
@@ -117548,6 +117548,7 @@ var init_package = __esm(() => {
117548
117548
  "@opentelemetry/semantic-conventions": "1.40.0",
117549
117549
  ajv: "8.18.0",
117550
117550
  asciichart: "1.5.25",
117551
+ "async-mutex": "^0.5.0",
117551
117552
  "auto-bind": "5.0.1",
117552
117553
  axios: "1.14.0",
117553
117554
  "bidi-js": "1.0.3",
@@ -210289,27 +210290,50 @@ function createDumpPromptsFetch(agentIdOrSessionId) {
210289
210290
  const reader = cloned.body.getReader();
210290
210291
  const decoder = new TextDecoder;
210291
210292
  let buffer = "";
210293
+ const chunks = [];
210292
210294
  try {
210293
210295
  while (true) {
210294
210296
  const { done, value } = await reader.read();
210295
210297
  if (done)
210296
210298
  break;
210297
210299
  buffer += decoder.decode(value, { stream: true });
210300
+ const lastDoubleNewline = buffer.lastIndexOf(`
210301
+
210302
+ `);
210303
+ if (lastDoubleNewline !== -1) {
210304
+ const completeEvents = buffer.slice(0, lastDoubleNewline);
210305
+ buffer = buffer.slice(lastDoubleNewline + 2);
210306
+ for (const event of completeEvents.split(`
210307
+
210308
+ `)) {
210309
+ for (const line of event.split(`
210310
+ `)) {
210311
+ if (line.startsWith("data: ") && line !== "data: [DONE]") {
210312
+ try {
210313
+ chunks.push(jsonParse(line.slice(6)));
210314
+ } catch (err2) {
210315
+ logForDebugging(`dumpPrompts.SSE parse error: ${err2}`, { level: "error" });
210316
+ }
210317
+ }
210318
+ }
210319
+ }
210320
+ }
210298
210321
  }
210299
210322
  } finally {
210300
210323
  reader.releaseLock();
210301
210324
  }
210302
- const chunks = [];
210303
- for (const event of buffer.split(`
210325
+ if (buffer.trim()) {
210326
+ for (const event of buffer.split(`
210304
210327
 
210305
210328
  `)) {
210306
- for (const line of event.split(`
210329
+ for (const line of event.split(`
210307
210330
  `)) {
210308
- if (line.startsWith("data: ") && line !== "data: [DONE]") {
210309
- try {
210310
- chunks.push(jsonParse(line.slice(6)));
210311
- } catch (err2) {
210312
- logForDebugging(`dumpPrompts.SSE parse error: ${err2}`, { level: "error" });
210331
+ if (line.startsWith("data: ") && line !== "data: [DONE]") {
210332
+ try {
210333
+ chunks.push(jsonParse(line.slice(6)));
210334
+ } catch (err2) {
210335
+ logForDebugging(`dumpPrompts.SSE parse error: ${err2}`, { level: "error" });
210336
+ }
210313
210337
  }
210314
210338
  }
210315
210339
  }
@@ -300876,6 +300900,214 @@ var init_gracefulShutdown = __esm(() => {
300876
300900
  };
300877
300901
  });
300878
300902
 
300903
+ // node_modules/async-mutex/index.mjs
300904
+ class Semaphore {
300905
+ constructor(_value, _cancelError = E_CANCELED) {
300906
+ this._value = _value;
300907
+ this._cancelError = _cancelError;
300908
+ this._queue = [];
300909
+ this._weightedWaiters = [];
300910
+ }
300911
+ acquire(weight = 1, priority = 0) {
300912
+ if (weight <= 0)
300913
+ throw new Error(`invalid weight ${weight}: must be positive`);
300914
+ return new Promise((resolve28, reject2) => {
300915
+ const task = { resolve: resolve28, reject: reject2, weight, priority };
300916
+ const i3 = findIndexFromEnd(this._queue, (other) => priority <= other.priority);
300917
+ if (i3 === -1 && weight <= this._value) {
300918
+ this._dispatchItem(task);
300919
+ } else {
300920
+ this._queue.splice(i3 + 1, 0, task);
300921
+ }
300922
+ });
300923
+ }
300924
+ runExclusive(callback_1) {
300925
+ return __awaiter$2(this, arguments, undefined, function* (callback, weight = 1, priority = 0) {
300926
+ const [value, release] = yield this.acquire(weight, priority);
300927
+ try {
300928
+ return yield callback(value);
300929
+ } finally {
300930
+ release();
300931
+ }
300932
+ });
300933
+ }
300934
+ waitForUnlock(weight = 1, priority = 0) {
300935
+ if (weight <= 0)
300936
+ throw new Error(`invalid weight ${weight}: must be positive`);
300937
+ if (this._couldLockImmediately(weight, priority)) {
300938
+ return Promise.resolve();
300939
+ } else {
300940
+ return new Promise((resolve28) => {
300941
+ if (!this._weightedWaiters[weight - 1])
300942
+ this._weightedWaiters[weight - 1] = [];
300943
+ insertSorted(this._weightedWaiters[weight - 1], { resolve: resolve28, priority });
300944
+ });
300945
+ }
300946
+ }
300947
+ isLocked() {
300948
+ return this._value <= 0;
300949
+ }
300950
+ getValue() {
300951
+ return this._value;
300952
+ }
300953
+ setValue(value) {
300954
+ this._value = value;
300955
+ this._dispatchQueue();
300956
+ }
300957
+ release(weight = 1) {
300958
+ if (weight <= 0)
300959
+ throw new Error(`invalid weight ${weight}: must be positive`);
300960
+ this._value += weight;
300961
+ this._dispatchQueue();
300962
+ }
300963
+ cancel() {
300964
+ this._queue.forEach((entry) => entry.reject(this._cancelError));
300965
+ this._queue = [];
300966
+ }
300967
+ _dispatchQueue() {
300968
+ this._drainUnlockWaiters();
300969
+ while (this._queue.length > 0 && this._queue[0].weight <= this._value) {
300970
+ this._dispatchItem(this._queue.shift());
300971
+ this._drainUnlockWaiters();
300972
+ }
300973
+ }
300974
+ _dispatchItem(item) {
300975
+ const previousValue = this._value;
300976
+ this._value -= item.weight;
300977
+ item.resolve([previousValue, this._newReleaser(item.weight)]);
300978
+ }
300979
+ _newReleaser(weight) {
300980
+ let called = false;
300981
+ return () => {
300982
+ if (called)
300983
+ return;
300984
+ called = true;
300985
+ this.release(weight);
300986
+ };
300987
+ }
300988
+ _drainUnlockWaiters() {
300989
+ if (this._queue.length === 0) {
300990
+ for (let weight = this._value;weight > 0; weight--) {
300991
+ const waiters = this._weightedWaiters[weight - 1];
300992
+ if (!waiters)
300993
+ continue;
300994
+ waiters.forEach((waiter) => waiter.resolve());
300995
+ this._weightedWaiters[weight - 1] = [];
300996
+ }
300997
+ } else {
300998
+ const queuedPriority = this._queue[0].priority;
300999
+ for (let weight = this._value;weight > 0; weight--) {
301000
+ const waiters = this._weightedWaiters[weight - 1];
301001
+ if (!waiters)
301002
+ continue;
301003
+ const i3 = waiters.findIndex((waiter) => waiter.priority <= queuedPriority);
301004
+ (i3 === -1 ? waiters : waiters.splice(0, i3)).forEach((waiter) => waiter.resolve());
301005
+ }
301006
+ }
301007
+ }
301008
+ _couldLockImmediately(weight, priority) {
301009
+ return (this._queue.length === 0 || this._queue[0].priority < priority) && weight <= this._value;
301010
+ }
301011
+ }
301012
+ function insertSorted(a2, v2) {
301013
+ const i3 = findIndexFromEnd(a2, (other) => v2.priority <= other.priority);
301014
+ a2.splice(i3 + 1, 0, v2);
301015
+ }
301016
+ function findIndexFromEnd(a2, predicate) {
301017
+ for (let i3 = a2.length - 1;i3 >= 0; i3--) {
301018
+ if (predicate(a2[i3])) {
301019
+ return i3;
301020
+ }
301021
+ }
301022
+ return -1;
301023
+ }
301024
+
301025
+ class Mutex {
301026
+ constructor(cancelError) {
301027
+ this._semaphore = new Semaphore(1, cancelError);
301028
+ }
301029
+ acquire() {
301030
+ return __awaiter$1(this, arguments, undefined, function* (priority = 0) {
301031
+ const [, releaser] = yield this._semaphore.acquire(1, priority);
301032
+ return releaser;
301033
+ });
301034
+ }
301035
+ runExclusive(callback, priority = 0) {
301036
+ return this._semaphore.runExclusive(() => callback(), 1, priority);
301037
+ }
301038
+ isLocked() {
301039
+ return this._semaphore.isLocked();
301040
+ }
301041
+ waitForUnlock(priority = 0) {
301042
+ return this._semaphore.waitForUnlock(1, priority);
301043
+ }
301044
+ release() {
301045
+ if (this._semaphore.isLocked())
301046
+ this._semaphore.release();
301047
+ }
301048
+ cancel() {
301049
+ return this._semaphore.cancel();
301050
+ }
301051
+ }
301052
+ var E_TIMEOUT, E_ALREADY_LOCKED, E_CANCELED, __awaiter$2 = function(thisArg, _arguments, P2, generator) {
301053
+ function adopt(value) {
301054
+ return value instanceof P2 ? value : new P2(function(resolve28) {
301055
+ resolve28(value);
301056
+ });
301057
+ }
301058
+ return new (P2 || (P2 = Promise))(function(resolve28, reject2) {
301059
+ function fulfilled(value) {
301060
+ try {
301061
+ step(generator.next(value));
301062
+ } catch (e) {
301063
+ reject2(e);
301064
+ }
301065
+ }
301066
+ function rejected(value) {
301067
+ try {
301068
+ step(generator["throw"](value));
301069
+ } catch (e) {
301070
+ reject2(e);
301071
+ }
301072
+ }
301073
+ function step(result) {
301074
+ result.done ? resolve28(result.value) : adopt(result.value).then(fulfilled, rejected);
301075
+ }
301076
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
301077
+ });
301078
+ }, __awaiter$1 = function(thisArg, _arguments, P2, generator) {
301079
+ function adopt(value) {
301080
+ return value instanceof P2 ? value : new P2(function(resolve28) {
301081
+ resolve28(value);
301082
+ });
301083
+ }
301084
+ return new (P2 || (P2 = Promise))(function(resolve28, reject2) {
301085
+ function fulfilled(value) {
301086
+ try {
301087
+ step(generator.next(value));
301088
+ } catch (e) {
301089
+ reject2(e);
301090
+ }
301091
+ }
301092
+ function rejected(value) {
301093
+ try {
301094
+ step(generator["throw"](value));
301095
+ } catch (e) {
301096
+ reject2(e);
301097
+ }
301098
+ }
301099
+ function step(result) {
301100
+ result.done ? resolve28(result.value) : adopt(result.value).then(fulfilled, rejected);
301101
+ }
301102
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
301103
+ });
301104
+ };
301105
+ var init_async_mutex = __esm(() => {
301106
+ E_TIMEOUT = new Error("timeout while waiting for mutex to become available");
301107
+ E_ALREADY_LOCKED = new Error("mutex already locked");
301108
+ E_CANCELED = new Error("request for lock canceled");
301109
+ });
301110
+
300879
301111
  // src/services/api/grove.ts
300880
301112
  function memoizeWithTTL(fn, ttlMs) {
300881
301113
  let lastCachedAt = 0;
@@ -300891,6 +301123,9 @@ function memoizeWithTTL(fn, ttlMs) {
300891
301123
  const result = await memoized(...args);
300892
301124
  if (result && typeof result === "object" && "success" in result && result.success === true) {
300893
301125
  lastCachedAt = Date.now();
301126
+ } else if (result && typeof result === "object" && "success" in result && result.success === false) {
301127
+ originalClear();
301128
+ lastCachedAt = 0;
300894
301129
  }
300895
301130
  return result;
300896
301131
  } catch (error49) {
@@ -300972,13 +301207,12 @@ async function isQualifiedForGrove() {
300972
301207
  return cachedEntry.grove_enabled;
300973
301208
  }
300974
301209
  async function fetchAndStoreGroveConfig(accountId) {
300975
- let releaseLock;
300976
- const lockPromise = new Promise((resolve28) => {
300977
- releaseLock = resolve28;
300978
- });
300979
- const previous = groveConfigLocks.get(accountId) ?? Promise.resolve();
300980
- groveConfigLocks.set(accountId, lockPromise);
300981
- await previous;
301210
+ let mutex = groveConfigMutexes.get(accountId);
301211
+ if (!mutex) {
301212
+ mutex = new Mutex;
301213
+ groveConfigMutexes.set(accountId, mutex);
301214
+ }
301215
+ const release = await mutex.acquire();
300982
301216
  try {
300983
301217
  const result = await getGroveNoticeConfig();
300984
301218
  if (!result.success) {
@@ -301002,10 +301236,7 @@ async function fetchAndStoreGroveConfig(accountId) {
301002
301236
  } catch (err2) {
301003
301237
  logForDebugging(`Grove: Failed to fetch and store config: ${err2}`);
301004
301238
  } finally {
301005
- releaseLock();
301006
- if (groveConfigLocks.get(accountId) === lockPromise) {
301007
- groveConfigLocks.delete(accountId);
301008
- }
301239
+ release();
301009
301240
  }
301010
301241
  }
301011
301242
  function calculateShouldShowGrove(settingsResult, configResult, showIfAlreadyViewed) {
@@ -301059,7 +301290,7 @@ An update to our Consumer Terms and Privacy Policy will take effect on October 8
301059
301290
  }
301060
301291
  }
301061
301292
  }
301062
- var groveConfigLocks, GROVE_CACHE_EXPIRATION_MS, GROVE_API_TIMEOUT_MS, getGroveSettings, getGroveNoticeConfig;
301293
+ var groveConfigMutexes, GROVE_CACHE_EXPIRATION_MS, GROVE_API_TIMEOUT_MS, getGroveSettings, getGroveNoticeConfig;
301063
301294
  var init_grove = __esm(() => {
301064
301295
  init_axios2();
301065
301296
  init_memoize();
@@ -301071,7 +301302,8 @@ var init_grove = __esm(() => {
301071
301302
  init_config();
301072
301303
  init_http2();
301073
301304
  init_log3();
301074
- groveConfigLocks = new Map;
301305
+ init_async_mutex();
301306
+ groveConfigMutexes = new Map;
301075
301307
  GROVE_CACHE_EXPIRATION_MS = 24 * 60 * 60 * 1000;
301076
301308
  GROVE_API_TIMEOUT_MS = parseInt(process.env.GROVE_API_TIMEOUT_MS ?? "3000", 10);
301077
301309
  getGroveSettings = memoizeWithTTL(async () => {
@@ -342110,17 +342342,20 @@ async function appendSessionLogImpl(sessionId, entry, url3, headers) {
342110
342342
  logForDebugging(`Session 409: adopting server lastUuid=${serverLastUuid} from header, retrying entry ${entry.uuid}`);
342111
342343
  } else {
342112
342344
  const sequentialFetch = getOrCreateSequentialFetch(sessionId);
342113
- const logs2 = await sequentialFetch(sessionId, url3, headers);
342345
+ let logs2 = null;
342346
+ try {
342347
+ logs2 = await sequentialFetch(sessionId, url3, headers);
342348
+ } catch (fetchError) {
342349
+ logError2(new Error(`Session 409: fetch failed for session ${sessionId}, entry ${entry.uuid}: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`));
342350
+ logForDiagnosticsNoPII("error", "session_persist_409_fetch_fail");
342351
+ }
342114
342352
  const adoptedUuid = findLastUuid(logs2);
342115
342353
  if (adoptedUuid) {
342116
342354
  lastUuidMap.set(sessionId, adoptedUuid);
342117
342355
  logForDebugging(`Session 409: re-fetched ${logs2.length} entries, adopting lastUuid=${adoptedUuid}, retrying entry ${entry.uuid}`);
342118
342356
  } else {
342119
- const errorData = response.data;
342120
- const errorMessage2 = errorData.error?.message || "Concurrent modification detected";
342121
- logError2(new Error(`Session persistence conflict: UUID mismatch for session ${sessionId}, entry ${entry.uuid}. ${errorMessage2}`));
342122
- logForDiagnosticsNoPII("error", "session_persist_fail_concurrent_modification");
342123
- return false;
342357
+ logForDebugging(`Session 409: could not determine server state for session ${sessionId}, entry ${entry.uuid}`);
342358
+ logForDiagnosticsNoPII("warn", "session_persist_409_no_adopted_uuid");
342124
342359
  }
342125
342360
  }
342126
342361
  logForDiagnosticsNoPII("info", "session_persist_409_adopt_server_uuid");
@@ -342137,10 +342372,11 @@ async function appendSessionLogImpl(sessionId, entry, url3, headers) {
342137
342372
  attempt
342138
342373
  });
342139
342374
  } catch (error49) {
342140
- const axiosError = error49;
342141
- logError2(new Error(`Error persisting session log: ${axiosError.message}`));
342375
+ const errorMessage2 = error49 instanceof Error ? error49.message : String(error49);
342376
+ const axiosStatus = error49 && typeof error49 === "object" && "status" in error49 ? error49.status : undefined;
342377
+ logError2(new Error(`Error persisting session log: ${errorMessage2}`));
342142
342378
  logForDiagnosticsNoPII("error", "session_persist_fail_status", {
342143
- status: axiosError.status,
342379
+ status: axiosStatus,
342144
342380
  attempt
342145
342381
  });
342146
342382
  }
@@ -348844,7 +349080,7 @@ var require_semaphore = __commonJS((exports) => {
348844
349080
  exports.Semaphore = undefined;
348845
349081
  var ral_1 = require_ral();
348846
349082
 
348847
- class Semaphore {
349083
+ class Semaphore2 {
348848
349084
  constructor(capacity = 1) {
348849
349085
  if (capacity <= 0) {
348850
349086
  throw new Error("Capacity must be greater than 0");
@@ -348901,7 +349137,7 @@ var require_semaphore = __commonJS((exports) => {
348901
349137
  }
348902
349138
  }
348903
349139
  }
348904
- exports.Semaphore = Semaphore;
349140
+ exports.Semaphore = Semaphore2;
348905
349141
  });
348906
349142
 
348907
349143
  // node_modules/vscode-jsonrpc/lib/common/messageReader.js
@@ -453615,7 +453851,11 @@ async function fetchAndStorePassesEligibility() {
453615
453851
  logForDebugging("Passes: Reusing in-flight eligibility fetch");
453616
453852
  return fetchInProgress;
453617
453853
  }
453618
- fetchInProgress = (async () => {
453854
+ let resolvePromise;
453855
+ fetchInProgress = new Promise((resolve47) => {
453856
+ resolvePromise = resolve47;
453857
+ });
453858
+ (async () => {
453619
453859
  try {
453620
453860
  const response = await fetchReferralEligibility();
453621
453861
  const cacheEntry = {
@@ -453630,11 +453870,11 @@ async function fetchAndStorePassesEligibility() {
453630
453870
  }
453631
453871
  }));
453632
453872
  logForDebugging(`Passes eligibility cached for org ${orgId}: ${response.eligible}`);
453633
- return response;
453873
+ resolvePromise(response);
453634
453874
  } catch (error49) {
453635
453875
  logForDebugging("Failed to fetch and cache passes eligibility");
453636
453876
  logError2(error49);
453637
- return null;
453877
+ resolvePromise(null);
453638
453878
  } finally {
453639
453879
  fetchInProgress = null;
453640
453880
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnycode/myclaude",
3
- "version": "0.1.89",
3
+ "version": "0.1.90",
4
4
  "private": false,
5
5
  "description": "An open-source AI coding assistant in your terminal - powered by Claude",
6
6
  "license": "MIT",
@@ -64,6 +64,7 @@
64
64
  "@opentelemetry/semantic-conventions": "1.40.0",
65
65
  "ajv": "8.18.0",
66
66
  "asciichart": "1.5.25",
67
+ "async-mutex": "^0.5.0",
67
68
  "auto-bind": "5.0.1",
68
69
  "axios": "1.14.0",
69
70
  "bidi-js": "1.0.3",