gencode-ai 0.1.0 → 0.1.2

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 (356) hide show
  1. package/.gencode/settings.local.json +7 -0
  2. package/README.md +20 -102
  3. package/dist/agent/agent.d.ts +43 -2
  4. package/dist/agent/agent.d.ts.map +1 -1
  5. package/dist/agent/agent.js +90 -17
  6. package/dist/agent/agent.js.map +1 -1
  7. package/dist/agent/types.d.ts +9 -1
  8. package/dist/agent/types.d.ts.map +1 -1
  9. package/dist/cli/components/AllModelsSelector.d.ts +11 -0
  10. package/dist/cli/components/AllModelsSelector.d.ts.map +1 -0
  11. package/dist/cli/components/AllModelsSelector.js +153 -0
  12. package/dist/cli/components/AllModelsSelector.js.map +1 -0
  13. package/dist/cli/components/App.d.ts +8 -1
  14. package/dist/cli/components/App.d.ts.map +1 -1
  15. package/dist/cli/components/App.js +276 -40
  16. package/dist/cli/components/App.js.map +1 -1
  17. package/dist/cli/components/CommandSuggestions.d.ts.map +1 -1
  18. package/dist/cli/components/CommandSuggestions.js +3 -0
  19. package/dist/cli/components/CommandSuggestions.js.map +1 -1
  20. package/dist/cli/components/Header.d.ts +1 -1
  21. package/dist/cli/components/Header.d.ts.map +1 -1
  22. package/dist/cli/components/Header.js +4 -6
  23. package/dist/cli/components/Header.js.map +1 -1
  24. package/dist/cli/components/Logo.d.ts +1 -0
  25. package/dist/cli/components/Logo.d.ts.map +1 -1
  26. package/dist/cli/components/Logo.js +16 -3
  27. package/dist/cli/components/Logo.js.map +1 -1
  28. package/dist/cli/components/Messages.d.ts +17 -3
  29. package/dist/cli/components/Messages.d.ts.map +1 -1
  30. package/dist/cli/components/Messages.js +70 -18
  31. package/dist/cli/components/Messages.js.map +1 -1
  32. package/dist/cli/components/ModelSelector.d.ts +7 -7
  33. package/dist/cli/components/ModelSelector.d.ts.map +1 -1
  34. package/dist/cli/components/ModelSelector.js +116 -33
  35. package/dist/cli/components/ModelSelector.js.map +1 -1
  36. package/dist/cli/components/PermissionPrompt.d.ts +60 -0
  37. package/dist/cli/components/PermissionPrompt.d.ts.map +1 -0
  38. package/dist/cli/components/PermissionPrompt.js +192 -0
  39. package/dist/cli/components/PermissionPrompt.js.map +1 -0
  40. package/dist/cli/components/ProviderManager.d.ts +8 -0
  41. package/dist/cli/components/ProviderManager.d.ts.map +1 -0
  42. package/dist/cli/components/ProviderManager.js +280 -0
  43. package/dist/cli/components/ProviderManager.js.map +1 -0
  44. package/dist/cli/components/Spinner.d.ts +7 -2
  45. package/dist/cli/components/Spinner.d.ts.map +1 -1
  46. package/dist/cli/components/Spinner.js +116 -25
  47. package/dist/cli/components/Spinner.js.map +1 -1
  48. package/dist/cli/components/TodoList.d.ts +7 -0
  49. package/dist/cli/components/TodoList.d.ts.map +1 -0
  50. package/dist/cli/components/TodoList.js +34 -0
  51. package/dist/cli/components/TodoList.js.map +1 -0
  52. package/dist/cli/components/index.d.ts +1 -0
  53. package/dist/cli/components/index.d.ts.map +1 -1
  54. package/dist/cli/components/index.js +1 -0
  55. package/dist/cli/components/index.js.map +1 -1
  56. package/dist/cli/components/markdown.d.ts +9 -0
  57. package/dist/cli/components/markdown.d.ts.map +1 -0
  58. package/dist/cli/components/markdown.js +129 -0
  59. package/dist/cli/components/markdown.js.map +1 -0
  60. package/dist/cli/components/theme.d.ts +5 -0
  61. package/dist/cli/components/theme.d.ts.map +1 -1
  62. package/dist/cli/components/theme.js +7 -0
  63. package/dist/cli/components/theme.js.map +1 -1
  64. package/dist/cli/index.js +66 -12
  65. package/dist/cli/index.js.map +1 -1
  66. package/dist/config/index.d.ts +14 -4
  67. package/dist/config/index.d.ts.map +1 -1
  68. package/dist/config/index.js +19 -3
  69. package/dist/config/index.js.map +1 -1
  70. package/dist/config/levels.d.ts +49 -0
  71. package/dist/config/levels.d.ts.map +1 -0
  72. package/dist/config/levels.js +222 -0
  73. package/dist/config/levels.js.map +1 -0
  74. package/dist/config/loader.d.ts +46 -0
  75. package/dist/config/loader.d.ts.map +1 -0
  76. package/dist/config/loader.js +153 -0
  77. package/dist/config/loader.js.map +1 -0
  78. package/dist/config/manager.d.ts +115 -15
  79. package/dist/config/manager.d.ts.map +1 -1
  80. package/dist/config/manager.js +260 -34
  81. package/dist/config/manager.js.map +1 -1
  82. package/dist/config/manager.test.d.ts +5 -0
  83. package/dist/config/manager.test.d.ts.map +1 -0
  84. package/dist/config/manager.test.js +192 -0
  85. package/dist/config/manager.test.js.map +1 -0
  86. package/dist/config/merger.d.ts +56 -0
  87. package/dist/config/merger.d.ts.map +1 -0
  88. package/dist/config/merger.js +177 -0
  89. package/dist/config/merger.js.map +1 -0
  90. package/dist/config/providers-config.d.ts +28 -0
  91. package/dist/config/providers-config.d.ts.map +1 -0
  92. package/dist/config/providers-config.js +79 -0
  93. package/dist/config/providers-config.js.map +1 -0
  94. package/dist/config/test-utils.d.ts +24 -0
  95. package/dist/config/test-utils.d.ts.map +1 -0
  96. package/dist/config/test-utils.js +55 -0
  97. package/dist/config/test-utils.js.map +1 -0
  98. package/dist/config/types.d.ts +108 -9
  99. package/dist/config/types.d.ts.map +1 -1
  100. package/dist/config/types.js +53 -2
  101. package/dist/config/types.js.map +1 -1
  102. package/dist/memory/import-resolver.d.ts +46 -0
  103. package/dist/memory/import-resolver.d.ts.map +1 -0
  104. package/dist/memory/import-resolver.js +117 -0
  105. package/dist/memory/import-resolver.js.map +1 -0
  106. package/dist/memory/index.d.ts +7 -6
  107. package/dist/memory/index.d.ts.map +1 -1
  108. package/dist/memory/index.js +7 -5
  109. package/dist/memory/index.js.map +1 -1
  110. package/dist/memory/init-prompt.d.ts +22 -0
  111. package/dist/memory/init-prompt.d.ts.map +1 -0
  112. package/dist/memory/init-prompt.js +103 -0
  113. package/dist/memory/init-prompt.js.map +1 -0
  114. package/dist/memory/memory-manager.d.ts +119 -0
  115. package/dist/memory/memory-manager.d.ts.map +1 -0
  116. package/dist/memory/memory-manager.js +587 -0
  117. package/dist/memory/memory-manager.js.map +1 -0
  118. package/dist/memory/rules-parser.d.ts +38 -0
  119. package/dist/memory/rules-parser.d.ts.map +1 -0
  120. package/dist/memory/rules-parser.js +69 -0
  121. package/dist/memory/rules-parser.js.map +1 -0
  122. package/dist/memory/test-utils.d.ts +20 -0
  123. package/dist/memory/test-utils.d.ts.map +1 -0
  124. package/dist/memory/test-utils.js +44 -0
  125. package/dist/memory/test-utils.js.map +1 -0
  126. package/dist/memory/types.d.ts +70 -63
  127. package/dist/memory/types.d.ts.map +1 -1
  128. package/dist/memory/types.js +42 -2
  129. package/dist/memory/types.js.map +1 -1
  130. package/dist/permissions/audit.d.ts +82 -0
  131. package/dist/permissions/audit.d.ts.map +1 -0
  132. package/dist/permissions/audit.js +229 -0
  133. package/dist/permissions/audit.js.map +1 -0
  134. package/dist/permissions/index.d.ts +11 -1
  135. package/dist/permissions/index.d.ts.map +1 -1
  136. package/dist/permissions/index.js +15 -0
  137. package/dist/permissions/index.js.map +1 -1
  138. package/dist/permissions/manager.d.ts +149 -13
  139. package/dist/permissions/manager.d.ts.map +1 -1
  140. package/dist/permissions/manager.js +480 -35
  141. package/dist/permissions/manager.js.map +1 -1
  142. package/dist/permissions/manager.test.d.ts +5 -0
  143. package/dist/permissions/manager.test.d.ts.map +1 -0
  144. package/dist/permissions/manager.test.js +213 -0
  145. package/dist/permissions/manager.test.js.map +1 -0
  146. package/dist/permissions/persistence.d.ts +74 -0
  147. package/dist/permissions/persistence.d.ts.map +1 -0
  148. package/dist/permissions/persistence.js +248 -0
  149. package/dist/permissions/persistence.js.map +1 -0
  150. package/dist/permissions/persistence.test.d.ts +5 -0
  151. package/dist/permissions/persistence.test.d.ts.map +1 -0
  152. package/dist/permissions/persistence.test.js +171 -0
  153. package/dist/permissions/persistence.test.js.map +1 -0
  154. package/dist/permissions/prompt-matcher.d.ts +64 -0
  155. package/dist/permissions/prompt-matcher.d.ts.map +1 -0
  156. package/dist/permissions/prompt-matcher.js +415 -0
  157. package/dist/permissions/prompt-matcher.js.map +1 -0
  158. package/dist/permissions/prompt-matcher.test.d.ts +5 -0
  159. package/dist/permissions/prompt-matcher.test.d.ts.map +1 -0
  160. package/dist/permissions/prompt-matcher.test.js +107 -0
  161. package/dist/permissions/prompt-matcher.test.js.map +1 -0
  162. package/dist/permissions/types.d.ts +157 -0
  163. package/dist/permissions/types.d.ts.map +1 -1
  164. package/dist/permissions/types.js +43 -8
  165. package/dist/permissions/types.js.map +1 -1
  166. package/dist/prompts/index.d.ts +92 -0
  167. package/dist/prompts/index.d.ts.map +1 -0
  168. package/dist/prompts/index.js +241 -0
  169. package/dist/prompts/index.js.map +1 -0
  170. package/dist/providers/gemini.d.ts.map +1 -1
  171. package/dist/providers/gemini.js +14 -3
  172. package/dist/providers/gemini.js.map +1 -1
  173. package/dist/providers/index.d.ts +5 -3
  174. package/dist/providers/index.d.ts.map +1 -1
  175. package/dist/providers/index.js +13 -1
  176. package/dist/providers/index.js.map +1 -1
  177. package/dist/providers/registry.d.ts +66 -0
  178. package/dist/providers/registry.d.ts.map +1 -0
  179. package/dist/providers/registry.js +158 -0
  180. package/dist/providers/registry.js.map +1 -0
  181. package/dist/providers/search/brave.d.ts +14 -0
  182. package/dist/providers/search/brave.d.ts.map +1 -0
  183. package/dist/providers/search/brave.js +87 -0
  184. package/dist/providers/search/brave.js.map +1 -0
  185. package/dist/providers/search/exa.d.ts +12 -0
  186. package/dist/providers/search/exa.d.ts.map +1 -0
  187. package/dist/providers/search/exa.js +158 -0
  188. package/dist/providers/search/exa.js.map +1 -0
  189. package/dist/providers/search/index.d.ts +31 -0
  190. package/dist/providers/search/index.d.ts.map +1 -0
  191. package/dist/providers/search/index.js +75 -0
  192. package/dist/providers/search/index.js.map +1 -0
  193. package/dist/providers/search/serper.d.ts +14 -0
  194. package/dist/providers/search/serper.d.ts.map +1 -0
  195. package/dist/providers/search/serper.js +87 -0
  196. package/dist/providers/search/serper.js.map +1 -0
  197. package/dist/providers/search/types.d.ts +21 -0
  198. package/dist/providers/search/types.d.ts.map +1 -0
  199. package/dist/providers/search/types.js +5 -0
  200. package/dist/providers/search/types.js.map +1 -0
  201. package/dist/providers/store.d.ts +104 -0
  202. package/dist/providers/store.d.ts.map +1 -0
  203. package/dist/providers/store.js +171 -0
  204. package/dist/providers/store.js.map +1 -0
  205. package/dist/providers/types.d.ts +7 -1
  206. package/dist/providers/types.d.ts.map +1 -1
  207. package/dist/providers/vertex-ai.d.ts +33 -0
  208. package/dist/providers/vertex-ai.d.ts.map +1 -0
  209. package/dist/providers/vertex-ai.js +407 -0
  210. package/dist/providers/vertex-ai.js.map +1 -0
  211. package/dist/tools/builtin/bash.d.ts.map +1 -1
  212. package/dist/tools/builtin/bash.js +2 -1
  213. package/dist/tools/builtin/bash.js.map +1 -1
  214. package/dist/tools/builtin/edit.d.ts.map +1 -1
  215. package/dist/tools/builtin/edit.js +2 -1
  216. package/dist/tools/builtin/edit.js.map +1 -1
  217. package/dist/tools/builtin/glob.d.ts.map +1 -1
  218. package/dist/tools/builtin/glob.js +2 -1
  219. package/dist/tools/builtin/glob.js.map +1 -1
  220. package/dist/tools/builtin/grep.d.ts.map +1 -1
  221. package/dist/tools/builtin/grep.js +2 -1
  222. package/dist/tools/builtin/grep.js.map +1 -1
  223. package/dist/tools/builtin/read.d.ts.map +1 -1
  224. package/dist/tools/builtin/read.js +2 -1
  225. package/dist/tools/builtin/read.js.map +1 -1
  226. package/dist/tools/builtin/todowrite.d.ts +15 -0
  227. package/dist/tools/builtin/todowrite.d.ts.map +1 -0
  228. package/dist/tools/builtin/todowrite.js +88 -0
  229. package/dist/tools/builtin/todowrite.js.map +1 -0
  230. package/dist/tools/builtin/webfetch.d.ts +20 -0
  231. package/dist/tools/builtin/webfetch.d.ts.map +1 -0
  232. package/dist/tools/builtin/webfetch.js +228 -0
  233. package/dist/tools/builtin/webfetch.js.map +1 -0
  234. package/dist/tools/builtin/websearch.d.ts +17 -0
  235. package/dist/tools/builtin/websearch.d.ts.map +1 -0
  236. package/dist/tools/builtin/websearch.js +87 -0
  237. package/dist/tools/builtin/websearch.js.map +1 -0
  238. package/dist/tools/builtin/write.d.ts.map +1 -1
  239. package/dist/tools/builtin/write.js +2 -1
  240. package/dist/tools/builtin/write.js.map +1 -1
  241. package/dist/tools/index.d.ts +18 -0
  242. package/dist/tools/index.d.ts.map +1 -1
  243. package/dist/tools/index.js +28 -2
  244. package/dist/tools/index.js.map +1 -1
  245. package/dist/tools/types.d.ts +41 -0
  246. package/dist/tools/types.d.ts.map +1 -1
  247. package/dist/tools/types.js +16 -0
  248. package/dist/tools/types.js.map +1 -1
  249. package/dist/tools/utils/ssrf.d.ts +18 -0
  250. package/dist/tools/utils/ssrf.d.ts.map +1 -0
  251. package/dist/tools/utils/ssrf.js +70 -0
  252. package/dist/tools/utils/ssrf.js.map +1 -0
  253. package/docs/README.md +5 -4
  254. package/docs/config-system-comparison.md +707 -0
  255. package/docs/memory-system.md +238 -0
  256. package/docs/permissions.md +368 -0
  257. package/docs/proposals/0001-web-fetch-tool.md +32 -2
  258. package/docs/proposals/0002-web-search-tool.md +59 -2
  259. package/docs/proposals/0005-todo-system.md +350 -85
  260. package/docs/proposals/0006-memory-system.md +11 -10
  261. package/docs/proposals/0012-ask-user-question.md +941 -206
  262. package/docs/proposals/0023-permission-enhancements.md +61 -2
  263. package/docs/proposals/0041-configuration-system.md +587 -0
  264. package/docs/proposals/0042-prompt-optimization.md +866 -0
  265. package/docs/proposals/README.md +8 -6
  266. package/docs/providers.md +220 -0
  267. package/jest.config.js +26 -0
  268. package/package.json +14 -3
  269. package/src/agent/agent.ts +120 -18
  270. package/src/agent/types.ts +9 -1
  271. package/src/cli/components/App.tsx +369 -47
  272. package/src/cli/components/CommandSuggestions.tsx +3 -0
  273. package/src/cli/components/Header.tsx +11 -17
  274. package/src/cli/components/Logo.tsx +76 -9
  275. package/src/cli/components/Messages.tsx +146 -38
  276. package/src/cli/components/ModelSelector.tsx +169 -52
  277. package/src/cli/components/PermissionPrompt.tsx +388 -0
  278. package/src/cli/components/ProviderManager.tsx +534 -0
  279. package/src/cli/components/Spinner.tsx +138 -25
  280. package/src/cli/components/TodoList.tsx +54 -0
  281. package/src/cli/components/index.ts +6 -0
  282. package/src/cli/components/markdown.ts +157 -0
  283. package/src/cli/components/theme.ts +7 -0
  284. package/src/cli/index.tsx +76 -13
  285. package/src/config/index.ts +79 -4
  286. package/src/config/levels.test.ts +163 -0
  287. package/src/config/levels.ts +285 -0
  288. package/src/config/loader.test.ts +120 -0
  289. package/src/config/loader.ts +178 -0
  290. package/src/config/manager.test.ts +215 -0
  291. package/src/config/manager.ts +328 -40
  292. package/src/config/merger.test.ts +360 -0
  293. package/src/config/merger.ts +221 -0
  294. package/src/config/providers-config.ts +85 -0
  295. package/src/config/test-utils.ts +79 -0
  296. package/src/config/types.ts +186 -9
  297. package/src/memory/import-resolver.test.ts +117 -0
  298. package/src/memory/import-resolver.ts +149 -0
  299. package/src/memory/index.ts +11 -0
  300. package/src/memory/init-prompt.ts +113 -0
  301. package/src/memory/memory-manager.test.ts +198 -0
  302. package/src/memory/memory-manager.ts +716 -0
  303. package/src/memory/rules-parser.test.ts +182 -0
  304. package/src/memory/rules-parser.ts +82 -0
  305. package/src/memory/test-utils.ts +60 -0
  306. package/src/memory/types.ts +119 -0
  307. package/src/permissions/audit.ts +284 -0
  308. package/src/permissions/index.ts +20 -1
  309. package/src/permissions/manager.test.ts +260 -0
  310. package/src/permissions/manager.ts +592 -40
  311. package/src/permissions/persistence.test.ts +220 -0
  312. package/src/permissions/persistence.ts +301 -0
  313. package/src/permissions/prompt-matcher.test.ts +213 -0
  314. package/src/permissions/prompt-matcher.ts +472 -0
  315. package/src/permissions/types.ts +236 -8
  316. package/src/prompts/index.test.ts +279 -0
  317. package/src/prompts/index.ts +306 -0
  318. package/src/prompts/system/anthropic.txt +29 -0
  319. package/src/prompts/system/base.txt +124 -0
  320. package/src/prompts/system/gemini.txt +35 -0
  321. package/src/prompts/system/generic.txt +128 -0
  322. package/src/prompts/system/openai.txt +29 -0
  323. package/src/prompts/tools/bash.txt +60 -0
  324. package/src/prompts/tools/edit.txt +29 -0
  325. package/src/prompts/tools/glob.txt +35 -0
  326. package/src/prompts/tools/grep.txt +43 -0
  327. package/src/prompts/tools/read.txt +22 -0
  328. package/src/prompts/tools/todowrite.txt +71 -0
  329. package/src/prompts/tools/webfetch.txt +34 -0
  330. package/src/prompts/tools/websearch.txt +41 -0
  331. package/src/prompts/tools/write.txt +23 -0
  332. package/src/providers/gemini.ts +20 -4
  333. package/src/providers/index.ts +18 -3
  334. package/src/providers/registry.ts +198 -0
  335. package/src/providers/search/brave.ts +132 -0
  336. package/src/providers/search/exa.ts +217 -0
  337. package/src/providers/search/index.ts +79 -0
  338. package/src/providers/search/serper.ts +133 -0
  339. package/src/providers/search/types.ts +24 -0
  340. package/src/providers/store.ts +216 -0
  341. package/src/providers/types.ts +9 -1
  342. package/src/providers/vertex-ai.ts +594 -0
  343. package/src/tools/builtin/bash.ts +2 -1
  344. package/src/tools/builtin/edit.ts +2 -1
  345. package/src/tools/builtin/glob.ts +2 -1
  346. package/src/tools/builtin/grep.ts +2 -1
  347. package/src/tools/builtin/read.ts +2 -1
  348. package/src/tools/builtin/todowrite.ts +102 -0
  349. package/src/tools/builtin/webfetch.ts +261 -0
  350. package/src/tools/builtin/websearch.ts +103 -0
  351. package/src/tools/builtin/write.ts +2 -1
  352. package/src/tools/index.ts +28 -2
  353. package/src/tools/types.ts +32 -0
  354. package/src/tools/utils/ssrf.ts +79 -0
  355. package/tsconfig.json +1 -1
  356. package/CLAUDE.md +0 -70
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Serper.dev Search Provider
3
+ *
4
+ * Uses Google Search via Serper.dev API.
5
+ * Requires SERPER_API_KEY environment variable.
6
+ */
7
+
8
+ import type { SearchProvider, SearchResult, SearchOptions } from './types.js';
9
+
10
+ const API_CONFIG = {
11
+ BASE_URL: 'https://google.serper.dev',
12
+ ENDPOINT: '/search',
13
+ DEFAULT_NUM_RESULTS: 10,
14
+ DEFAULT_TIMEOUT: 10000,
15
+ } as const;
16
+
17
+ interface SerperRequest {
18
+ q: string;
19
+ num?: number;
20
+ }
21
+
22
+ interface SerperOrganicResult {
23
+ title: string;
24
+ link: string;
25
+ snippet: string;
26
+ position: number;
27
+ }
28
+
29
+ interface SerperResponse {
30
+ organic: SerperOrganicResult[];
31
+ searchParameters: {
32
+ q: string;
33
+ type: string;
34
+ num: number;
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Filter results by allowed/blocked domains
40
+ */
41
+ function filterByDomain(results: SearchResult[], options?: SearchOptions): SearchResult[] {
42
+ if (!options?.allowedDomains?.length && !options?.blockedDomains?.length) {
43
+ return results;
44
+ }
45
+
46
+ return results.filter((result) => {
47
+ try {
48
+ const domain = new URL(result.url).hostname;
49
+
50
+ if (options.allowedDomains?.length) {
51
+ return options.allowedDomains.some(
52
+ (allowed) => domain === allowed || domain.endsWith('.' + allowed)
53
+ );
54
+ }
55
+
56
+ if (options.blockedDomains?.length) {
57
+ return !options.blockedDomains.some(
58
+ (blocked) => domain === blocked || domain.endsWith('.' + blocked)
59
+ );
60
+ }
61
+
62
+ return true;
63
+ } catch {
64
+ return true;
65
+ }
66
+ });
67
+ }
68
+
69
+ export class SerperProvider implements SearchProvider {
70
+ readonly name = 'serper' as const;
71
+ private apiKey: string;
72
+
73
+ constructor(apiKey?: string) {
74
+ this.apiKey = apiKey ?? process.env.SERPER_API_KEY ?? '';
75
+ if (!this.apiKey) {
76
+ throw new Error('SERPER_API_KEY environment variable is required for Serper provider');
77
+ }
78
+ }
79
+
80
+ async search(query: string, options?: SearchOptions): Promise<SearchResult[]> {
81
+ const searchRequest: SerperRequest = {
82
+ q: query,
83
+ num: options?.numResults ?? API_CONFIG.DEFAULT_NUM_RESULTS,
84
+ };
85
+
86
+ const controller = new AbortController();
87
+ const timeoutId = setTimeout(
88
+ () => controller.abort(),
89
+ options?.timeout ?? API_CONFIG.DEFAULT_TIMEOUT
90
+ );
91
+
92
+ try {
93
+ const signals = options?.abortSignal
94
+ ? [controller.signal, options.abortSignal]
95
+ : [controller.signal];
96
+
97
+ const response = await fetch(`${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINT}`, {
98
+ method: 'POST',
99
+ headers: {
100
+ 'X-API-KEY': this.apiKey,
101
+ 'Content-Type': 'application/json',
102
+ },
103
+ body: JSON.stringify(searchRequest),
104
+ signal: AbortSignal.any(signals),
105
+ });
106
+
107
+ clearTimeout(timeoutId);
108
+
109
+ if (!response.ok) {
110
+ const errorText = await response.text();
111
+ throw new Error(`Serper search error (${response.status}): ${errorText}`);
112
+ }
113
+
114
+ const data = await response.json() as SerperResponse;
115
+
116
+ const results: SearchResult[] = (data.organic || []).map((item) => ({
117
+ title: item.title,
118
+ url: item.link,
119
+ snippet: item.snippet,
120
+ }));
121
+
122
+ return filterByDomain(results, options);
123
+ } catch (error) {
124
+ clearTimeout(timeoutId);
125
+
126
+ if (error instanceof Error && error.name === 'AbortError') {
127
+ throw new Error('Search request timed out');
128
+ }
129
+
130
+ throw error;
131
+ }
132
+ }
133
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Search Provider Types
3
+ */
4
+
5
+ export type SearchProviderName = 'exa' | 'serper' | 'brave';
6
+
7
+ export interface SearchResult {
8
+ title: string;
9
+ url: string;
10
+ snippet: string;
11
+ }
12
+
13
+ export interface SearchOptions {
14
+ numResults?: number;
15
+ allowedDomains?: string[];
16
+ blockedDomains?: string[];
17
+ timeout?: number;
18
+ abortSignal?: AbortSignal;
19
+ }
20
+
21
+ export interface SearchProvider {
22
+ readonly name: SearchProviderName;
23
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
24
+ }
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Provider Store - Manages provider connections and model cache
3
+ *
4
+ * Storage location: ~/.gencode/providers.json
5
+ */
6
+
7
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
8
+ import { join } from 'path';
9
+ import { homedir } from 'os';
10
+ import type { ProviderName } from './index.js';
11
+ import type { SearchProviderName } from './search/types.js';
12
+
13
+ export interface ModelInfo {
14
+ id: string;
15
+ name: string;
16
+ }
17
+
18
+ export interface ProviderConnection {
19
+ method: string;
20
+ connectedAt: string;
21
+ }
22
+
23
+ export interface ModelCache {
24
+ cachedAt: string;
25
+ list: ModelInfo[];
26
+ }
27
+
28
+ export interface ProvidersConfig {
29
+ connections: Record<string, ProviderConnection>;
30
+ models: Record<string, ModelCache>;
31
+ searchProvider?: SearchProviderName;
32
+ }
33
+
34
+ const CONFIG_DIR = join(homedir(), '.gencode');
35
+ const CONFIG_FILE = join(CONFIG_DIR, 'providers.json');
36
+
37
+ /**
38
+ * Provider Store - manages connection state and model cache
39
+ */
40
+ export class ProviderStore {
41
+ private config: ProvidersConfig;
42
+
43
+ constructor() {
44
+ this.config = this.load();
45
+ }
46
+
47
+ /**
48
+ * Load configuration from disk
49
+ */
50
+ private load(): ProvidersConfig {
51
+ try {
52
+ if (existsSync(CONFIG_FILE)) {
53
+ const data = readFileSync(CONFIG_FILE, 'utf-8');
54
+ return JSON.parse(data);
55
+ }
56
+ } catch {
57
+ // Ignore parse errors, start fresh
58
+ }
59
+ return { connections: {}, models: {} };
60
+ }
61
+
62
+ /**
63
+ * Save configuration to disk
64
+ */
65
+ private save(): void {
66
+ try {
67
+ if (!existsSync(CONFIG_DIR)) {
68
+ mkdirSync(CONFIG_DIR, { recursive: true });
69
+ }
70
+ writeFileSync(CONFIG_FILE, JSON.stringify(this.config, null, 2));
71
+ } catch {
72
+ // Silently fail if we can't write
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Check if a provider is connected
78
+ */
79
+ isConnected(providerId: ProviderName): boolean {
80
+ return !!this.config.connections[providerId];
81
+ }
82
+
83
+ /**
84
+ * Get connection info for a provider
85
+ */
86
+ getConnection(providerId: ProviderName): ProviderConnection | undefined {
87
+ return this.config.connections[providerId];
88
+ }
89
+
90
+ /**
91
+ * Get all connected provider IDs
92
+ */
93
+ getConnectedProviders(): ProviderName[] {
94
+ return Object.keys(this.config.connections) as ProviderName[];
95
+ }
96
+
97
+ /**
98
+ * Connect a provider
99
+ */
100
+ connect(providerId: ProviderName, method: string): void {
101
+ this.config.connections[providerId] = {
102
+ method,
103
+ connectedAt: new Date().toISOString(),
104
+ };
105
+ this.save();
106
+ }
107
+
108
+ /**
109
+ * Disconnect a provider
110
+ */
111
+ disconnect(providerId: ProviderName): void {
112
+ delete this.config.connections[providerId];
113
+ delete this.config.models[providerId];
114
+ this.save();
115
+ }
116
+
117
+ /**
118
+ * Get cached models for a provider
119
+ */
120
+ getModels(providerId: ProviderName): ModelInfo[] {
121
+ return this.config.models[providerId]?.list ?? [];
122
+ }
123
+
124
+ /**
125
+ * Get all cached models grouped by provider
126
+ */
127
+ getAllModels(): Record<ProviderName, ModelInfo[]> {
128
+ const result: Record<string, ModelInfo[]> = {};
129
+ for (const [providerId, cache] of Object.entries(this.config.models)) {
130
+ result[providerId] = cache.list;
131
+ }
132
+ return result as Record<ProviderName, ModelInfo[]>;
133
+ }
134
+
135
+ /**
136
+ * Cache models for a provider
137
+ */
138
+ cacheModels(providerId: ProviderName, models: ModelInfo[]): void {
139
+ this.config.models[providerId] = {
140
+ cachedAt: new Date().toISOString(),
141
+ list: models,
142
+ };
143
+ this.save();
144
+ }
145
+
146
+ /**
147
+ * Get cache timestamp for a provider
148
+ */
149
+ getCacheTime(providerId: ProviderName): Date | undefined {
150
+ const cache = this.config.models[providerId];
151
+ return cache ? new Date(cache.cachedAt) : undefined;
152
+ }
153
+
154
+ /**
155
+ * Check if model cache is stale (older than 24 hours)
156
+ */
157
+ isCacheStale(providerId: ProviderName): boolean {
158
+ const cacheTime = this.getCacheTime(providerId);
159
+ if (!cacheTime) return true;
160
+ const hoursSinceCache = (Date.now() - cacheTime.getTime()) / (1000 * 60 * 60);
161
+ return hoursSinceCache > 24;
162
+ }
163
+
164
+ /**
165
+ * Get total model count across all connected providers
166
+ */
167
+ getTotalModelCount(): number {
168
+ return Object.values(this.config.models).reduce(
169
+ (sum, cache) => sum + cache.list.length,
170
+ 0
171
+ );
172
+ }
173
+
174
+ /**
175
+ * Get model count for a specific provider
176
+ */
177
+ getModelCount(providerId: ProviderName): number {
178
+ return this.config.models[providerId]?.list.length ?? 0;
179
+ }
180
+
181
+ /**
182
+ * Get the configured search provider
183
+ */
184
+ getSearchProvider(): SearchProviderName | undefined {
185
+ return this.config.searchProvider;
186
+ }
187
+
188
+ /**
189
+ * Set the search provider
190
+ */
191
+ setSearchProvider(id: SearchProviderName): void {
192
+ this.config.searchProvider = id;
193
+ this.save();
194
+ }
195
+
196
+ /**
197
+ * Clear the search provider (use default)
198
+ */
199
+ clearSearchProvider(): void {
200
+ delete this.config.searchProvider;
201
+ this.save();
202
+ }
203
+ }
204
+
205
+ // Singleton instance
206
+ let storeInstance: ProviderStore | null = null;
207
+
208
+ /**
209
+ * Get the singleton provider store instance
210
+ */
211
+ export function getProviderStore(): ProviderStore {
212
+ if (!storeInstance) {
213
+ storeInstance = new ProviderStore();
214
+ }
215
+ return storeInstance;
216
+ }
@@ -19,6 +19,8 @@ export interface ToolUseContent {
19
19
  id: string;
20
20
  name: string;
21
21
  input: Record<string, unknown>;
22
+ // Gemini 3+ thought signature for maintaining reasoning chain
23
+ thoughtSignature?: string;
22
24
  }
23
25
 
24
26
  export interface ToolResultContent {
@@ -178,4 +180,10 @@ export interface GeminiConfig {
178
180
  apiKey?: string;
179
181
  }
180
182
 
181
- export type ProviderConfig = OpenAIConfig | AnthropicConfig | GeminiConfig;
183
+ export interface VertexAIConfig {
184
+ projectId?: string;
185
+ region?: string;
186
+ accessToken?: string;
187
+ }
188
+
189
+ export type ProviderConfig = OpenAIConfig | AnthropicConfig | GeminiConfig | VertexAIConfig;