@vibeapi/api-helper 2.0.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 (55) hide show
  1. package/LICENSE +25 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +18 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/auth.d.ts +1 -0
  6. package/dist/commands/auth.js +119 -0
  7. package/dist/commands/auth.js.map +1 -0
  8. package/dist/commands/config.d.ts +1 -0
  9. package/dist/commands/config.js +130 -0
  10. package/dist/commands/config.js.map +1 -0
  11. package/dist/commands/doctor.d.ts +1 -0
  12. package/dist/commands/doctor.js +105 -0
  13. package/dist/commands/doctor.js.map +1 -0
  14. package/dist/commands/index.d.ts +4 -0
  15. package/dist/commands/index.js +5 -0
  16. package/dist/commands/index.js.map +1 -0
  17. package/dist/commands/lang.d.ts +1 -0
  18. package/dist/commands/lang.js +28 -0
  19. package/dist/commands/lang.js.map +1 -0
  20. package/dist/index.d.ts +12 -0
  21. package/dist/index.js +10 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/lib/api-validator.d.ts +12 -0
  24. package/dist/lib/api-validator.js +79 -0
  25. package/dist/lib/api-validator.js.map +1 -0
  26. package/dist/lib/claude-code-manager.d.ts +86 -0
  27. package/dist/lib/claude-code-manager.js +233 -0
  28. package/dist/lib/claude-code-manager.js.map +1 -0
  29. package/dist/lib/command.d.ts +10 -0
  30. package/dist/lib/command.js +168 -0
  31. package/dist/lib/command.js.map +1 -0
  32. package/dist/lib/config.d.ts +64 -0
  33. package/dist/lib/config.js +226 -0
  34. package/dist/lib/config.js.map +1 -0
  35. package/dist/lib/i18n.d.ts +20 -0
  36. package/dist/lib/i18n.js +149 -0
  37. package/dist/lib/i18n.js.map +1 -0
  38. package/dist/lib/opencode-manager.d.ts +55 -0
  39. package/dist/lib/opencode-manager.js +134 -0
  40. package/dist/lib/opencode-manager.js.map +1 -0
  41. package/dist/lib/tool-manager.d.ts +25 -0
  42. package/dist/lib/tool-manager.js +280 -0
  43. package/dist/lib/tool-manager.js.map +1 -0
  44. package/dist/lib/wizard.d.ts +23 -0
  45. package/dist/lib/wizard.js +360 -0
  46. package/dist/lib/wizard.js.map +1 -0
  47. package/dist/locales/en_US.json +146 -0
  48. package/dist/locales/zh_CN.json +146 -0
  49. package/dist/utils/logger.d.ts +55 -0
  50. package/dist/utils/logger.js +202 -0
  51. package/dist/utils/logger.js.map +1 -0
  52. package/dist/utils/string-width.d.ts +38 -0
  53. package/dist/utils/string-width.js +131 -0
  54. package/dist/utils/string-width.js.map +1 -0
  55. package/package.json +73 -0
@@ -0,0 +1,226 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync, unlinkSync, readdirSync, statSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { homedir } from 'os';
4
+ import * as yaml from 'js-yaml';
5
+ import { logger } from '../utils/logger.js';
6
+ export const DEFAULT_BASE_URL = 'https://www.vibeapi.cn';
7
+ export const DEFAULT_MODELS = {
8
+ haiku: 'claude-haiku-4-5-20251001',
9
+ sonnet: 'claude-sonnet-4-6',
10
+ opus: 'claude-opus-4-6',
11
+ reasoning: 'claude-opus-4-6'
12
+ };
13
+ export class ConfigManager {
14
+ static instance;
15
+ configDir;
16
+ configPath;
17
+ config;
18
+ constructor() {
19
+ // chelper 配置文件路径(跨平台支持)
20
+ // - macOS/Linux: ~/.chelper/config.yaml
21
+ // - Windows: %USERPROFILE%\.chelper\config.yaml
22
+ // (例如: C:\Users\username\.chelper\config.yaml)
23
+ this.configDir = this.getConfigDir();
24
+ this.configPath = join(this.configDir, 'config.yaml');
25
+ this.config = this.loadConfig();
26
+ }
27
+ /**
28
+ * 获取配置目录路径,支持环境变量覆盖
29
+ */
30
+ getConfigDir() {
31
+ // 支持环境变量覆盖
32
+ const customDir = process.env.CHELPER_CONFIG_DIR;
33
+ if (customDir && customDir.trim()) {
34
+ return customDir.trim();
35
+ }
36
+ // 支持测试环境
37
+ const testHome = process.env.CHELPER_TEST_HOME;
38
+ if (testHome && testHome.trim()) {
39
+ return join(testHome.trim(), '.chelper');
40
+ }
41
+ return join(homedir(), '.chelper');
42
+ }
43
+ static getInstance() {
44
+ if (!ConfigManager.instance) {
45
+ ConfigManager.instance = new ConfigManager();
46
+ }
47
+ return ConfigManager.instance;
48
+ }
49
+ ensureConfigDir() {
50
+ if (!existsSync(this.configDir)) {
51
+ mkdirSync(this.configDir, { recursive: true });
52
+ }
53
+ }
54
+ loadConfig() {
55
+ try {
56
+ if (existsSync(this.configPath)) {
57
+ const fileContent = readFileSync(this.configPath, 'utf-8');
58
+ const config = yaml.load(fileContent);
59
+ const migratedConfig = this.migrateOldConfig(config || { lang: 'en_US' });
60
+ // 如果配置被迁移,保存新配置
61
+ if (this.needsMigration(config)) {
62
+ this.backupConfig();
63
+ this.atomicWrite(this.configPath, yaml.dump(migratedConfig));
64
+ }
65
+ return migratedConfig;
66
+ }
67
+ }
68
+ catch (error) {
69
+ console.warn('Failed to load config, using defaults:', error);
70
+ logger.logError('ConfigManager.loadConfig', error);
71
+ }
72
+ return { lang: 'en_US' };
73
+ }
74
+ /**
75
+ * 检查配置是否需要迁移
76
+ */
77
+ needsMigration(config) {
78
+ return config && 'plan' in config;
79
+ }
80
+ /**
81
+ * 迁移旧配置格式
82
+ */
83
+ migrateOldConfig(config) {
84
+ if (config.plan) {
85
+ // 迁移旧配置,删除 plan 字段,添加 models 默认值
86
+ const { plan, ...rest } = config;
87
+ return {
88
+ ...rest,
89
+ lang: config.lang || 'en_US',
90
+ api_key: config.api_key,
91
+ models: DEFAULT_MODELS
92
+ };
93
+ }
94
+ return config;
95
+ }
96
+ /**
97
+ * 原子写入文件
98
+ */
99
+ atomicWrite(path, content) {
100
+ const tempPath = `${path}.tmp`;
101
+ try {
102
+ writeFileSync(tempPath, content, 'utf-8');
103
+ renameSync(tempPath, path);
104
+ }
105
+ catch (error) {
106
+ // 清理临时文件
107
+ if (existsSync(tempPath)) {
108
+ try {
109
+ unlinkSync(tempPath);
110
+ }
111
+ catch {
112
+ // 忽略清理错误
113
+ }
114
+ }
115
+ throw error;
116
+ }
117
+ }
118
+ /**
119
+ * 备份当前配置
120
+ */
121
+ backupConfig() {
122
+ if (!existsSync(this.configPath)) {
123
+ return;
124
+ }
125
+ const backupDir = join(this.configDir, 'backups');
126
+ if (!existsSync(backupDir)) {
127
+ mkdirSync(backupDir, { recursive: true });
128
+ }
129
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
130
+ const backupPath = join(backupDir, `config-${timestamp}.yaml`);
131
+ try {
132
+ const content = readFileSync(this.configPath, 'utf-8');
133
+ writeFileSync(backupPath, content, 'utf-8');
134
+ // 保留最近 10 个备份
135
+ this.rotateBackups(backupDir, 10);
136
+ }
137
+ catch (error) {
138
+ logger.logError('ConfigManager.backupConfig', error);
139
+ }
140
+ }
141
+ /**
142
+ * 轮转备份文件,保留最近的 N 个
143
+ */
144
+ rotateBackups(backupDir, maxBackups) {
145
+ try {
146
+ const files = readdirSync(backupDir)
147
+ .filter(f => f.startsWith('config-') && f.endsWith('.yaml'))
148
+ .map(f => ({
149
+ name: f,
150
+ path: join(backupDir, f),
151
+ mtime: statSync(join(backupDir, f)).mtime
152
+ }))
153
+ .sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
154
+ // 删除超出数量的旧备份
155
+ files.slice(maxBackups).forEach(file => {
156
+ try {
157
+ unlinkSync(file.path);
158
+ }
159
+ catch (error) {
160
+ logger.logError('ConfigManager.rotateBackups', error);
161
+ }
162
+ });
163
+ }
164
+ catch (error) {
165
+ logger.logError('ConfigManager.rotateBackups', error);
166
+ }
167
+ }
168
+ saveConfig(config) {
169
+ try {
170
+ this.ensureConfigDir();
171
+ this.backupConfig(); // 保存前先备份
172
+ const configToSave = config || this.config;
173
+ const yamlContent = yaml.dump(configToSave);
174
+ this.atomicWrite(this.configPath, yamlContent);
175
+ this.config = configToSave;
176
+ }
177
+ catch (error) {
178
+ console.error('Failed to save config:', error);
179
+ logger.logError('ConfigManager.saveConfig', error);
180
+ throw error;
181
+ }
182
+ }
183
+ getConfig() {
184
+ return { ...this.config };
185
+ }
186
+ updateConfig(updates) {
187
+ this.config = { ...this.config, ...updates };
188
+ this.saveConfig();
189
+ }
190
+ isFirstRun() {
191
+ return !existsSync(this.configPath);
192
+ }
193
+ getLang() {
194
+ return this.config.lang || 'en_US';
195
+ }
196
+ setLang(lang) {
197
+ this.updateConfig({ lang });
198
+ }
199
+ getApiKey() {
200
+ return this.config.api_key;
201
+ }
202
+ setApiKey(apiKey) {
203
+ this.updateConfig({ api_key: apiKey });
204
+ }
205
+ revokeApiKey() {
206
+ this.updateConfig({ api_key: undefined });
207
+ }
208
+ getModels() {
209
+ return this.config.models || DEFAULT_MODELS;
210
+ }
211
+ setModels(models) {
212
+ this.updateConfig({ models });
213
+ }
214
+ updateModels(partial) {
215
+ const currentModels = this.getModels();
216
+ const updatedModels = {
217
+ haiku: partial.haiku ?? currentModels.haiku,
218
+ sonnet: partial.sonnet ?? currentModels.sonnet,
219
+ opus: partial.opus ?? currentModels.opus,
220
+ reasoning: partial.reasoning ?? currentModels.reasoning
221
+ };
222
+ this.updateConfig({ models: updatedModels });
223
+ }
224
+ }
225
+ export const configManager = ConfigManager.getInstance();
226
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ declare class I18n {
2
+ private static instance;
3
+ private currentLocale;
4
+ private translations;
5
+ private fallbackLocale;
6
+ private localesDir;
7
+ private constructor();
8
+ static getInstance(): I18n;
9
+ private loadTranslations;
10
+ setLocale(locale: string): void;
11
+ getLocale(): string;
12
+ getAvailableLocales(): string[];
13
+ translate(key: string, params?: Record<string, string>): string;
14
+ t(key: string, params?: Record<string, string>): string;
15
+ private saveLocale;
16
+ private loadSavedLocale;
17
+ loadFromConfig(locale: string): void;
18
+ }
19
+ export declare const i18n: I18n;
20
+ export { i18n as I18n };
@@ -0,0 +1,149 @@
1
+ import { readFileSync, existsSync, readdirSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ class I18n {
5
+ static instance;
6
+ currentLocale = 'en_US';
7
+ translations = new Map();
8
+ fallbackLocale = 'en_US';
9
+ localesDir;
10
+ constructor() {
11
+ // Determine the locales directory path
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = dirname(__filename);
14
+ // Both in development (src/lib/i18n.ts) and production (dist/lib/i18n.js),
15
+ // locales is at the same relative path: lib -> parent -> locales
16
+ this.localesDir = join(__dirname, '..', 'locales');
17
+ this.loadTranslations();
18
+ this.loadSavedLocale();
19
+ }
20
+ static getInstance() {
21
+ if (!I18n.instance) {
22
+ I18n.instance = new I18n();
23
+ }
24
+ return I18n.instance;
25
+ }
26
+ loadTranslations() {
27
+ try {
28
+ // Check if locales directory exists
29
+ if (!existsSync(this.localesDir)) {
30
+ console.warn(`Locales directory not found at ${this.localesDir}`);
31
+ return;
32
+ }
33
+ // Get all JSON files in the locales directory
34
+ const files = readdirSync(this.localesDir);
35
+ const localeFiles = files.filter(file => file.endsWith('.json'));
36
+ if (localeFiles.length === 0) {
37
+ console.warn('No locale files found in locales directory');
38
+ return;
39
+ }
40
+ // Load each locale file
41
+ for (const file of localeFiles) {
42
+ const locale = file.replace('.json', '');
43
+ const filePath = join(this.localesDir, file);
44
+ try {
45
+ const fileContent = readFileSync(filePath, 'utf-8');
46
+ const translations = JSON.parse(fileContent);
47
+ this.translations.set(locale, translations);
48
+ }
49
+ catch (error) {
50
+ console.warn(`Failed to load locale file ${file}:`, error);
51
+ }
52
+ }
53
+ // Try to detect locale from environment
54
+ const envLocale = process.env.LANG || process.env.LC_ALL || process.env.LC_MESSAGES;
55
+ if (envLocale) {
56
+ const localeCode = envLocale.split('.')[0].replace('_', '-');
57
+ // First try exact match
58
+ if (this.translations.has(localeCode)) {
59
+ this.currentLocale = localeCode;
60
+ }
61
+ else {
62
+ // Try language-only match (e.g., 'en' from 'en-US')
63
+ const langOnly = localeCode.split('-')[0];
64
+ const matchingLocale = Array.from(this.translations.keys()).find(key => key.startsWith(langOnly + '_'));
65
+ if (matchingLocale) {
66
+ this.currentLocale = matchingLocale;
67
+ }
68
+ else if (langOnly === 'zh') {
69
+ // Fallback to zh_CN for Chinese
70
+ this.currentLocale = 'zh_CN';
71
+ }
72
+ else if (langOnly === 'en') {
73
+ // Fallback to en_US for English
74
+ this.currentLocale = 'en_US';
75
+ }
76
+ }
77
+ }
78
+ }
79
+ catch (error) {
80
+ console.warn('Failed to load translations:', error);
81
+ }
82
+ }
83
+ setLocale(locale) {
84
+ if (this.translations.has(locale)) {
85
+ this.currentLocale = locale;
86
+ this.saveLocale();
87
+ }
88
+ else {
89
+ console.warn(`Locale '${locale}' not supported, falling back to '${this.currentLocale}'`);
90
+ }
91
+ }
92
+ getLocale() {
93
+ return this.currentLocale;
94
+ }
95
+ getAvailableLocales() {
96
+ return Array.from(this.translations.keys());
97
+ }
98
+ translate(key, params) {
99
+ const keys = key.split('.');
100
+ let translation = this.translations.get(this.currentLocale);
101
+ for (const k of keys) {
102
+ if (translation && typeof translation === 'object' && k in translation) {
103
+ translation = translation[k];
104
+ }
105
+ else {
106
+ // Fallback to fallback locale
107
+ translation = this.translations.get(this.fallbackLocale);
108
+ for (const fallbackKey of keys) {
109
+ if (translation && typeof translation === 'object' && fallbackKey in translation) {
110
+ translation = translation[fallbackKey];
111
+ }
112
+ else {
113
+ return key; // Return key if translation not found
114
+ }
115
+ }
116
+ break;
117
+ }
118
+ }
119
+ if (typeof translation !== 'string') {
120
+ return key;
121
+ }
122
+ // Replace parameters in the translation string
123
+ if (params) {
124
+ return translation.replace(/\{\{(\w+)\}\}/g, (match, param) => {
125
+ return params[param] || match;
126
+ });
127
+ }
128
+ return translation;
129
+ }
130
+ t(key, params) {
131
+ return this.translate(key, params);
132
+ }
133
+ saveLocale() {
134
+ // Language is now saved via ConfigManager
135
+ // This method is kept for compatibility
136
+ }
137
+ loadSavedLocale() {
138
+ // Language is now loaded via ConfigManager
139
+ // This method is kept for compatibility
140
+ }
141
+ loadFromConfig(locale) {
142
+ if (this.translations.has(locale)) {
143
+ this.currentLocale = locale;
144
+ }
145
+ }
146
+ }
147
+ export const i18n = I18n.getInstance();
148
+ export { i18n as I18n };
149
+ //# sourceMappingURL=i18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/lib/i18n.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import { DEFAULT_MODELS } from './config.js';
2
+ export interface OpenCodeConfig {
3
+ $schema?: string;
4
+ provider?: Record<string, {
5
+ options?: {
6
+ apiKey?: string;
7
+ [key: string]: any;
8
+ };
9
+ [key: string]: any;
10
+ }>;
11
+ model?: string;
12
+ small_model?: string;
13
+ mcp?: Record<string, OpenCodeMCPServerConfig>;
14
+ [key: string]: any;
15
+ }
16
+ export interface OpenCodeMCPServerConfig {
17
+ type: 'local' | 'remote';
18
+ command?: string[];
19
+ environment?: Record<string, string>;
20
+ url?: string;
21
+ headers?: Record<string, string>;
22
+ }
23
+ export declare class OpenCodeManager {
24
+ private static instance;
25
+ private configPath;
26
+ private constructor();
27
+ static getInstance(): OpenCodeManager;
28
+ /**
29
+ * 确保配置目录存在
30
+ */
31
+ private ensureConfigDir;
32
+ /**
33
+ * 读取配置
34
+ */
35
+ getConfig(): OpenCodeConfig;
36
+ /**
37
+ * 保存配置
38
+ */
39
+ saveConfig(config: OpenCodeConfig): void;
40
+ /**
41
+ * 加载私有 NewAPI 配置到 OpenCode
42
+ */
43
+ loadPrivateConfig(apiKey: string, models: typeof DEFAULT_MODELS): void;
44
+ /**
45
+ * 卸载私有配置
46
+ */
47
+ unloadPrivateConfig(): void;
48
+ /**
49
+ * 检测当前 OpenCode 配置的 API Key
50
+ */
51
+ detectCurrentConfig(): {
52
+ apiKey: string | null;
53
+ };
54
+ }
55
+ export declare const openCodeManager: OpenCodeManager;
@@ -0,0 +1,134 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { homedir } from 'os';
4
+ import { logger } from '../utils/logger.js';
5
+ import { DEFAULT_BASE_URL, DEFAULT_MODELS } from './config.js';
6
+ export class OpenCodeManager {
7
+ static instance;
8
+ configPath;
9
+ constructor() {
10
+ // OpenCode 配置文件路径
11
+ // ~/.config/opencode/opencode.json
12
+ this.configPath = join(homedir(), '.config', 'opencode', 'opencode.json');
13
+ }
14
+ static getInstance() {
15
+ if (!OpenCodeManager.instance) {
16
+ OpenCodeManager.instance = new OpenCodeManager();
17
+ }
18
+ return OpenCodeManager.instance;
19
+ }
20
+ /**
21
+ * 确保配置目录存在
22
+ */
23
+ ensureConfigDir() {
24
+ const dir = dirname(this.configPath);
25
+ if (!existsSync(dir)) {
26
+ mkdirSync(dir, { recursive: true });
27
+ }
28
+ }
29
+ /**
30
+ * 读取配置
31
+ */
32
+ getConfig() {
33
+ try {
34
+ if (existsSync(this.configPath)) {
35
+ const content = readFileSync(this.configPath, 'utf-8');
36
+ return JSON.parse(content);
37
+ }
38
+ }
39
+ catch (error) {
40
+ console.warn('Failed to read OpenCode config:', error);
41
+ logger.logError('OpenCodeManager.getConfig', error);
42
+ }
43
+ return {};
44
+ }
45
+ /**
46
+ * 保存配置
47
+ */
48
+ saveConfig(config) {
49
+ try {
50
+ this.ensureConfigDir();
51
+ writeFileSync(this.configPath, JSON.stringify(config, null, 4), 'utf-8');
52
+ }
53
+ catch (error) {
54
+ throw new Error(`Failed to save OpenCode config: ${error}`);
55
+ }
56
+ }
57
+ /**
58
+ * 加载私有 NewAPI 配置到 OpenCode
59
+ */
60
+ loadPrivateConfig(apiKey, models) {
61
+ const currentConfig = this.getConfig();
62
+ // 移除旧的 provider 配置(如果存在)
63
+ const { provider: oldProvider, ...restConfig } = currentConfig;
64
+ const newProvider = {};
65
+ // 保留其他 provider(如果有的话),但移除旧的配置
66
+ if (oldProvider) {
67
+ for (const [key, value] of Object.entries(oldProvider)) {
68
+ if (key !== 'private-newapi') {
69
+ newProvider[key] = value;
70
+ }
71
+ }
72
+ }
73
+ // 添加新的 provider 配置
74
+ newProvider['private-newapi'] = {
75
+ options: {
76
+ apiKey: apiKey,
77
+ baseURL: DEFAULT_BASE_URL
78
+ }
79
+ };
80
+ const newConfig = {
81
+ $schema: 'https://opencode.ai/config.json',
82
+ ...restConfig,
83
+ provider: newProvider,
84
+ model: `private-newapi/${models.opus || DEFAULT_MODELS.opus}`,
85
+ small_model: `private-newapi/${models.haiku || DEFAULT_MODELS.haiku}`
86
+ };
87
+ this.saveConfig(newConfig);
88
+ }
89
+ /**
90
+ * 卸载私有配置
91
+ */
92
+ unloadPrivateConfig() {
93
+ const currentConfig = this.getConfig();
94
+ // 移除 provider 中的 private-newapi 配置
95
+ if (currentConfig.provider) {
96
+ delete currentConfig.provider['private-newapi'];
97
+ // 如果 provider 为空,删除 provider 字段
98
+ if (Object.keys(currentConfig.provider).length === 0) {
99
+ delete currentConfig.provider;
100
+ }
101
+ }
102
+ // 移除 model 和 small_model(如果是 private-newapi 的)
103
+ if (currentConfig.model?.includes('private-newapi')) {
104
+ delete currentConfig.model;
105
+ }
106
+ if (currentConfig.small_model?.includes('private-newapi')) {
107
+ delete currentConfig.small_model;
108
+ }
109
+ this.saveConfig(currentConfig);
110
+ }
111
+ /**
112
+ * 检测当前 OpenCode 配置的 API Key
113
+ */
114
+ detectCurrentConfig() {
115
+ try {
116
+ const config = this.getConfig();
117
+ // 检查 provider 配置
118
+ if (!config.provider) {
119
+ return { apiKey: null };
120
+ }
121
+ // 检查是否有 private-newapi
122
+ let apiKey = null;
123
+ if (config.provider['private-newapi']) {
124
+ apiKey = config.provider['private-newapi'].options?.apiKey || null;
125
+ }
126
+ return { apiKey };
127
+ }
128
+ catch {
129
+ return { apiKey: null };
130
+ }
131
+ }
132
+ }
133
+ export const openCodeManager = OpenCodeManager.getInstance();
134
+ //# sourceMappingURL=opencode-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-manager.js","sourceRoot":"","sources":["../../src/lib/opencode-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { DEFAULT_MODELS } from './config.js';
2
+ export interface ToolInfo {
3
+ name: string;
4
+ command: string;
5
+ installCommand: string;
6
+ configPath: string;
7
+ displayName: string;
8
+ hidden?: boolean;
9
+ }
10
+ export declare const SUPPORTED_TOOLS: Record<string, ToolInfo>;
11
+ export declare class ToolManager {
12
+ private static instance;
13
+ private constructor();
14
+ static getInstance(): ToolManager;
15
+ isToolInstalled(toolName: string): boolean;
16
+ installTool(toolName: string): Promise<void>;
17
+ getToolConfig(toolName: string): any;
18
+ updateToolConfig(toolName: string, config: any): void;
19
+ loadPrivateConfig(toolName: string, apiKey: string, models: typeof DEFAULT_MODELS): void;
20
+ getInstalledTools(): string[];
21
+ unloadPrivateConfig(toolName: string): void;
22
+ getSupportedTools(): ToolInfo[];
23
+ isGitInstalled(): boolean;
24
+ }
25
+ export declare const toolManager: ToolManager;