@quantiya/codevibe-antigravity-plugin 2.0.22 → 2.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/server.js +33 -9
  2. package/package.json +2 -2
package/dist/server.js CHANGED
@@ -3300,6 +3300,7 @@ var McpServer = class _McpServer {
3300
3300
  * under this single sessionId. /resume does NOT create a new
3301
3301
  * session — same row. */
3302
3302
  this.session = null;
3303
+ this.promptPublications = new import_codevibe_core5.PromptPublicationTracker();
3303
3304
  this.transcriptHandlers = /* @__PURE__ */ new Set();
3304
3305
  this.toolActivityKeyRefresh = null;
3305
3306
  // E1 (§4/§6a-4) — per-promptId durable raise entries for the agy producer.
@@ -4154,11 +4155,18 @@ var McpServer = class _McpServer {
4154
4155
  /** Encrypt and send one individual event, refreshing a stale session key once. */
4155
4156
  async createEncryptedEvent(session, input) {
4156
4157
  const lifecycleGen = this.lifecycleGen;
4158
+ const promptId = input.producerKind === "PLUGIN_APPROVAL" ? input.promptId : void 0;
4159
+ const promptEntry = promptId ? this.e1PromptRaises.get(promptId) : void 0;
4157
4160
  const sendOnce = async () => {
4161
+ if (promptId && !(0, import_codevibe_core5.isOpenPromptRaise)(
4162
+ promptEntry,
4163
+ this.e1PromptRaises.get(promptId),
4164
+ this.e1NeedsResolution.has(promptId)
4165
+ )) return null;
4158
4166
  if (lifecycleGen !== this.lifecycleGen || !this.started || this.session !== session || input.sessionId !== session.sessionId) return null;
4159
4167
  const outbound = this.encryptOutbound(session, input);
4160
4168
  if (!outbound) return null;
4161
- return this.appSyncClient.createEvent(outbound);
4169
+ return promptId ? this.promptPublications.run(promptId, () => this.appSyncClient.createEvent(outbound)) : this.appSyncClient.createEvent(outbound);
4162
4170
  };
4163
4171
  try {
4164
4172
  return await sendOnce();
@@ -4215,9 +4223,11 @@ var McpServer = class _McpServer {
4215
4223
  this.e1NeedsResolution.delete(promptId);
4216
4224
  return true;
4217
4225
  }
4226
+ entry.resolutionStarted = true;
4218
4227
  this.e1NeedsResolution.add(promptId);
4219
4228
  const operation = (async () => {
4220
4229
  try {
4230
+ if (this.promptPublications.isPublishing(promptId)) await this.promptPublications.waitFor(promptId);
4221
4231
  const ack = await this.appSyncClient.createEvent({
4222
4232
  sessionId: entry.record.sessionId || sessionId,
4223
4233
  type: import_codevibe_core5.EventType.NOTIFICATION,
@@ -4353,7 +4363,7 @@ var McpServer = class _McpServer {
4353
4363
  };
4354
4364
  this.e1PromptRaises.set(entry.record.promptId, entry);
4355
4365
  const acked = await this.reRaiseOneE1(replacementSession, entry, opts);
4356
- if (!acked) unacked.push(snap);
4366
+ if (!acked && !entry.resolutionStarted) unacked.push(snap);
4357
4367
  }
4358
4368
  if (!this.e1TtlRefreshTimer) this.startE1TtlRefresh();
4359
4369
  return unacked;
@@ -4441,11 +4451,20 @@ var McpServer = class _McpServer {
4441
4451
  */
4442
4452
  async reRaiseOneE1(session, entry, opts) {
4443
4453
  const rec = entry.record;
4454
+ if (this.e1NeedsResolution.has(rec.promptId)) return false;
4455
+ if (!(0, import_codevibe_core5.canRecoverPromptRaise)(entry, this.promptPublications.isPublishing(rec.promptId))) {
4456
+ return false;
4457
+ }
4444
4458
  const actionable = rec.mobileActionable && entry.contentPlain !== void 0;
4445
4459
  const retryUntilAck = opts?.retryUntilAck === true;
4446
4460
  const gen = opts?.gen;
4447
4461
  const MAX_ATTEMPTS = 4;
4448
4462
  for (let attempt = 1; ; attempt++) {
4463
+ if (!(0, import_codevibe_core5.isOpenPromptRaise)(
4464
+ entry,
4465
+ this.e1PromptRaises.get(rec.promptId),
4466
+ this.e1NeedsResolution.has(rec.promptId)
4467
+ )) return false;
4449
4468
  if (retryUntilAck && this.reRaiseSuperseded(gen)) {
4450
4469
  this.e1NeedsReRaise.add(rec.promptId);
4451
4470
  logger.warn("E1: block-until-ack re-raise aborted (lifecycle superseded/stopping) \u2014 flagged for retry-until-ack (entry retained)", {
@@ -4466,6 +4485,11 @@ var McpServer = class _McpServer {
4466
4485
  timestamp: (0, import_codevibe_core5.prepareEventTimestamp)({ orderingKey: session.sessionId })
4467
4486
  };
4468
4487
  await this.flushToolActivityAtBoundary(import_codevibe_core5.EventType.INTERACTIVE_PROMPT);
4488
+ if (!(0, import_codevibe_core5.isOpenPromptRaise)(
4489
+ entry,
4490
+ this.e1PromptRaises.get(rec.promptId),
4491
+ this.e1NeedsResolution.has(rec.promptId)
4492
+ )) return false;
4469
4493
  if (!await this.createEncryptedEvent(session, input)) return false;
4470
4494
  } else {
4471
4495
  rec.mobileActionable = false;
@@ -4534,7 +4558,7 @@ var McpServer = class _McpServer {
4534
4558
  const session = this.session;
4535
4559
  if (!session) return;
4536
4560
  const sid = session.sessionId;
4537
- const promptIds = [...this.e1PromptRaises.values()].filter((e) => e.record.sessionId === sid).map((e) => e.record.promptId);
4561
+ const promptIds = [...this.e1PromptRaises.values()].filter((e) => e.record.sessionId === sid && !this.e1NeedsResolution.has(e.record.promptId) && (0, import_codevibe_core5.canRecoverPromptRaise)(e, this.promptPublications.isPublishing(e.record.promptId))).map((e) => e.record.promptId);
4538
4562
  if (promptIds.length === 0) return;
4539
4563
  try {
4540
4564
  const agedOut = await this.appSyncClient.refreshOpenPromptTtl(promptIds);
@@ -4719,6 +4743,9 @@ var McpServer = class _McpServer {
4719
4743
  return last;
4720
4744
  }
4721
4745
  async handlePendingPrompt(state) {
4746
+ await this.promptPublications.run(state.promptId, () => this.publishPendingPrompt(state));
4747
+ }
4748
+ async publishPendingPrompt(state) {
4722
4749
  if (!this.started) return;
4723
4750
  const session = this.getSessionByConversation(state.conversationId);
4724
4751
  if (!session) {
@@ -4728,7 +4755,6 @@ var McpServer = class _McpServer {
4728
4755
  });
4729
4756
  return;
4730
4757
  }
4731
- await this.flushToolActivityAtBoundary(import_codevibe_core5.EventType.INTERACTIVE_PROMPT);
4732
4758
  const e1existing = this.e1PromptRaises.get(state.promptId);
4733
4759
  const e1rec = e1existing ? e1existing.record : this.newE1Raise(session.sessionId, true);
4734
4760
  if (!e1existing) state.promptId = e1rec.promptId;
@@ -4784,12 +4810,10 @@ var McpServer = class _McpServer {
4784
4810
  })
4785
4811
  };
4786
4812
  try {
4813
+ this.stashE1RaiseContent(e1rec.promptId, content, optionsForMobile);
4814
+ await this.flushToolActivityAtBoundary(import_codevibe_core5.EventType.INTERACTIVE_PROMPT);
4815
+ if (this.e1NeedsResolution.has(e1rec.promptId) || this.e1PromptRaises.get(e1rec.promptId)?.record !== e1rec) return;
4787
4816
  if (!await this.createEncryptedEvent(session, input)) return;
4788
- this.stashE1RaiseContent(
4789
- e1rec.promptId,
4790
- content,
4791
- optionsForMobile
4792
- );
4793
4817
  } catch (err) {
4794
4818
  logger.error("createEvent INTERACTIVE_PROMPT failed", {
4795
4819
  promptId: state.promptId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-antigravity-plugin",
3
- "version": "2.0.22",
3
+ "version": "2.0.23",
4
4
  "description": "Control Antigravity 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": {
@@ -48,7 +48,7 @@
48
48
  "node": ">=22.0.0"
49
49
  },
50
50
  "dependencies": {
51
- "@quantiya/codevibe-core": "2.0.20",
51
+ "@quantiya/codevibe-core": "2.0.21",
52
52
  "chokidar": "^5.0.0",
53
53
  "dotenv": "^16.6.1",
54
54
  "express": "^5.1.0",