@quantiya/codevibe-codex-plugin 2.0.71 → 2.0.73

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.
@@ -6741,6 +6741,11 @@ function invalid3() {
6741
6741
  function badResponse() {
6742
6742
  throw new SyncReadClientError("INVALID_SYNC_READ_RESPONSE");
6743
6743
  }
6744
+ function gatewayUnavailable(status, value) {
6745
+ if (!closed3(value, ["message"]) || typeof value.message != "string") return !1;
6746
+ let message = value.message.toLowerCase();
6747
+ return [500, 502, 503, 504].includes(status) && message === "internal server error" || status === 429 && message === "too many requests";
6748
+ }
6744
6749
  function syncReadResponseError(value) {
6745
6750
  return (!plain4(value) || value.ok !== !1 || typeof value.errorCode != "string" || Object.keys(value).some((k) => !["ok", "errorCode", "retryAfterMs"].includes(k)) || value.retryAfterMs !== void 0 && (!Number.isSafeInteger(value.retryAfterMs) || value.retryAfterMs < 0)) && badResponse(), new SyncReadClientError(
6746
6751
  "SYNC_READ_UNAVAILABLE",
@@ -6770,7 +6775,7 @@ var DesktopSyncReadClient = class {
6770
6775
  }
6771
6776
  event(value) {
6772
6777
  let mobileInput = plain4(value) && value.source === "MOBILE" && ["USER_PROMPT", "PROMPT_RESPONSE"].includes(value.type), legacyStatusRevision = plain4(value) && value.deliveryStatus === "SENT" ? "0" : plain4(value) && value.deliveryStatus === "DELIVERED" ? "1" : plain4(value) && value.deliveryStatus === "EXECUTED" ? "2" : void 0, legacyInput = mobileInput && value.syncLegacyProjection === 1 && value.syncLifecycleVersion === void 0 && value.syncVisibility === "VISIBLE_METERED" && value.syncEventRevision === legacyStatusRevision && value.syncOperationId === void 0 && value.syncImmutableIdentityDigest === void 0;
6773
- return (!plain4(value) || typeof value.eventId != "string" || !ID2.test(value.eventId) || value.sessionId !== this.scope.sessionId || value.sessionGenerationId !== this.scope.sessionGenerationId || !timestamp2(value.timestamp) || typeof value.type != "string" || !/^[A-Z][A-Z0-9_]{0,63}$/.test(value.type) || !["DESKTOP", "MOBILE"].includes(value.source) || value.syncLegacyProjection !== void 0 && !legacyInput || mobileInput && value.syncLifecycleVersion !== 1 && !legacyInput || value.content !== void 0 && typeof value.content != "string" || value.metadata !== void 0 && typeof value.metadata != "string" || value.isEncrypted !== void 0 && typeof value.isEncrypted != "boolean" || value.isEncrypted === !0 && value.encryptionVersion !== 1 || Buffer.byteLength(JSON.stringify(value)) > 350 * 1024) && badResponse(), Object.freeze(value);
6778
+ return (!plain4(value) || typeof value.eventId != "string" || !ID2.test(value.eventId) || value.sessionId !== this.scope.sessionId || value.sessionGenerationId !== this.scope.sessionGenerationId || !timestamp2(value.timestamp) || typeof value.type != "string" || !/^[A-Z][A-Z0-9_]{0,63}$/.test(value.type) || !["DESKTOP", "MOBILE"].includes(value.source) || value.syncLegacyProjection !== void 0 && !legacyInput || mobileInput && value.syncLifecycleVersion !== 1 && !legacyInput || value.content !== void 0 && typeof value.content != "string" || value.metadata !== void 0 && typeof value.metadata != "string" || value.isEncrypted !== void 0 && typeof value.isEncrypted != "boolean" || value.isEncrypted === !0 && value.encryptionVersion !== 1 && !(legacyInput && value.encryptionVersion === void 0) || Buffer.byteLength(JSON.stringify(value)) > 350 * 1024) && badResponse(), Object.freeze(value);
6774
6779
  }
6775
6780
  async request(method, path83, body, proofPayload, action, bound, headers, signal) {
6776
6781
  this.fence(signal);
@@ -6819,7 +6824,7 @@ var DesktopSyncReadClient = class {
6819
6824
  return badResponse();
6820
6825
  }
6821
6826
  if (!response.ok)
6822
- throw syncReadResponseError(value);
6827
+ throw gatewayUnavailable(response.status, value) ? new SyncReadClientError("SYNC_READ_UNAVAILABLE") : syncReadResponseError(value);
6823
6828
  return { text: text2, value };
6824
6829
  } finally {
6825
6830
  controller.abort(), clearTimeout(timer), signal?.removeEventListener("abort", cancel);
@@ -10969,7 +10974,7 @@ function coerceAwsJsonObject(raw, op) {
10969
10974
  }
10970
10975
  var AppSyncGraphQLError = class extends Error {
10971
10976
  constructor(opts) {
10972
- super(`GraphQL error: ${opts.message}`), this.name = "AppSyncGraphQLError", this.responseMessage = opts.message, this.errorType = opts.errorType, this.extensions = opts.extensions, this.path = opts.path;
10977
+ super(`GraphQL error: ${opts.message}`), this.name = "AppSyncGraphQLError", this.responseMessage = opts.message, this.errorType = opts.errorType, this.extensions = opts.extensions, this.path = opts.path, this.data = opts.data, this.requestId = typeof opts.requestId == "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(opts.requestId) ? opts.requestId : void 0;
10973
10978
  }
10974
10979
  }, AppSyncAuthenticationError = class extends Error {
10975
10980
  constructor(kind) {
@@ -11032,6 +11037,12 @@ var AppSyncClient = class _AppSyncClient {
11032
11037
  this.syncDisplayAppliedSequence = 0;
11033
11038
  this.syncDisplay = null;
11034
11039
  this.syncDisplayListeners = /* @__PURE__ */ new Set();
11040
+ this.syncStateRead = null;
11041
+ this.syncStateRetry = null;
11042
+ /** Passive server-denial deadlines shared by existing source retry owners.
11043
+ * Exactly two producer families; no timer, durable state or admission grant. */
11044
+ this.syncProducerEpoch = 0;
11045
+ this.syncProducerRetry = /* @__PURE__ */ new Map();
11035
11046
  this.activeSubscriptions = /* @__PURE__ */ new Map();
11036
11047
  /**
11037
11048
  * Set by `authenticateWithStoredTokens()` on every false-return path
@@ -11187,7 +11198,7 @@ var AppSyncClient = class _AppSyncClient {
11187
11198
  * Authenticate using stored OAuth tokens from keychain
11188
11199
  */
11189
11200
  async authenticateWithStoredTokens() {
11190
- this.lastAuthFailureKind = null, this.lastAuthFailureDetail = null, this.resetCompanionSyncDisplay();
11201
+ this.lastAuthFailureKind = null, this.lastAuthFailureDetail = null, this.resetSyncProducerAuthority(), this.resetCompanionSyncDisplay();
11191
11202
  try {
11192
11203
  let tokens;
11193
11204
  try {
@@ -11229,6 +11240,16 @@ var AppSyncClient = class _AppSyncClient {
11229
11240
  static throwIfAborted(signal) {
11230
11241
  if (signal?.aborted) throw _AppSyncClient.abortReason(signal);
11231
11242
  }
11243
+ static async waitForSyncStateRetry(delayMs, signal) {
11244
+ _AppSyncClient.throwIfAborted(signal), await new Promise((resolve28, reject) => {
11245
+ let timer = setTimeout(() => {
11246
+ signal?.removeEventListener("abort", onAbort), resolve28();
11247
+ }, delayMs), onAbort = () => {
11248
+ clearTimeout(timer), signal?.removeEventListener("abort", onAbort), reject(_AppSyncClient.abortReason(signal));
11249
+ };
11250
+ signal?.addEventListener("abort", onAbort, { once: !0 }), signal?.aborted && onAbort();
11251
+ });
11252
+ }
11232
11253
  /**
11233
11254
  * Bound one stage by its owning operation's absolute deadline. Every stage
11234
11255
  * receives the same `deadlineAtMs`; a storage-backed retry therefore consumes
@@ -11507,20 +11528,22 @@ var AppSyncClient = class _AppSyncClient {
11507
11528
  * Sign out
11508
11529
  */
11509
11530
  signOut() {
11510
- this.authenticated = !1, this.replaceTokens(null), this.currentUserId = null, this.currentEmail = null, this.resetCompanionSyncDisplay(), this.cleanupSubscriptions(), logger.info("[AppSyncClient] Signed out");
11531
+ this.resetSyncProducerAuthority(), this.authenticated = !1, this.replaceTokens(null), this.currentUserId = null, this.currentEmail = null, this.resetCompanionSyncDisplay(), this.cleanupSubscriptions(), logger.info("[AppSyncClient] Signed out");
11511
11532
  }
11512
11533
  /**
11513
11534
  * Make a GraphQL request
11514
11535
  */
11515
- async graphqlRequest(query, variables, isRetry = !1, signal, expectedUserId, maxResponseBytes) {
11536
+ async graphqlRequest(query, variables, isRetry = !1, signal, expectedUserId, maxResponseBytes, beforeSend) {
11516
11537
  _AppSyncClient.throwIfAborted(signal), expectedUserId !== void 0 && this.assertSyncAccount(expectedUserId);
11517
- let config = getConfig();
11538
+ let syncUserId = this.currentUserId, syncEpoch = this.syncDisplayEpoch, config = getConfig();
11518
11539
  if (!this.tokens?.idToken)
11519
11540
  throw new Error('Not authenticated. Run "codevibe login" first.');
11520
11541
  let headers = {
11521
11542
  "Content-Type": "application/json",
11522
11543
  Authorization: this.tokens.idToken
11523
- }, response = await fetchWithDiagnostics(
11544
+ };
11545
+ beforeSend?.();
11546
+ let response = await fetchWithDiagnostics(
11524
11547
  config.aws.appsyncUrl,
11525
11548
  {
11526
11549
  method: "POST",
@@ -11536,7 +11559,7 @@ var AppSyncClient = class _AppSyncClient {
11536
11559
  logger.info("[AppSyncClient] 401 Unauthorized, refreshing token..."), _AppSyncClient.throwIfAborted(signal);
11537
11560
  let refreshed = await this.refreshTokens(this.tokens, signal);
11538
11561
  if (_AppSyncClient.throwIfAborted(signal), refreshed)
11539
- return this.graphqlRequest(query, variables, !0, signal, expectedUserId, maxResponseBytes);
11562
+ return this.graphqlRequest(query, variables, !0, signal, expectedUserId, maxResponseBytes, beforeSend);
11540
11563
  throw new AppSyncAuthenticationError(
11541
11564
  this.lastRefreshNetworkError ? "refresh_network" : "refresh_auth_rejected"
11542
11565
  );
@@ -11546,11 +11569,22 @@ var AppSyncClient = class _AppSyncClient {
11546
11569
  let result = maxResponseBytes === void 0 ? await response.json() : await this.boundedGraphQLJson(response, maxResponseBytes, signal);
11547
11570
  if (expectedUserId !== void 0 && this.assertSyncAccount(expectedUserId), result.errors?.length) {
11548
11571
  let first = result.errors[0];
11549
- throw new AppSyncGraphQLError({
11572
+ throw [
11573
+ mutations.createEvent,
11574
+ mutations.updateEventStatus,
11575
+ mutations.recordWorkspaceOutcomeV2,
11576
+ mutations.reportSecurityPostureV2,
11577
+ queries.listEvents,
11578
+ queries.listSupervisionEvents,
11579
+ queries.getGateResolution,
11580
+ queries.getGateResolutionV2
11581
+ ].includes(query) && syncUserId === this.currentUserId && syncEpoch === this.syncDisplayEpoch && ["UPDATE_REQUIRED", "AUTHORITY_UNAVAILABLE", "SYNC_BLOCKED"].includes(first.errorType ?? "") && this.resetCompanionSyncDisplay(), new AppSyncGraphQLError({
11550
11582
  message: first.message,
11551
11583
  errorType: first.errorType,
11552
11584
  extensions: first.extensions,
11553
- path: first.path
11585
+ path: first.path,
11586
+ data: first.data,
11587
+ requestId: response.headers?.get("x-amzn-requestid")
11554
11588
  });
11555
11589
  }
11556
11590
  return result;
@@ -11589,15 +11623,70 @@ var AppSyncClient = class _AppSyncClient {
11589
11623
  if (!this.authenticated || this.currentUserId !== userId || this.tokens?.userId !== userId)
11590
11624
  throw new SyncEventClientError("SYNC_ACCOUNT_CHANGED");
11591
11625
  }
11592
- /** Bounded cloud routing/usage read, pinned to the current account. No fallback. */
11626
+ /** Concurrent fresh reads share one account/epoch-bound request and retry
11627
+ * loop. Sequential status/quota reads remain fresh; one cancelled caller
11628
+ * cannot cancel another caller's read. No cached admission authority. */
11593
11629
  async getCompanionSyncState(signal) {
11594
- let userId = this.getCurrentUserId();
11630
+ let userId = this.getCurrentUserId(), epoch = this.syncDisplayEpoch, check = () => {
11631
+ if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), epoch !== this.syncDisplayEpoch) throw new SyncEventClientError("INVALID_SYNC_STATE");
11632
+ };
11633
+ check();
11634
+ let flight = this.syncStateRead;
11635
+ if (!flight || flight.userId !== userId || flight.epoch !== epoch || flight.controller.signal.aborted) {
11636
+ let controller = new AbortController();
11637
+ flight = { userId, epoch, controller, promise: this.readCompanionSyncState(userId, epoch, controller.signal), waiters: 0, settled: !1 }, this.syncStateRead = flight;
11638
+ let owned2 = flight, settled = () => {
11639
+ owned2.settled = !0, this.syncStateRead === owned2 && (this.syncStateRead = null);
11640
+ };
11641
+ owned2.promise.then(settled, settled);
11642
+ }
11643
+ let owned = flight;
11644
+ return owned.waiters++, new Promise((resolve28, reject) => {
11645
+ let finished = !1, finish = (error) => {
11646
+ if (!finished) {
11647
+ finished = !0, signal?.removeEventListener("abort", onAbort), --owned.waiters === 0 && !owned.settled && (this.syncStateRead === owned && (this.syncStateRead = null), owned.controller.abort(new Error("Sync state read has no callers")));
11648
+ try {
11649
+ if (check(), error !== void 0) throw error;
11650
+ let state = this.companionSyncStatusSnapshot(userId);
11651
+ if (!state) throw new SyncEventClientError("INVALID_SYNC_STATE");
11652
+ resolve28(state);
11653
+ } catch (failure2) {
11654
+ reject(failure2);
11655
+ }
11656
+ }
11657
+ }, onAbort = () => finish(_AppSyncClient.abortReason(signal));
11658
+ signal?.addEventListener("abort", onAbort, { once: !0 }), owned.promise.then(() => finish(), (error) => finish(error)), signal?.aborted && onAbort();
11659
+ });
11660
+ }
11661
+ /** Only explicit HISTORY_RETRY_AFTER permits two retries / ten seconds of
11662
+ * added wait. Retain the server's earliest retry time after cancellation or
11663
+ * exhaustion so a later caller cannot restart I/O before that time. */
11664
+ async readCompanionSyncState(userId, epoch, signal) {
11595
11665
  this.assertSyncAccount(userId);
11596
- let epoch = this.syncDisplayEpoch, sequence = ++this.syncDisplaySequence;
11666
+ let sequence = ++this.syncDisplaySequence;
11597
11667
  try {
11598
- _AppSyncClient.throwIfAborted(signal);
11599
- let response = await this.graphqlRequest(queries.getCompanionSyncState, {}, !1, signal, userId);
11600
- this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal);
11668
+ let response, retries = 0, waitedMs = 0;
11669
+ for (; ; ) {
11670
+ this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal);
11671
+ let cooldown = this.syncStateRetry;
11672
+ if (cooldown?.userId === userId && cooldown.epoch === epoch) {
11673
+ let delayMs = cooldown.retryAtMs - Date.now();
11674
+ if (delayMs > 1e4 - waitedMs) throw cooldown.error;
11675
+ delayMs > 0 && (waitedMs += delayMs, await _AppSyncClient.waitForSyncStateRetry(delayMs, signal), this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal));
11676
+ }
11677
+ try {
11678
+ response = await this.graphqlRequest(queries.getCompanionSyncState, {}, !1, signal, userId);
11679
+ break;
11680
+ } catch (error) {
11681
+ this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal);
11682
+ let data = error instanceof AppSyncGraphQLError ? error.data : void 0, retryAfterMs = data && typeof data == "object" && !Array.isArray(data) ? data.retryAfterMs : void 0;
11683
+ if (!(error instanceof AppSyncGraphQLError) || error.errorType !== "HISTORY_RETRY_AFTER" || typeof retryAfterMs != "number" || !Number.isSafeInteger(retryAfterMs) || retryAfterMs < 0) throw error;
11684
+ let retryAtMs = Date.now() + Math.max(1, retryAfterMs);
11685
+ if (!Number.isSafeInteger(retryAtMs) || (this.syncStateRetry = { userId, epoch, retryAtMs, error }, retries >= 2)) throw error;
11686
+ retries++;
11687
+ }
11688
+ }
11689
+ this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), this.syncStateRetry?.userId === userId && this.syncStateRetry.epoch === epoch && (this.syncStateRetry = null);
11601
11690
  let state = parseCompanionSyncState(response?.data?.getCompanionSyncState, this.environment), effective = this.publishCompanionSyncDisplay(userId, state, epoch, sequence), now = Date.now();
11602
11691
  if (!effective || !Number.isSafeInteger(now) || effective.observedAtEpochMs > now + SYNC_STATE_CLOCK_SKEW_MS || effective.validUntilEpochMs <= now)
11603
11692
  throw new SyncEventClientError("INVALID_SYNC_STATE");
@@ -11606,6 +11695,19 @@ var AppSyncClient = class _AppSyncClient {
11606
11695
  throw this.publishCompanionSyncDisplay(userId, null, epoch, sequence), error;
11607
11696
  }
11608
11697
  }
11698
+ /** Reuse only the server-unexpired protocol selection, never its entitlement
11699
+ * or usage as admission authority. Every selected cloud operation still
11700
+ * authorizes itself. Explicit status/quota refreshes remain fresh reads. */
11701
+ async getCompanionSyncRoute(signal) {
11702
+ let userId = this.getCurrentUserId(), epoch = this.syncDisplayEpoch, check = () => {
11703
+ if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), epoch !== this.syncDisplayEpoch) throw new SyncEventClientError("INVALID_SYNC_STATE");
11704
+ };
11705
+ check();
11706
+ let cached = this.companionSyncStatusSnapshot(userId);
11707
+ if (cached) return { protocol: cached.protocol };
11708
+ let state = await this.getCompanionSyncState(signal);
11709
+ return check(), { protocol: state.protocol };
11710
+ }
11609
11711
  /** Subscribe to validated reads already performed by this client. No new
11610
11712
  * request, persistent journal, producer grant or retry is created here. */
11611
11713
  subscribeCompanionSyncState(userId, listener) {
@@ -11634,8 +11736,13 @@ var AppSyncClient = class _AppSyncClient {
11634
11736
  logger.warn("[AppSyncClient] Companion status display listener failed");
11635
11737
  }
11636
11738
  }
11739
+ resetSyncProducerAuthority() {
11740
+ this.syncProducerEpoch++, this.syncProducerRetry.clear();
11741
+ }
11637
11742
  resetCompanionSyncDisplay() {
11638
- this.syncDisplayEpoch += 1, this.syncDisplay = null, this.syncDisplayAppliedSequence = this.syncDisplaySequence;
11743
+ this.syncDisplayEpoch += 1;
11744
+ let flight = this.syncStateRead;
11745
+ this.syncStateRead = null, this.syncStateRetry = null, flight?.controller.abort(new Error("Sync routing observation invalidated")), this.syncDisplay = null, this.syncDisplayAppliedSequence = this.syncDisplaySequence;
11639
11746
  for (let entry5 of this.syncDisplayListeners) this.notifyCompanionSyncDisplay(entry5);
11640
11747
  }
11641
11748
  publishCompanionSyncDisplay(userId, state, epoch, sequence) {
@@ -11661,7 +11768,7 @@ var AppSyncClient = class _AppSyncClient {
11661
11768
  posture
11662
11769
  }, userId = this.getCurrentUserId();
11663
11770
  this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal);
11664
- let state = await this.getCompanionSyncState(signal);
11771
+ let state = await this.getCompanionSyncRoute(signal);
11665
11772
  if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), state.protocol === "LEGACY") return null;
11666
11773
  if (state.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
11667
11774
  if (!scope.sessionGenerationId) throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
@@ -11689,7 +11796,7 @@ var AppSyncClient = class _AppSyncClient {
11689
11796
  async desktopSyncReadClient(sessionScope, signal) {
11690
11797
  let scope = { ...sessionScope }, userId = this.getCurrentUserId();
11691
11798
  this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal);
11692
- let state = await this.getCompanionSyncState(signal);
11799
+ let state = await this.getCompanionSyncRoute(signal);
11693
11800
  if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), state.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
11694
11801
  let config = getConfig();
11695
11802
  if (config.environment !== this.environment || !config.aws.syncHttpUrl) throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
@@ -11996,13 +12103,13 @@ var AppSyncClient = class _AppSyncClient {
11996
12103
  getEncryptionContext: selected.getEncryptionContext
11997
12104
  });
11998
12105
  }
11999
- /** Shared cloud-selected authority for tools and ordinary native sources. */
12106
+ /** Shared cloud-selected routing for tools and ordinary native sources. */
12000
12107
  async selectCompanionSourceTransport(options) {
12001
12108
  let { sessionId, root } = options;
12002
12109
  if (typeof sessionId != "string" || !/^[A-Za-z0-9_-]{1,256}$/.test(sessionId)) throw new SyncEventClientError("INVALID_SYNC_INPUT");
12003
12110
  let userId = this.getCurrentUserId();
12004
12111
  this.assertSyncAccount(userId);
12005
- let state = await this.getCompanionSyncState();
12112
+ let state = await this.getCompanionSyncRoute();
12006
12113
  if (this.assertSyncAccount(userId), state.protocol === "FROZEN") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12007
12114
  if (state.protocol === "LEGACY") return Object.freeze({ protocol: "LEGACY" });
12008
12115
  let readSession = async () => {
@@ -12151,12 +12258,12 @@ var AppSyncClient = class _AppSyncClient {
12151
12258
  let resolutions = await writer.promptResolutions();
12152
12259
  check();
12153
12260
  let knownV2 = [...publications, ...resolutions].some((row3) => row3.sessionId === input.sessionId && row3.promptId === input.promptId), durable = (control, selected) => writer.runPromptResolution(control, async (saved, fence) => {
12154
- let state2 = selected ?? await this.getCompanionSyncState();
12261
+ let state2 = selected ?? await this.getCompanionSyncRoute();
12155
12262
  if (await fence(), state2.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12156
12263
  return this.finishPromptResolution(saved, options, fence);
12157
12264
  });
12158
12265
  if (knownV2) return durable(prepareV2());
12159
- let state = await this.getCompanionSyncState();
12266
+ let state = await this.getCompanionSyncRoute();
12160
12267
  if (check(), state.protocol === "LEGACY")
12161
12268
  return this.resolvePromptPublication(input, async (hasV2Publication) => {
12162
12269
  if (hasV2Publication || (await writer.promptResolutions()).some((row3) => row3.sessionId === input.sessionId && row3.promptId === input.promptId))
@@ -12187,7 +12294,7 @@ var AppSyncClient = class _AppSyncClient {
12187
12294
  check();
12188
12295
  let records = (await writer.promptResolutions()).filter((row3) => row3.sessionId === sessionId);
12189
12296
  if (check(), !records.length) return 0;
12190
- let state = await this.getCompanionSyncState(signal);
12297
+ let state = await this.getCompanionSyncRoute(signal);
12191
12298
  if (check(), state.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12192
12299
  let completed = 0, firstFailure;
12193
12300
  for (let input of records) {
@@ -12440,10 +12547,18 @@ var AppSyncClient = class _AppSyncClient {
12440
12547
  }
12441
12548
  async mutateDesktopSyncEvent(action, input, signal) {
12442
12549
  _AppSyncClient.throwIfAborted(signal);
12443
- let data = snapshotDesktopSyncInput(action, input), userId = this.getCurrentUserId();
12444
- this.assertSyncAccount(userId);
12550
+ let data = snapshotDesktopSyncInput(action, input), userId = this.getCurrentUserId(), epoch = this.syncProducerEpoch, deniedLocally = !1, check = () => {
12551
+ if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), epoch !== this.syncProducerEpoch) throw new SyncEventClientError("SYNC_ACCOUNT_CHANGED");
12552
+ for (let family of ["PRODUCER", "ENRICHMENT"]) {
12553
+ if (family === "ENRICHMENT" && action !== "UPDATE_EVENT") continue;
12554
+ let cooldown = this.syncProducerRetry.get(family);
12555
+ if (cooldown?.userId === userId && cooldown.epoch === epoch && cooldown.retryAtMs > Date.now())
12556
+ throw deniedLocally = !0, cooldown.error;
12557
+ }
12558
+ };
12559
+ check();
12445
12560
  let identity = await keychainManager.getDeviceIdentity();
12446
- if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), !identity) throw new SyncEventClientError("SYNC_IDENTITY_UNAVAILABLE");
12561
+ if (check(), !identity) throw new SyncEventClientError("SYNC_IDENTITY_UNAVAILABLE");
12447
12562
  let prepared = signDesktopSyncInput(
12448
12563
  action,
12449
12564
  data,
@@ -12452,9 +12567,16 @@ var AppSyncClient = class _AppSyncClient {
12452
12567
  Date.now()
12453
12568
  ), field2 = action === "CREATE_EVENT" ? "createEventV2" : "updateEventV2", response;
12454
12569
  try {
12455
- response = await this.graphqlRequest(mutations[field2], { input: prepared }, !1, signal, userId);
12570
+ response = await this.graphqlRequest(mutations[field2], { input: prepared }, !1, signal, userId, void 0, check);
12456
12571
  } catch (error) {
12457
- if (this.assertSyncAccount(userId), error instanceof AppSyncGraphQLError && error.errorType === "SYNC_QUOTA_EXHAUSTED") {
12572
+ if (this.assertSyncAccount(userId), !deniedLocally && epoch === this.syncProducerEpoch && error instanceof AppSyncGraphQLError) {
12573
+ let serverDelay = error.data && typeof error.data == "object" && !Array.isArray(error.data) ? error.data.retryAfterMs : void 0, retryFamily = error.errorType === "PRODUCER_RETRY_AFTER" ? "PRODUCER" : action === "UPDATE_EVENT" && error.errorType === "UPDATE_ENRICHMENT_RETRY_AFTER" ? "ENRICHMENT" : null, family = retryFamily ?? "PRODUCER", delay = retryFamily !== null && typeof serverDelay == "number" && Number.isSafeInteger(serverDelay) && serverDelay >= 0 ? Math.max(1, serverDelay) : error.errorType === "CONTROL_BREAKER_CONTENTION" ? 1e4 : null;
12574
+ if (delay !== null) {
12575
+ let retryAtMs = Date.now() + delay, prior = this.syncProducerRetry.get(family);
12576
+ Number.isSafeInteger(retryAtMs) && (!prior || prior.userId !== userId || prior.epoch !== epoch || prior.retryAtMs < retryAtMs) && this.syncProducerRetry.set(family, { userId, epoch, retryAtMs, error });
12577
+ }
12578
+ }
12579
+ if (error instanceof AppSyncGraphQLError && error.errorType === "SYNC_QUOTA_EXHAUSTED") {
12458
12580
  let displayed = this.syncDisplay?.userId === userId ? this.syncDisplay.state : null;
12459
12581
  if (displayed?.usage?.syncState !== "PAUSED" || displayed.validUntilEpochMs <= Date.now()) {
12460
12582
  try {
@@ -12606,7 +12728,7 @@ var AppSyncClient = class _AppSyncClient {
12606
12728
  async submitWorkspaceOutcome(value, options = {}) {
12607
12729
  let input = snapshotWorkspaceOutcomeInput(value), userId = this.getCurrentUserId();
12608
12730
  this.assertSyncAccount(userId);
12609
- let route = await this.getCompanionSyncState();
12731
+ let route = await this.getCompanionSyncRoute();
12610
12732
  if (this.assertSyncAccount(userId), route.protocol === "FROZEN") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12611
12733
  if (route.protocol === "LEGACY") {
12612
12734
  if (options.requiresV2) throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
@@ -12710,7 +12832,7 @@ var AppSyncClient = class _AppSyncClient {
12710
12832
  source: "MOBILE" /* MOBILE */,
12711
12833
  type: expected.type
12712
12834
  }), this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal));
12713
- let route = await this.getCompanionSyncState(signal);
12835
+ let route = await this.getCompanionSyncRoute(signal);
12714
12836
  if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), route.protocol === "FROZEN") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12715
12837
  if (requiredSessionGenerationId !== void 0 && route.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12716
12838
  if (route.protocol === "LEGACY") {
@@ -12738,7 +12860,7 @@ var AppSyncClient = class _AppSyncClient {
12738
12860
  * List events for a session
12739
12861
  */
12740
12862
  async listEvents(sessionId, source2, limit) {
12741
- let route = await this.getCompanionSyncState();
12863
+ let route = await this.getCompanionSyncRoute();
12742
12864
  if (route.protocol === "FROZEN") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12743
12865
  if (route.protocol === "SYNC_V2") {
12744
12866
  if (limit !== void 0 && (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)) throw new SyncEventClientError("INVALID_SYNC_INPUT");
@@ -12752,7 +12874,7 @@ var AppSyncClient = class _AppSyncClient {
12752
12874
  * can merge each page through the same strict event classifier as live data.
12753
12875
  */
12754
12876
  async listSupervisionEvents(input) {
12755
- let route = await this.getCompanionSyncState();
12877
+ let route = await this.getCompanionSyncRoute();
12756
12878
  if (route.protocol === "FROZEN") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12757
12879
  if (route.protocol === "SYNC_V2") {
12758
12880
  if (input.limit !== void 0 && input.limit !== 100) throw new SyncEventClientError("INVALID_SYNC_INPUT");
@@ -13201,7 +13323,7 @@ var AppSyncClient = class _AppSyncClient {
13201
13323
  async getGateResolution(input) {
13202
13324
  let expected = { ...input }, userId = this.getCurrentUserId(), epoch = this.syncReadEpoch;
13203
13325
  this.assertSyncAccount(userId), this.assertSyncReadAdmission(expected.sessionId);
13204
- let route = await this.getCompanionSyncState();
13326
+ let route = await this.getCompanionSyncRoute();
13205
13327
  if (this.assertSyncAccount(userId), this.assertSyncReadAdmission(expected.sessionId), epoch !== this.syncReadEpoch) throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
13206
13328
  if (route.protocol === "LEGACY") {
13207
13329
  let response = await this.graphqlRequest(
@@ -14233,7 +14355,7 @@ var AppSyncClient = class _AppSyncClient {
14233
14355
  createSubscription(state) {
14234
14356
  let abort = state.setupAbort = new AbortController(), current = () => !state.destroyed && !abort.signal.aborted && this.activeSubscriptions.get(state.sessionId) === state, setup = (async () => {
14235
14357
  if (await this.joinSyncSubscriptionClosures(state.sessionId), !current()) return;
14236
- let userId = this.getCurrentUserId(), route = await this.getCompanionSyncState(abort.signal);
14358
+ let userId = this.getCurrentUserId(), route = await this.getCompanionSyncRoute(abort.signal);
14237
14359
  if (!current()) return;
14238
14360
  if (this.assertSyncAccount(userId), route.protocol === "FROZEN") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
14239
14361
  if (route.protocol === "LEGACY") {
@@ -77322,10 +77444,47 @@ var OrchestrationShellStartupError = class extends Error {
77322
77444
  super(message), this.name = "OrchestrationShellStartupError", this.cause = cause;
77323
77445
  }
77324
77446
  }, STARTUP_SUBSCRIPTION_TIMEOUT_MS = 15e3;
77447
+ function logStartupFailure(boundary, errorValue, reason) {
77448
+ try {
77449
+ let error = errorValue, classes = [
77450
+ "AppSyncGraphQLError",
77451
+ "AppSyncAuthenticationError",
77452
+ "SyncEventClientError",
77453
+ "SyncReadClientError",
77454
+ "Error",
77455
+ "TypeError"
77456
+ ], codes = [
77457
+ "HISTORY_RETRY_AFTER",
77458
+ "CONTROL_BREAKER_CONTENTION",
77459
+ "AUTHORITY_UNAVAILABLE",
77460
+ "INVALID_SYNC_STATE",
77461
+ "INVALID_SYNC_READ_RESPONSE",
77462
+ "SYNC_PRODUCER_FROZEN",
77463
+ "SYNC_ACCOUNT_CHANGED",
77464
+ "SYNC_SESSION_UNAVAILABLE",
77465
+ "EPERM",
77466
+ "EACCES",
77467
+ "ENOENT",
77468
+ "ENETUNREACH",
77469
+ "EAI_AGAIN",
77470
+ "ECONNREFUSED",
77471
+ "ECONNRESET",
77472
+ "ETIMEDOUT"
77473
+ ], code = [error?.errorType, error?.code].find((value) => typeof value == "string" && codes.includes(value)), requestId = typeof error?.requestId == "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(error.requestId) ? error.requestId : void 0, delay = error?.data?.retryAfterMs, retryAfterMs = code === "HISTORY_RETRY_AFTER" && typeof delay == "number" && Number.isSafeInteger(delay) && delay >= 0 ? delay : void 0;
77474
+ logger.warn(`[orchestration-shell] startup ${boundary} failed`, {
77475
+ ...reason !== void 0 && { reason },
77476
+ errorClass: typeof error?.name == "string" && classes.includes(error.name) ? error.name : "UNKNOWN",
77477
+ errorCode: code ?? "UNKNOWN",
77478
+ ...requestId && { requestId },
77479
+ ...retryAfterMs !== void 0 && { retryAfterMs }
77480
+ });
77481
+ } catch {
77482
+ }
77483
+ }
77325
77484
  function startupEventFailure(result) {
77326
77485
  if (result.emitted)
77327
77486
  return new OrchestrationShellStartupError("Unexpected successful startup event result");
77328
- switch (result.reason) {
77487
+ switch (logStartupFailure("event", result.error, result.reason), result.reason) {
77329
77488
  case "missing_session_key":
77330
77489
  return new OrchestrationShellStartupError(
77331
77490
  "CodeVibe could not access the orchestration session encryption key. Exit and launch CodeVibe again; if the problem persists, run `codevibe login`.",
@@ -77864,7 +78023,7 @@ async function runOrchestrationShell(args) {
77864
78023
  // an event actually arrives (async) — never during this synchronous setup.
77865
78024
  subscribedEventDispatcher,
77866
78025
  (err) => {
77867
- initialCatchUpStarted && rejectInitialSubscription(err), logger.warn("[orchestration-shell] subscribeToEvents error", {
78026
+ initialSubscriptionSettled || logStartupFailure("subscription", err), initialCatchUpStarted && rejectInitialSubscription(err), logger.warn("[orchestration-shell] subscribeToEvents error", {
77868
78027
  error: err.message
77869
78028
  });
77870
78029
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "2.0.62",
3
+ "version": "2.0.64",
4
4
  "description": "Core library for CodeVibe plugins - shared keychain, crypto, AppSync, and auth functionality",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-codex-plugin",
3
- "version": "2.0.71",
3
+ "version": "2.0.73",
4
4
  "description": "Control OpenAI Codex CLI from your iPhone and Android — real-time sync, approve file edits, send prompts by voice. Part of CodeVibe.",
5
5
  "main": "dist/server.js",
6
6
  "codevibe": {
@@ -47,7 +47,7 @@
47
47
  "node": ">=22.0.0"
48
48
  },
49
49
  "dependencies": {
50
- "@quantiya/codevibe-core": "^2.0.62",
50
+ "@quantiya/codevibe-core": "^2.0.64",
51
51
  "@quantiya/quorum-core": "^1.0.1",
52
52
  "chokidar": "^4.0.0",
53
53
  "dotenv": "^16.6.1",