@quantiya/codevibe-antigravity-plugin 2.0.81 → 2.0.83

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/agy-hook.js CHANGED
@@ -97,7 +97,9 @@ function buildBody(raw) {
97
97
  const kept = {};
98
98
  for (const key of FORWARDED_TOOL_ARG_KEYS) {
99
99
  const value = source[key];
100
- if (typeof value === "string") kept[key] = value.slice(0, MAX_TOOL_ARG_CHARS);
100
+ if (typeof value === "string") {
101
+ kept[key] = value.slice(0, MAX_TOOL_ARG_CHARS);
102
+ }
101
103
  }
102
104
  body.toolArgs = kept;
103
105
  }
@@ -230,8 +232,9 @@ function finishProcess() {
230
232
  process.exit(0);
231
233
  }
232
234
  if (require.main === module) {
233
- setTimeout(finishProcess, HARD_DEADLINE_MS);
234
- runHook({ event: process.argv[2], env: process.env, stdin: process.stdin }).then(finishProcess, finishProcess);
235
+ const exitHandler = () => finishProcess();
236
+ setTimeout(exitHandler, HARD_DEADLINE_MS);
237
+ runHook({ event: process.argv[2], env: process.env, stdin: process.stdin }).then(exitHandler, exitHandler);
235
238
  }
236
239
  // Annotate the CommonJS export names for ESM import in node:
237
240
  0 && (module.exports = {
package/dist/server.js CHANGED
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/server.ts
31
31
  var server_exports = {};
32
32
  __export(server_exports, {
33
+ ApprovalDetector: () => ApprovalDetector,
33
34
  McpServer: () => McpServer,
34
35
  SessionNotFoundError: () => SessionNotFoundError,
35
36
  StoredAuthFailureError: () => StoredAuthFailureError,
@@ -47,13 +48,15 @@ __export(server_exports, {
47
48
  isAgyStatusFooterLine: () => isAgyStatusFooterLine,
48
49
  isComposedStatusFooter: () => isComposedStatusFooter,
49
50
  isPaneInputSafetyBlocked: () => isPaneInputSafetyBlocked,
51
+ isQuestionFooterLine: () => isQuestionFooterLine,
50
52
  isSystemErrorActiveFromIndex: () => isSystemErrorActiveFromIndex,
51
53
  looksLikePromptSnapshot: () => looksLikePromptSnapshot,
52
54
  parseApprovalSnapshot: () => parseApprovalSnapshot,
53
55
  parseMaybeJson: () => parseMaybeJson,
54
56
  readTranscriptFirstType: () => readTranscriptFirstType,
55
57
  reconstructFooter: () => reconstructFooter,
56
- runForeignSpawnIdle: () => runForeignSpawnIdle
58
+ runForeignSpawnIdle: () => runForeignSpawnIdle,
59
+ safeIsoTimestamp: () => safeIsoTimestamp
57
60
  });
58
61
  module.exports = __toCommonJS(server_exports);
59
62
  var crypto3 = __toESM(require("crypto"));
@@ -2982,7 +2985,7 @@ function isPaneInputSafetyBlocked(input) {
2982
2985
  if (inInnerFence) {
2983
2986
  continue;
2984
2987
  }
2985
- if (isAgyStatusFooterLine(trimmed) || /^\s*(?:[❯>]\s*)?\?\s+for\s+(?:shortcuts|help)\b/i.test(trimmed) || isComposerBoxAt(lines, j)) {
2988
+ if (isAgyStatusFooterLine(trimmed) || /^\s*(?:[❯>]\s*)?\?\s+for\s+(?:shortcuts|help)\b/i.test(trimmed) || isComposerBoxAt(lines, j) || optCount > 0 && isResumedTurnSignal(trimmed)) {
2986
2989
  composerEncountered = true;
2987
2990
  break;
2988
2991
  }
@@ -3055,7 +3058,7 @@ function isPaneInputSafetyBlocked(input) {
3055
3058
  if (inInnerFence) {
3056
3059
  continue;
3057
3060
  }
3058
- if (isAgyStatusFooterLine(trimmed) || /^\s*(?:[❯>]\s*)?\?\s+for\s+(?:shortcuts|help)\b/i.test(trimmed) || isComposerBoxAt(lines, j)) {
3061
+ if (isAgyStatusFooterLine(trimmed) || /^\s*(?:[❯>]\s*)?\?\s+for\s+(?:shortcuts|help)\b/i.test(trimmed) || isComposerBoxAt(lines, j) || optCount > 0 && isResumedTurnSignal(trimmed)) {
3059
3062
  composerEncountered = true;
3060
3063
  break;
3061
3064
  }
@@ -3200,6 +3203,11 @@ function computeFenceMask(lines) {
3200
3203
  }
3201
3204
  return inFence;
3202
3205
  }
3206
+ function isResumedTurnSignal(line) {
3207
+ if (!line) return false;
3208
+ const trimmed = line.trim();
3209
+ return /^[❯>]\s+(?![1-9][.)\]])\S/.test(trimmed) || /^[▶▸○]\s*Thought\b/i.test(trimmed) || /^(?:[\u2800-\u28FF]\s*)?Working(?:\.\.\.)?\s*$/i.test(trimmed) || /^●\s+(?:Ran|Run|Running|Execute|Executing|Completed|Explored|Exploring|Read|Reading|Wrote|Writing|Edited|Editing|Created|Creating|Updated|Updating|Deleted|Deleting|Fetched|Fetching|Searched|Searching)\b/i.test(trimmed) || /^●.*\(ctrl\+[a-z0-9]+\s+to\s+(?:expand|view)\)/i.test(trimmed);
3210
+ }
3203
3211
  function hasTrailingAgyComposer(lines, afterLineIdx, fenceMask) {
3204
3212
  if (afterLineIdx < -1 || afterLineIdx >= lines.length - 1) return false;
3205
3213
  const trailingLines = [];
@@ -3224,9 +3232,21 @@ function hasTrailingAgyComposer(lines, afterLineIdx, fenceMask) {
3224
3232
  }
3225
3233
  }
3226
3234
  }
3227
- if (trailingLines.some((l) => isAgyStatusFooterLine(l) && /(?:Gemini|Flash|Pro|Claude|Sonnet|Opus|GPT|auto|high|low|medium)/i.test(l))) {
3235
+ if (trailingLines.some((l) => isResumedTurnSignal(l))) {
3228
3236
  return true;
3229
3237
  }
3238
+ const hasStatusLine = trailingLines.some(
3239
+ (l) => isAgyStatusFooterLine(l) && /(?:Gemini|Flash|Pro|Claude|Sonnet|Opus|GPT|auto|high|low|medium)/i.test(l)
3240
+ );
3241
+ if (hasStatusLine) {
3242
+ const nonDecorativeNonStatus = trailingLines.filter(
3243
+ (l) => !isAgyStatusFooterLine(l) && !isQuestionFooterLine(l) && !/^[─━│╭╰╮╯\s_-]{3,}$/.test(l)
3244
+ );
3245
+ if (nonDecorativeNonStatus.length > 0) {
3246
+ return true;
3247
+ }
3248
+ return false;
3249
+ }
3230
3250
  return false;
3231
3251
  }
3232
3252
  function reconstructFooter(rawLines) {
@@ -3405,7 +3425,13 @@ function looksLikePromptSnapshot(snapshot) {
3405
3425
  let footerIdx = lastOptionIdx;
3406
3426
  if (!hasQuestionFooter) {
3407
3427
  for (let i = lastOptionIdx + 1; i < allLines.length; i++) {
3408
- if (!fenceMask[i] && isQuestionFooterLine(allLines[i].trim())) {
3428
+ if (fenceMask[i]) continue;
3429
+ const trimmed = allLines[i].trim();
3430
+ if (!trimmed) continue;
3431
+ if (isResumedTurnSignal(trimmed)) {
3432
+ break;
3433
+ }
3434
+ if (isQuestionFooterLine(trimmed)) {
3409
3435
  hasQuestionFooter = true;
3410
3436
  footerIdx = i;
3411
3437
  break;
@@ -3742,6 +3768,9 @@ function detectActivePromptKind(snapshot) {
3742
3768
  for (let j = lastSystemErrorLineIdx + 1; j < lines.length; j++) {
3743
3769
  if (!lineInFence[j]) {
3744
3770
  const trimmed = lines[j].trim();
3771
+ if (hasQuestionOptions && isResumedTurnSignal(trimmed)) {
3772
+ break;
3773
+ }
3745
3774
  if (/^[>\s❯]*[1-9][.)]\s+\S/.test(trimmed)) {
3746
3775
  hasQuestionOptions = true;
3747
3776
  promptEndIdx = j;
@@ -3784,12 +3813,20 @@ function detectActivePromptKind(snapshot) {
3784
3813
  }
3785
3814
  if (latestChooserIdx === lastQuestionLineIdx) {
3786
3815
  let promptEndIdx = lastQuestionLineIdx;
3816
+ let hasFoundOptions = false;
3787
3817
  for (let j = lastQuestionLineIdx + 1; j < lines.length; j++) {
3788
3818
  if (!lineInFence[j]) {
3789
- if (isAgyStatusFooterLine(lines[j].trim()) || /^\s*(?:[❯>]\s*)?\?\s+for\s+(?:shortcuts|help)\b/i.test(lines[j].trim()) || isComposerBoxAt(lines, j)) {
3819
+ const trimmed = lines[j].trim();
3820
+ if (isAgyStatusFooterLine(trimmed) || /^\s*(?:[❯>]\s*)?\?\s+for\s+(?:shortcuts|help)\b/i.test(trimmed) || isComposerBoxAt(lines, j)) {
3790
3821
  break;
3791
3822
  }
3792
- if (/^[>\s❯]*[1-9][.)]\s+\S/.test(lines[j].trim()) || isQuestionFooterLine(lines[j])) {
3823
+ if (hasFoundOptions && isResumedTurnSignal(trimmed)) {
3824
+ break;
3825
+ }
3826
+ if (/^[>\s❯]*[1-9][.)]\s+\S/.test(trimmed)) {
3827
+ hasFoundOptions = true;
3828
+ promptEndIdx = j;
3829
+ } else if (isQuestionFooterLine(lines[j])) {
3793
3830
  promptEndIdx = j;
3794
3831
  }
3795
3832
  }
@@ -4168,7 +4205,7 @@ function isQuestionFooterLine(line) {
4168
4205
  }
4169
4206
  if (/^[>\s❯]*[1-9][.)]\s+\S/.test(trimmed)) return false;
4170
4207
  if (isQuestionHeaderLine(trimmed)) return false;
4171
- return /^(?:esc|<esc>)\s+(?:to\s+)?(?:cancel|skip)(?:\s*[·│,]\s*(?:enter|<enter>)\s+(?:to\s+)?select)?$/i.test(trimmed) || /^(?:enter|<enter>)\s+(?:to\s+)?select(?:\s*[·│,]\s*(?:esc|<esc>)\s+(?:to\s+)?(?:cancel|skip))?$/i.test(trimmed) || /^(?:↑\/↓|↑|↓|\^|v)\s*(?:\/|\s+)?Navigate(?:\s*[·│,]\s*(?:enter|<enter>)?\s*(?:Select|to select))?(?:\s*[·│,]\s*(?:esc|<esc>)?\s*(?:Skip|Cancel))?$/i.test(trimmed) || /^press\s+<?(?:enter|return|space)>?\s+to\s+select$/i.test(trimmed) || /^space\s+to\s+select$/i.test(trimmed) || /^(?:\(?use\s+arrow\s+keys(?:\s+to\s+navigate)?\)?)$/i.test(trimmed) || /^waiting(?:\.\.\.)?$/i.test(trimmed);
4208
+ return /^(?:esc|<esc>)\s+(?:to\s+)?(?:cancel|skip)(?:\s*[·│,]\s*(?:enter|<enter>)\s+(?:to\s+)?select)?(?:\s*[·│,]\s*ctrl\+[a-z0-9]+\s+[a-zA-Z]+)*$/i.test(trimmed) || /^(?:enter|<enter>)\s+(?:to\s+)?select(?:\s*[·│,]\s*(?:esc|<esc>)\s+(?:to\s+)?(?:cancel|skip))?(?:\s*[·│,]\s*ctrl\+[a-z0-9]+\s+[a-zA-Z]+)*$/i.test(trimmed) || /^(?:↑\/↓|↑|↓|\^|v)\s*(?:\/|\s+)?Navigate(?:\s*[·│,]\s*(?:enter|<enter>)?\s*(?:Select|to select))(?:\s*[·│,]\s*(?:esc|<esc>)?\s*(?:Skip|Cancel))?(?:\s*[·│,]\s*ctrl\+[a-z0-9]+\s+[a-zA-Z]+)*$/i.test(trimmed) || /^(?:↑\/↓|↑|↓|\^|v)\s*(?:\/|\s+)?Navigate(?:\s*[·│,]\s*(?:esc|<esc>)?\s*(?:Skip|Cancel))?$/i.test(trimmed) || /^press\s+<?(?:enter|return|space)>?\s+to\s+select$/i.test(trimmed) || /^space\s+to\s+select$/i.test(trimmed) || /^(?:\(?use\s+arrow\s+keys(?:\s+to\s+navigate)?\)?)$/i.test(trimmed) || /^(?:[\u2800-\u28FF]+(?:\s*waiting(?:\.\.\.)?)?|waiting(?:\.\.\.)?)$/i.test(trimmed);
4172
4209
  }
4173
4210
  function extractQuestionHeader(snapshot) {
4174
4211
  const stripped = snapshot.replace(ANSI_ESCAPE_REGEX, "");
@@ -4339,8 +4376,33 @@ function parseQuestionSnapshot(stripped, originalSnapshot, header) {
4339
4376
  const options = parseOptions(belowHeader);
4340
4377
  if (options.length < 2) return null;
4341
4378
  const normalizedHeader = header.fullLine.replace(/^[❯>\s*•-]+\s*/, "").trim();
4342
- const hasArrowKeyHint = /\((?:Use\s+arrow\s+keys|Use\s+\S+\s+keys)[^)]*\)/i.test(normalizedHeader);
4343
- const isBaseNumberedWizard = /^Question\s+\d+\/\d+:/i.test(normalizedHeader) && !hasArrowKeyHint;
4379
+ const headerHasArrowHint = /\((?:Use\s+arrow\s+keys|Use\s+\S+\s+keys)[^)]*\)/i.test(normalizedHeader);
4380
+ let footerHasArrowHint = false;
4381
+ let footerHasCtrlRReview = false;
4382
+ const startLine = headerIdx >= 0 ? headerIdx + 1 : 0;
4383
+ let hasSeenOptions = false;
4384
+ for (let i = startLine; i < lines.length; i++) {
4385
+ if (lineInFence[i]) continue;
4386
+ const trimmed = lines[i].trim();
4387
+ if (!trimmed) continue;
4388
+ if (hasSeenOptions && isResumedTurnSignal(trimmed)) break;
4389
+ if (/^[>\s❯]*[1-9][.)]\s+\S/.test(trimmed)) {
4390
+ hasSeenOptions = true;
4391
+ }
4392
+ const isFooter = isQuestionFooterLine(trimmed) || /^(?:ctrl\+[a-z0-9]+\s+[a-zA-Z]+|\(?use\s+arrow\s+keys(?:\s+to\s+navigate)?\)?)$/i.test(trimmed);
4393
+ if (isFooter) {
4394
+ if (/(?:↑\/↓|↑|↓|\^|v)\s*(?:\/|\s+)?Navigate\b/i.test(trimmed) || /\(?use\s+arrow\s+keys(?:\s+to\s+navigate)?\)?/i.test(trimmed)) {
4395
+ footerHasArrowHint = true;
4396
+ }
4397
+ if (/ctrl\+r\s+Review\b/i.test(trimmed)) {
4398
+ footerHasCtrlRReview = true;
4399
+ }
4400
+ }
4401
+ }
4402
+ const hasArrowKeyHint = headerHasArrowHint || footerHasArrowHint;
4403
+ const hasWriteInOption = options.some((opt) => /^\s*write-?in\b/i.test(opt.text));
4404
+ const hasCtrlRReviewFooter = footerHasCtrlRReview;
4405
+ const isBaseNumberedWizard = /^Question\s+\d+\/\d+:/i.test(normalizedHeader) && !hasArrowKeyHint && !hasWriteInOption && !hasCtrlRReviewFooter;
4344
4406
  const submitMap = isBaseNumberedWizard ? buildQuestionSubmitMap(options) : {};
4345
4407
  const body = extractBodyBetweenHeaderAndFirstOption(belowHeader);
4346
4408
  return {
@@ -4403,7 +4465,9 @@ function buildApprovalSubmitMap(options) {
4403
4465
  function buildQuestionSubmitMap(options) {
4404
4466
  const map = {};
4405
4467
  for (const opt of options) {
4406
- map[opt.number] = [opt.number, "Enter"];
4468
+ if (!/^\s*write-?in\b/i.test(opt.text)) {
4469
+ map[opt.number] = [opt.number, "Enter"];
4470
+ }
4407
4471
  }
4408
4472
  return map;
4409
4473
  }
@@ -4586,23 +4650,31 @@ var ApprovalDetector = class extends import_events3.EventEmitter {
4586
4650
  return null;
4587
4651
  }
4588
4652
  const promptId = forcedPromptId ?? (0, import_uuid.v4)();
4653
+ const matchingCall = candidate.kind === "question" ? this.findMatchingPendingCall(candidate, conversationId) : null;
4654
+ if (matchingCall) {
4655
+ matchingCall.matchedPromptId = promptId;
4656
+ }
4589
4657
  const syntheticCall = {
4590
4658
  conversationId,
4591
- intentStepIndex: -1,
4659
+ intentStepIndex: matchingCall?.intentStepIndex ?? -1,
4592
4660
  // sentinel: "no transcript origin"
4593
- toolCallIndex: 0,
4594
- intentByteOffset: 0,
4661
+ toolCallIndex: matchingCall?.toolCallIndex ?? 0,
4662
+ intentByteOffset: matchingCall?.intentByteOffset ?? 0,
4595
4663
  // Best-effort tool-type inference from the candidate. For shell
4596
4664
  // commands → RUN_COMMAND. For edit-style headers with a file
4597
4665
  // path → CODE_ACTION. For questions → ASK_QUESTION. Default: GENERIC.
4598
- toolType: guessToolTypeFromIdentity(candidate),
4599
- command: candidate.command,
4600
- filePath: candidate.filePath,
4601
- rawToolName: candidate.kind === "question" ? "ask_question" : candidate.command ?? candidate.filePath ?? "unknown",
4602
- questionText: candidate.kind === "question" ? candidate.headerText : void 0,
4666
+ toolType: matchingCall?.toolType ?? guessToolTypeFromIdentity(candidate),
4667
+ command: matchingCall?.command ?? candidate.command,
4668
+ filePath: matchingCall?.filePath ?? candidate.filePath,
4669
+ rawToolName: matchingCall?.rawToolName ?? (candidate.kind === "question" ? "ask_question" : candidate.command ?? candidate.filePath ?? "unknown"),
4670
+ questionText: candidate.kind === "question" && candidate.headerText ? candidate.headerText : matchingCall?.questionText,
4671
+ // NOTE (Codex R3-F1 / Claude R3-F2): Pane options are authoritative ground truth
4672
+ // that directly correspond to desktop keystrokes (submitMap). Transcript options
4673
+ // serve solely as fallback when pane options cannot be parsed.
4674
+ questionOptions: candidate.kind === "question" && candidate.options && candidate.options.length > 0 ? candidate.options : matchingCall?.questionOptions,
4603
4675
  promptId,
4604
- startedAt: Date.now(),
4605
- intentCreatedAt: (/* @__PURE__ */ new Date()).toISOString()
4676
+ startedAt: matchingCall?.startedAt ?? Date.now(),
4677
+ intentCreatedAt: matchingCall?.intentCreatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
4606
4678
  };
4607
4679
  const state = {
4608
4680
  promptId,
@@ -4896,6 +4968,11 @@ var ApprovalDetector = class extends import_events3.EventEmitter {
4896
4968
  if (state.pendingCall.promptId === promptId) {
4897
4969
  state.pendingCall.promptId = void 0;
4898
4970
  }
4971
+ for (const call of this.pendingCalls.values()) {
4972
+ if (call.matchedPromptId === promptId) {
4973
+ call.matchedPromptId = void 0;
4974
+ }
4975
+ }
4899
4976
  this.paneOnlyEmittedHashes.clear();
4900
4977
  return state;
4901
4978
  }
@@ -4922,7 +4999,11 @@ var ApprovalDetector = class extends import_events3.EventEmitter {
4922
4999
  }
4923
5000
  findMatchingPendingCall(candidate, conversationId) {
4924
5001
  if (candidate.kind === "question") {
4925
- const questionCalls = Array.from(this.pendingCalls.values()).filter((c) => c.conversationId === conversationId).filter(
5002
+ const questionCalls = Array.from(this.pendingCalls.values()).filter((c) => c.conversationId === conversationId).filter((c) => c.resultStepIndex === void 0).filter((c) => {
5003
+ const associatedPromptId = c.matchedPromptId || c.promptId;
5004
+ if (!associatedPromptId) return true;
5005
+ return !this.resolvedPrompts.has(associatedPromptId) && !this.pendingPrompts.has(associatedPromptId);
5006
+ }).filter(
4926
5007
  (c) => c.toolType === "ASK_QUESTION" || c.rawToolName?.toLowerCase() === "ask_question"
4927
5008
  ).sort((a, b) => a.intentStepIndex - b.intentStepIndex);
4928
5009
  if (questionCalls.length > 0 && candidate.headerText) {
@@ -5642,6 +5723,7 @@ function mapTranscriptEvent(emit, sessionId, notBeforeMs) {
5642
5723
  command: extractCommandFromArgs(name, args),
5643
5724
  filePath: extractFilePathFromArgs(name, args),
5644
5725
  questionText: extractQuestionFromArgs(name, args),
5726
+ questionOptions: extractQuestionOptionsFromArgs(name, args),
5645
5727
  cwd: extractCwdFromArgs(args),
5646
5728
  rawToolName: name,
5647
5729
  startedAt: Date.now(),
@@ -5793,8 +5875,15 @@ function extractQuestionFromArgs(toolName, args) {
5793
5875
  if (typeof a.prompt === "string" && a.prompt.trim().length > 0) {
5794
5876
  return stripWrappingQuotes2(a.prompt.trim());
5795
5877
  }
5796
- if (Array.isArray(a.questions) && a.questions.length > 0) {
5797
- const first = a.questions[0];
5878
+ let questions = a.questions;
5879
+ if (typeof questions === "string") {
5880
+ try {
5881
+ questions = JSON.parse(questions.trim());
5882
+ } catch {
5883
+ }
5884
+ }
5885
+ if (Array.isArray(questions) && questions.length > 0) {
5886
+ const first = questions[0];
5798
5887
  if (typeof first === "string" && first.trim().length > 0) {
5799
5888
  return stripWrappingQuotes2(first.trim());
5800
5889
  }
@@ -5807,6 +5896,40 @@ function extractQuestionFromArgs(toolName, args) {
5807
5896
  }
5808
5897
  return void 0;
5809
5898
  }
5899
+ function extractQuestionOptionsFromArgs(toolName, args) {
5900
+ if (!args || typeof args !== "object") return void 0;
5901
+ const tn = (toolName || "").toLowerCase().trim();
5902
+ const isQuestionTool = tn === "ask_question" || tn === "question" || tn === "ask";
5903
+ if (!isQuestionTool) return void 0;
5904
+ const a = args;
5905
+ let questions = a.questions;
5906
+ if (typeof questions === "string") {
5907
+ try {
5908
+ questions = JSON.parse(questions.trim());
5909
+ } catch {
5910
+ }
5911
+ }
5912
+ if (Array.isArray(questions) && questions.length > 0) {
5913
+ const first = questions[0];
5914
+ if (first && typeof first === "object" && Array.isArray(first.options)) {
5915
+ const rawOptions = first.options;
5916
+ const result = [];
5917
+ for (let i = 0; i < rawOptions.length; i++) {
5918
+ const opt = rawOptions[i];
5919
+ if (typeof opt === "string" && opt.trim().length > 0) {
5920
+ result.push({ number: String(i + 1), text: stripWrappingQuotes2(opt.trim()) });
5921
+ } else if (opt && typeof opt === "object" && typeof opt.text === "string") {
5922
+ result.push({
5923
+ number: String(opt.number ?? i + 1),
5924
+ text: stripWrappingQuotes2(String(opt.text).trim())
5925
+ });
5926
+ }
5927
+ }
5928
+ if (result.length > 0) return result;
5929
+ }
5930
+ }
5931
+ return void 0;
5932
+ }
5810
5933
  function extractCwdFromArgs(args) {
5811
5934
  if (!args || typeof args !== "object") return void 0;
5812
5935
  const a = args;
@@ -5912,6 +6035,15 @@ function friendlyHookToolName(rawName, resultType) {
5912
6035
  return transcriptTypeToFriendlyToolName(resultType);
5913
6036
  }
5914
6037
  }
6038
+ function safeIsoTimestamp(rawTimestamp) {
6039
+ if (typeof rawTimestamp === "string" && rawTimestamp.trim().length > 0) {
6040
+ const parsed = Date.parse(rawTimestamp);
6041
+ if (!Number.isNaN(parsed)) {
6042
+ return new Date(parsed).toISOString();
6043
+ }
6044
+ }
6045
+ return (/* @__PURE__ */ new Date()).toISOString();
6046
+ }
5915
6047
  function commandTarget(command) {
5916
6048
  return command?.trim().split(/\s+/)[0] || void 0;
5917
6049
  }
@@ -5998,7 +6130,7 @@ var AgyToolActivityIntegration = class {
5998
6130
  id: agyOccurrenceId(emit, matchedCall),
5999
6131
  tool: friendlyHookToolName(matchedCall?.rawToolName, resultType),
6000
6132
  ...target ? { normalizedTarget: target } : {},
6001
- ts: emit.event.created_at,
6133
+ ts: safeIsoTimestamp(emit.event.created_at),
6002
6134
  byteOffset: emit.byteOffset,
6003
6135
  ...inputIdentity ? { digest: (0, import_codevibe_core6.digestOf)(inputIdentity) } : {}
6004
6136
  });
@@ -8153,7 +8285,8 @@ var McpServer = class _McpServer {
8153
8285
  const e1existing = this.e1PromptRaises.get(state.promptId);
8154
8286
  const e1rec = e1existing ? e1existing.record : this.newE1Raise(session.sessionId, !isDisplayOnly);
8155
8287
  if (!e1existing) state.promptId = e1rec.promptId;
8156
- const optionsArr = isDisplayOnly ? [] : state.paneOptions ? state.paneOptions.map((o) => ({ number: o.number, text: o.text })) : Object.keys(state.submitMap).map((n) => ({ number: n }));
8288
+ const resolvedOptions = state.paneOptions && state.paneOptions.length > 0 ? state.paneOptions : state.pendingCall?.questionOptions && state.pendingCall.questionOptions.length > 0 ? state.pendingCall.questionOptions : void 0;
8289
+ const optionsArr = isDisplayOnly ? [] : resolvedOptions ? resolvedOptions.map((o) => ({ number: o.number, text: o.text })) : Object.keys(state.submitMap).map((n) => ({ number: n }));
8157
8290
  const diffParsed = parseFencedDiffFromBody(
8158
8291
  state.body,
8159
8292
  state.paneDisplayHeader
@@ -8183,7 +8316,14 @@ var McpServer = class _McpServer {
8183
8316
  command: state.pendingCall.command,
8184
8317
  file_path: filePath,
8185
8318
  options: optionsArr,
8186
- ...toolInput ? { tool_input: toolInput } : {}
8319
+ ...toolInput ? { tool_input: toolInput } : {},
8320
+ ...state.kind === "question" && resolvedOptions && resolvedOptions.length > 0 ? {
8321
+ questions: [{
8322
+ question: state.pendingCall?.questionText || state.matchedPaneHeader || state.paneDisplayHeader || "Question",
8323
+ options: resolvedOptions,
8324
+ ...isDisplayOnly ? { instructions: "Answer this question in your desktop terminal" } : {}
8325
+ }]
8326
+ } : {}
8187
8327
  } : { promptId: state.promptId };
8188
8328
  const content = state.paneDisplayHeader || state.matchedPaneHeader || state.pendingCall?.command || state.pendingCall?.filePath || "approval requested";
8189
8329
  const input = {
@@ -9088,6 +9228,7 @@ var __testing = {
9088
9228
  };
9089
9229
  // Annotate the CommonJS export names for ESM import in node:
9090
9230
  0 && (module.exports = {
9231
+ ApprovalDetector,
9091
9232
  McpServer,
9092
9233
  SessionNotFoundError,
9093
9234
  StoredAuthFailureError,
@@ -9105,11 +9246,13 @@ var __testing = {
9105
9246
  isAgyStatusFooterLine,
9106
9247
  isComposedStatusFooter,
9107
9248
  isPaneInputSafetyBlocked,
9249
+ isQuestionFooterLine,
9108
9250
  isSystemErrorActiveFromIndex,
9109
9251
  looksLikePromptSnapshot,
9110
9252
  parseApprovalSnapshot,
9111
9253
  parseMaybeJson,
9112
9254
  readTranscriptFirstType,
9113
9255
  reconstructFooter,
9114
- runForeignSpawnIdle
9256
+ runForeignSpawnIdle,
9257
+ safeIsoTimestamp
9115
9258
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-antigravity-plugin",
3
- "version": "2.0.81",
3
+ "version": "2.0.83",
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": {