viberag 0.3.2 → 0.4.0

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 (209) hide show
  1. package/README.md +2 -2
  2. package/dist/cli/app.d.ts +3 -0
  3. package/dist/cli/app.js +100 -102
  4. package/dist/cli/commands/handlers.d.ts +8 -6
  5. package/dist/cli/commands/handlers.js +90 -32
  6. package/dist/cli/commands/useCommands.d.ts +20 -0
  7. package/dist/cli/commands/useCommands.js +189 -0
  8. package/dist/cli/commands/useRagCommands.d.ts +2 -5
  9. package/dist/cli/commands/useRagCommands.js +11 -18
  10. package/dist/cli/components/InitWizard.js +66 -27
  11. package/dist/cli/components/McpSetupWizard.js +23 -4
  12. package/dist/cli/components/SlotRow.d.ts +22 -0
  13. package/dist/cli/components/SlotRow.js +55 -0
  14. package/dist/cli/components/StatusBar.d.ts +14 -0
  15. package/dist/cli/components/StatusBar.js +156 -0
  16. package/dist/cli/contexts/DaemonStatusContext.d.ts +38 -0
  17. package/dist/cli/contexts/DaemonStatusContext.js +106 -0
  18. package/dist/cli/hooks/useStatusPolling.d.ts +34 -0
  19. package/dist/cli/hooks/useStatusPolling.js +121 -0
  20. package/dist/cli/store/app/selectors.d.ts +87 -0
  21. package/dist/cli/store/app/selectors.js +28 -0
  22. package/dist/cli/store/app/slice.d.ts +1013 -0
  23. package/dist/cli/store/app/slice.js +112 -0
  24. package/dist/cli/store/hooks.d.ts +22 -0
  25. package/dist/cli/store/hooks.js +17 -0
  26. package/dist/cli/store/store.d.ts +17 -0
  27. package/dist/cli/store/store.js +18 -0
  28. package/dist/cli/store/wizard/selectors.d.ts +115 -0
  29. package/dist/cli/store/wizard/selectors.js +36 -0
  30. package/dist/cli/store/wizard/slice.d.ts +523 -0
  31. package/dist/cli/store/wizard/slice.js +119 -0
  32. package/dist/cli/utils/error-handler.d.ts +55 -0
  33. package/dist/cli/utils/error-handler.js +92 -0
  34. package/dist/client/auto-start.d.ts +42 -0
  35. package/dist/client/auto-start.js +250 -0
  36. package/dist/client/connection.d.ts +48 -0
  37. package/dist/client/connection.js +200 -0
  38. package/dist/client/index.d.ts +93 -0
  39. package/dist/client/index.js +209 -0
  40. package/dist/client/types.d.ts +105 -0
  41. package/dist/client/types.js +7 -0
  42. package/dist/common/components/SlotRow.d.ts +22 -0
  43. package/dist/common/components/SlotRow.js +53 -0
  44. package/dist/common/components/StatusBar.js +82 -31
  45. package/dist/common/types.d.ts +12 -13
  46. package/dist/daemon/handlers.d.ts +15 -0
  47. package/dist/daemon/handlers.js +157 -0
  48. package/dist/daemon/index.d.ts +21 -0
  49. package/dist/daemon/index.js +123 -0
  50. package/dist/daemon/lib/chunker/bounded-channel.d.ts +51 -0
  51. package/dist/daemon/lib/chunker/bounded-channel.js +138 -0
  52. package/dist/daemon/lib/chunker/index.d.ts +135 -0
  53. package/dist/daemon/lib/chunker/index.js +1370 -0
  54. package/dist/daemon/lib/chunker/types.d.ts +77 -0
  55. package/dist/daemon/lib/chunker/types.js +50 -0
  56. package/dist/daemon/lib/config.d.ts +73 -0
  57. package/dist/daemon/lib/config.js +149 -0
  58. package/dist/daemon/lib/constants.d.ts +75 -0
  59. package/dist/daemon/lib/constants.js +114 -0
  60. package/dist/daemon/lib/gitignore.d.ts +57 -0
  61. package/dist/daemon/lib/gitignore.js +246 -0
  62. package/dist/daemon/lib/logger.d.ts +51 -0
  63. package/dist/daemon/lib/logger.js +167 -0
  64. package/dist/daemon/lib/manifest.d.ts +58 -0
  65. package/dist/daemon/lib/manifest.js +116 -0
  66. package/dist/daemon/lib/merkle/diff.d.ts +32 -0
  67. package/dist/daemon/lib/merkle/diff.js +107 -0
  68. package/dist/daemon/lib/merkle/hash.d.ts +40 -0
  69. package/dist/daemon/lib/merkle/hash.js +180 -0
  70. package/dist/daemon/lib/merkle/index.d.ts +71 -0
  71. package/dist/daemon/lib/merkle/index.js +309 -0
  72. package/dist/daemon/lib/merkle/node.d.ts +55 -0
  73. package/dist/daemon/lib/merkle/node.js +82 -0
  74. package/dist/daemon/lifecycle.d.ts +50 -0
  75. package/dist/daemon/lifecycle.js +142 -0
  76. package/dist/daemon/owner.d.ts +175 -0
  77. package/dist/daemon/owner.js +609 -0
  78. package/dist/daemon/protocol.d.ts +100 -0
  79. package/dist/daemon/protocol.js +163 -0
  80. package/dist/daemon/providers/api-utils.d.ts +130 -0
  81. package/dist/daemon/providers/api-utils.js +248 -0
  82. package/dist/daemon/providers/gemini.d.ts +39 -0
  83. package/dist/daemon/providers/gemini.js +205 -0
  84. package/dist/daemon/providers/index.d.ts +14 -0
  85. package/dist/daemon/providers/index.js +14 -0
  86. package/dist/daemon/providers/local-4b.d.ts +28 -0
  87. package/dist/daemon/providers/local-4b.js +51 -0
  88. package/dist/daemon/providers/local.d.ts +36 -0
  89. package/dist/daemon/providers/local.js +166 -0
  90. package/dist/daemon/providers/mistral.d.ts +35 -0
  91. package/dist/daemon/providers/mistral.js +160 -0
  92. package/dist/daemon/providers/mock.d.ts +35 -0
  93. package/dist/daemon/providers/mock.js +69 -0
  94. package/dist/daemon/providers/openai.d.ts +41 -0
  95. package/dist/daemon/providers/openai.js +190 -0
  96. package/dist/daemon/providers/types.d.ts +68 -0
  97. package/dist/daemon/providers/types.js +6 -0
  98. package/dist/daemon/providers/validate.d.ts +30 -0
  99. package/dist/daemon/providers/validate.js +162 -0
  100. package/dist/daemon/server.d.ts +79 -0
  101. package/dist/daemon/server.js +293 -0
  102. package/dist/daemon/services/index.d.ts +11 -0
  103. package/dist/daemon/services/index.js +16 -0
  104. package/dist/daemon/services/indexing.d.ts +117 -0
  105. package/dist/daemon/services/indexing.js +573 -0
  106. package/dist/daemon/services/search/filters.d.ts +21 -0
  107. package/dist/daemon/services/search/filters.js +106 -0
  108. package/dist/daemon/services/search/fts.d.ts +32 -0
  109. package/dist/daemon/services/search/fts.js +61 -0
  110. package/dist/daemon/services/search/hybrid.d.ts +17 -0
  111. package/dist/daemon/services/search/hybrid.js +58 -0
  112. package/dist/daemon/services/search/index.d.ts +108 -0
  113. package/dist/daemon/services/search/index.js +417 -0
  114. package/dist/daemon/services/search/types.d.ts +126 -0
  115. package/dist/daemon/services/search/types.js +4 -0
  116. package/dist/daemon/services/search/vector.d.ts +25 -0
  117. package/dist/daemon/services/search/vector.js +44 -0
  118. package/dist/daemon/services/storage/index.d.ts +110 -0
  119. package/dist/daemon/services/storage/index.js +378 -0
  120. package/dist/daemon/services/storage/schema.d.ts +24 -0
  121. package/dist/daemon/services/storage/schema.js +51 -0
  122. package/dist/daemon/services/storage/types.d.ts +105 -0
  123. package/dist/daemon/services/storage/types.js +71 -0
  124. package/dist/daemon/services/types.d.ts +192 -0
  125. package/dist/daemon/services/types.js +53 -0
  126. package/dist/daemon/services/watcher.d.ts +98 -0
  127. package/dist/daemon/services/watcher.js +386 -0
  128. package/dist/daemon/state.d.ts +119 -0
  129. package/dist/daemon/state.js +161 -0
  130. package/dist/mcp/index.d.ts +1 -1
  131. package/dist/mcp/index.js +44 -60
  132. package/dist/mcp/server.d.ts +10 -14
  133. package/dist/mcp/server.js +75 -74
  134. package/dist/mcp/services/lazy-loader.d.ts +23 -0
  135. package/dist/mcp/services/lazy-loader.js +34 -0
  136. package/dist/mcp/warmup.d.ts +3 -3
  137. package/dist/mcp/warmup.js +39 -40
  138. package/dist/mcp/watcher.d.ts +5 -7
  139. package/dist/mcp/watcher.js +73 -64
  140. package/dist/rag/config/index.d.ts +2 -0
  141. package/dist/rag/constants.d.ts +30 -0
  142. package/dist/rag/constants.js +38 -0
  143. package/dist/rag/embeddings/api-utils.d.ts +121 -0
  144. package/dist/rag/embeddings/api-utils.js +259 -0
  145. package/dist/rag/embeddings/gemini.d.ts +4 -12
  146. package/dist/rag/embeddings/gemini.js +22 -72
  147. package/dist/rag/embeddings/index.d.ts +5 -3
  148. package/dist/rag/embeddings/index.js +5 -2
  149. package/dist/rag/embeddings/local-4b.d.ts +2 -2
  150. package/dist/rag/embeddings/local-4b.js +1 -1
  151. package/dist/rag/embeddings/local.d.ts +10 -3
  152. package/dist/rag/embeddings/local.js +58 -12
  153. package/dist/rag/embeddings/mistral.d.ts +4 -12
  154. package/dist/rag/embeddings/mistral.js +22 -72
  155. package/dist/rag/embeddings/mock.d.ts +35 -0
  156. package/dist/rag/embeddings/mock.js +69 -0
  157. package/dist/rag/embeddings/openai.d.ts +11 -13
  158. package/dist/rag/embeddings/openai.js +47 -75
  159. package/dist/rag/embeddings/types.d.ts +27 -1
  160. package/dist/rag/embeddings/validate.d.ts +9 -1
  161. package/dist/rag/embeddings/validate.js +17 -4
  162. package/dist/rag/index.d.ts +2 -2
  163. package/dist/rag/index.js +1 -1
  164. package/dist/rag/indexer/bounded-channel.d.ts +51 -0
  165. package/dist/rag/indexer/bounded-channel.js +138 -0
  166. package/dist/rag/indexer/indexer.d.ts +4 -14
  167. package/dist/rag/indexer/indexer.js +246 -169
  168. package/dist/rag/indexer/types.d.ts +1 -0
  169. package/dist/rag/logger/index.d.ts +22 -0
  170. package/dist/rag/logger/index.js +78 -1
  171. package/dist/rag/manifest/index.js +1 -2
  172. package/dist/rag/search/index.js +1 -1
  173. package/dist/rag/storage/schema.d.ts +2 -4
  174. package/dist/rag/storage/schema.js +3 -5
  175. package/dist/store/app/selectors.d.ts +87 -0
  176. package/dist/store/app/selectors.js +28 -0
  177. package/dist/store/app/slice.d.ts +1013 -0
  178. package/dist/store/app/slice.js +112 -0
  179. package/dist/store/hooks.d.ts +22 -0
  180. package/dist/store/hooks.js +17 -0
  181. package/dist/store/index.d.ts +12 -0
  182. package/dist/store/index.js +18 -0
  183. package/dist/store/indexing/listeners.d.ts +25 -0
  184. package/dist/store/indexing/listeners.js +46 -0
  185. package/dist/store/indexing/selectors.d.ts +195 -0
  186. package/dist/store/indexing/selectors.js +69 -0
  187. package/dist/store/indexing/slice.d.ts +309 -0
  188. package/dist/store/indexing/slice.js +113 -0
  189. package/dist/store/slot-progress/listeners.d.ts +23 -0
  190. package/dist/store/slot-progress/listeners.js +33 -0
  191. package/dist/store/slot-progress/selectors.d.ts +67 -0
  192. package/dist/store/slot-progress/selectors.js +36 -0
  193. package/dist/store/slot-progress/slice.d.ts +246 -0
  194. package/dist/store/slot-progress/slice.js +70 -0
  195. package/dist/store/store.d.ts +17 -0
  196. package/dist/store/store.js +18 -0
  197. package/dist/store/warmup/selectors.d.ts +109 -0
  198. package/dist/store/warmup/selectors.js +44 -0
  199. package/dist/store/warmup/slice.d.ts +137 -0
  200. package/dist/store/warmup/slice.js +72 -0
  201. package/dist/store/watcher/selectors.d.ts +115 -0
  202. package/dist/store/watcher/selectors.js +52 -0
  203. package/dist/store/watcher/slice.d.ts +269 -0
  204. package/dist/store/watcher/slice.js +100 -0
  205. package/dist/store/wizard/selectors.d.ts +115 -0
  206. package/dist/store/wizard/selectors.js +36 -0
  207. package/dist/store/wizard/slice.d.ts +523 -0
  208. package/dist/store/wizard/slice.js +119 -0
  209. package/package.json +10 -2
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Daemon Client
3
+ *
4
+ * High-level client for daemon communication.
5
+ * Provides typed API methods and handles connection lifecycle.
6
+ *
7
+ * Simplified for polling-based architecture:
8
+ * - Pure request/response, no push notifications
9
+ * - No reconnection logic - clients poll and reconnect as needed
10
+ * - Auto-starts daemon if not running
11
+ */
12
+ import type { DaemonClientOptions, ClientSearchOptions, ClientIndexOptions, IndexStartResponse, DaemonStatusResponse, PingResponse, SearchResults, IndexStats, WatcherStatus } from './types.js';
13
+ /**
14
+ * Client for communicating with the VibeRAG daemon.
15
+ * Pure request/response - clients poll status() for updates.
16
+ */
17
+ export declare class DaemonClient {
18
+ private readonly projectRoot;
19
+ private readonly socketPath;
20
+ private readonly autoStart;
21
+ private readonly connectTimeout;
22
+ private connection;
23
+ private connectPromise;
24
+ constructor(options: DaemonClientOptions | string);
25
+ /**
26
+ * Check if connected.
27
+ */
28
+ isConnected(): boolean;
29
+ /**
30
+ * Connect to the daemon.
31
+ * Auto-starts daemon if not running (when autoStart is true).
32
+ * Safe for concurrent calls - will reuse in-flight connection attempt.
33
+ */
34
+ connect(): Promise<void>;
35
+ /**
36
+ * Internal connection logic.
37
+ */
38
+ private doConnect;
39
+ /**
40
+ * Disconnect from the daemon.
41
+ */
42
+ disconnect(): Promise<void>;
43
+ /**
44
+ * Check if daemon is running (without connecting).
45
+ */
46
+ isRunning(): Promise<boolean>;
47
+ /**
48
+ * Ensure connected before making a request.
49
+ */
50
+ private ensureConnected;
51
+ /**
52
+ * Search the codebase.
53
+ */
54
+ search(query: string, options?: ClientSearchOptions): Promise<SearchResults>;
55
+ /**
56
+ * Index the codebase.
57
+ */
58
+ index(options?: ClientIndexOptions): Promise<IndexStats>;
59
+ /**
60
+ * Start indexing asynchronously.
61
+ */
62
+ indexAsync(options?: ClientIndexOptions): Promise<IndexStartResponse>;
63
+ /**
64
+ * Get daemon status.
65
+ * Clients should poll this endpoint for state updates.
66
+ */
67
+ status(): Promise<DaemonStatusResponse>;
68
+ /**
69
+ * Get watcher status.
70
+ */
71
+ watchStatus(): Promise<WatcherStatus>;
72
+ /**
73
+ * Request daemon shutdown.
74
+ */
75
+ shutdown(reason?: string): Promise<void>;
76
+ /**
77
+ * Ping the daemon.
78
+ */
79
+ ping(): Promise<PingResponse>;
80
+ /**
81
+ * Get health information.
82
+ */
83
+ health(): Promise<{
84
+ healthy: boolean;
85
+ uptime: number;
86
+ memoryUsage: NodeJS.MemoryUsage;
87
+ clients: number;
88
+ indexStatus: string;
89
+ protocolVersion: number;
90
+ }>;
91
+ }
92
+ export { getSocketPath, getLockPath, isDaemonRunning, isDaemonLocked, } from './auto-start.js';
93
+ export type { DaemonClientOptions, ClientSearchOptions, ClientIndexOptions, DaemonStatusResponse, PingResponse, SearchResults, IndexStats, WatcherStatus, SlotState, FailedChunk, } from './types.js';
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Daemon Client
3
+ *
4
+ * High-level client for daemon communication.
5
+ * Provides typed API methods and handles connection lifecycle.
6
+ *
7
+ * Simplified for polling-based architecture:
8
+ * - Pure request/response, no push notifications
9
+ * - No reconnection logic - clients poll and reconnect as needed
10
+ * - Auto-starts daemon if not running
11
+ */
12
+ import { DaemonConnection } from './connection.js';
13
+ import { ensureDaemonRunning, isDaemonRunning, getSocketPath, } from './auto-start.js';
14
+ // ============================================================================
15
+ // DaemonClient
16
+ // ============================================================================
17
+ /**
18
+ * Client for communicating with the VibeRAG daemon.
19
+ * Pure request/response - clients poll status() for updates.
20
+ */
21
+ export class DaemonClient {
22
+ constructor(options) {
23
+ Object.defineProperty(this, "projectRoot", {
24
+ enumerable: true,
25
+ configurable: true,
26
+ writable: true,
27
+ value: void 0
28
+ });
29
+ Object.defineProperty(this, "socketPath", {
30
+ enumerable: true,
31
+ configurable: true,
32
+ writable: true,
33
+ value: void 0
34
+ });
35
+ Object.defineProperty(this, "autoStart", {
36
+ enumerable: true,
37
+ configurable: true,
38
+ writable: true,
39
+ value: void 0
40
+ });
41
+ Object.defineProperty(this, "connectTimeout", {
42
+ enumerable: true,
43
+ configurable: true,
44
+ writable: true,
45
+ value: void 0
46
+ });
47
+ Object.defineProperty(this, "connection", {
48
+ enumerable: true,
49
+ configurable: true,
50
+ writable: true,
51
+ value: null
52
+ });
53
+ Object.defineProperty(this, "connectPromise", {
54
+ enumerable: true,
55
+ configurable: true,
56
+ writable: true,
57
+ value: null
58
+ });
59
+ // Handle simple string constructor
60
+ if (typeof options === 'string') {
61
+ this.projectRoot = options;
62
+ this.autoStart = true;
63
+ this.connectTimeout = 5000;
64
+ }
65
+ else {
66
+ this.projectRoot = options.projectRoot;
67
+ this.autoStart = options.autoStart ?? true;
68
+ this.connectTimeout = options.connectTimeout ?? 5000;
69
+ }
70
+ this.socketPath = getSocketPath(this.projectRoot);
71
+ }
72
+ // ==========================================================================
73
+ // Connection Management
74
+ // ==========================================================================
75
+ /**
76
+ * Check if connected.
77
+ */
78
+ isConnected() {
79
+ return this.connection?.isConnected() === true;
80
+ }
81
+ /**
82
+ * Connect to the daemon.
83
+ * Auto-starts daemon if not running (when autoStart is true).
84
+ * Safe for concurrent calls - will reuse in-flight connection attempt.
85
+ */
86
+ async connect() {
87
+ if (this.isConnected()) {
88
+ return;
89
+ }
90
+ // Reuse existing connection attempt if one is in progress
91
+ if (this.connectPromise) {
92
+ return this.connectPromise;
93
+ }
94
+ this.connectPromise = this.doConnect();
95
+ try {
96
+ await this.connectPromise;
97
+ }
98
+ finally {
99
+ this.connectPromise = null;
100
+ }
101
+ }
102
+ /**
103
+ * Internal connection logic.
104
+ */
105
+ async doConnect() {
106
+ try {
107
+ // Auto-start daemon if needed
108
+ if (this.autoStart) {
109
+ await ensureDaemonRunning(this.projectRoot);
110
+ }
111
+ // Create connection
112
+ this.connection = new DaemonConnection(this.socketPath);
113
+ // Connect
114
+ await this.connection.connect(this.connectTimeout);
115
+ }
116
+ catch (error) {
117
+ this.connection = null;
118
+ throw error;
119
+ }
120
+ }
121
+ /**
122
+ * Disconnect from the daemon.
123
+ */
124
+ async disconnect() {
125
+ if (this.connection) {
126
+ this.connection.disconnect();
127
+ this.connection = null;
128
+ }
129
+ }
130
+ /**
131
+ * Check if daemon is running (without connecting).
132
+ */
133
+ async isRunning() {
134
+ return isDaemonRunning(this.projectRoot);
135
+ }
136
+ // ==========================================================================
137
+ // API Methods
138
+ // ==========================================================================
139
+ /**
140
+ * Ensure connected before making a request.
141
+ */
142
+ async ensureConnected() {
143
+ if (!this.isConnected()) {
144
+ await this.connect();
145
+ }
146
+ }
147
+ /**
148
+ * Search the codebase.
149
+ */
150
+ async search(query, options) {
151
+ await this.ensureConnected();
152
+ return this.connection.request('search', {
153
+ query,
154
+ ...options,
155
+ });
156
+ }
157
+ /**
158
+ * Index the codebase.
159
+ */
160
+ async index(options) {
161
+ await this.ensureConnected();
162
+ return this.connection.request('index', options);
163
+ }
164
+ /**
165
+ * Start indexing asynchronously.
166
+ */
167
+ async indexAsync(options) {
168
+ await this.ensureConnected();
169
+ return this.connection.request('indexAsync', options);
170
+ }
171
+ /**
172
+ * Get daemon status.
173
+ * Clients should poll this endpoint for state updates.
174
+ */
175
+ async status() {
176
+ await this.ensureConnected();
177
+ return this.connection.request('status');
178
+ }
179
+ /**
180
+ * Get watcher status.
181
+ */
182
+ async watchStatus() {
183
+ await this.ensureConnected();
184
+ return this.connection.request('watchStatus');
185
+ }
186
+ /**
187
+ * Request daemon shutdown.
188
+ */
189
+ async shutdown(reason) {
190
+ await this.ensureConnected();
191
+ await this.connection.request('shutdown', { reason });
192
+ }
193
+ /**
194
+ * Ping the daemon.
195
+ */
196
+ async ping() {
197
+ await this.ensureConnected();
198
+ return this.connection.request('ping');
199
+ }
200
+ /**
201
+ * Get health information.
202
+ */
203
+ async health() {
204
+ await this.ensureConnected();
205
+ return this.connection.request('health');
206
+ }
207
+ }
208
+ // Re-export types and utilities
209
+ export { getSocketPath, getLockPath, isDaemonRunning, isDaemonLocked, } from './auto-start.js';
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Client Types
3
+ *
4
+ * Types for daemon client communication.
5
+ * Simplified for polling-based architecture.
6
+ */
7
+ import type { SearchResults } from '../daemon/services/search/types.js';
8
+ import type { IndexStats } from '../daemon/services/indexing.js';
9
+ import type { WatcherStatus } from '../daemon/services/watcher.js';
10
+ /**
11
+ * Slot state for concurrent embedding tracking.
12
+ */
13
+ export interface SlotState {
14
+ state: 'idle' | 'processing' | 'rate-limited';
15
+ batchInfo: string | null;
16
+ retryInfo: string | null;
17
+ }
18
+ /**
19
+ * Failed chunk info.
20
+ */
21
+ export interface FailedChunk {
22
+ batchInfo: string;
23
+ error: string;
24
+ timestamp: string;
25
+ }
26
+ /**
27
+ * Options for DaemonClient constructor.
28
+ */
29
+ export interface DaemonClientOptions {
30
+ /** Project root directory */
31
+ projectRoot: string;
32
+ /** Auto-start daemon if not running (default: true) */
33
+ autoStart?: boolean;
34
+ /** Connection timeout in ms (default: 5000) */
35
+ connectTimeout?: number;
36
+ }
37
+ /**
38
+ * Search options for client.
39
+ */
40
+ export interface ClientSearchOptions {
41
+ mode?: 'semantic' | 'exact' | 'hybrid' | 'definition' | 'similar';
42
+ limit?: number;
43
+ bm25Weight?: number;
44
+ minScore?: number;
45
+ filters?: Record<string, unknown>;
46
+ codeSnippet?: string;
47
+ symbolName?: string;
48
+ autoBoost?: boolean;
49
+ autoBoostThreshold?: number;
50
+ returnDebug?: boolean;
51
+ }
52
+ /**
53
+ * Index options for client.
54
+ */
55
+ export interface ClientIndexOptions {
56
+ force?: boolean;
57
+ }
58
+ /**
59
+ * Index start response for async indexing.
60
+ */
61
+ export interface IndexStartResponse {
62
+ started: boolean;
63
+ reason?: 'in_progress';
64
+ }
65
+ /**
66
+ * Daemon status response.
67
+ * Enhanced to support polling-based state synchronization.
68
+ */
69
+ export interface DaemonStatusResponse {
70
+ initialized: boolean;
71
+ indexed: boolean;
72
+ version?: number;
73
+ createdAt?: string;
74
+ updatedAt?: string;
75
+ totalFiles?: number;
76
+ totalChunks?: number;
77
+ embeddingProvider?: string;
78
+ embeddingModel?: string;
79
+ warmupStatus: string;
80
+ warmupElapsedMs?: number;
81
+ watcherStatus: WatcherStatus;
82
+ indexing: {
83
+ status: 'idle' | 'initializing' | 'indexing' | 'complete' | 'error';
84
+ current: number;
85
+ total: number;
86
+ stage: string;
87
+ chunksProcessed: number;
88
+ throttleMessage: string | null;
89
+ error: string | null;
90
+ lastCompleted: string | null;
91
+ lastStats: IndexStats | null;
92
+ percent: number;
93
+ };
94
+ slots: SlotState[];
95
+ failures: FailedChunk[];
96
+ }
97
+ /**
98
+ * Ping response.
99
+ */
100
+ export interface PingResponse {
101
+ pong: boolean;
102
+ timestamp: number;
103
+ protocolVersion: number;
104
+ }
105
+ export type { SearchResults, IndexStats, WatcherStatus };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Client Types
3
+ *
4
+ * Types for daemon client communication.
5
+ * Simplified for polling-based architecture.
6
+ */
7
+ export {};
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Individual slot row component for displaying batch processing progress.
3
+ *
4
+ * Each SlotRow watches its own slice of Redux state and renders independently.
5
+ * This follows the Single Responsibility Principle - each row manages its own
6
+ * rendering logic based on its slot index.
7
+ */
8
+ import React from 'react';
9
+ type Props = {
10
+ /** The slot index (0 to CONCURRENCY-1) */
11
+ slotIndex: number;
12
+ /** Whether this is the last visible slot (for tree-drawing) */
13
+ isLast: boolean;
14
+ };
15
+ /**
16
+ * Renders a single slot's progress status.
17
+ *
18
+ * Always renders a fixed-height row to prevent UI jumping when slots
19
+ * become active/idle. Idle slots show an empty placeholder.
20
+ */
21
+ export declare function SlotRow({ slotIndex, isLast }: Props): React.ReactElement;
22
+ export {};
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Individual slot row component for displaying batch processing progress.
3
+ *
4
+ * Each SlotRow watches its own slice of Redux state and renders independently.
5
+ * This follows the Single Responsibility Principle - each row manages its own
6
+ * rendering logic based on its slot index.
7
+ */
8
+ import React, { useState, useEffect } from 'react';
9
+ import { Box, Text } from 'ink';
10
+ import { useAppSelector } from '../../store/hooks.js';
11
+ import { selectSlot } from '../../store/slot-progress/selectors.js';
12
+ // ============================================================================
13
+ // Constants
14
+ // ============================================================================
15
+ /** Braille dots spinner frames */
16
+ const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
17
+ /**
18
+ * Renders a single slot's progress status.
19
+ *
20
+ * Always renders a fixed-height row to prevent UI jumping when slots
21
+ * become active/idle. Idle slots show an empty placeholder.
22
+ */
23
+ export function SlotRow({ slotIndex, isLast }) {
24
+ const slot = useAppSelector(state => selectSlot(state, slotIndex));
25
+ const [frame, setFrame] = useState(0);
26
+ // Spinner animation - only runs when processing
27
+ useEffect(() => {
28
+ if (slot.state !== 'processing')
29
+ return;
30
+ const timer = setInterval(() => {
31
+ setFrame(f => (f + 1) % SPINNER_FRAMES.length);
32
+ }, 80);
33
+ return () => clearInterval(timer);
34
+ }, [slot.state]);
35
+ // Tree-drawing prefix
36
+ const prefix = isLast ? '└ ' : '├ ';
37
+ // Idle slots render empty placeholder to maintain fixed height
38
+ if (slot.state === 'idle') {
39
+ return (React.createElement(Box, null,
40
+ React.createElement(Text, { dimColor: true }, prefix),
41
+ React.createElement(Text, { dimColor: true }, "\u00B7")));
42
+ }
43
+ return (React.createElement(Box, null,
44
+ React.createElement(Text, { dimColor: true }, prefix),
45
+ slot.state === 'rate-limited' ? (React.createElement(Text, { color: "yellow" },
46
+ "\u26A0 ",
47
+ slot.batchInfo,
48
+ slot.retryInfo && ` · ${slot.retryInfo}`)) : (React.createElement(React.Fragment, null,
49
+ React.createElement(Text, { color: "cyan" },
50
+ SPINNER_FRAMES[frame],
51
+ " "),
52
+ React.createElement(Text, { dimColor: true }, slot.batchInfo)))));
53
+ }
@@ -1,5 +1,9 @@
1
1
  import React, { useState, useEffect } from 'react';
2
2
  import { Box, Text } from 'ink';
3
+ import { useAppSelector } from '../../store/hooks.js';
4
+ import { selectSlotCount, selectFailures, selectHasActiveSlots, } from '../../store/slot-progress/selectors.js';
5
+ import { selectIndexingDisplay, selectIsIndexing, } from '../../store/indexing/selectors.js';
6
+ import { SlotRow } from './SlotRow.js';
3
7
  /** Braille dots spinner frames */
4
8
  const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
5
9
  /**
@@ -17,37 +21,25 @@ function Spinner({ color }) {
17
21
  SPINNER_FRAMES[frame],
18
22
  " ");
19
23
  }
24
+ /**
25
+ * Progress bar component for visual progress indication.
26
+ */
27
+ function ProgressBar({ percent, width = 20, }) {
28
+ const filled = Math.round((percent / 100) * width);
29
+ const empty = width - filled;
30
+ return (React.createElement(Text, null,
31
+ React.createElement(Text, { color: "cyan" }, '█'.repeat(filled)),
32
+ React.createElement(Text, { dimColor: true }, '░'.repeat(empty))));
33
+ }
20
34
  /**
21
35
  * Format status message for display.
36
+ * Note: Indexing state is derived from Redux via selectIsIndexing.
37
+ * This function only handles non-indexing app states.
22
38
  */
23
- function formatStatus(status) {
39
+ function formatNonIndexingStatus(status) {
24
40
  switch (status.state) {
25
41
  case 'ready':
26
42
  return { text: 'Ready', color: 'green', showSpinner: false };
27
- case 'indexing': {
28
- // Throttle status takes precedence - show in yellow
29
- if (status.throttleMessage) {
30
- return {
31
- text: status.throttleMessage,
32
- color: 'yellow',
33
- showSpinner: true,
34
- };
35
- }
36
- // Normal indexing display
37
- if (status.total === 0) {
38
- return { text: `${status.stage}`, color: 'cyan', showSpinner: true };
39
- }
40
- const percent = Math.round((status.current / status.total) * 100);
41
- // Include chunk count if available
42
- const chunkInfo = status.chunksProcessed !== undefined
43
- ? ` · ${status.chunksProcessed} chunks`
44
- : '';
45
- return {
46
- text: `${status.stage} ${status.current}/${status.total} (${percent}%)${chunkInfo}`,
47
- color: 'cyan',
48
- showSpinner: true,
49
- };
50
- }
51
43
  case 'searching':
52
44
  return { text: 'Searching', color: 'cyan', showSpinner: true };
53
45
  case 'warning':
@@ -67,11 +59,70 @@ function formatStats(stats) {
67
59
  return `${stats.totalFiles} files · ${stats.totalChunks} chunks`;
68
60
  }
69
61
  export default function StatusBar({ status, stats }) {
70
- const { text, color, showSpinner } = formatStatus(status);
71
62
  const statsText = formatStats(stats);
72
- return (React.createElement(Box, { paddingX: 1, justifyContent: "space-between" },
73
- React.createElement(Box, null,
74
- showSpinner && React.createElement(Spinner, { color: color }),
75
- React.createElement(Text, { color: color }, text)),
76
- React.createElement(Text, { dimColor: true }, statsText)));
63
+ // Redux selectors for indexing progress
64
+ const indexingDisplay = useAppSelector(selectIndexingDisplay);
65
+ const isIndexingActive = useAppSelector(selectIsIndexing);
66
+ // Redux selectors for slot progress
67
+ const slotCount = useAppSelector(selectSlotCount);
68
+ const failures = useAppSelector(selectFailures);
69
+ const hasActiveSlots = useAppSelector(selectHasActiveSlots);
70
+ // Determine display values based on state source
71
+ // For indexing: use Redux state (synced from daemon - single source of truth)
72
+ // For other states: use props (local app state)
73
+ const nonIndexingStatus = formatNonIndexingStatus(status);
74
+ // Use Redux for indexing display, props for everything else
75
+ const displayValues = isIndexingActive
76
+ ? {
77
+ text: indexingDisplay.stage,
78
+ color: indexingDisplay.color,
79
+ showSpinner: true,
80
+ showProgressBar: indexingDisplay.showProgressBar,
81
+ percent: indexingDisplay.percent,
82
+ stage: indexingDisplay.stage,
83
+ chunkInfo: indexingDisplay.chunkInfo,
84
+ throttleInfo: indexingDisplay.throttleInfo,
85
+ }
86
+ : {
87
+ text: nonIndexingStatus.text,
88
+ color: nonIndexingStatus.color,
89
+ showSpinner: nonIndexingStatus.showSpinner,
90
+ showProgressBar: false,
91
+ percent: 0,
92
+ stage: '',
93
+ chunkInfo: undefined,
94
+ throttleInfo: null,
95
+ };
96
+ const { text, color, showSpinner, showProgressBar, percent, stage, chunkInfo, throttleInfo, } = displayValues;
97
+ // Only show slots when there's actual activity (API providers use slots, local doesn't)
98
+ const showSlots = isIndexingActive && hasActiveSlots;
99
+ // Show failure summary if any batches failed
100
+ const hasFailures = failures.length > 0;
101
+ return (React.createElement(Box, { flexDirection: "column" },
102
+ React.createElement(Box, { paddingX: 1, justifyContent: "space-between" },
103
+ React.createElement(Box, null,
104
+ showSpinner && React.createElement(Spinner, { color: color }),
105
+ showProgressBar ? (React.createElement(React.Fragment, null,
106
+ React.createElement(Text, { color: color },
107
+ stage,
108
+ " "),
109
+ React.createElement(Text, null, "["),
110
+ React.createElement(ProgressBar, { percent: percent }),
111
+ React.createElement(Text, null, "] "),
112
+ React.createElement(Text, { color: color },
113
+ percent,
114
+ "%"),
115
+ chunkInfo && React.createElement(Text, { dimColor: true },
116
+ " \u00B7 ",
117
+ chunkInfo),
118
+ throttleInfo && React.createElement(Text, { color: "yellow" },
119
+ " \u00B7 ",
120
+ throttleInfo))) : (React.createElement(Text, { color: color }, text))),
121
+ React.createElement(Text, { dimColor: true }, statsText)),
122
+ showSlots && (React.createElement(Box, { flexDirection: "column", paddingLeft: 2 }, Array.from({ length: slotCount }, (_, i) => (React.createElement(SlotRow, { key: i, slotIndex: i, isLast: i === slotCount - 1 }))))),
123
+ hasFailures && (React.createElement(Box, { paddingLeft: 2 },
124
+ React.createElement(Text, { color: "red" },
125
+ "\u26A0 ",
126
+ failures.length,
127
+ " batch(es) failed - see .viberag/debug.log")))));
77
128
  }
@@ -53,18 +53,12 @@ export type TextBufferState = {
53
53
  };
54
54
  /**
55
55
  * App status for the status bar.
56
+ *
57
+ * Note: Indexing state is derived from the indexing Redux slice (synced from daemon).
58
+ * Do NOT use appStatus for indexing - use selectIsIndexing() instead.
56
59
  */
57
60
  export type AppStatus = {
58
61
  state: 'ready';
59
- } | {
60
- state: 'indexing';
61
- current: number;
62
- total: number;
63
- stage: string;
64
- /** Rate limit message (shown in yellow when set) */
65
- throttleMessage?: string | null;
66
- /** Number of chunks embedded so far */
67
- chunksProcessed?: number;
68
62
  } | {
69
63
  state: 'searching';
70
64
  } | {
@@ -81,16 +75,19 @@ export type IndexDisplayStats = {
81
75
  /**
82
76
  * Embedding provider types.
83
77
  *
84
- * Local providers (no API key required):
78
+ * Local provider (no API key required):
85
79
  * - local: Qwen3-Embedding-0.6B Q8 (1024d) - ~700MB download, ~1.2GB RAM
86
- * - local-4b: Qwen3-Embedding-4B FP32 (2560d) - ~8GB download, ~8GB RAM
87
80
  *
88
81
  * API providers:
89
82
  * - gemini: gemini-embedding-001 (1536d) - Free tier
90
83
  * - mistral: codestral-embed (1536d) - Code-optimized
91
- * - openai: text-embedding-3-small (1536d) - Fast API
84
+ * - openai: text-embedding-3-large (1536d) - Highest quality
85
+ */
86
+ export type EmbeddingProviderType = 'local' | 'gemini' | 'mistral' | 'openai';
87
+ /**
88
+ * OpenAI API regional endpoints for data residency.
92
89
  */
93
- export type EmbeddingProviderType = 'local' | 'local-4b' | 'gemini' | 'mistral' | 'openai';
90
+ export type OpenAIRegion = 'default' | 'us' | 'eu';
94
91
  /**
95
92
  * Configuration collected from the init wizard.
96
93
  */
@@ -98,6 +95,8 @@ export type InitWizardConfig = {
98
95
  provider: EmbeddingProviderType;
99
96
  /** API key for cloud providers (gemini, mistral, openai) */
100
97
  apiKey?: string;
98
+ /** OpenAI regional endpoint (for corporate accounts with data residency) */
99
+ openaiRegion?: OpenAIRegion;
101
100
  };
102
101
  /**
103
102
  * MCP editor identifiers.