@quantiya/codevibe-codex-plugin 2.0.49 → 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.
@@ -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
  /**
@@ -328,6 +328,7 @@ export { extractQueryRelevantSnippets, htmlToText } from './web/extract';
328
328
  export { validateAgyArgPrompt, AGY_ARG_PROMPT_MAX_UTF8_BYTES, } from '../agy-cli-contract';
329
329
  export type { Mode, Tier, PlannerDecision, AgentKind, PlannerHealthState, RunningTaskState, ReviewerSeatState, GateState, ExecutionEventEntry, RefusalEventEntry, BypassEventEntry, MobileEventEntry, EventStreamEntry, ConversationEntry, QueuedTask, PendingClarification, OrchestrationState, OrchestrationAction, LastModeFile, TeamState, TeamTrackEntry, TeamTrackState, TeamMergeGateStatus, LiveProgress, } from './types';
330
330
  export { formatElapsed, isSpinnerPhase, renderProgressLine, type TaskProgressEvent, type OnProgress, } from './task-progress';
331
+ export { createTaskProgressRelay, formatMobileProgressMessage, MAX_MOBILE_PROGRESS_MESSAGE_LENGTH, type TaskProgressRelay, type TaskProgressRelayDeps, } from './task-progress-relay';
331
332
  export { runDeclaredTestSurfaces, DECLARED_TEST_TIMEOUT_MS, type DeclaredTestResult, type DeclaredTestReason, type RunDeclaredTestSurfacesArgs, } from './declared-test-runner';
332
333
  export { QuorumLoop, type QuorumLoopDeps } from './quorum-loop';
333
334
  /**
@@ -619,6 +620,7 @@ export declare function routeReadOnlyAgentMention(args: {
619
620
  promptText?: string;
620
621
  promptOrigin?: 'desktop' | 'mobile';
621
622
  mobilePromptEventId?: string;
623
+ onProgress?: (event: TaskProgressEvent) => void;
622
624
  }): Promise<boolean>;
623
625
  /**
624
626
  * PHASE-590 §3.D step 0 / §4.4 — compose the LOSSLESS implementation brief.
@@ -767,6 +769,7 @@ export declare function routeTeamDecompose(deps: {
767
769
  singleFallbackBrief?: string;
768
770
  /** Stage-2 R3 HIGH — the loop's durable store, so the live launch persists the retained spec + attachments. */
769
771
  durableStore?: RevertManifestStore;
772
+ onProgress?: (event: TaskProgressEvent) => void;
770
773
  }): Promise<void>;
771
774
  /**
772
775
  * Shared helper for handling LaunchTeamOutcome for both unconfirmed (auto-launch)
@@ -852,6 +855,7 @@ export declare function routeFamiliarize(deps: {
852
855
  ensureFreshContextStoreFn?: typeof ensureFreshContextStore;
853
856
  /** Current user turn, used only for the local familiarization advisory prompt. */
854
857
  userPrompt?: string;
858
+ onProgress?: (event: TaskProgressEvent) => void;
855
859
  }): Promise<void>;
856
860
  export declare function routeBrainstorm(deps: {
857
861
  store: OrchestrationStore;
@@ -865,6 +869,7 @@ export declare function routeBrainstorm(deps: {
865
869
  priorTurns?: string[];
866
870
  /** RAW base64 images (IMAGE-ATTACHMENT-DESIGN.md §6) — Ollama-runtime only; text-mode. */
867
871
  images?: string[];
872
+ onProgress?: (event: TaskProgressEvent) => void;
868
873
  }): Promise<void>;
869
874
  /**
870
875
  * The MULTIMODAL image answerer for `advisory_response` + ≥1 attached image
@@ -954,6 +959,7 @@ interface StructuralSummaryRunDeps {
954
959
  args: RunOrchestrationShellArgs;
955
960
  emitShellEventBound: ReturnType<typeof createShellEventEmitter>;
956
961
  generator: StructuralSummaryGenerator;
962
+ onProgress?: (event: TaskProgressEvent) => void;
957
963
  }
958
964
  /**
959
965
  * Test seam — accepts an injected `addBodyPath` so unit tests can drive
@@ -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[];
@@ -2,6 +2,7 @@ import type { OrchestrationStore } from './store';
2
2
  import type { LocalGemmaAdvisoryRunner } from '../planner/local-advisory';
3
3
  import { guardedFetch } from './web/fetch';
4
4
  import { webSearch } from './web/search';
5
+ import type { TaskProgressEvent } from './task-progress';
5
6
  /**
6
7
  * A page the shell read this session, retained (2026-09-12) so a follow-up
7
8
  * ("that sounds like a summary, I am looking for your thoughts") can be answered
@@ -42,6 +43,10 @@ export interface RouteBrowseDeps {
42
43
  header: string;
43
44
  page?: RetainedBrowsePage;
44
45
  }) => Promise<boolean>;
46
+ /** Optional task progress event handler for surfacing real-time status and mobile notifications. */
47
+ onProgress?: (event: TaskProgressEvent) => void;
48
+ /** Optional epoch timestamp for progress events to preserve timer monotonicity across steps. */
49
+ epoch?: number;
45
50
  }
46
51
  /**
47
52
  * Strip leading agent mention tokens, common command/browse noise, redact paths,
@@ -0,0 +1,34 @@
1
+ import type { TaskProgressEvent } from './task-progress';
2
+ import type { ShellEventEmit } from './emit-shell-event';
3
+ export interface TaskProgressRelayDeps {
4
+ emitShellEvent: (args: ShellEventEmit) => Promise<unknown>;
5
+ sessionId: string;
6
+ minIntervalMs?: number;
7
+ }
8
+ export interface TaskProgressRelay {
9
+ relay(event: TaskProgressEvent): Promise<boolean>;
10
+ reset(): void;
11
+ }
12
+ export declare const TERMINAL_MILESTONES: Set<"preparing_workspace" | "shadow_created" | "implementor_running" | "diff_captured" | "submitting_diff" | "reviewers_dispatched" | "seat_update" | "verdicts_progress" | "revise_round" | "round_failed" | "continuation_offered" | "declared_tests_skipped" | "promoting" | "promoted" | "discarding" | "discarded" | "not_applied" | "waiting_user" | "planner_classifying" | "familiarizing" | "agent_advisory" | "web_formulating_query" | "web_searching" | "web_fetching" | "web_synthesizing" | "advisory_dispatched" | "advisory_seat_update" | "advisory_synthesizing" | "familiarize_scanning" | "familiarize_generating" | "brainstorming" | "team_decomposing" | "progress_cleared" | "halt_notice">;
13
+ /**
14
+ * Milestones that must be emitted immediately to mobile without debounce delay.
15
+ * Includes terminal task outcomes, discrete reviewer verdict submissions, and
16
+ * verdict collection progress, ensuring mobile notifications always precede gate prompts.
17
+ */
18
+ export declare function isImmediateMilestone(event: TaskProgressEvent): boolean;
19
+ export declare const MAX_MOBILE_PROGRESS_MESSAGE_LENGTH = 120;
20
+ export declare const DEFAULT_MIN_RELAY_INTERVAL_MS = 2500;
21
+ /**
22
+ * Format the user-facing mobile NOTIFICATION text for a progress event.
23
+ * Returns null if the phase is an internal/silent phase that should not be wired to mobile.
24
+ *
25
+ * HARD ZERO-PLAINTEXT INVARIANT:
26
+ * Never returns file paths, code diffs, prompts, tokens, or query parameters.
27
+ * Only sanitized queries, hostnames, agent names, and bounded counts.
28
+ */
29
+ export declare function formatMobileProgressMessage(event: TaskProgressEvent): string | null;
30
+ /**
31
+ * Creates a rate-limited task progress relay that forwards discrete operational
32
+ * progress milestones as encrypted NOTIFICATION events to AppSync for mobile visibility.
33
+ */
34
+ export declare function createTaskProgressRelay(deps: TaskProgressRelayDeps): TaskProgressRelay;
@@ -80,6 +80,37 @@ export type TaskProgressEvent = ({
80
80
  phase: 'familiarizing';
81
81
  } | {
82
82
  phase: 'agent_advisory';
83
+ } | {
84
+ phase: 'web_formulating_query';
85
+ } | {
86
+ phase: 'web_searching';
87
+ query?: string;
88
+ } | {
89
+ phase: 'web_fetching';
90
+ count?: number;
91
+ url?: string;
92
+ } | {
93
+ phase: 'web_synthesizing';
94
+ } | {
95
+ phase: 'advisory_dispatched';
96
+ agents?: string[];
97
+ } | {
98
+ phase: 'advisory_seat_update';
99
+ agent: string;
100
+ completedCount: number;
101
+ totalCount: number;
102
+ state: 'running' | 'completed' | 'failed';
103
+ } | {
104
+ phase: 'advisory_synthesizing';
105
+ } | {
106
+ phase: 'familiarize_scanning';
107
+ } | {
108
+ phase: 'familiarize_generating';
109
+ agent?: string;
110
+ } | {
111
+ phase: 'brainstorming';
112
+ } | {
113
+ phase: 'team_decomposing';
83
114
  } | {
84
115
  phase: 'progress_cleared';
85
116
  } | {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "2.0.42",
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.49",
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.42",
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",