@quantiya/codevibe-claude-plugin 2.0.72 → 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.
@@ -6349,7 +6349,9 @@ function createSourcePair(options) {
6349
6349
  discardUntilNewline: row3.discardUntilNewline
6350
6350
  }), earliest = (rows) => {
6351
6351
  let ordered = [...rows].sort((a, b) => a.byteOffset - b.byteOffset);
6352
- return ordered.length === 2 && ordered[0].byteOffset === ordered[1].byteOffset && JSON.stringify(position2(ordered[0])) !== JSON.stringify(position2(ordered[1])) ? options.invalid() : position2(ordered[0]);
6352
+ if (ordered.length === 2 && ordered[0].byteOffset === ordered[1].byteOffset && JSON.stringify(position2(ordered[0])) !== JSON.stringify(position2(ordered[1]))) return options.invalid();
6353
+ let baseline = position2(ordered[0]), pending = rows.flatMap((row3) => row3.entries.filter((entry5) => entry5.state === "PREPARING" && entry5.frame.startOffset === baseline.byteOffset).map((entry5) => entry5.frame.endOffset));
6354
+ return { ...baseline, ...pending.length && { pendingFrameEndOffset: Math.min(...pending) } };
6353
6355
  };
6354
6356
  return Object.freeze({
6355
6357
  open: (initial) => {
@@ -6377,6 +6379,7 @@ function createSourcePair(options) {
6377
6379
  skip: (gap2) => {
6378
6380
  let snapshot2 = { ...gap2, anchor: { ...gap2.anchor } };
6379
6381
  return options.locked(async () => {
6382
+ if (await recover(), (await Promise.all(lanes.map((lane) => lane.load()))).some((row3) => row3?.entries.some((entry5) => entry5.state === "PREPARING"))) return options.invalid();
6380
6383
  for (let lane of lanes) await lane.skip(snapshot2);
6381
6384
  });
6382
6385
  },
@@ -11931,7 +11934,8 @@ var AppSyncClient = class _AppSyncClient {
11931
11934
  omitNewPayload: async (signal) => {
11932
11935
  this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal);
11933
11936
  let observed = this.companionSyncStatusSnapshot(userId), state = observed?.mode === "SHADOW" ? observed : await this.getCompanionSyncState(signal);
11934
- if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), state.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
11937
+ if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), state.protocol !== "SYNC_V2" && !(state.mode === "SHADOW" && state.protocol === "LEGACY"))
11938
+ throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
11935
11939
  return state.usage?.syncState === "PAUSED";
11936
11940
  }
11937
11941
  });
@@ -11993,8 +11997,15 @@ var AppSyncClient = class _AppSyncClient {
11993
11997
  let selected = await this.selectCompanionSourceTransport({ sessionId, root });
11994
11998
  if (check(), selected.protocol === "LEGACY") {
11995
11999
  let prior = await this.desktopSyncWriter({ root }).shellSources();
11996
- if (check(), prior.some((row3) => row3.sessionId === sessionId && row3.pendingCount > 0))
11997
- throw owner.recovery.start(), new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12000
+ if (check(), prior.some((row3) => row3.sessionId === sessionId && row3.pendingCount > 0)) {
12001
+ try {
12002
+ await this.recoverPreparedCompanionEvents({ sessionId, root }, void 0, prior);
12003
+ } catch (error) {
12004
+ throw owner.recovery.start(), error;
12005
+ }
12006
+ if (check(), (await this.desktopSyncWriter({ root }).shellSources()).some((row3) => row3.sessionId === sessionId && row3.pendingCount > 0))
12007
+ throw owner.recovery.start(), new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12008
+ }
11998
12009
  let result = await legacy();
11999
12010
  return check(), { protocol: "LEGACY", value: result };
12000
12011
  }
@@ -12030,7 +12041,7 @@ var AppSyncClient = class _AppSyncClient {
12030
12041
  this.assertSyncAccount(userId);
12031
12042
  let settled = resolved;
12032
12043
  for (let source2 of sources) {
12033
- if (source2.sessionId !== sessionId || source2.pendingCount === 0) continue;
12044
+ if (source2.sessionId !== sessionId || (this.rememberSyncRegistration({ sessionId, sessionGenerationId: source2.sessionGenerationId, root }), source2.pendingCount === 0)) continue;
12034
12045
  _AppSyncClient.throwIfAborted(signal), this.assertSyncAccount(userId);
12035
12046
  let cursor = this.desktopSyncWriter({ root, sessionScope: {
12036
12047
  sessionId,
@@ -12088,7 +12099,7 @@ var AppSyncClient = class _AppSyncClient {
12088
12099
  this.assertSyncAccount(userId), await recoverToolActivityWindows({ sessionId, outbox, ledger, transportForGeneration: (sessionGenerationId) => {
12089
12100
  this.assertSyncAccount(userId);
12090
12101
  let sessionScope = { sessionId, sessionGenerationId };
12091
- return createToolActivitySyncTransport({
12102
+ return this.rememberSyncRegistration({ ...sessionScope, root }), createToolActivitySyncTransport({
12092
12103
  sessionScope,
12093
12104
  writer: this.desktopSyncWriter({ root, sessionScope }),
12094
12105
  recoveryOnly: !0,
@@ -12123,14 +12134,29 @@ var AppSyncClient = class _AppSyncClient {
12123
12134
  this.assertSyncAccount(userId);
12124
12135
  let state = await this.getCompanionSyncRoute();
12125
12136
  if (this.assertSyncAccount(userId), state.protocol === "FROZEN") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12126
- if (state.protocol === "LEGACY") return Object.freeze({ protocol: "LEGACY" });
12137
+ let existingGeneration = options.existingSessionGenerationId;
12138
+ if (state.protocol === "LEGACY") {
12139
+ if (this.companionSyncStatusSnapshot(userId)?.mode !== "SHADOW") {
12140
+ if (existingGeneration === void 0) return Object.freeze({ protocol: "LEGACY" });
12141
+ throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12142
+ }
12143
+ if (existingGeneration === void 0) {
12144
+ let generations = new Set([...this.syncRegistrations.get(sessionId)?.values() ?? []].filter((row3) => row3.userId === userId && (row3.scope.root ?? null) === (root ?? null)).map((row3) => row3.scope.sessionGenerationId));
12145
+ if (!generations.size) return Object.freeze({ protocol: "LEGACY" });
12146
+ if (generations.size !== 1) throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
12147
+ existingGeneration = [...generations][0];
12148
+ }
12149
+ }
12127
12150
  let readSession = async () => {
12128
12151
  this.assertSyncAccount(userId);
12129
12152
  let session3 = await this.getSession(sessionId);
12130
12153
  if (this.assertSyncAccount(userId), !session3 || session3.sessionId !== sessionId || session3.userId !== userId || session3.status !== "ACTIVE" || session3.isEncrypted !== !0 || typeof session3.sessionGenerationId != "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(session3.sessionGenerationId))
12131
12154
  throw new SyncEventClientError("SYNC_SESSION_UNAVAILABLE");
12132
12155
  return session3;
12133
- }, session2 = await readSession(), scope = Object.freeze({ sessionId, sessionGenerationId: session2.sessionGenerationId.toLowerCase() }), getEncryptionContext = async () => {
12156
+ }, session2 = await readSession(), scope = Object.freeze({ sessionId, sessionGenerationId: session2.sessionGenerationId.toLowerCase() });
12157
+ if (existingGeneration !== void 0 && existingGeneration !== scope.sessionGenerationId)
12158
+ throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
12159
+ let getEncryptionContext = async () => {
12134
12160
  let current = await readSession();
12135
12161
  if (current.sessionGenerationId.toLowerCase() !== scope.sessionGenerationId)
12136
12162
  throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
@@ -12186,18 +12212,33 @@ var AppSyncClient = class _AppSyncClient {
12186
12212
  return Promise.reject(new SyncEventClientError("INVALID_SYNC_INPUT"));
12187
12213
  let { root, reRaiseToken } = options, sessionId = input.sessionId, userId = this.getCurrentUserId(), check = () => {
12188
12214
  this.assertSyncAccount(userId), this.assertSyncReadAdmission(sessionId);
12189
- }, work = (async () => {
12215
+ }, { timestamp: _retryClock, isEncrypted: _plain, ...source2 } = input, sourceSha256 = (0, import_node_crypto17.createHash)("sha256").update((0, import_json_freeze13.canonicalize)(source2)).digest("hex"), work = (async () => {
12190
12216
  check();
12191
12217
  let selected = await this.selectCompanionSourceTransport({ sessionId, root });
12192
12218
  if (check(), selected.protocol === "LEGACY") {
12193
12219
  let previous = await this.desktopSyncWriter({ root }).promptPublications();
12194
- if (check(), previous.some((row3) => row3.sessionId === sessionId && row3.promptId === prompt.promptId))
12195
- throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12196
- let accepted = await legacy();
12197
- return check(), accepted ? "RERAISED" : "RETRY";
12220
+ check();
12221
+ let existing = previous.filter((row3) => row3.sessionId === sessionId && row3.promptId === prompt.promptId);
12222
+ if (existing.length) {
12223
+ if (existing.length !== 1) throw new SyncEventClientError("SYNC_SESSION_GENERATION_CHANGED");
12224
+ let result2 = await this.desktopSyncWriter({ root, sessionScope: existing[0] }).promptPublication(prompt.promptId).publish(sourceSha256, async (operationId2) => {
12225
+ let retained = await this.selectCompanionSourceTransport({
12226
+ sessionId,
12227
+ root,
12228
+ existingSessionGenerationId: existing[0].sessionGenerationId
12229
+ });
12230
+ if (check(), retained.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12231
+ return this.rememberSyncRegistration({ ...retained.sessionScope, root }), retained.prepareEvent(input, operationId2);
12232
+ }, { reRaiseToken });
12233
+ return check(), result2.status === "OMITTED" ? "OMITTED" : "RERAISED";
12234
+ } else {
12235
+ let accepted = await legacy();
12236
+ return check(), accepted ? "RERAISED" : "RETRY";
12237
+ }
12198
12238
  }
12239
+ if (selected.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12199
12240
  this.rememberSyncRegistration({ ...selected.sessionScope, root });
12200
- let { timestamp: _retryClock, isEncrypted: _plain, ...source2 } = input, sourceSha256 = (0, import_node_crypto17.createHash)("sha256").update((0, import_json_freeze13.canonicalize)(source2)).digest("hex"), result = await selected.writer.promptPublication(prompt.promptId).publish(
12241
+ let result = await selected.writer.promptPublication(prompt.promptId).publish(
12201
12242
  sourceSha256,
12202
12243
  (operationId2) => selected.prepareEvent(input, operationId2),
12203
12244
  { reRaiseToken }
@@ -12269,11 +12310,7 @@ var AppSyncClient = class _AppSyncClient {
12269
12310
  check();
12270
12311
  let resolutions = await writer.promptResolutions();
12271
12312
  check();
12272
- let knownV2 = [...publications, ...resolutions].some((row3) => row3.sessionId === input.sessionId && row3.promptId === input.promptId), durable = (control, selected) => writer.runPromptResolution(control, async (saved, fence) => {
12273
- let state2 = selected ?? await this.getCompanionSyncRoute();
12274
- if (await fence(), state2.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12275
- return this.finishPromptResolution(saved, options, fence);
12276
- });
12313
+ let knownV2 = [...publications, ...resolutions].some((row3) => row3.sessionId === input.sessionId && row3.promptId === input.promptId), durable = (control) => writer.runPromptResolution(control, async (saved, fence) => (await fence(), this.finishPromptResolution(saved, options, fence)));
12277
12314
  if (knownV2) return durable(prepareV2());
12278
12315
  let state = await this.getCompanionSyncRoute();
12279
12316
  if (check(), state.protocol === "LEGACY")
@@ -12283,7 +12320,7 @@ var AppSyncClient = class _AppSyncClient {
12283
12320
  return check(), legacy();
12284
12321
  }, options);
12285
12322
  if (state.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12286
- return durable(prepareV2(), state);
12323
+ return durable(prepareV2());
12287
12324
  })();
12288
12325
  return this.trackSyncClosure(input.sessionId, work.then(() => {
12289
12326
  }, () => {
@@ -12306,8 +12343,6 @@ var AppSyncClient = class _AppSyncClient {
12306
12343
  check();
12307
12344
  let records = (await writer.promptResolutions()).filter((row3) => row3.sessionId === sessionId);
12308
12345
  if (check(), !records.length) return 0;
12309
- let state = await this.getCompanionSyncRoute(signal);
12310
- if (check(), state.protocol !== "SYNC_V2") throw new SyncEventClientError("SYNC_PRODUCER_FROZEN");
12311
12346
  let completed = 0, firstFailure;
12312
12347
  for (let input of records) {
12313
12348
  check();
@@ -117,6 +117,9 @@ export declare class ToolActivityConsolidator {
117
117
  private inFlight;
118
118
  /** Windows currently in backoff-limbo (neither queued nor in flight). */
119
119
  private retrying;
120
+ /** One session-wide pause for an explicit shared transport/status denial. */
121
+ private sendNotBefore;
122
+ private sendWakeTimer;
120
123
  private closed;
121
124
  /**
122
125
  * §4.5(b)/#232 — waiters woken by {@link deliver}'s finally so a bounded drain
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "2.0.67",
3
+ "version": "2.0.68",
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-claude-plugin",
3
- "version": "2.0.72",
3
+ "version": "2.0.73",
4
4
  "description": "Control Claude Code 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": {
@@ -48,7 +48,7 @@
48
48
  "node": ">=22.0.0"
49
49
  },
50
50
  "dependencies": {
51
- "@quantiya/codevibe-core": "^2.0.67",
51
+ "@quantiya/codevibe-core": "^2.0.68",
52
52
  "@quantiya/quorum-core": "^1.0.1",
53
53
  "dotenv": "^16.6.1",
54
54
  "express": "^5.1.0",