@quantiya/codevibe-codex-plugin 2.0.50 → 2.0.51

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.
@@ -60818,14 +60818,17 @@ function estimateEntryLines(entry) {
60818
60818
  return 2;
60819
60819
  }
60820
60820
  }
60821
- function capLiveEntries(entries, terminalRows, reservedRows = RESERVED_ROWS) {
60822
- let budget = Math.max(terminalRows - reservedRows, MIN_LIVE_ROWS), activeGateIdx = -1;
60821
+ function forcedKeepIndex(entries) {
60823
60822
  for (let i = entries.length - 1; i >= 0; i--)
60824
- if (entries[i].kind === "gate-prompt") {
60825
- activeGateIdx = i;
60826
- break;
60827
- }
60828
- let keptIndices = /* @__PURE__ */ new Set(), used = 0;
60823
+ if (entries[i].kind === "gate-prompt") return i;
60824
+ return -1;
60825
+ }
60826
+ function forcedKeepRows(entries) {
60827
+ let idx = forcedKeepIndex(entries);
60828
+ return idx === -1 ? 0 : estimateEntryLines(entries[idx]);
60829
+ }
60830
+ function capLiveEntries(entries, terminalRows, reservedRows = RESERVED_ROWS) {
60831
+ let budget = Math.max(terminalRows - reservedRows, MIN_LIVE_ROWS), activeGateIdx = forcedKeepIndex(entries), keptIndices = /* @__PURE__ */ new Set(), used = 0;
60829
60832
  activeGateIdx !== -1 && (keptIndices.add(activeGateIdx), used += estimateEntryLines(entries[activeGateIdx]));
60830
60833
  for (let i = entries.length - 1; i >= 0; i--) {
60831
60834
  if (i === activeGateIdx)
@@ -61051,7 +61054,7 @@ function OrchestrationApp(props) {
61051
61054
  activeGateEntry,
61052
61055
  state.gateActionRecoveryBlocked,
61053
61056
  trackLabelByTaskId
61054
- ), terminalRows = process.stdout.rows ?? 24, FIXED_CHROME_ROWS = 8, teamReserveRows = state.team ? 5 + state.team.tracks.size : 0, taskProgressEntries = [...state.progressByTask?.entries() ?? []], shownTaskProgress = taskProgressEntries.slice(0, MAX_TASK_PROGRESS_LINES), hiddenTaskProgress = taskProgressEntries.length - shownTaskProgress.length, untaskedProgress = taskProgressEntries.length === 0 || state.progress && !state.progress.taskId ? state.progress : null, progressLineCount = shownTaskProgress.length + (untaskedProgress ? 1 : 0), progressReserveRows = Math.max(0, progressLineCount - 1), dropdownFits = terminalRows - FIXED_CHROME_ROWS - teamReserveRows - progressReserveRows >= DROPDOWN_MAX_ROWS + MIN_LIVE_ROWS, dropdownActive = gatePromptMode === null && state.reviewerWizard === null && dropdownFits, dropdownReserveRows = dropdownActive ? DROPDOWN_MAX_ROWS : 0, wizardReserveRows = state.reviewerWizard ? WIZARD_MAX_ROWS : state.implementorWizard ? IMPLEMENTOR_WIZARD_MAX_ROWS : 0, { rendered: cappedNonFinal, hiddenCount } = capLiveEntries(
61057
+ ), terminalRows = process.stdout.rows ?? 24, FIXED_CHROME_ROWS = 8, teamReserveRows = state.team ? 5 + state.team.tracks.size : 0, taskProgressEntries = [...state.progressByTask?.entries() ?? []], shownTaskProgress = taskProgressEntries.slice(0, MAX_TASK_PROGRESS_LINES), hiddenTaskProgress = taskProgressEntries.length - shownTaskProgress.length, untaskedProgress = taskProgressEntries.length === 0 || state.progress && !state.progress.taskId ? state.progress : null, progressLineCount = shownTaskProgress.length + (untaskedProgress ? 1 : 0), progressReserveRows = Math.max(0, progressLineCount - 1), gateCardReserveRows = forcedKeepRows(nonFinal), dropdownFits = terminalRows - FIXED_CHROME_ROWS - teamReserveRows - progressReserveRows - gateCardReserveRows >= DROPDOWN_MAX_ROWS + MIN_LIVE_ROWS, dropdownActive = state.reviewerWizard === null && dropdownFits, dropdownReserveRows = dropdownActive ? DROPDOWN_MAX_ROWS : 0, wizardReserveRows = state.reviewerWizard ? WIZARD_MAX_ROWS : state.implementorWizard ? IMPLEMENTOR_WIZARD_MAX_ROWS : 0, { rendered: cappedNonFinal, hiddenCount } = capLiveEntries(
61055
61058
  nonFinal,
61056
61059
  terminalRows,
61057
61060
  FIXED_CHROME_ROWS + teamReserveRows + progressReserveRows + dropdownReserveRows + wizardReserveRows
@@ -61244,11 +61247,22 @@ ${formatImplementorPolicy(detected, updated, props.tier)}`
61244
61247
  onCancel: props.onCancel,
61245
61248
  placeholder: "Ask CodeVibe to build, or /help",
61246
61249
  gatePromptMode,
61247
- // Offer autocomplete ONLY when the conversation is quiet (no streaming
61248
- // task AND no pinned gate-prompt card) — Stage-1 MEDIUM + Stage-2 #469.
61249
- // The matching DROPDOWN_MAX_ROWS reserve above guarantees it always fits.
61250
+ // Offer autocomplete whenever it FITS — the height budget above is the
61251
+ // only gate (Stage-1 MEDIUM + Stage-2 #469; P46b §3.7 dropped the
61252
+ // streaming-task condition, FU-13 the pinned-gate one, each replaced by
61253
+ // rows in that budget). The matching DROPDOWN_MAX_ROWS reserve above
61254
+ // guarantees an open dropdown always fits.
61250
61255
  slashCommands: dropdownActive ? slashCommands : NO_SLASH_COMMANDS,
61251
- mentionSuggestions: dropdownActive ? mentionSuggestions : NO_MENTION_SUGGESTIONS
61256
+ // Mentions do NOT simply ride the same flag (Stage-1 r1 R1-F2). Slash
61257
+ // commands have an escape hatch out of a gate — `doSubmit` routes any
61258
+ // `/`-prefixed line to the shell router before the digit check — but
61259
+ // `awaiting-number` discards everything else with "Please type a number
61260
+ // 1..N". Offering an `@` completion there would be a dead end: the user
61261
+ // picks a mention, presses Enter, and the text is thrown away. So the
61262
+ // mention list stays suppressed for that one mode. `awaiting-notes` is
61263
+ // different — non-`/` text becomes the notes — so mentions are useful
61264
+ // there and are offered.
61265
+ mentionSuggestions: dropdownActive && gatePromptMode?.kind !== "awaiting-number" ? mentionSuggestions : NO_MENTION_SUGGESTIONS
61252
61266
  }),
61253
61267
  // [TUI re-render fix #469] Layout reorder — the status chrome moves BELOW
61254
61268
  // the InputBar so the changing status panel does not push the live region
@@ -116,8 +116,10 @@ export interface InputBarProps {
116
116
  /**
117
117
  * TUI redesign (2026-06-29) — the tier-filtered slash catalog for
118
118
  * autocomplete (built by the parent via `listSlashCommands(tier)`). Absent /
119
- * empty (CP-1.a callers, or the parent suppressing the dropdown while a task
120
- * streams / a gate is pinned) no dropdown.
119
+ * empty (CP-1.a callers, or the parent's height budget leaving no room) → no
120
+ * dropdown. A streaming task and a pinned gate card no longer suppress it —
121
+ * both were replaced by rows in that budget (P46b §3.7 and FU-13); see
122
+ * `dropdownActive` in `OrchestrationApp.tsx`.
121
123
  */
122
124
  slashCommands?: SlashCommandInfo[];
123
125
  /**
@@ -4,17 +4,6 @@ import { ConversationEntry, PostDecisionAction, Tier } from '../types';
4
4
  import type { PlannerRuntimeKind } from '../status-format';
5
5
  import type { UpdateReviewerPolicyInput, UserReviewerPolicySnapshot } from '../../types/reviewer';
6
6
  import { type ApplyUserDecisionClient as SharedApplyUserDecisionClient, type GroupDecisionSubmitDeps } from '../gate-decision-submit';
7
- /**
8
- * Stable empty list passed to <InputBar> to SUPPRESS slash autocomplete unless
9
- * it fits (Stage-1 MEDIUM + Stage-2 — #469): the dropdown lives in the live
10
- * region below the input, so an open dropdown while the live region is tall
11
- * could push total output over the terminal height and re-trigger Ink's
12
- * whole-scrollback reprint. P46b §3.7 — the dropdown is offered while tasks run
13
- * (progress lines no longer suppress it); a pinned gate-prompt card or the
14
- * reviewer wizard still does, and while it can be open we reserve
15
- * DROPDOWN_MAX_ROWS plus every progress line beyond the first in the height cap
16
- * (below) so it always fits. Module-scope constant → stable identity.
17
- */
18
7
  /** P46b §3.7 — at most this many per-task progress lines render (`+n more` after). */
19
8
  export declare const MAX_TASK_PROGRESS_LINES = 3;
20
9
  /**
@@ -42,6 +42,17 @@ export declare const MIN_LIVE_ROWS = 6;
42
42
  * - default → 2
43
43
  */
44
44
  export declare function estimateEntryLines(entry: ConversationEntry): number;
45
+ /**
46
+ * Rows the live region must spend no matter how small the budget gets: the
47
+ * force-kept gate card's height, or 0 when none is pinned.
48
+ *
49
+ * A caller sizing OTHER chrome against the live budget (the slash-autocomplete
50
+ * dropdown in `OrchestrationApp.tsx`) has to subtract this first. Every other
51
+ * live entry yields to the budget, so the generic
52
+ * `budget = max(rows − reserve, MIN_LIVE_ROWS)` already bounds them; the forced
53
+ * entry does not yield, and is the only way the live region can exceed budget.
54
+ */
55
+ export declare function forcedKeepRows(entries: ConversationEntry[]): number;
45
56
  export interface CapLiveEntriesResult {
46
57
  /** The kept entries, in their ORIGINAL order. */
47
58
  rendered: ConversationEntry[];
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "2.0.43",
3
+ "version": "2.0.44",
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.50",
3
+ "version": "2.0.51",
4
4
  "description": "Control OpenAI Codex CLI from your iPhone and Android \u2014 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.43",
50
+ "@quantiya/codevibe-core": "^2.0.44",
51
51
  "@quantiya/quorum-core": "^1.0.1",
52
52
  "chokidar": "^4.0.0",
53
53
  "dotenv": "^16.6.1",