@openharmonyinsight/opencode-oh 0.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 (51) hide show
  1. package/AGENTS.md +98 -0
  2. package/README.md +80 -0
  3. package/dist/src/cli.d.ts +3 -0
  4. package/dist/src/cli.d.ts.map +1 -0
  5. package/dist/src/cli.js +7 -0
  6. package/dist/src/cli.js.map +1 -0
  7. package/dist/src/config/index.d.ts +13 -0
  8. package/dist/src/config/index.d.ts.map +1 -0
  9. package/dist/src/config/index.js +95 -0
  10. package/dist/src/config/index.js.map +1 -0
  11. package/dist/src/config/types.d.ts +29 -0
  12. package/dist/src/config/types.d.ts.map +1 -0
  13. package/dist/src/config/types.js +2 -0
  14. package/dist/src/config/types.js.map +1 -0
  15. package/dist/src/index.d.ts +2 -0
  16. package/dist/src/index.d.ts.map +1 -0
  17. package/dist/src/index.js +24 -0
  18. package/dist/src/index.js.map +1 -0
  19. package/dist/src/provider/templates.d.ts +5 -0
  20. package/dist/src/provider/templates.d.ts.map +1 -0
  21. package/dist/src/provider/templates.js +74 -0
  22. package/dist/src/provider/templates.js.map +1 -0
  23. package/dist/src/tui/index.d.ts +12 -0
  24. package/dist/src/tui/index.d.ts.map +1 -0
  25. package/dist/src/tui/index.js +136 -0
  26. package/dist/src/tui/index.js.map +1 -0
  27. package/dist/src/validation/index.d.ts +6 -0
  28. package/dist/src/validation/index.d.ts.map +1 -0
  29. package/dist/src/validation/index.js +24 -0
  30. package/dist/src/validation/index.js.map +1 -0
  31. package/dist/tests/config.test.d.ts +2 -0
  32. package/dist/tests/config.test.d.ts.map +1 -0
  33. package/dist/tests/config.test.js +104 -0
  34. package/dist/tests/config.test.js.map +1 -0
  35. package/dist/tests/validation.test.d.ts +2 -0
  36. package/dist/tests/validation.test.d.ts.map +1 -0
  37. package/dist/tests/validation.test.js +37 -0
  38. package/dist/tests/validation.test.js.map +1 -0
  39. package/docs/plans/2026-02-12-opencode-oh-design.md +90 -0
  40. package/package.json +38 -0
  41. package/src/cli.ts +8 -0
  42. package/src/config/index.ts +106 -0
  43. package/src/config/types.ts +29 -0
  44. package/src/index.ts +26 -0
  45. package/src/provider/templates.ts +76 -0
  46. package/src/tui/index.ts +159 -0
  47. package/src/validation/index.ts +30 -0
  48. package/tests/config.test.ts +117 -0
  49. package/tests/validation.test.ts +44 -0
  50. package/tsconfig.json +20 -0
  51. package/vitest.config.ts +19 -0
package/AGENTS.md ADDED
@@ -0,0 +1,98 @@
1
+ # AGENTS.md - Agent Guidelines for opencode-oh
2
+
3
+ Guidelines for agentic coding assistants working on this project.
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ npm run build # Build TypeScript to dist/
9
+ npm test # Run all tests (vitest with globals)
10
+ npm run test:coverage # Run tests with coverage
11
+ npm run lint # ESLint on src directory
12
+ npm run dev # Run in dev mode (tsx)
13
+
14
+ # Run single tests
15
+ npx vitest tests/config.test.ts # Specific test file
16
+ npx vitest -t "should validate" # Pattern matching
17
+ npx vitest --watch # Watch mode
18
+ ```
19
+
20
+ ## Code Style
21
+
22
+ ### TypeScript & Imports
23
+ - **Target**: ES2022, **Modules**: ESNext, **Strict**: enabled
24
+ - Use `.js` extensions in all imports (ES modules with `"type": "module"`)
25
+ - Named imports: `import { describe, expect } from 'vitest'`
26
+ - Type imports: `import type { ProviderConfig } from './config/types.js'`
27
+
28
+ ### Naming Conventions
29
+ - Classes/Interfaces/Types: PascalCase (`ConfigManager`, `ProviderConfig`, `ValidationResult`)
30
+ - Functions/Methods: camelCase (`validateApiKey`, `getConfigPath`)
31
+ - Constants: UPPER_SNAKE_CASE (`CONFIG_DIR`, `DEFAULT_SCHEMA`)
32
+
33
+ ### Error Handling
34
+ ```typescript
35
+ // Throw descriptive errors with context
36
+ throw new Error(`Failed to read: ${error instanceof Error ? error.message : String(error)}`);
37
+
38
+ // Async functions return Result objects
39
+ export interface ValidationResult { valid: boolean; error?: string; }
40
+
41
+ // Try-catch for I/O operations
42
+ try {
43
+ const content = fs.readFileSync(path, 'utf-8');
44
+ return JSON.parse(content);
45
+ } catch (error) {
46
+ throw new Error(`Failed: ${error instanceof Error ? error.message : String(error)}`);
47
+ }
48
+ ```
49
+
50
+ ### Testing Patterns
51
+ ```typescript
52
+ describe('functionName', () => {
53
+ beforeEach(() => {
54
+ vi.restoreAllMocks();
55
+ const mockFetch = vi.fn().mockResolvedValue({ ok: true });
56
+ global.fetch = mockFetch;
57
+ });
58
+
59
+ afterEach(() => {
60
+ // Clean up temp files with fs.rmSync
61
+ });
62
+
63
+ it('should do something', () => expect(result).toBe(expected));
64
+ });
65
+ ```
66
+
67
+ ### Formatting
68
+ - 2-space indentation, single quotes (double for import/export)
69
+ - Optional semicolons, `JSON.stringify(config, null, 2)` for JSON
70
+
71
+ ### File Organization
72
+ ```
73
+ src/module/
74
+ index.ts # Barrel exports
75
+ types.ts # Type definitions
76
+ tests/module.test.ts
77
+ ```
78
+
79
+ ### Configuration
80
+ - Config path: `~/.config/opencode/opencode.json`
81
+ - Backup: `opencode.json.<timestamp>.bak` (always create before modifying)
82
+
83
+ ### Provider Templates
84
+ ```typescript
85
+ export const PROVIDER_TEMPLATES: Record<string, ProviderTemplate> = {
86
+ providerId: {
87
+ id, displayName, npm, baseURL,
88
+ supportsApiKeyValidation,
89
+ validateApiKey: async (apiKey: string, model?: string) => Promise<boolean>
90
+ }
91
+ };
92
+ ```
93
+
94
+ ### Important Notes
95
+ - Check null/undefined before accessing nested properties
96
+ - Provider IDs with hyphens use quotes: `'volcengine-codingplan'`
97
+ - Create temp test dirs and clean up in afterEach
98
+ - Bilingual support (en/zh) via message objects
package/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # opencode-oh
2
+
3
+ OpenHarmony OpenCode Helper Tool - Configure opencode with third-party model providers through an interactive TUI.
4
+
5
+ ## Features
6
+
7
+ - Interactive TUI interface for easy configuration
8
+ - Support for multiple providers (Volcengine, OpenAI, DeepSeek, etc.)
9
+ - API key validation before applying configuration
10
+ - Automatic backup of existing configuration
11
+ - Bilingual support (Chinese/English)
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install -g opencode-oh
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ Run the tool:
22
+
23
+ ```bash
24
+ opencode-oh
25
+ ```
26
+
27
+ Follow the interactive prompts to:
28
+
29
+ 1. Select a provider
30
+ 2. Enter your API key
31
+ 3. Enter the model name
32
+ 4. Validate your API key
33
+ 5. Apply the configuration
34
+
35
+ ## Supported Providers
36
+
37
+ - **Volcengine** (火山引擎) - OpenAI-compatible API
38
+ - **OpenAI** - Official OpenAI API
39
+ - **DeepSeek** - OpenAI-compatible API
40
+
41
+ ## Configuration
42
+
43
+ The tool modifies `~/.config/opencode/opencode.json`. Before making any changes, it automatically creates a timestamped backup file.
44
+
45
+ ## Development
46
+
47
+ ```bash
48
+ # Install dependencies
49
+ npm install
50
+
51
+ # Build the project
52
+ npm run build
53
+
54
+ # Run tests
55
+ npm test
56
+
57
+ # Run in development mode
58
+ npm run dev
59
+ ```
60
+
61
+ ## Project Structure
62
+
63
+ ```
64
+ src/
65
+ cli.ts # CLI entry point
66
+ index.ts # Main module
67
+ config/ # Configuration management
68
+ index.ts
69
+ types.ts
70
+ provider/ # Provider templates
71
+ templates.ts
72
+ tui/ # TUI interface
73
+ index.ts
74
+ validation/ # API key validation
75
+ index.ts
76
+ ```
77
+
78
+ ## License
79
+
80
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { run } from './index.js';
3
+ run().catch(error => {
4
+ console.error('Fatal error:', error);
5
+ process.exit(1);
6
+ });
7
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEjC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;IAClB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { OpenCodeConfig, ProviderInput } from './types.js';
2
+ export declare class ConfigManager {
3
+ private configPath;
4
+ constructor();
5
+ getConfigPath(): string;
6
+ readConfig(): OpenCodeConfig | null;
7
+ writeConfig(config: OpenCodeConfig): void;
8
+ backupConfig(): string | null;
9
+ restoreBackup(backupPath: string): void;
10
+ addProvider(input: ProviderInput): void;
11
+ getDefaultConfig(): OpenCodeConfig;
12
+ }
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAkB,aAAa,EAAE,MAAM,YAAY,CAAC;AAOhF,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAS;;IAM3B,aAAa,IAAI,MAAM;IAIvB,UAAU,IAAI,cAAc,GAAG,IAAI;IAYnC,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAYzC,YAAY,IAAI,MAAM,GAAG,IAAI;IAgB7B,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAQvC,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IA8BvC,gBAAgB,IAAI,cAAc;CAMnC"}
@@ -0,0 +1,95 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ import { getProviderTemplate } from '../provider/templates.js';
5
+ const CONFIG_DIR = path.join(os.homedir(), '.config', 'opencode');
6
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'opencode.json');
7
+ const DEFAULT_SCHEMA = 'https://opencode.ai/config.json';
8
+ export class ConfigManager {
9
+ configPath;
10
+ constructor() {
11
+ this.configPath = CONFIG_FILE;
12
+ }
13
+ getConfigPath() {
14
+ return this.configPath;
15
+ }
16
+ readConfig() {
17
+ try {
18
+ if (!fs.existsSync(this.configPath)) {
19
+ return null;
20
+ }
21
+ const content = fs.readFileSync(this.configPath, 'utf-8');
22
+ return JSON.parse(content);
23
+ }
24
+ catch (error) {
25
+ throw new Error(`Failed to read config: ${error instanceof Error ? error.message : String(error)}`);
26
+ }
27
+ }
28
+ writeConfig(config) {
29
+ try {
30
+ const configDir = path.dirname(this.configPath);
31
+ if (!fs.existsSync(configDir)) {
32
+ fs.mkdirSync(configDir, { recursive: true });
33
+ }
34
+ fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2), 'utf-8');
35
+ }
36
+ catch (error) {
37
+ throw new Error(`Failed to write config: ${error instanceof Error ? error.message : String(error)}`);
38
+ }
39
+ }
40
+ backupConfig() {
41
+ try {
42
+ if (!fs.existsSync(this.configPath)) {
43
+ return null;
44
+ }
45
+ const backupPath = `${this.configPath}.bak`;
46
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
47
+ const timestampedBackupPath = `${this.configPath}.${timestamp}.bak`;
48
+ fs.copyFileSync(this.configPath, timestampedBackupPath);
49
+ return timestampedBackupPath;
50
+ }
51
+ catch (error) {
52
+ throw new Error(`Failed to backup config: ${error instanceof Error ? error.message : String(error)}`);
53
+ }
54
+ }
55
+ restoreBackup(backupPath) {
56
+ try {
57
+ fs.copyFileSync(backupPath, this.configPath);
58
+ }
59
+ catch (error) {
60
+ throw new Error(`Failed to restore backup: ${error instanceof Error ? error.message : String(error)}`);
61
+ }
62
+ }
63
+ addProvider(input) {
64
+ const config = this.readConfig() || this.getDefaultConfig();
65
+ if (!config.provider || typeof config.provider !== 'object') {
66
+ config.provider = {};
67
+ }
68
+ const template = getProviderTemplate(input.providerId);
69
+ if (!template) {
70
+ throw new Error(`Unknown provider: ${input.providerId}`);
71
+ }
72
+ const providerConfig = {
73
+ npm: template.npm,
74
+ name: template.id,
75
+ options: {
76
+ baseURL: template.baseURL,
77
+ apiKey: input.apiKey
78
+ },
79
+ models: {
80
+ [input.modelName]: {
81
+ name: input.modelName
82
+ }
83
+ }
84
+ };
85
+ config.provider[input.providerId] = providerConfig;
86
+ this.writeConfig(config);
87
+ }
88
+ getDefaultConfig() {
89
+ return {
90
+ $schema: DEFAULT_SCHEMA,
91
+ provider: {}
92
+ };
93
+ }
94
+ }
95
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ export interface ProviderConfig {
2
+ npm: string;
3
+ name: string;
4
+ options: {
5
+ baseURL: string;
6
+ apiKey: string;
7
+ };
8
+ models: Record<string, {
9
+ name: string;
10
+ }>;
11
+ }
12
+ export interface OpenCodeConfig {
13
+ $schema: string;
14
+ provider: Record<string, ProviderConfig>;
15
+ }
16
+ export interface ProviderTemplate {
17
+ id: string;
18
+ displayName: string;
19
+ npm: string;
20
+ baseURL: string;
21
+ supportsApiKeyValidation: boolean;
22
+ validateApiKey?: (apiKey: string, model: string) => Promise<boolean>;
23
+ }
24
+ export interface ProviderInput {
25
+ providerId: string;
26
+ apiKey: string;
27
+ modelName: string;
28
+ }
29
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB,EAAE,OAAO,CAAC;IAClC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/config/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export declare function run(): Promise<void>;
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAsBzC"}
@@ -0,0 +1,24 @@
1
+ import { ConfigManager } from './config/index.js';
2
+ import { TUIManager } from './tui/index.js';
3
+ export async function run() {
4
+ const configManager = new ConfigManager();
5
+ const tuiManager = new TUIManager();
6
+ try {
7
+ const input = await tuiManager.run();
8
+ if (!input) {
9
+ console.log('Cancelled');
10
+ return;
11
+ }
12
+ const backupPath = configManager.backupConfig();
13
+ if (backupPath) {
14
+ tuiManager.showBackup(backupPath);
15
+ }
16
+ configManager.addProvider(input);
17
+ tuiManager.showMessage('configUpdated');
18
+ }
19
+ catch (error) {
20
+ tuiManager.showError(error instanceof Error ? error.message : String(error));
21
+ process.exit(1);
22
+ }
23
+ }
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,GAAG;IACvB,MAAM,aAAa,GAAG,IAAI,aAAa,EAAE,CAAC;IAC1C,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC;IAEpC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACzB,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,aAAa,CAAC,YAAY,EAAE,CAAC;QAChD,IAAI,UAAU,EAAE,CAAC;YACf,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QACpC,CAAC;QAED,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACjC,UAAU,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,UAAU,CAAC,SAAS,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { ProviderTemplate } from '../config/types.js';
2
+ export declare const PROVIDER_TEMPLATES: Record<string, ProviderTemplate>;
3
+ export declare function getProviderTemplate(id: string): ProviderTemplate | undefined;
4
+ export declare function getAllProviderTemplates(): ProviderTemplate[];
5
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../src/provider/templates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAiE/D,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE5E;AAED,wBAAgB,uBAAuB,IAAI,gBAAgB,EAAE,CAE5D"}
@@ -0,0 +1,74 @@
1
+ export const PROVIDER_TEMPLATES = {
2
+ volcengine: {
3
+ id: 'volcengine',
4
+ displayName: '火山引擎',
5
+ npm: '@ai-sdk/openai-compatible',
6
+ baseURL: 'https://ark.cn-beijing.volces.com/api/v3',
7
+ supportsApiKeyValidation: true,
8
+ validateApiKey: async (apiKey, model) => {
9
+ try {
10
+ const response = await fetch('https://ark.cn-beijing.volces.com/api/v3/models', {
11
+ method: 'GET',
12
+ headers: {
13
+ 'Authorization': `Bearer ${apiKey}`,
14
+ 'Content-Type': 'application/json'
15
+ }
16
+ });
17
+ return response.ok;
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ },
24
+ 'volcengine-codingplan': {
25
+ id: 'volcengine-codingplan',
26
+ displayName: '火山引擎CodingPlan',
27
+ npm: '@ai-sdk/openai-compatible',
28
+ baseURL: 'https://ark.cn-beijing.volces.com/api/coding/v3',
29
+ supportsApiKeyValidation: true,
30
+ validateApiKey: async (apiKey, model) => {
31
+ try {
32
+ const response = await fetch('https://ark.cn-beijing.volces.com/api/coding/v3/models', {
33
+ method: 'GET',
34
+ headers: {
35
+ 'Authorization': `Bearer ${apiKey}`,
36
+ 'Content-Type': 'application/json'
37
+ }
38
+ });
39
+ return response.ok;
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ }
45
+ },
46
+ 'ZhiPu-CodingPlan': {
47
+ id: 'ZhiPu-CodingPlan',
48
+ displayName: '智谱CodingPlan',
49
+ npm: '@ai-sdk/openai-compatible',
50
+ baseURL: 'https://open.bigmodel.cn/api/paas/v4',
51
+ supportsApiKeyValidation: true,
52
+ validateApiKey: async (apiKey) => {
53
+ try {
54
+ const response = await fetch('https://open.bigmodel.cn/api/paas/v4/models', {
55
+ method: 'GET',
56
+ headers: {
57
+ 'Authorization': `Bearer ${apiKey}`
58
+ }
59
+ });
60
+ return response.ok;
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ }
66
+ }
67
+ };
68
+ export function getProviderTemplate(id) {
69
+ return PROVIDER_TEMPLATES[id];
70
+ }
71
+ export function getAllProviderTemplates() {
72
+ return Object.values(PROVIDER_TEMPLATES);
73
+ }
74
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../../src/provider/templates.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kBAAkB,GAAqC;IAClE,UAAU,EAAE;QACV,EAAE,EAAE,YAAY;QAChB,WAAW,EAAE,MAAM;QACnB,GAAG,EAAE,2BAA2B;QAChC,OAAO,EAAE,0CAA0C;QACnD,wBAAwB,EAAE,IAAI;QAC9B,cAAc,EAAE,KAAK,EAAE,MAAc,EAAE,KAAa,EAAE,EAAE;YACtD,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,iDAAiD,EAAE;oBAC9E,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE;wBACP,eAAe,EAAE,UAAU,MAAM,EAAE;wBACnC,cAAc,EAAE,kBAAkB;qBACnC;iBACF,CAAC,CAAC;gBACH,OAAO,QAAQ,CAAC,EAAE,CAAC;YACrB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;KACF;IAED,uBAAuB,EAAE;QACvB,EAAE,EAAE,uBAAuB;QAC3B,WAAW,EAAE,gBAAgB;QAC7B,GAAG,EAAE,2BAA2B;QAChC,OAAO,EAAE,iDAAiD;QAC1D,wBAAwB,EAAE,IAAI;QAC9B,cAAc,EAAE,KAAK,EAAE,MAAc,EAAE,KAAa,EAAE,EAAE;YACtD,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,wDAAwD,EAAE;oBACrF,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE;wBACP,eAAe,EAAE,UAAU,MAAM,EAAE;wBACnC,cAAc,EAAE,kBAAkB;qBACnC;iBACF,CAAC,CAAC;gBACH,OAAO,QAAQ,CAAC,EAAE,CAAC;YACrB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;KACF;IAED,kBAAkB,EAAE;QAClB,EAAE,EAAE,kBAAkB;QACtB,WAAW,EAAE,cAAc;QAC3B,GAAG,EAAE,2BAA2B;QAChC,OAAO,EAAE,sCAAsC;QAC/C,wBAAwB,EAAE,IAAI;QAC9B,cAAc,EAAE,KAAK,EAAE,MAAc,EAAE,EAAE;YACvC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,6CAA6C,EAAE;oBAC1E,MAAM,EAAE,KAAK;oBACb,OAAO,EAAE;wBACP,eAAe,EAAE,UAAU,MAAM,EAAE;qBACpC;iBACF,CAAC,CAAC;gBACH,OAAO,QAAQ,CAAC,EAAE,CAAC;YACrB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;KACF;CACF,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,EAAU;IAC5C,OAAO,kBAAkB,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,OAAO,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ProviderInput } from '../config/types.js';
2
+ export declare class TUIManager {
3
+ private language;
4
+ private messages;
5
+ constructor();
6
+ run(): Promise<ProviderInput | null>;
7
+ private validateWithRetry;
8
+ showMessage(key: string): void;
9
+ showError(message: string): void;
10
+ showBackup(path: string): void;
11
+ }
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tui/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AA0CxD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,QAAQ,CAAyB;;IAQnC,GAAG,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;YAiD5B,iBAAiB;IA6C/B,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI9B,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIhC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAG/B"}
@@ -0,0 +1,136 @@
1
+ import inquirer from 'inquirer';
2
+ import { getAllProviderTemplates } from '../provider/templates.js';
3
+ import { validateApiKey } from '../validation/index.js';
4
+ const MESSAGES = {
5
+ en: {
6
+ welcome: 'Welcome to opencode-oh - OpenCode Helper Tool',
7
+ selectProvider: 'Select a provider to configure:',
8
+ providerBaseURL: 'Provider Base URL:',
9
+ enterApiKey: 'Enter API key:',
10
+ enterModelName: 'Enter model name:',
11
+ validating: 'Validating API key...',
12
+ validationSuccess: 'API key validated successfully',
13
+ validationFailed: 'API key validation failed',
14
+ retry: 'Would you like to retry?',
15
+ skipValidation: 'Skip validation and proceed?',
16
+ configUpdated: 'Configuration updated successfully',
17
+ backupCreated: 'Backup created at:',
18
+ errorOccurred: 'An error occurred:',
19
+ noProviders: 'No providers available'
20
+ },
21
+ zh: {
22
+ welcome: '欢迎使用 opencode-oh - OpenCode 辅助工具',
23
+ selectProvider: '选择要配置的提供商:',
24
+ providerBaseURL: '提供商 Base URL:',
25
+ enterApiKey: '输入 API key:',
26
+ enterModelName: '输入模型名称:',
27
+ validating: '正在验证 API key...',
28
+ validationSuccess: 'API key 验证成功',
29
+ validationFailed: 'API key 验证失败',
30
+ retry: '是否重试?',
31
+ skipValidation: '跳过验证并继续?',
32
+ configUpdated: '配置更新成功',
33
+ backupCreated: '备份已创建于:',
34
+ errorOccurred: '发生错误:',
35
+ noProviders: '没有可用的提供商'
36
+ }
37
+ };
38
+ export class TUIManager {
39
+ language;
40
+ messages;
41
+ constructor() {
42
+ const locale = process.env.LANG || 'en_US';
43
+ this.language = locale.startsWith('zh') ? 'zh' : 'en';
44
+ this.messages = MESSAGES[this.language];
45
+ }
46
+ async run() {
47
+ console.log(`\n${this.messages.welcome}\n`);
48
+ const providers = getAllProviderTemplates();
49
+ if (providers.length === 0) {
50
+ console.error(this.messages.noProviders);
51
+ return null;
52
+ }
53
+ const { providerId } = await inquirer.prompt([
54
+ {
55
+ type: 'list',
56
+ name: 'providerId',
57
+ message: this.messages.selectProvider,
58
+ choices: providers.map(p => ({
59
+ name: p.displayName,
60
+ value: p.id
61
+ }))
62
+ }
63
+ ]);
64
+ const selectedProvider = providers.find(p => p.id === providerId);
65
+ if (selectedProvider) {
66
+ console.log(`\n${this.messages.providerBaseURL} ${selectedProvider.baseURL}\n`);
67
+ }
68
+ const { apiKey } = await inquirer.prompt([
69
+ {
70
+ type: 'password',
71
+ name: 'apiKey',
72
+ message: this.messages.enterApiKey,
73
+ validate: (input) => input.length > 0 || 'API key is required'
74
+ }
75
+ ]);
76
+ const { modelName } = await inquirer.prompt([
77
+ {
78
+ type: 'input',
79
+ name: 'modelName',
80
+ message: this.messages.enterModelName,
81
+ validate: (input) => input.length > 0 || 'Model name is required'
82
+ }
83
+ ]);
84
+ const input = { providerId, apiKey, modelName };
85
+ return await this.validateWithRetry(input);
86
+ }
87
+ async validateWithRetry(input) {
88
+ console.log(`\n${this.messages.validating}`);
89
+ const result = await validateApiKey(input.providerId, input.apiKey, input.modelName);
90
+ if (result.valid) {
91
+ console.log(`✓ ${this.messages.validationSuccess}\n`);
92
+ return input;
93
+ }
94
+ console.log(`✗ ${this.messages.validationFailed}`);
95
+ if (result.error) {
96
+ console.log(` ${result.error}`);
97
+ }
98
+ const { action } = await inquirer.prompt([
99
+ {
100
+ type: 'list',
101
+ name: 'action',
102
+ message: this.messages.retry,
103
+ choices: [
104
+ { name: 'Retry', value: 'retry' },
105
+ { name: 'Skip', value: 'skip' },
106
+ { name: 'Cancel', value: 'cancel' }
107
+ ]
108
+ }
109
+ ]);
110
+ if (action === 'retry') {
111
+ const { apiKey } = await inquirer.prompt([
112
+ {
113
+ type: 'password',
114
+ name: 'apiKey',
115
+ message: this.messages.enterApiKey
116
+ }
117
+ ]);
118
+ input.apiKey = apiKey;
119
+ return this.validateWithRetry(input);
120
+ }
121
+ else if (action === 'skip') {
122
+ return input;
123
+ }
124
+ return null;
125
+ }
126
+ showMessage(key) {
127
+ console.log(this.messages[key]);
128
+ }
129
+ showError(message) {
130
+ console.error(`${this.messages.errorOccurred} ${message}`);
131
+ }
132
+ showBackup(path) {
133
+ console.log(`${this.messages.backupCreated} ${path}`);
134
+ }
135
+ }
136
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tui/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface ValidationResult {
2
+ valid: boolean;
3
+ error?: string;
4
+ }
5
+ export declare function validateApiKey(providerId: string, apiKey: string, model?: string): Promise<ValidationResult>;
6
+ //# sourceMappingURL=index.d.ts.map