gencode-ai 0.1.0 → 0.1.1

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 (149) hide show
  1. package/README.md +8 -90
  2. package/dist/agent/agent.d.ts +1 -1
  3. package/dist/agent/agent.d.ts.map +1 -1
  4. package/dist/agent/agent.js +8 -2
  5. package/dist/agent/agent.js.map +1 -1
  6. package/dist/agent/types.d.ts +9 -1
  7. package/dist/agent/types.d.ts.map +1 -1
  8. package/dist/cli/components/AllModelsSelector.d.ts +11 -0
  9. package/dist/cli/components/AllModelsSelector.d.ts.map +1 -0
  10. package/dist/cli/components/AllModelsSelector.js +153 -0
  11. package/dist/cli/components/AllModelsSelector.js.map +1 -0
  12. package/dist/cli/components/App.d.ts.map +1 -1
  13. package/dist/cli/components/App.js +59 -25
  14. package/dist/cli/components/App.js.map +1 -1
  15. package/dist/cli/components/CommandSuggestions.d.ts.map +1 -1
  16. package/dist/cli/components/CommandSuggestions.js +1 -0
  17. package/dist/cli/components/CommandSuggestions.js.map +1 -1
  18. package/dist/cli/components/Messages.d.ts +15 -1
  19. package/dist/cli/components/Messages.d.ts.map +1 -1
  20. package/dist/cli/components/Messages.js +41 -15
  21. package/dist/cli/components/Messages.js.map +1 -1
  22. package/dist/cli/components/ModelSelector.d.ts +7 -7
  23. package/dist/cli/components/ModelSelector.d.ts.map +1 -1
  24. package/dist/cli/components/ModelSelector.js +116 -33
  25. package/dist/cli/components/ModelSelector.js.map +1 -1
  26. package/dist/cli/components/ProviderManager.d.ts +8 -0
  27. package/dist/cli/components/ProviderManager.d.ts.map +1 -0
  28. package/dist/cli/components/ProviderManager.js +280 -0
  29. package/dist/cli/components/ProviderManager.js.map +1 -0
  30. package/dist/cli/components/markdown.d.ts +9 -0
  31. package/dist/cli/components/markdown.d.ts.map +1 -0
  32. package/dist/cli/components/markdown.js +129 -0
  33. package/dist/cli/components/markdown.js.map +1 -0
  34. package/dist/cli/components/theme.d.ts +5 -0
  35. package/dist/cli/components/theme.d.ts.map +1 -1
  36. package/dist/cli/components/theme.js +7 -0
  37. package/dist/cli/components/theme.js.map +1 -1
  38. package/dist/cli/index.js +19 -5
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/config/index.d.ts +3 -2
  41. package/dist/config/index.d.ts.map +1 -1
  42. package/dist/config/index.js +2 -1
  43. package/dist/config/index.js.map +1 -1
  44. package/dist/config/providers-config.d.ts +28 -0
  45. package/dist/config/providers-config.d.ts.map +1 -0
  46. package/dist/config/providers-config.js +79 -0
  47. package/dist/config/providers-config.js.map +1 -0
  48. package/dist/config/types.d.ts +31 -1
  49. package/dist/config/types.d.ts.map +1 -1
  50. package/dist/config/types.js +1 -0
  51. package/dist/config/types.js.map +1 -1
  52. package/dist/providers/gemini.d.ts.map +1 -1
  53. package/dist/providers/gemini.js +14 -3
  54. package/dist/providers/gemini.js.map +1 -1
  55. package/dist/providers/index.d.ts +5 -3
  56. package/dist/providers/index.d.ts.map +1 -1
  57. package/dist/providers/index.js +13 -1
  58. package/dist/providers/index.js.map +1 -1
  59. package/dist/providers/registry.d.ts +66 -0
  60. package/dist/providers/registry.d.ts.map +1 -0
  61. package/dist/providers/registry.js +158 -0
  62. package/dist/providers/registry.js.map +1 -0
  63. package/dist/providers/search/brave.d.ts +14 -0
  64. package/dist/providers/search/brave.d.ts.map +1 -0
  65. package/dist/providers/search/brave.js +87 -0
  66. package/dist/providers/search/brave.js.map +1 -0
  67. package/dist/providers/search/exa.d.ts +12 -0
  68. package/dist/providers/search/exa.d.ts.map +1 -0
  69. package/dist/providers/search/exa.js +158 -0
  70. package/dist/providers/search/exa.js.map +1 -0
  71. package/dist/providers/search/index.d.ts +31 -0
  72. package/dist/providers/search/index.d.ts.map +1 -0
  73. package/dist/providers/search/index.js +75 -0
  74. package/dist/providers/search/index.js.map +1 -0
  75. package/dist/providers/search/serper.d.ts +14 -0
  76. package/dist/providers/search/serper.d.ts.map +1 -0
  77. package/dist/providers/search/serper.js +87 -0
  78. package/dist/providers/search/serper.js.map +1 -0
  79. package/dist/providers/search/types.d.ts +21 -0
  80. package/dist/providers/search/types.d.ts.map +1 -0
  81. package/dist/providers/search/types.js +5 -0
  82. package/dist/providers/search/types.js.map +1 -0
  83. package/dist/providers/store.d.ts +104 -0
  84. package/dist/providers/store.d.ts.map +1 -0
  85. package/dist/providers/store.js +171 -0
  86. package/dist/providers/store.js.map +1 -0
  87. package/dist/providers/types.d.ts +7 -1
  88. package/dist/providers/types.d.ts.map +1 -1
  89. package/dist/providers/vertex-ai.d.ts +33 -0
  90. package/dist/providers/vertex-ai.d.ts.map +1 -0
  91. package/dist/providers/vertex-ai.js +407 -0
  92. package/dist/providers/vertex-ai.js.map +1 -0
  93. package/dist/tools/builtin/webfetch.d.ts +20 -0
  94. package/dist/tools/builtin/webfetch.d.ts.map +1 -0
  95. package/dist/tools/builtin/webfetch.js +231 -0
  96. package/dist/tools/builtin/webfetch.js.map +1 -0
  97. package/dist/tools/builtin/websearch.d.ts +17 -0
  98. package/dist/tools/builtin/websearch.d.ts.map +1 -0
  99. package/dist/tools/builtin/websearch.js +101 -0
  100. package/dist/tools/builtin/websearch.js.map +1 -0
  101. package/dist/tools/index.d.ts +11 -0
  102. package/dist/tools/index.d.ts.map +1 -1
  103. package/dist/tools/index.js +24 -2
  104. package/dist/tools/index.js.map +1 -1
  105. package/dist/tools/types.d.ts +19 -0
  106. package/dist/tools/types.d.ts.map +1 -1
  107. package/dist/tools/types.js +8 -0
  108. package/dist/tools/types.js.map +1 -1
  109. package/dist/tools/utils/ssrf.d.ts +18 -0
  110. package/dist/tools/utils/ssrf.d.ts.map +1 -0
  111. package/dist/tools/utils/ssrf.js +70 -0
  112. package/dist/tools/utils/ssrf.js.map +1 -0
  113. package/docs/README.md +5 -4
  114. package/docs/proposals/0001-web-fetch-tool.md +32 -2
  115. package/docs/proposals/0002-web-search-tool.md +59 -2
  116. package/docs/proposals/0041-configuration-system.md +556 -0
  117. package/docs/proposals/README.md +3 -2
  118. package/docs/providers.md +220 -0
  119. package/package.json +7 -2
  120. package/src/agent/agent.ts +9 -2
  121. package/src/agent/types.ts +9 -1
  122. package/src/cli/components/App.tsx +72 -23
  123. package/src/cli/components/CommandSuggestions.tsx +1 -0
  124. package/src/cli/components/Messages.tsx +117 -29
  125. package/src/cli/components/ModelSelector.tsx +169 -52
  126. package/src/cli/components/ProviderManager.tsx +534 -0
  127. package/src/cli/components/markdown.ts +157 -0
  128. package/src/cli/components/theme.ts +7 -0
  129. package/src/cli/index.tsx +22 -7
  130. package/src/config/index.ts +3 -2
  131. package/src/config/providers-config.ts +85 -0
  132. package/src/config/types.ts +35 -1
  133. package/src/providers/gemini.ts +20 -4
  134. package/src/providers/index.ts +18 -3
  135. package/src/providers/registry.ts +198 -0
  136. package/src/providers/search/brave.ts +132 -0
  137. package/src/providers/search/exa.ts +217 -0
  138. package/src/providers/search/index.ts +79 -0
  139. package/src/providers/search/serper.ts +133 -0
  140. package/src/providers/search/types.ts +24 -0
  141. package/src/providers/store.ts +216 -0
  142. package/src/providers/types.ts +9 -1
  143. package/src/providers/vertex-ai.ts +594 -0
  144. package/src/tools/builtin/webfetch.ts +264 -0
  145. package/src/tools/builtin/websearch.ts +117 -0
  146. package/src/tools/index.ts +24 -2
  147. package/src/tools/types.ts +20 -0
  148. package/src/tools/utils/ssrf.ts +79 -0
  149. package/CLAUDE.md +0 -70
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Brave Search Provider
3
+ *
4
+ * Uses Brave Search API (same as Claude Code).
5
+ * Requires BRAVE_API_KEY environment variable.
6
+ */
7
+ const API_CONFIG = {
8
+ BASE_URL: 'https://api.search.brave.com',
9
+ ENDPOINT: '/res/v1/web/search',
10
+ DEFAULT_NUM_RESULTS: 10,
11
+ DEFAULT_TIMEOUT: 10000,
12
+ };
13
+ /**
14
+ * Filter results by allowed/blocked domains
15
+ */
16
+ function filterByDomain(results, options) {
17
+ if (!options?.allowedDomains?.length && !options?.blockedDomains?.length) {
18
+ return results;
19
+ }
20
+ return results.filter((result) => {
21
+ try {
22
+ const domain = new URL(result.url).hostname;
23
+ if (options.allowedDomains?.length) {
24
+ return options.allowedDomains.some((allowed) => domain === allowed || domain.endsWith('.' + allowed));
25
+ }
26
+ if (options.blockedDomains?.length) {
27
+ return !options.blockedDomains.some((blocked) => domain === blocked || domain.endsWith('.' + blocked));
28
+ }
29
+ return true;
30
+ }
31
+ catch {
32
+ return true;
33
+ }
34
+ });
35
+ }
36
+ export class BraveProvider {
37
+ name = 'brave';
38
+ apiKey;
39
+ constructor(apiKey) {
40
+ this.apiKey = apiKey ?? process.env.BRAVE_API_KEY ?? '';
41
+ if (!this.apiKey) {
42
+ throw new Error('BRAVE_API_KEY environment variable is required for Brave provider');
43
+ }
44
+ }
45
+ async search(query, options) {
46
+ const params = new URLSearchParams({
47
+ q: query,
48
+ count: String(options?.numResults ?? API_CONFIG.DEFAULT_NUM_RESULTS),
49
+ });
50
+ const controller = new AbortController();
51
+ const timeoutId = setTimeout(() => controller.abort(), options?.timeout ?? API_CONFIG.DEFAULT_TIMEOUT);
52
+ try {
53
+ const signals = options?.abortSignal
54
+ ? [controller.signal, options.abortSignal]
55
+ : [controller.signal];
56
+ const response = await fetch(`${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINT}?${params.toString()}`, {
57
+ method: 'GET',
58
+ headers: {
59
+ Accept: 'application/json',
60
+ 'Accept-Encoding': 'gzip',
61
+ 'X-Subscription-Token': this.apiKey,
62
+ },
63
+ signal: AbortSignal.any(signals),
64
+ });
65
+ clearTimeout(timeoutId);
66
+ if (!response.ok) {
67
+ const errorText = await response.text();
68
+ throw new Error(`Brave search error (${response.status}): ${errorText}`);
69
+ }
70
+ const data = (await response.json());
71
+ const results = (data.web?.results || []).map((item) => ({
72
+ title: item.title,
73
+ url: item.url,
74
+ snippet: item.description,
75
+ }));
76
+ return filterByDomain(results, options);
77
+ }
78
+ catch (error) {
79
+ clearTimeout(timeoutId);
80
+ if (error instanceof Error && error.name === 'AbortError') {
81
+ throw new Error('Search request timed out');
82
+ }
83
+ throw error;
84
+ }
85
+ }
86
+ }
87
+ //# sourceMappingURL=brave.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brave.js","sourceRoot":"","sources":["../../../src/providers/search/brave.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Exa AI Search Provider
3
+ *
4
+ * Uses Exa's public MCP endpoint (no API key required).
5
+ * Based on OpenCode's implementation pattern.
6
+ */
7
+ import type { SearchProvider, SearchResult, SearchOptions } from './types.js';
8
+ export declare class ExaProvider implements SearchProvider {
9
+ readonly name: "exa";
10
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
11
+ }
12
+ //# sourceMappingURL=exa.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exa.d.ts","sourceRoot":"","sources":["../../../src/providers/search/exa.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAuI9E,qBAAa,WAAY,YAAW,cAAc;IAChD,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAEzB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CAuE9E"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Exa AI Search Provider
3
+ *
4
+ * Uses Exa's public MCP endpoint (no API key required).
5
+ * Based on OpenCode's implementation pattern.
6
+ */
7
+ const API_CONFIG = {
8
+ BASE_URL: 'https://mcp.exa.ai',
9
+ ENDPOINT: '/mcp',
10
+ DEFAULT_NUM_RESULTS: 8,
11
+ DEFAULT_TIMEOUT: 25000,
12
+ };
13
+ /**
14
+ * Parse Exa's response text into structured search results
15
+ *
16
+ * Exa returns results in this format:
17
+ * Title: ...
18
+ * URL: ...
19
+ * Text: ...
20
+ */
21
+ function parseExaResults(text) {
22
+ const results = [];
23
+ const lines = text.split('\n');
24
+ let currentResult = {};
25
+ let collectingText = false;
26
+ let textBuffer = [];
27
+ for (const line of lines) {
28
+ const trimmed = line.trim();
29
+ // Check for "Title: ..." line
30
+ if (trimmed.startsWith('Title:')) {
31
+ // Save previous result if exists
32
+ if (currentResult.title && currentResult.url) {
33
+ results.push({
34
+ title: currentResult.title,
35
+ url: currentResult.url,
36
+ snippet: textBuffer.join(' ').trim().substring(0, 300),
37
+ });
38
+ }
39
+ currentResult = { title: trimmed.substring(6).trim() };
40
+ collectingText = false;
41
+ textBuffer = [];
42
+ continue;
43
+ }
44
+ // Check for "URL: ..." line
45
+ if (trimmed.startsWith('URL:')) {
46
+ currentResult.url = trimmed.substring(4).trim();
47
+ continue;
48
+ }
49
+ // Check for "Text: ..." line - start of snippet
50
+ if (trimmed.startsWith('Text:')) {
51
+ collectingText = true;
52
+ const initialText = trimmed.substring(5).trim();
53
+ if (initialText) {
54
+ textBuffer.push(initialText);
55
+ }
56
+ continue;
57
+ }
58
+ // Collect text lines until next Title
59
+ if (collectingText && trimmed && !trimmed.startsWith('Title:')) {
60
+ textBuffer.push(trimmed);
61
+ }
62
+ }
63
+ // Add the last result
64
+ if (currentResult.title && currentResult.url) {
65
+ results.push({
66
+ title: currentResult.title,
67
+ url: currentResult.url,
68
+ snippet: textBuffer.join(' ').trim().substring(0, 300),
69
+ });
70
+ }
71
+ return results;
72
+ }
73
+ /**
74
+ * Filter results by allowed/blocked domains
75
+ */
76
+ function filterByDomain(results, options) {
77
+ if (!options?.allowedDomains?.length && !options?.blockedDomains?.length) {
78
+ return results;
79
+ }
80
+ return results.filter((result) => {
81
+ try {
82
+ const domain = new URL(result.url).hostname;
83
+ if (options.allowedDomains?.length) {
84
+ return options.allowedDomains.some((allowed) => domain === allowed || domain.endsWith('.' + allowed));
85
+ }
86
+ if (options.blockedDomains?.length) {
87
+ return !options.blockedDomains.some((blocked) => domain === blocked || domain.endsWith('.' + blocked));
88
+ }
89
+ return true;
90
+ }
91
+ catch {
92
+ return true;
93
+ }
94
+ });
95
+ }
96
+ export class ExaProvider {
97
+ name = 'exa';
98
+ async search(query, options) {
99
+ const searchRequest = {
100
+ jsonrpc: '2.0',
101
+ id: 1,
102
+ method: 'tools/call',
103
+ params: {
104
+ name: 'web_search_exa',
105
+ arguments: {
106
+ query,
107
+ type: 'auto',
108
+ numResults: options?.numResults ?? API_CONFIG.DEFAULT_NUM_RESULTS,
109
+ livecrawl: 'fallback',
110
+ contextMaxCharacters: 10000,
111
+ },
112
+ },
113
+ };
114
+ const controller = new AbortController();
115
+ const timeoutId = setTimeout(() => controller.abort(), options?.timeout ?? API_CONFIG.DEFAULT_TIMEOUT);
116
+ try {
117
+ const signals = options?.abortSignal
118
+ ? [controller.signal, options.abortSignal]
119
+ : [controller.signal];
120
+ const response = await fetch(`${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINT}`, {
121
+ method: 'POST',
122
+ headers: {
123
+ Accept: 'application/json, text/event-stream',
124
+ 'Content-Type': 'application/json',
125
+ },
126
+ body: JSON.stringify(searchRequest),
127
+ signal: AbortSignal.any(signals),
128
+ });
129
+ clearTimeout(timeoutId);
130
+ if (!response.ok) {
131
+ const errorText = await response.text();
132
+ throw new Error(`Exa search error (${response.status}): ${errorText}`);
133
+ }
134
+ const responseText = await response.text();
135
+ // Parse SSE response
136
+ const lines = responseText.split('\n');
137
+ for (const line of lines) {
138
+ if (line.startsWith('data: ')) {
139
+ const data = JSON.parse(line.substring(6));
140
+ if (data.result?.content?.length > 0) {
141
+ const text = data.result.content[0].text;
142
+ const results = parseExaResults(text);
143
+ return filterByDomain(results, options);
144
+ }
145
+ }
146
+ }
147
+ return [];
148
+ }
149
+ catch (error) {
150
+ clearTimeout(timeoutId);
151
+ if (error instanceof Error && error.name === 'AbortError') {
152
+ throw new Error('Search request timed out');
153
+ }
154
+ throw error;
155
+ }
156
+ }
157
+ }
158
+ //# sourceMappingURL=exa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exa.js","sourceRoot":"","sources":["../../../src/providers/search/exa.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Search Providers - Factory and exports
3
+ */
4
+ export * from './types.js';
5
+ export { ExaProvider } from './exa.js';
6
+ export { SerperProvider } from './serper.js';
7
+ export { BraveProvider } from './brave.js';
8
+ import type { SearchProvider, SearchProviderName } from './types.js';
9
+ /**
10
+ * Create a search provider instance
11
+ *
12
+ * Priority:
13
+ * 1. Explicit name parameter
14
+ * 2. Configured in provider store
15
+ * 3. Detected from environment variables
16
+ * 4. Default: Exa (no key required)
17
+ */
18
+ export declare function createSearchProvider(name?: SearchProviderName): SearchProvider;
19
+ /**
20
+ * Get the name of the current search provider
21
+ */
22
+ export declare function getCurrentSearchProviderName(): SearchProviderName;
23
+ /**
24
+ * Check if a search provider is available (has required API keys)
25
+ */
26
+ export declare function isSearchProviderAvailable(name: SearchProviderName): boolean;
27
+ /**
28
+ * Get all available search providers
29
+ */
30
+ export declare function getAvailableSearchProviders(): SearchProviderName[];
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/search/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAerE;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,CAAC,EAAE,kBAAkB,GAAG,cAAc,CAY9E;AAED;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,kBAAkB,CAEjE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAW3E;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,kBAAkB,EAAE,CAKlE"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Search Providers - Factory and exports
3
+ */
4
+ export * from './types.js';
5
+ export { ExaProvider } from './exa.js';
6
+ export { SerperProvider } from './serper.js';
7
+ export { BraveProvider } from './brave.js';
8
+ import { ExaProvider } from './exa.js';
9
+ import { SerperProvider } from './serper.js';
10
+ import { BraveProvider } from './brave.js';
11
+ import { getProviderStore } from '../store.js';
12
+ /**
13
+ * Detect search provider from environment variables
14
+ */
15
+ function detectFromEnv() {
16
+ if (process.env.SERPER_API_KEY)
17
+ return 'serper';
18
+ if (process.env.BRAVE_API_KEY)
19
+ return 'brave';
20
+ return undefined;
21
+ }
22
+ /**
23
+ * Create a search provider instance
24
+ *
25
+ * Priority:
26
+ * 1. Explicit name parameter
27
+ * 2. Configured in provider store
28
+ * 3. Detected from environment variables
29
+ * 4. Default: Exa (no key required)
30
+ */
31
+ export function createSearchProvider(name) {
32
+ const providerName = name ?? getProviderStore().getSearchProvider() ?? detectFromEnv() ?? 'exa';
33
+ switch (providerName) {
34
+ case 'serper':
35
+ return new SerperProvider();
36
+ case 'brave':
37
+ return new BraveProvider();
38
+ case 'exa':
39
+ default:
40
+ return new ExaProvider();
41
+ }
42
+ }
43
+ /**
44
+ * Get the name of the current search provider
45
+ */
46
+ export function getCurrentSearchProviderName() {
47
+ return getProviderStore().getSearchProvider() ?? detectFromEnv() ?? 'exa';
48
+ }
49
+ /**
50
+ * Check if a search provider is available (has required API keys)
51
+ */
52
+ export function isSearchProviderAvailable(name) {
53
+ switch (name) {
54
+ case 'exa':
55
+ return true; // Always available
56
+ case 'serper':
57
+ return !!process.env.SERPER_API_KEY;
58
+ case 'brave':
59
+ return !!process.env.BRAVE_API_KEY;
60
+ default:
61
+ return false;
62
+ }
63
+ }
64
+ /**
65
+ * Get all available search providers
66
+ */
67
+ export function getAvailableSearchProviders() {
68
+ const providers = ['exa']; // Always available
69
+ if (process.env.SERPER_API_KEY)
70
+ providers.push('serper');
71
+ if (process.env.BRAVE_API_KEY)
72
+ providers.push('brave');
73
+ return providers;
74
+ }
75
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/search/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C;;GAEG;AACH,SAAS,aAAa;IACpB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,QAAQ,CAAC;IAChD,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa;QAAE,OAAO,OAAO,CAAC;IAC9C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAyB;IAC5D,MAAM,YAAY,GAAG,IAAI,IAAI,gBAAgB,EAAE,CAAC,iBAAiB,EAAE,IAAI,aAAa,EAAE,IAAI,KAAK,CAAC;IAEhG,QAAQ,YAAY,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,OAAO,IAAI,cAAc,EAAE,CAAC;QAC9B,KAAK,OAAO;YACV,OAAO,IAAI,aAAa,EAAE,CAAC;QAC7B,KAAK,KAAK,CAAC;QACX;YACE,OAAO,IAAI,WAAW,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,4BAA4B;IAC1C,OAAO,gBAAgB,EAAE,CAAC,iBAAiB,EAAE,IAAI,aAAa,EAAE,IAAI,KAAK,CAAC;AAC5E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAwB;IAChE,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,KAAK;YACR,OAAO,IAAI,CAAC,CAAC,mBAAmB;QAClC,KAAK,QAAQ;YACX,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QACtC,KAAK,OAAO;YACV,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;QACrC;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,2BAA2B;IACzC,MAAM,SAAS,GAAyB,CAAC,KAAK,CAAC,CAAC,CAAC,mBAAmB;IACpE,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzD,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa;QAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Serper.dev Search Provider
3
+ *
4
+ * Uses Google Search via Serper.dev API.
5
+ * Requires SERPER_API_KEY environment variable.
6
+ */
7
+ import type { SearchProvider, SearchResult, SearchOptions } from './types.js';
8
+ export declare class SerperProvider implements SearchProvider {
9
+ readonly name: "serper";
10
+ private apiKey;
11
+ constructor(apiKey?: string);
12
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
13
+ }
14
+ //# sourceMappingURL=serper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serper.d.ts","sourceRoot":"","sources":["../../../src/providers/search/serper.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA6D9E,qBAAa,cAAe,YAAW,cAAc;IACnD,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAClC,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,CAAC,EAAE,MAAM;IAOrB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CAqD9E"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Serper.dev Search Provider
3
+ *
4
+ * Uses Google Search via Serper.dev API.
5
+ * Requires SERPER_API_KEY environment variable.
6
+ */
7
+ const API_CONFIG = {
8
+ BASE_URL: 'https://google.serper.dev',
9
+ ENDPOINT: '/search',
10
+ DEFAULT_NUM_RESULTS: 10,
11
+ DEFAULT_TIMEOUT: 10000,
12
+ };
13
+ /**
14
+ * Filter results by allowed/blocked domains
15
+ */
16
+ function filterByDomain(results, options) {
17
+ if (!options?.allowedDomains?.length && !options?.blockedDomains?.length) {
18
+ return results;
19
+ }
20
+ return results.filter((result) => {
21
+ try {
22
+ const domain = new URL(result.url).hostname;
23
+ if (options.allowedDomains?.length) {
24
+ return options.allowedDomains.some((allowed) => domain === allowed || domain.endsWith('.' + allowed));
25
+ }
26
+ if (options.blockedDomains?.length) {
27
+ return !options.blockedDomains.some((blocked) => domain === blocked || domain.endsWith('.' + blocked));
28
+ }
29
+ return true;
30
+ }
31
+ catch {
32
+ return true;
33
+ }
34
+ });
35
+ }
36
+ export class SerperProvider {
37
+ name = 'serper';
38
+ apiKey;
39
+ constructor(apiKey) {
40
+ this.apiKey = apiKey ?? process.env.SERPER_API_KEY ?? '';
41
+ if (!this.apiKey) {
42
+ throw new Error('SERPER_API_KEY environment variable is required for Serper provider');
43
+ }
44
+ }
45
+ async search(query, options) {
46
+ const searchRequest = {
47
+ q: query,
48
+ num: options?.numResults ?? API_CONFIG.DEFAULT_NUM_RESULTS,
49
+ };
50
+ const controller = new AbortController();
51
+ const timeoutId = setTimeout(() => controller.abort(), options?.timeout ?? API_CONFIG.DEFAULT_TIMEOUT);
52
+ try {
53
+ const signals = options?.abortSignal
54
+ ? [controller.signal, options.abortSignal]
55
+ : [controller.signal];
56
+ const response = await fetch(`${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINT}`, {
57
+ method: 'POST',
58
+ headers: {
59
+ 'X-API-KEY': this.apiKey,
60
+ 'Content-Type': 'application/json',
61
+ },
62
+ body: JSON.stringify(searchRequest),
63
+ signal: AbortSignal.any(signals),
64
+ });
65
+ clearTimeout(timeoutId);
66
+ if (!response.ok) {
67
+ const errorText = await response.text();
68
+ throw new Error(`Serper search error (${response.status}): ${errorText}`);
69
+ }
70
+ const data = await response.json();
71
+ const results = (data.organic || []).map((item) => ({
72
+ title: item.title,
73
+ url: item.link,
74
+ snippet: item.snippet,
75
+ }));
76
+ return filterByDomain(results, options);
77
+ }
78
+ catch (error) {
79
+ clearTimeout(timeoutId);
80
+ if (error instanceof Error && error.name === 'AbortError') {
81
+ throw new Error('Search request timed out');
82
+ }
83
+ throw error;
84
+ }
85
+ }
86
+ }
87
+ //# sourceMappingURL=serper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serper.js","sourceRoot":"","sources":["../../../src/providers/search/serper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Search Provider Types
3
+ */
4
+ export type SearchProviderName = 'exa' | 'serper' | 'brave';
5
+ export interface SearchResult {
6
+ title: string;
7
+ url: string;
8
+ snippet: string;
9
+ }
10
+ export interface SearchOptions {
11
+ numResults?: number;
12
+ allowedDomains?: string[];
13
+ blockedDomains?: string[];
14
+ timeout?: number;
15
+ abortSignal?: AbortSignal;
16
+ }
17
+ export interface SearchProvider {
18
+ readonly name: SearchProviderName;
19
+ search(query: string, options?: SearchOptions): Promise<SearchResult[]>;
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/providers/search/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE5D,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CACzE"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Search Provider Types
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/providers/search/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Provider Store - Manages provider connections and model cache
3
+ *
4
+ * Storage location: ~/.gencode/providers.json
5
+ */
6
+ import type { ProviderName } from './index.js';
7
+ import type { SearchProviderName } from './search/types.js';
8
+ export interface ModelInfo {
9
+ id: string;
10
+ name: string;
11
+ }
12
+ export interface ProviderConnection {
13
+ method: string;
14
+ connectedAt: string;
15
+ }
16
+ export interface ModelCache {
17
+ cachedAt: string;
18
+ list: ModelInfo[];
19
+ }
20
+ export interface ProvidersConfig {
21
+ connections: Record<string, ProviderConnection>;
22
+ models: Record<string, ModelCache>;
23
+ searchProvider?: SearchProviderName;
24
+ }
25
+ /**
26
+ * Provider Store - manages connection state and model cache
27
+ */
28
+ export declare class ProviderStore {
29
+ private config;
30
+ constructor();
31
+ /**
32
+ * Load configuration from disk
33
+ */
34
+ private load;
35
+ /**
36
+ * Save configuration to disk
37
+ */
38
+ private save;
39
+ /**
40
+ * Check if a provider is connected
41
+ */
42
+ isConnected(providerId: ProviderName): boolean;
43
+ /**
44
+ * Get connection info for a provider
45
+ */
46
+ getConnection(providerId: ProviderName): ProviderConnection | undefined;
47
+ /**
48
+ * Get all connected provider IDs
49
+ */
50
+ getConnectedProviders(): ProviderName[];
51
+ /**
52
+ * Connect a provider
53
+ */
54
+ connect(providerId: ProviderName, method: string): void;
55
+ /**
56
+ * Disconnect a provider
57
+ */
58
+ disconnect(providerId: ProviderName): void;
59
+ /**
60
+ * Get cached models for a provider
61
+ */
62
+ getModels(providerId: ProviderName): ModelInfo[];
63
+ /**
64
+ * Get all cached models grouped by provider
65
+ */
66
+ getAllModels(): Record<ProviderName, ModelInfo[]>;
67
+ /**
68
+ * Cache models for a provider
69
+ */
70
+ cacheModels(providerId: ProviderName, models: ModelInfo[]): void;
71
+ /**
72
+ * Get cache timestamp for a provider
73
+ */
74
+ getCacheTime(providerId: ProviderName): Date | undefined;
75
+ /**
76
+ * Check if model cache is stale (older than 24 hours)
77
+ */
78
+ isCacheStale(providerId: ProviderName): boolean;
79
+ /**
80
+ * Get total model count across all connected providers
81
+ */
82
+ getTotalModelCount(): number;
83
+ /**
84
+ * Get model count for a specific provider
85
+ */
86
+ getModelCount(providerId: ProviderName): number;
87
+ /**
88
+ * Get the configured search provider
89
+ */
90
+ getSearchProvider(): SearchProviderName | undefined;
91
+ /**
92
+ * Set the search provider
93
+ */
94
+ setSearchProvider(id: SearchProviderName): void;
95
+ /**
96
+ * Clear the search provider (use default)
97
+ */
98
+ clearSearchProvider(): void;
99
+ }
100
+ /**
101
+ * Get the singleton provider store instance
102
+ */
103
+ export declare function getProviderStore(): ProviderStore;
104
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/providers/store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAChD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACnC,cAAc,CAAC,EAAE,kBAAkB,CAAC;CACrC;AAKD;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAkB;;IAMhC;;OAEG;IACH,OAAO,CAAC,IAAI;IAYZ;;OAEG;IACH,OAAO,CAAC,IAAI;IAWZ;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,YAAY,GAAG,OAAO;IAI9C;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,YAAY,GAAG,kBAAkB,GAAG,SAAS;IAIvE;;OAEG;IACH,qBAAqB,IAAI,YAAY,EAAE;IAIvC;;OAEG;IACH,OAAO,CAAC,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAQvD;;OAEG;IACH,UAAU,CAAC,UAAU,EAAE,YAAY,GAAG,IAAI;IAM1C;;OAEG;IACH,SAAS,CAAC,UAAU,EAAE,YAAY,GAAG,SAAS,EAAE;IAIhD;;OAEG;IACH,YAAY,IAAI,MAAM,CAAC,YAAY,EAAE,SAAS,EAAE,CAAC;IAQjD;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI;IAQhE;;OAEG;IACH,YAAY,CAAC,UAAU,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS;IAKxD;;OAEG;IACH,YAAY,CAAC,UAAU,EAAE,YAAY,GAAG,OAAO;IAO/C;;OAEG;IACH,kBAAkB,IAAI,MAAM;IAO5B;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,YAAY,GAAG,MAAM;IAI/C;;OAEG;IACH,iBAAiB,IAAI,kBAAkB,GAAG,SAAS;IAInD;;OAEG;IACH,iBAAiB,CAAC,EAAE,EAAE,kBAAkB,GAAG,IAAI;IAK/C;;OAEG;IACH,mBAAmB,IAAI,IAAI;CAI5B;AAKD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAKhD"}