Skip to content

Commit e86c3a3

Browse files
Base profiles
1 parent d2d741a commit e86c3a3

File tree

6 files changed

+358
-33
lines changed

6 files changed

+358
-33
lines changed

src/core/providers/openai.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {ChatOpenAI} from '@langchain/openai'
2+
3+
export interface OpenAIConfig {
4+
apiKey: string
5+
maxTokens?: number
6+
model: string
7+
temperature?: number
8+
}
9+
10+
export function createClient(config: OpenAIConfig): ChatOpenAI {
11+
return new ChatOpenAI({
12+
apiKey: config.apiKey,
13+
maxRetries: 3,
14+
maxTokens: config.maxTokens || 2000,
15+
model: config.model,
16+
temperature: config.temperature || 0.3,
17+
})
18+
}

src/core/providers/watsonx.ts

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,24 @@
11
import {ChatWatsonx} from '@langchain/community/chat_models/ibm'
22

3-
/**
4-
* Configuration for watsonx.ai client
5-
*/
63
export interface WatsonxConfig {
74
apiKey: string
85
maxNewTokens?: number
9-
model?: string
6+
model: string
107
projectId: string
118
serviceUrl: string
129
temperature?: number
1310
}
1411

15-
/**
16-
* Creates and returns a configured watsonx.ai chat model with IAM authentication
17-
*/
18-
export function createClient(config?: Partial<WatsonxConfig>): ChatWatsonx {
19-
// Get configuration from environment variables or provided config
20-
const serviceUrl = config?.serviceUrl || process.env.WATSONX_AI_SERVICE_URL
21-
const projectId = config?.projectId || process.env.WATSONX_AI_PROJECT_ID
22-
const apiKey = config?.apiKey || process.env.WATSONX_AI_APIKEY
23-
24-
// Validate required configuration
25-
if (!serviceUrl) {
26-
throw new Error('WATSONX_AI_SERVICE_URL is required')
27-
}
28-
29-
if (!projectId) {
30-
throw new Error('WATSONX_AI_PROJECT_ID is required')
31-
}
32-
33-
if (!apiKey) {
34-
throw new Error('WATSONX_AI_APIKEY is required')
35-
}
36-
37-
// Create and return the chat model with IAM authentication
12+
export function createClient(config: WatsonxConfig): ChatWatsonx {
3813
return new ChatWatsonx({
3914
maxRetries: 3,
40-
maxTokens: config?.maxNewTokens || 2000,
41-
model: config?.model || 'ibm/granite-4-h-small',
42-
projectId,
43-
serviceUrl,
44-
temperature: config?.temperature || 0.3,
15+
maxTokens: config.maxNewTokens || 2000,
16+
model: config.model,
17+
projectId: config.projectId,
18+
serviceUrl: config.serviceUrl,
19+
temperature: config.temperature || 0.3,
4520
version: '2024-05-31',
46-
watsonxAIApikey: apiKey,
21+
watsonxAIApikey: config.apiKey,
4722
watsonxAIAuthType: 'iam',
4823
})
4924
}

src/lib/profile/factory.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type {BaseChatModel} from '@langchain/core/language_models/chat_models'
2+
3+
import type {Profile} from './types.js'
4+
5+
import {createClient as createOpenAIClient} from '../../core/providers/openai.js'
6+
import {createClient as createWatsonxClient} from '../../core/providers/watsonx.js'
7+
8+
export function createProviderFromProfile(profile: Profile): BaseChatModel {
9+
switch (profile.provider) {
10+
case 'openai': {
11+
return createOpenAIClient(profile.config)
12+
}
13+
14+
case 'watsonx': {
15+
return createWatsonxClient(profile.config)
16+
}
17+
}
18+
}

src/lib/profile/storage.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import {existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync} from 'node:fs'
2+
import {homedir} from 'node:os'
3+
import {join} from 'node:path'
4+
5+
import type {Profile} from './types.js'
6+
7+
export function getProfilesDir(): string {
8+
const home = process.env.HOME || homedir()
9+
return join(home, '.config', 'translation-ai-cli', 'profiles')
10+
}
11+
12+
export function ensureProfilesDir(): void {
13+
const dir = getProfilesDir()
14+
if (!existsSync(dir)) {
15+
mkdirSync(dir, {recursive: true})
16+
}
17+
}
18+
19+
export function getProfilePath(name: string): string {
20+
return join(getProfilesDir(), `${name}.json`)
21+
}
22+
23+
export function saveProfile(profile: Profile): void {
24+
ensureProfilesDir()
25+
const path = getProfilePath(profile.name)
26+
writeFileSync(path, JSON.stringify(profile, null, 2), {
27+
encoding: 'utf8',
28+
mode: 0o600, // only owner can read/write
29+
})
30+
}
31+
32+
export function loadProfile(name: string): Profile {
33+
const path = getProfilePath(name)
34+
if (!existsSync(path)) {
35+
throw new Error(`Profile "${name}" does not exist`)
36+
}
37+
38+
const content = readFileSync(path, 'utf8')
39+
return JSON.parse(content) as Profile
40+
}
41+
42+
export function listProfiles(): string[] {
43+
const dir = getProfilesDir()
44+
if (!existsSync(dir)) {
45+
return []
46+
}
47+
48+
return readdirSync(dir)
49+
.filter((file) => file.endsWith('.json'))
50+
.map((file) => file.replace(/\.json$/, ''))
51+
}
52+
53+
export function deleteProfile(name: string): void {
54+
const path = getProfilePath(name)
55+
if (!existsSync(path)) {
56+
throw new Error(`Profile "${name}" does not exist`)
57+
}
58+
59+
rmSync(path)
60+
}
61+
62+
export function profileExists(name: string): boolean {
63+
return existsSync(getProfilePath(name))
64+
}

src/lib/profile/types.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
export interface OpenAIProfileConfig {
2+
apiKey: string
3+
model: string
4+
}
5+
6+
export interface WatsonxProfileConfig {
7+
apiKey: string
8+
model: string
9+
projectId: string
10+
serviceUrl: string
11+
}
12+
13+
export interface OpenAIProfile {
14+
config: OpenAIProfileConfig
15+
name: string
16+
provider: 'openai'
17+
}
18+
19+
export interface WatsonxProfile {
20+
config: WatsonxProfileConfig
21+
name: string
22+
provider: 'watsonx'
23+
}
24+
25+
export type Profile = OpenAIProfile | WatsonxProfile

0 commit comments

Comments
 (0)