byterover-cli 2.0.0 → 2.1.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 (181) hide show
  1. package/README.md +6 -81
  2. package/dist/agent/core/domain/llm/index.d.ts +1 -1
  3. package/dist/agent/core/domain/llm/index.js +1 -1
  4. package/dist/agent/core/domain/llm/registry.d.ts +8 -0
  5. package/dist/agent/core/domain/llm/registry.js +34 -0
  6. package/dist/agent/core/domain/sandbox/types.d.ts +2 -0
  7. package/dist/agent/core/domain/tools/constants.d.ts +3 -0
  8. package/dist/agent/core/domain/tools/constants.js +3 -0
  9. package/dist/agent/core/interfaces/cipher-services.d.ts +2 -4
  10. package/dist/agent/core/interfaces/i-cipher-agent.d.ts +9 -1
  11. package/dist/agent/core/interfaces/i-sandbox-service.d.ts +8 -0
  12. package/dist/agent/core/interfaces/i-tool-provider.d.ts +10 -0
  13. package/dist/agent/core/interfaces/i-tool-scheduler.d.ts +9 -0
  14. package/dist/agent/infra/agent/agent-schemas.d.ts +0 -9
  15. package/dist/agent/infra/agent/agent-schemas.js +0 -3
  16. package/dist/agent/infra/agent/cipher-agent.d.ts +25 -1
  17. package/dist/agent/infra/agent/cipher-agent.js +138 -11
  18. package/dist/agent/infra/agent/provider-update-config.d.ts +0 -2
  19. package/dist/agent/infra/agent/service-initializer.d.ts +2 -6
  20. package/dist/agent/infra/agent/service-initializer.js +45 -38
  21. package/dist/agent/infra/blob/blob-storage-factory.d.ts +2 -2
  22. package/dist/agent/infra/blob/blob-storage-factory.js +4 -4
  23. package/dist/agent/infra/blob/file-blob-storage.d.ts +96 -0
  24. package/dist/agent/infra/blob/file-blob-storage.js +454 -0
  25. package/dist/agent/infra/blob/index.d.ts +2 -3
  26. package/dist/agent/infra/blob/index.js +4 -6
  27. package/dist/agent/infra/llm/agent-llm-service.d.ts +3 -0
  28. package/dist/agent/infra/llm/agent-llm-service.js +34 -52
  29. package/dist/agent/infra/llm/context/compression/compression-helpers.d.ts +35 -0
  30. package/dist/agent/infra/llm/context/compression/compression-helpers.js +124 -0
  31. package/dist/agent/infra/llm/context/compression/escalated-compression.d.ts +62 -0
  32. package/dist/agent/infra/llm/context/compression/escalated-compression.js +144 -0
  33. package/dist/agent/infra/llm/context/compression/index.d.ts +3 -0
  34. package/dist/agent/infra/llm/context/compression/index.js +3 -0
  35. package/dist/agent/infra/llm/context/compression/reactive-overflow.d.ts +0 -27
  36. package/dist/agent/infra/llm/context/compression/reactive-overflow.js +5 -122
  37. package/dist/agent/infra/llm/context/context-manager.d.ts +20 -1
  38. package/dist/agent/infra/llm/context/context-manager.js +37 -7
  39. package/dist/agent/infra/llm/providers/index.js +0 -2
  40. package/dist/agent/infra/llm/providers/types.d.ts +1 -5
  41. package/dist/agent/infra/map/agentic-map-service.d.ts +97 -0
  42. package/dist/agent/infra/map/agentic-map-service.js +309 -0
  43. package/dist/agent/infra/map/context-tree-store.d.ts +94 -0
  44. package/dist/agent/infra/map/context-tree-store.js +278 -0
  45. package/dist/agent/infra/map/index.d.ts +4 -0
  46. package/dist/agent/infra/map/index.js +4 -0
  47. package/dist/agent/infra/map/llm-map-memory.d.ts +59 -0
  48. package/dist/agent/infra/map/llm-map-memory.js +187 -0
  49. package/dist/agent/infra/map/llm-map-service.d.ts +36 -0
  50. package/dist/agent/infra/map/llm-map-service.js +118 -0
  51. package/dist/agent/infra/map/map-shared.d.ts +140 -0
  52. package/dist/agent/infra/map/map-shared.js +325 -0
  53. package/dist/agent/infra/map/worker-pool.d.ts +45 -0
  54. package/dist/agent/infra/map/worker-pool.js +73 -0
  55. package/dist/agent/infra/sandbox/curation-helpers.d.ts +62 -0
  56. package/dist/agent/infra/sandbox/curation-helpers.js +219 -0
  57. package/dist/agent/infra/sandbox/sandbox-service.d.ts +12 -0
  58. package/dist/agent/infra/sandbox/sandbox-service.js +39 -7
  59. package/dist/agent/infra/sandbox/tools-sdk.d.ts +48 -1
  60. package/dist/agent/infra/sandbox/tools-sdk.js +52 -1
  61. package/dist/agent/infra/session/session-manager.d.ts +8 -1
  62. package/dist/agent/infra/session/session-manager.js +24 -4
  63. package/dist/agent/infra/storage/file-key-storage.d.ts +142 -0
  64. package/dist/agent/infra/storage/file-key-storage.js +572 -0
  65. package/dist/agent/infra/storage/granular-history-storage.d.ts +1 -1
  66. package/dist/agent/infra/storage/granular-history-storage.js +1 -1
  67. package/dist/agent/infra/system-prompt/contributors/context-tree-structure-contributor.d.ts +4 -0
  68. package/dist/agent/infra/system-prompt/contributors/context-tree-structure-contributor.js +42 -14
  69. package/dist/agent/infra/system-prompt/contributors/map-selection-contributor.d.ts +16 -0
  70. package/dist/agent/infra/system-prompt/contributors/map-selection-contributor.js +47 -0
  71. package/dist/agent/infra/tools/core-tool-scheduler.js +3 -1
  72. package/dist/agent/infra/tools/implementations/agentic-map-tool.d.ts +35 -0
  73. package/dist/agent/infra/tools/implementations/agentic-map-tool.js +156 -0
  74. package/dist/agent/infra/tools/implementations/code-exec-tool.js +1 -0
  75. package/dist/agent/infra/tools/implementations/curate-tool.d.ts +9 -9
  76. package/dist/agent/infra/tools/implementations/expand-knowledge-tool.d.ts +18 -0
  77. package/dist/agent/infra/tools/implementations/expand-knowledge-tool.js +43 -0
  78. package/dist/agent/infra/tools/implementations/llm-map-tool.d.ts +24 -0
  79. package/dist/agent/infra/tools/implementations/llm-map-tool.js +87 -0
  80. package/dist/agent/infra/tools/implementations/memory-symbol-tree.d.ts +28 -1
  81. package/dist/agent/infra/tools/implementations/memory-symbol-tree.js +27 -3
  82. package/dist/agent/infra/tools/implementations/search-knowledge-service.d.ts +1 -0
  83. package/dist/agent/infra/tools/implementations/search-knowledge-service.js +83 -12
  84. package/dist/agent/infra/tools/implementations/search-knowledge-tool.js +2 -2
  85. package/dist/agent/infra/tools/tool-manager.js +6 -0
  86. package/dist/agent/infra/tools/tool-provider.d.ts +12 -0
  87. package/dist/agent/infra/tools/tool-provider.js +78 -0
  88. package/dist/agent/infra/tools/tool-registry.d.ts +14 -0
  89. package/dist/agent/infra/tools/tool-registry.js +32 -0
  90. package/dist/agent/resources/prompts/system-prompt.yml +48 -74
  91. package/dist/agent/resources/tools/expand_knowledge.txt +20 -0
  92. package/dist/oclif/commands/curate/index.js +1 -2
  93. package/dist/oclif/commands/main.js +1 -0
  94. package/dist/oclif/commands/providers/connect.d.ts +1 -3
  95. package/dist/oclif/commands/providers/connect.js +7 -29
  96. package/dist/oclif/commands/query.js +1 -2
  97. package/dist/server/constants.d.ts +7 -0
  98. package/dist/server/constants.js +8 -0
  99. package/dist/server/core/domain/entities/provider-registry.js +1 -15
  100. package/dist/server/core/domain/knowledge/memory-scoring.js +1 -1
  101. package/dist/server/core/domain/knowledge/summary-types.d.ts +126 -0
  102. package/dist/server/core/domain/knowledge/summary-types.js +7 -0
  103. package/dist/server/core/domain/transport/schemas.d.ts +0 -4
  104. package/dist/server/core/interfaces/context-tree/i-context-tree-archive-service.d.ts +30 -0
  105. package/dist/server/core/interfaces/context-tree/i-context-tree-archive-service.js +1 -0
  106. package/dist/server/core/interfaces/context-tree/i-context-tree-manifest-service.d.ts +30 -0
  107. package/dist/server/core/interfaces/context-tree/i-context-tree-manifest-service.js +1 -0
  108. package/dist/server/core/interfaces/context-tree/i-context-tree-summary-service.d.ts +29 -0
  109. package/dist/server/core/interfaces/context-tree/i-context-tree-summary-service.js +1 -0
  110. package/dist/server/infra/cogit/context-tree-to-push-context-mapper.js +10 -3
  111. package/dist/server/infra/connectors/skill/skill-connector.d.ts +4 -0
  112. package/dist/server/infra/connectors/skill/skill-connector.js +4 -0
  113. package/dist/server/infra/context-tree/children-hash.d.ts +20 -0
  114. package/dist/server/infra/context-tree/children-hash.js +22 -0
  115. package/dist/server/infra/context-tree/derived-artifact.d.ts +28 -0
  116. package/dist/server/infra/context-tree/derived-artifact.js +48 -0
  117. package/dist/server/infra/context-tree/file-context-tree-archive-service.d.ts +37 -0
  118. package/dist/server/infra/context-tree/file-context-tree-archive-service.js +219 -0
  119. package/dist/server/infra/context-tree/file-context-tree-manifest-service.d.ts +50 -0
  120. package/dist/server/infra/context-tree/file-context-tree-manifest-service.js +278 -0
  121. package/dist/server/infra/context-tree/file-context-tree-merger.js +4 -0
  122. package/dist/server/infra/context-tree/file-context-tree-snapshot-service.js +12 -4
  123. package/dist/server/infra/context-tree/file-context-tree-summary-service.d.ts +44 -0
  124. package/dist/server/infra/context-tree/file-context-tree-summary-service.js +313 -0
  125. package/dist/server/infra/context-tree/file-context-tree-writer-service.js +5 -0
  126. package/dist/server/infra/context-tree/prompts/summary-generation.d.ts +22 -0
  127. package/dist/server/infra/context-tree/prompts/summary-generation.js +45 -0
  128. package/dist/server/infra/context-tree/snapshot-diff.d.ts +19 -0
  129. package/dist/server/infra/context-tree/snapshot-diff.js +39 -0
  130. package/dist/server/infra/context-tree/summary-frontmatter.d.ts +24 -0
  131. package/dist/server/infra/context-tree/summary-frontmatter.js +111 -0
  132. package/dist/server/infra/daemon/agent-process.js +2 -14
  133. package/dist/server/infra/executor/curate-executor.d.ts +1 -0
  134. package/dist/server/infra/executor/curate-executor.js +82 -34
  135. package/dist/server/infra/executor/folder-pack-executor.js +1 -1
  136. package/dist/server/infra/executor/pre-compaction/compaction-escalation.d.ts +6 -0
  137. package/dist/server/infra/executor/pre-compaction/compaction-escalation.js +6 -0
  138. package/dist/server/infra/executor/pre-compaction/index.d.ts +3 -0
  139. package/dist/server/infra/executor/pre-compaction/index.js +1 -0
  140. package/dist/server/infra/executor/pre-compaction/pre-compaction-service.d.ts +59 -0
  141. package/dist/server/infra/executor/pre-compaction/pre-compaction-service.js +124 -0
  142. package/dist/server/infra/executor/pre-compaction/prompts.d.ts +24 -0
  143. package/dist/server/infra/executor/pre-compaction/prompts.js +47 -0
  144. package/dist/server/infra/executor/query-executor.d.ts +3 -0
  145. package/dist/server/infra/executor/query-executor.js +39 -4
  146. package/dist/server/infra/http/authenticated-http-client.js +4 -0
  147. package/dist/server/infra/http/provider-model-fetcher-registry.js +1 -5
  148. package/dist/server/infra/http/provider-model-fetchers.d.ts +0 -14
  149. package/dist/server/infra/http/provider-model-fetchers.js +0 -132
  150. package/dist/server/infra/provider/provider-config-resolver.js +0 -55
  151. package/dist/server/utils/curate-result-parser.d.ts +4 -4
  152. package/dist/shared/constants/curation.d.ts +6 -0
  153. package/dist/shared/constants/curation.js +6 -0
  154. package/dist/shared/utils/escalation-utils.d.ts +59 -0
  155. package/dist/shared/utils/escalation-utils.js +141 -0
  156. package/dist/tui/components/command-input.js +1 -1
  157. package/dist/tui/components/inline-prompts/inline-confirm.js +6 -1
  158. package/dist/tui/features/commands/definitions/exit.d.ts +2 -0
  159. package/dist/tui/features/commands/definitions/exit.js +9 -0
  160. package/dist/tui/features/commands/definitions/index.js +3 -0
  161. package/dist/tui/features/exit/components/exit-flow.d.ts +10 -0
  162. package/dist/tui/features/exit/components/exit-flow.js +19 -0
  163. package/dist/tui/features/provider/components/provider-flow.js +1 -21
  164. package/oclif.manifest.json +100 -109
  165. package/package.json +11 -4
  166. package/dist/agent/infra/blob/migrations.d.ts +0 -63
  167. package/dist/agent/infra/blob/migrations.js +0 -148
  168. package/dist/agent/infra/blob/sqlite-blob-storage.d.ts +0 -82
  169. package/dist/agent/infra/blob/sqlite-blob-storage.js +0 -307
  170. package/dist/agent/infra/llm/providers/google-vertex.d.ts +0 -15
  171. package/dist/agent/infra/llm/providers/google-vertex.js +0 -36
  172. package/dist/agent/infra/storage/blob-history-storage.d.ts +0 -81
  173. package/dist/agent/infra/storage/blob-history-storage.js +0 -193
  174. package/dist/agent/infra/storage/dual-format-history-storage.d.ts +0 -83
  175. package/dist/agent/infra/storage/dual-format-history-storage.js +0 -165
  176. package/dist/agent/infra/storage/sqlite-key-storage.d.ts +0 -113
  177. package/dist/agent/infra/storage/sqlite-key-storage.js +0 -438
  178. package/dist/server/infra/provider/vertex-ai-utils.d.ts +0 -10
  179. package/dist/server/infra/provider/vertex-ai-utils.js +0 -28
  180. package/dist/tui/features/provider/components/credential-path-dialog.d.ts +0 -30
  181. package/dist/tui/features/provider/components/credential-path-dialog.js +0 -85
@@ -1,438 +0,0 @@
1
- var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
2
- if (value !== null && value !== void 0) {
3
- if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
4
- var dispose, inner;
5
- if (async) {
6
- if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
7
- dispose = value[Symbol.asyncDispose];
8
- }
9
- if (dispose === void 0) {
10
- if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
11
- dispose = value[Symbol.dispose];
12
- if (async) inner = dispose;
13
- }
14
- if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
15
- if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
16
- env.stack.push({ value: value, dispose: dispose, async: async });
17
- }
18
- else if (async) {
19
- env.stack.push({ async: true });
20
- }
21
- return value;
22
- };
23
- var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
24
- return function (env) {
25
- function fail(e) {
26
- env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
27
- env.hasError = true;
28
- }
29
- var r, s = 0;
30
- function next() {
31
- while (r = env.stack.pop()) {
32
- try {
33
- if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
34
- if (r.dispose) {
35
- var result = r.dispose.call(r.value);
36
- if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
37
- }
38
- else s |= 1;
39
- }
40
- catch (e) {
41
- fail(e);
42
- }
43
- }
44
- if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
45
- if (env.hasError) throw env.error;
46
- }
47
- return next();
48
- };
49
- })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
50
- var e = new Error(message);
51
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
- });
53
- import Database from 'better-sqlite3';
54
- import * as fs from 'node:fs/promises';
55
- import { join } from 'node:path';
56
- import { lockKeyFromStorageKey, RWLock } from '../llm/context/rw-lock.js';
57
- /**
58
- * SQLite-based key storage implementation.
59
- *
60
- * Stores key-value pairs where keys are hierarchical (StorageKey = string[])
61
- * and values are JSON-serializable objects.
62
- *
63
- * Key path structure:
64
- * - ["session", sessionId] → Session metadata
65
- * - ["message", sessionId, messageId] → Individual message
66
- * - ["part", messageId, partId] → Message part (tool output, file, etc.)
67
- *
68
- * Schema:
69
- * - key_store: key_path (primary), value (JSON blob), created_at, updated_at
70
- *
71
- * Features:
72
- * - Hierarchical key organization with prefix-based listing
73
- * - Reader-writer locks for concurrent access
74
- * - Atomic batch operations
75
- * - ACID transactions via SQLite
76
- */
77
- export class SqliteKeyStorage {
78
- db = null;
79
- dbPath;
80
- initialized = false;
81
- inMemory;
82
- storageDir;
83
- constructor(config) {
84
- this.inMemory = config?.inMemory ?? false;
85
- this.storageDir = config?.storageDir ?? '';
86
- if (!this.inMemory && !this.storageDir) {
87
- throw new Error('SqliteKeyStorage: storageDir is required when inMemory is false');
88
- }
89
- this.dbPath = this.inMemory ? ':memory:' : join(this.storageDir, config?.dbPath ?? 'context.db');
90
- }
91
- /**
92
- * Execute batch operations atomically.
93
- * All operations succeed or fail together.
94
- */
95
- async batch(operations) {
96
- const env_1 = { stack: [], error: void 0, hasError: false };
97
- try {
98
- this.ensureInitialized();
99
- if (operations.length === 0) {
100
- return;
101
- }
102
- // Acquire write lock for all affected keys
103
- const lockKey = 'batch:global';
104
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
105
- const _lock = __addDisposableResource(env_1, await RWLock.write(lockKey), false);
106
- const runBatch = this.db.transaction(() => {
107
- for (const op of operations) {
108
- const keyPath = this.serializeKey(op.key);
109
- if (op.type === 'set') {
110
- const now = Date.now();
111
- const valueJson = JSON.stringify(op.value);
112
- // Check if exists to preserve created_at
113
- const existing = this.db.prepare('SELECT created_at FROM key_store WHERE key_path = ?').get(keyPath);
114
- this.db.prepare(`
115
- INSERT INTO key_store (key_path, value, created_at, updated_at)
116
- VALUES (?, ?, ?, ?)
117
- ON CONFLICT(key_path) DO UPDATE SET
118
- value = excluded.value,
119
- updated_at = excluded.updated_at
120
- `).run(keyPath, Buffer.from(valueJson), existing?.created_at ?? now, now);
121
- }
122
- else if (op.type === 'delete') {
123
- this.db.prepare('DELETE FROM key_store WHERE key_path = ?').run(keyPath);
124
- }
125
- }
126
- });
127
- try {
128
- runBatch();
129
- }
130
- catch (error) {
131
- throw new Error(`Batch operation failed: ${error instanceof Error ? error.message : String(error)}`);
132
- }
133
- }
134
- catch (e_1) {
135
- env_1.error = e_1;
136
- env_1.hasError = true;
137
- }
138
- finally {
139
- __disposeResources(env_1);
140
- }
141
- }
142
- /**
143
- * Close the database connection.
144
- */
145
- close() {
146
- if (this.db) {
147
- this.db.close();
148
- this.db = null;
149
- this.initialized = false;
150
- }
151
- }
152
- /**
153
- * Delete a value by its composite key.
154
- */
155
- async delete(key) {
156
- const env_2 = { stack: [], error: void 0, hasError: false };
157
- try {
158
- this.ensureInitialized();
159
- const keyPath = this.serializeKey(key);
160
- const lockKey = lockKeyFromStorageKey(key);
161
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
162
- const _lock = __addDisposableResource(env_2, await RWLock.write(lockKey), false);
163
- try {
164
- const result = this.db.prepare('DELETE FROM key_store WHERE key_path = ?').run(keyPath);
165
- return result.changes > 0;
166
- }
167
- catch (error) {
168
- throw new Error(`Failed to delete key ${keyPath}: ${error instanceof Error ? error.message : String(error)}`);
169
- }
170
- }
171
- catch (e_2) {
172
- env_2.error = e_2;
173
- env_2.hasError = true;
174
- }
175
- finally {
176
- __disposeResources(env_2);
177
- }
178
- }
179
- /**
180
- * Check if a key exists.
181
- */
182
- async exists(key) {
183
- const env_3 = { stack: [], error: void 0, hasError: false };
184
- try {
185
- this.ensureInitialized();
186
- const keyPath = this.serializeKey(key);
187
- const lockKey = lockKeyFromStorageKey(key);
188
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
189
- const _lock = __addDisposableResource(env_3, await RWLock.read(lockKey), false);
190
- const row = this.db.prepare('SELECT 1 FROM key_store WHERE key_path = ?').get(keyPath);
191
- return row !== undefined;
192
- }
193
- catch (e_3) {
194
- env_3.error = e_3;
195
- env_3.hasError = true;
196
- }
197
- finally {
198
- __disposeResources(env_3);
199
- }
200
- }
201
- /**
202
- * Get a value by its composite key.
203
- */
204
- async get(key) {
205
- const env_4 = { stack: [], error: void 0, hasError: false };
206
- try {
207
- this.ensureInitialized();
208
- const keyPath = this.serializeKey(key);
209
- const lockKey = lockKeyFromStorageKey(key);
210
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
211
- const _lock = __addDisposableResource(env_4, await RWLock.read(lockKey), false);
212
- try {
213
- const row = this.db.prepare('SELECT value FROM key_store WHERE key_path = ?').get(keyPath);
214
- if (!row) {
215
- return undefined;
216
- }
217
- return JSON.parse(row.value.toString('utf8'));
218
- }
219
- catch (error) {
220
- throw new Error(`Failed to get key ${keyPath}: ${error instanceof Error ? error.message : String(error)}`);
221
- }
222
- }
223
- catch (e_4) {
224
- env_4.error = e_4;
225
- env_4.hasError = true;
226
- }
227
- finally {
228
- __disposeResources(env_4);
229
- }
230
- }
231
- /**
232
- * Initialize the storage backend.
233
- * Creates the database and runs migrations.
234
- */
235
- async initialize() {
236
- if (this.initialized) {
237
- return;
238
- }
239
- try {
240
- // Ensure storage directory exists (skip for in-memory)
241
- if (!this.inMemory) {
242
- await fs.mkdir(this.storageDir, { recursive: true });
243
- }
244
- // Open/create database
245
- this.db = new Database(this.dbPath);
246
- // Enable WAL mode for better concurrent performance
247
- this.db.pragma('journal_mode = WAL');
248
- // Create key_store table
249
- this.db.exec(`
250
- CREATE TABLE IF NOT EXISTS key_store (
251
- key_path TEXT PRIMARY KEY,
252
- value BLOB NOT NULL,
253
- created_at INTEGER NOT NULL,
254
- updated_at INTEGER NOT NULL
255
- )
256
- `);
257
- // Create index for prefix-based listing
258
- this.db.exec(`CREATE INDEX IF NOT EXISTS idx_key_store_prefix ON key_store(key_path)`);
259
- this.initialized = true;
260
- }
261
- catch (error) {
262
- throw new Error(`Failed to initialize SQLite key storage: ${error instanceof Error ? error.message : String(error)}`);
263
- }
264
- }
265
- /**
266
- * List all keys matching a prefix.
267
- */
268
- async list(prefix) {
269
- const env_5 = { stack: [], error: void 0, hasError: false };
270
- try {
271
- this.ensureInitialized();
272
- const prefixPath = this.serializeKey(prefix);
273
- const lockKey = lockKeyFromStorageKey(prefix);
274
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
275
- const _lock = __addDisposableResource(env_5, await RWLock.read(lockKey), false);
276
- try {
277
- // Use LIKE with prefix pattern for efficient prefix matching
278
- const rows = this.db.prepare('SELECT key_path FROM key_store WHERE key_path LIKE ? ORDER BY key_path').all(`${prefixPath}%`);
279
- return rows.map((row) => this.deserializeKey(row.key_path));
280
- }
281
- catch (error) {
282
- throw new Error(`Failed to list keys with prefix ${prefixPath}: ${error instanceof Error ? error.message : String(error)}`);
283
- }
284
- }
285
- catch (e_5) {
286
- env_5.error = e_5;
287
- env_5.hasError = true;
288
- }
289
- finally {
290
- __disposeResources(env_5);
291
- }
292
- }
293
- /**
294
- * List all key-value pairs matching a prefix.
295
- * More efficient than list() followed by individual get() calls.
296
- */
297
- async listWithValues(prefix) {
298
- const env_6 = { stack: [], error: void 0, hasError: false };
299
- try {
300
- this.ensureInitialized();
301
- const prefixPath = this.serializeKey(prefix);
302
- const lockKey = lockKeyFromStorageKey(prefix);
303
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
304
- const _lock = __addDisposableResource(env_6, await RWLock.read(lockKey), false);
305
- try {
306
- const rows = this.db.prepare('SELECT key_path, value FROM key_store WHERE key_path LIKE ? ORDER BY key_path').all(`${prefixPath}%`);
307
- return rows.map((row) => ({
308
- key: this.deserializeKey(row.key_path),
309
- value: JSON.parse(row.value.toString('utf8')),
310
- }));
311
- }
312
- catch (error) {
313
- throw new Error(`Failed to list keys with values for prefix ${prefixPath}: ${error instanceof Error ? error.message : String(error)}`);
314
- }
315
- }
316
- catch (e_6) {
317
- env_6.error = e_6;
318
- env_6.hasError = true;
319
- }
320
- finally {
321
- __disposeResources(env_6);
322
- }
323
- }
324
- /**
325
- * Set a value at a composite key.
326
- */
327
- async set(key, value) {
328
- const env_7 = { stack: [], error: void 0, hasError: false };
329
- try {
330
- this.ensureInitialized();
331
- const keyPath = this.serializeKey(key);
332
- const lockKey = lockKeyFromStorageKey(key);
333
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
334
- const _lock = __addDisposableResource(env_7, await RWLock.write(lockKey), false);
335
- const now = Date.now();
336
- const valueJson = JSON.stringify(value);
337
- try {
338
- // Check if exists to preserve created_at
339
- const existing = this.db.prepare('SELECT created_at FROM key_store WHERE key_path = ?').get(keyPath);
340
- this.db.prepare(`
341
- INSERT INTO key_store (key_path, value, created_at, updated_at)
342
- VALUES (?, ?, ?, ?)
343
- ON CONFLICT(key_path) DO UPDATE SET
344
- value = excluded.value,
345
- updated_at = excluded.updated_at
346
- `).run(keyPath, Buffer.from(valueJson), existing?.created_at ?? now, now);
347
- }
348
- catch (error) {
349
- throw new Error(`Failed to set key ${keyPath}: ${error instanceof Error ? error.message : String(error)}`);
350
- }
351
- }
352
- catch (e_7) {
353
- env_7.error = e_7;
354
- env_7.hasError = true;
355
- }
356
- finally {
357
- __disposeResources(env_7);
358
- }
359
- }
360
- /**
361
- * Atomic update with optimistic locking.
362
- */
363
- async update(key, updater) {
364
- const env_8 = { stack: [], error: void 0, hasError: false };
365
- try {
366
- this.ensureInitialized();
367
- const keyPath = this.serializeKey(key);
368
- const lockKey = lockKeyFromStorageKey(key);
369
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
370
- const _lock = __addDisposableResource(env_8, await RWLock.write(lockKey), false);
371
- try {
372
- // Read current value
373
- const row = this.db.prepare('SELECT value, created_at FROM key_store WHERE key_path = ?').get(keyPath);
374
- const currentValue = row ? JSON.parse(row.value.toString('utf8')) : undefined;
375
- // Apply updater function
376
- const newValue = updater(currentValue);
377
- // Write new value
378
- const now = Date.now();
379
- const valueJson = JSON.stringify(newValue);
380
- this.db.prepare(`
381
- INSERT INTO key_store (key_path, value, created_at, updated_at)
382
- VALUES (?, ?, ?, ?)
383
- ON CONFLICT(key_path) DO UPDATE SET
384
- value = excluded.value,
385
- updated_at = excluded.updated_at
386
- `).run(keyPath, Buffer.from(valueJson), row?.created_at ?? now, now);
387
- return newValue;
388
- }
389
- catch (error) {
390
- throw new Error(`Failed to update key ${keyPath}: ${error instanceof Error ? error.message : String(error)}`);
391
- }
392
- }
393
- catch (e_8) {
394
- env_8.error = e_8;
395
- env_8.hasError = true;
396
- }
397
- finally {
398
- __disposeResources(env_8);
399
- }
400
- }
401
- /**
402
- * Deserialize a key path string back to StorageKey.
403
- * Converts "message:session123:msg456" to ["message", "session123", "msg456"]
404
- */
405
- deserializeKey(keyPath) {
406
- return keyPath.split(':');
407
- }
408
- /**
409
- * Ensure storage has been initialized.
410
- */
411
- ensureInitialized() {
412
- if (!this.initialized || !this.db) {
413
- throw new Error('SqliteKeyStorage not initialized. Call initialize() first.');
414
- }
415
- }
416
- /**
417
- * Serialize a StorageKey to a string path.
418
- * Converts ["message", "session123", "msg456"] to "message:session123:msg456"
419
- */
420
- serializeKey(key) {
421
- if (key.length === 0) {
422
- throw new Error('Storage key cannot be empty');
423
- }
424
- // Validate key segments don't contain the separator
425
- for (const segment of key) {
426
- if (segment.includes(':')) {
427
- throw new Error(`Key segment cannot contain ':': ${segment}`);
428
- }
429
- }
430
- return key.join(':');
431
- }
432
- }
433
- /**
434
- * Factory function to create SqliteKeyStorage with common defaults.
435
- */
436
- export function createKeyStorage(config) {
437
- return new SqliteKeyStorage(config);
438
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * Vertex AI Utilities
3
- *
4
- * Shared helpers for Google Vertex AI provider configuration.
5
- */
6
- /**
7
- * Resolve the Google Cloud project ID for Vertex AI.
8
- * Priority: GOOGLE_CLOUD_PROJECT env var → project_id from service account JSON.
9
- */
10
- export declare function resolveVertexAiProject(credentialPath: string | undefined): string | undefined;
@@ -1,28 +0,0 @@
1
- /**
2
- * Vertex AI Utilities
3
- *
4
- * Shared helpers for Google Vertex AI provider configuration.
5
- */
6
- import { readFileSync } from 'node:fs';
7
- /**
8
- * Resolve the Google Cloud project ID for Vertex AI.
9
- * Priority: GOOGLE_CLOUD_PROJECT env var → project_id from service account JSON.
10
- */
11
- export function resolveVertexAiProject(credentialPath) {
12
- if (process.env.GOOGLE_CLOUD_PROJECT) {
13
- return process.env.GOOGLE_CLOUD_PROJECT;
14
- }
15
- const filePath = credentialPath || process.env.GOOGLE_APPLICATION_CREDENTIALS;
16
- if (filePath) {
17
- try {
18
- const content = JSON.parse(readFileSync(filePath, 'utf8'));
19
- if (typeof content.project_id === 'string' && content.project_id) {
20
- return content.project_id;
21
- }
22
- }
23
- catch {
24
- // File read/parse failed — fall through to undefined
25
- }
26
- }
27
- return undefined;
28
- }
@@ -1,30 +0,0 @@
1
- /**
2
- * CredentialPathDialog Component
3
- *
4
- * Dialog for entering a file path to a service account JSON credential.
5
- * Used by Google Vertex AI provider which uses file-based credentials
6
- * instead of API keys.
7
- * Features:
8
- * - Unmasked input (file paths, not secrets)
9
- * - Real-time validation (file existence + JSON parse)
10
- * - Error message display
11
- * - Link to service account key page
12
- */
13
- import React from 'react';
14
- import type { ProviderDTO } from '../../../../shared/transport/types/dto.js';
15
- export interface CredentialPathDialogProps {
16
- /** Whether the dialog is active for keyboard input */
17
- isActive?: boolean;
18
- /** Callback when dialog is cancelled */
19
- onCancel: () => void;
20
- /** Callback when credential path is successfully validated */
21
- onSuccess: (credentialPath: string) => void;
22
- /** The provider to connect to */
23
- provider: ProviderDTO;
24
- /** Optional validation function */
25
- validateCredential?: (path: string, provider: ProviderDTO) => Promise<{
26
- error?: string;
27
- isValid: boolean;
28
- }>;
29
- }
30
- export declare const CredentialPathDialog: React.FC<CredentialPathDialogProps>;
@@ -1,85 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- /**
3
- * CredentialPathDialog Component
4
- *
5
- * Dialog for entering a file path to a service account JSON credential.
6
- * Used by Google Vertex AI provider which uses file-based credentials
7
- * instead of API keys.
8
- * Features:
9
- * - Unmasked input (file paths, not secrets)
10
- * - Real-time validation (file existence + JSON parse)
11
- * - Error message display
12
- * - Link to service account key page
13
- */
14
- import { Box, Text, useInput } from 'ink';
15
- import { homedir } from 'node:os';
16
- import { useCallback, useState } from 'react';
17
- import { useTheme } from '../../../hooks/index.js';
18
- import { stripBracketedPaste } from '../../../utils/index.js';
19
- function expandTilde(filePath) {
20
- if (filePath === '~')
21
- return homedir();
22
- if (filePath.startsWith('~/'))
23
- return homedir() + filePath.slice(1);
24
- return filePath;
25
- }
26
- const defaultValidate = async () => ({ isValid: true });
27
- export const CredentialPathDialog = ({ isActive = true, onCancel, onSuccess, provider, validateCredential = defaultValidate, }) => {
28
- const { theme: { colors } } = useTheme();
29
- const [filePath, setFilePath] = useState('');
30
- const [isValidating, setIsValidating] = useState(false);
31
- const [error, setError] = useState();
32
- const handleSubmit = useCallback(async () => {
33
- if (!filePath.trim()) {
34
- setError('File path is required');
35
- return;
36
- }
37
- const resolvedPath = expandTilde(filePath.trim());
38
- setIsValidating(true);
39
- setError(undefined);
40
- try {
41
- const result = await validateCredential(resolvedPath, provider);
42
- if (result.isValid) {
43
- onSuccess(resolvedPath);
44
- }
45
- else {
46
- setError(result.error ?? 'Invalid credential file');
47
- }
48
- }
49
- catch (error_) {
50
- setError(error_ instanceof Error ? error_.message : 'Validation failed');
51
- }
52
- finally {
53
- setIsValidating(false);
54
- }
55
- }, [filePath, provider, validateCredential, onSuccess]);
56
- useInput((input, key) => {
57
- if (key.return && !isValidating) {
58
- handleSubmit();
59
- return;
60
- }
61
- if (key.escape) {
62
- if (filePath.length > 0) {
63
- setFilePath('');
64
- setError(undefined);
65
- }
66
- else {
67
- onCancel();
68
- }
69
- return;
70
- }
71
- if (key.backspace || key.delete) {
72
- setFilePath((prev) => prev.slice(0, -1));
73
- setError(undefined);
74
- return;
75
- }
76
- if (input && !key.ctrl && !key.meta) {
77
- const cleaned = stripBracketedPaste(input);
78
- if (cleaned) {
79
- setFilePath((prev) => prev + cleaned);
80
- setError(undefined);
81
- }
82
- }
83
- }, { isActive });
84
- return (_jsxs(Box, { borderColor: colors.border, borderStyle: "single", flexDirection: "column", paddingX: 2, paddingY: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { bold: true, color: colors.text, children: ["Connect to ", provider.name] }) }), provider.apiKeyUrl && (_jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: colors.dimText, children: ["Get your service account key at:", ' '] }), _jsx(Text, { color: colors.dimText, underline: true, children: provider.apiKeyUrl })] })), _jsx(Box, { marginBottom: 1, children: isValidating ? (_jsx(Text, { color: colors.primary, children: "\u27F3 Validating..." })) : (_jsxs(Box, { children: [_jsx(Box, { flexShrink: 0, children: _jsxs(Text, { color: colors.primary, children: ["Service account JSON key file path:", ' '] }) }), _jsx(Box, { children: _jsxs(Text, { children: [_jsx(Text, { color: filePath ? colors.text : colors.dimText, children: filePath || '/path/to/service-account.json' }), filePath && _jsx(Text, { color: colors.primary, children: "\u258E" })] }) })] })) }), _jsx(Box, { marginBottom: 1, children: error && !isValidating && (_jsxs(Text, { color: colors.warning, children: ["\u2717 ", error] })) }), !isValidating && (_jsxs(Box, { gap: 2, children: [_jsxs(Text, { color: colors.dimText, children: [_jsx(Text, { color: colors.text, children: "Enter" }), " Submit"] }), _jsxs(Text, { color: colors.dimText, children: [_jsx(Text, { color: colors.text, children: "Esc" }), " ", filePath.length > 0 ? 'Clear' : 'Cancel'] })] }))] }));
85
- };