@dxtmisha/scripts 0.9.0 → 0.10.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.
- package/CHANGELOG.md +30 -0
- package/package.json +2 -1
- package/src/classes/Ai/AiClaudeAgent.ts +16 -0
- package/src/classes/Ai/AiClaudeAgentLite.ts +86 -0
- package/src/classes/Ai/AiClaudeCliLite.ts +29 -65
- package/src/classes/Ai/AiClaudeLite.ts +19 -7
- package/src/classes/Ai/AiGoogleCliLite.ts +27 -64
- package/src/classes/Ai/AiOpenAi.ts +26 -0
- package/src/classes/Ai/AiOpenAiLite.ts +107 -0
- package/src/classes/Ai/AiZAi.ts +17 -0
- package/src/classes/Ai/AiZAiLite.ts +26 -0
- package/src/classes/Ai/ApiTmp.ts +43 -0
- package/src/classes/Build/BuildPackages.ts +33 -7
- package/src/classes/Design/DesignComponent.ts +1 -1
- package/src/classes/Library/LibraryAiPromptItem.ts +36 -2
- package/src/composables/useAi.ts +15 -0
- package/src/config.ts +2 -0
- package/src/demo/ai.ts +10 -0
- package/src/library-ai.ts +4 -4
- package/src/library.ts +67 -54
- package/src/media/templates/componentDoc/materials/README.md +8 -0
- package/src/media/templates/componentDoc/materials/prompt.txt +28 -0
- package/src/media/templates/componentDoc/wiki/prompt.txt +21 -0
- package/src/media/templates/componentDoc/wiki/run.ts +2 -1
- package/src/media/templates/prompts/aiCodeGlobalPrompt.en.txt +19 -0
- package/src/media/templates/prompts/aiCodeGlobalPrompt.ru.txt +21 -0
- package/src/media/templates/prompts/componentPrompt.en.txt +71 -16
- package/src/media/templates/prompts/componentPrompt.ru.txt +71 -16
- package/src/types/configTypes.ts +9 -2
- package/src/classes/Component/__tests__/ComponentCreator.test.ts +0 -71
- package/src/classes/Component/__tests__/ComponentItem.test.ts +0 -71
- package/src/classes/Git/__tests__/GitRead.test.ts +0 -70
- package/src/composables/__tests__/useAi.test.ts +0 -75
- package/src/functions/__tests__/getComponentPaths.test.ts +0 -19
- package/src/functions/__tests__/getConfigAi.test.ts +0 -26
- package/src/functions/__tests__/getConstructorProperties.test.ts +0 -51
- package/src/functions/__tests__/getDirname.test.ts +0 -31
- package/src/functions/__tests__/getNameDirByPaths.test.ts +0 -40
- package/src/functions/__tests__/getPackageJson.test.ts +0 -34
- package/src/functions/__tests__/hasNativeDirname.test.ts +0 -18
- package/src/functions/__tests__/toPathStandardSep.test.ts +0 -31
- package/src/media/templates/componentDoc/figma/run-figma.ts +0 -26
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.10.0] - 2026-05-20
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **OpenAI Provider**: Implemented `AiOpenAiLite` and `AiOpenAi` classes providing a fully typed OpenAI SDK integration, supporting chat completions with image and text content blocks.
|
|
9
|
+
- **Z.ai Provider**: Implemented `AiZAiLite` and `AiZAi` classes as OpenAI-compatible Zhipu AI integration, automatically routing to the correct endpoint (`api.z.ai` for international access). The `baseURL` is configurable via `aiConfig.baseURL` in `design.config.json`.
|
|
10
|
+
- **Claude Agent Provider**: Added `AiClaudeAgent` and `AiClaudeAgentLite` classes supporting the extended Anthropic agent API workflow.
|
|
11
|
+
- **Build Orchestration**: Introduced `BuildPackages` and `BuildPublishPackages` classes for comprehensive monorepo build and publish orchestration with incremental tracking support.
|
|
12
|
+
- **Package Management**: Added `PackageFile` class for structured package configuration file handling.
|
|
13
|
+
- **`run` utility**: Added a new `run()` utility function for streamlined subprocess execution across scripts.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- **`AiType` config type**: Expanded `AiType` to include all supported providers: `'claude' | 'claude-cli' | 'claude-agent' | 'gemini' | 'gemini-cli' | 'openai' | 'zai'`. Previously only `gemini` and `gemini-cli` were available.
|
|
17
|
+
- **`useAi` composable**: Updated routing switch to instantiate the correct AI class for all providers including `claude`, `claude-agent`, `claude-cli`, `openai`, and `zai`.
|
|
18
|
+
- **Library exports**: Updated `library.ts` and `library-ai.ts` to export all new AI provider classes, agent classes, build orchestration classes and the `run` utility.
|
|
19
|
+
|
|
20
|
+
### Removed
|
|
21
|
+
- **CLI variants from `library-ai.ts`**: Removed exports of `AiGoogleCli`, `AiGoogleCliLite`, `AiClaudeCli`, and `AiClaudeCliLite` from the lightweight AI-only export surface. These remain accessible via the main `library.ts` entry point.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## [0.9.1] - 2026-05-18
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- **Component Documentation Prompts**: Overhauled `componentPrompt.en.txt` and `componentPrompt.ru.txt` to enforce `storybookStyle.scss` helper usage in Storybook stories, standardized slot/expose signature formatting, and mandatory `<Source />` code block inclusion.
|
|
29
|
+
- **Architectural Guardrails**: Added strict instructions against code modifications and hallucinations during AI-assisted code and documentation generation.
|
|
30
|
+
- **Wiki Template**: Updated `componentDoc/wiki/run.ts` to dynamically resolve and read prompt instructions from `prompt.txt`.
|
|
31
|
+
- **Template Structure**: Created `componentDoc/materials/` workspace directory with `README.md` and `prompt.txt` templates containing target implementation instructions and monorepo context.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
5
35
|
## [0.8.2] - 2026-05-13
|
|
6
36
|
|
|
7
37
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxtmisha/scripts",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.10.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Development scripts and CLI tools for DXT UI projects - automated component generation, library building and project management tools",
|
|
7
7
|
"keywords": [
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"@dxtmisha/styles": "*",
|
|
79
79
|
"@dxtmisha/wiki": "*",
|
|
80
80
|
"@google/genai": "*",
|
|
81
|
+
"openai": "*",
|
|
81
82
|
"puppeteer": "*",
|
|
82
83
|
"typescript": "*",
|
|
83
84
|
"vue": "*"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { getConfigAi } from '../../functions/getConfigAi'
|
|
2
|
+
import { AiClaudeAgentLite } from './AiClaudeAgentLite'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Claude AI implementation via Agent SDK.
|
|
6
|
+
* Uses @anthropic-ai/claude-agent-sdk to interact with Claude as an agent.
|
|
7
|
+
*
|
|
8
|
+
* Реализация Claude AI через Agent SDK.
|
|
9
|
+
*/
|
|
10
|
+
export class AiClaudeAgent extends AiClaudeAgentLite {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(
|
|
13
|
+
...getConfigAi()
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { query } from '@anthropic-ai/claude-agent-sdk'
|
|
2
|
+
import { AiAbstract } from './AiAbstract'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Claude AI implementation via Agent SDK.
|
|
6
|
+
* Uses @anthropic-ai/claude-agent-sdk to interact with Claude as an agent.
|
|
7
|
+
*
|
|
8
|
+
* Реализация Claude AI через Agent SDK.
|
|
9
|
+
* Использует @anthropic-ai/claude-agent-sdk для взаимодействия с Claude в режиме агента.
|
|
10
|
+
*
|
|
11
|
+
* Responsibilities / Ответственности:
|
|
12
|
+
* - Initialize Agent SDK client / Инициализировать Agent SDK клиент
|
|
13
|
+
* - Execute query via Agent SDK / Выполнить запрос через Agent SDK
|
|
14
|
+
* - Extract and return textual result / Извлечь и вернуть текстовый результат
|
|
15
|
+
*/
|
|
16
|
+
export class AiClaudeAgentLite extends AiAbstract<{}> {
|
|
17
|
+
/**
|
|
18
|
+
* Initializes the "client".
|
|
19
|
+
* For Agent SDK, we mark it as initialized.
|
|
20
|
+
*/
|
|
21
|
+
protected init(): void {
|
|
22
|
+
this.ai = {}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Implementation hook: convert accumulated images to model-specific format.
|
|
27
|
+
* Agent SDK implementation logic for images can be added if supported by the SDK.
|
|
28
|
+
*/
|
|
29
|
+
protected toImages(): any {
|
|
30
|
+
return []
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Implementation hook: convert accumulated contents to model-specific format.
|
|
35
|
+
*/
|
|
36
|
+
protected toContents(): any {
|
|
37
|
+
return this.contents.join('\n\n')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Performs content generation request via Agent SDK and returns textual result.
|
|
42
|
+
*
|
|
43
|
+
* @param model Model identifier / Идентификатор модели
|
|
44
|
+
* @param contents Composed contents for generation / Собранный контент для генерации
|
|
45
|
+
*/
|
|
46
|
+
protected async response(
|
|
47
|
+
model: string,
|
|
48
|
+
contents: string
|
|
49
|
+
): Promise<string> {
|
|
50
|
+
const fullPrompt = [
|
|
51
|
+
this.toContents(),
|
|
52
|
+
contents
|
|
53
|
+
].filter(Boolean).join('\n\n')
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const q = query({
|
|
57
|
+
prompt: fullPrompt,
|
|
58
|
+
options: {
|
|
59
|
+
model: model || undefined,
|
|
60
|
+
env: {
|
|
61
|
+
...process.env,
|
|
62
|
+
ANTHROPIC_API_KEY: this.key
|
|
63
|
+
},
|
|
64
|
+
permissionMode: 'acceptEdits', // Auto-accept file changes if any
|
|
65
|
+
allowDangerouslySkipPermissions: true,
|
|
66
|
+
...this.config
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
let lastResult = ''
|
|
71
|
+
|
|
72
|
+
for await (const message of q) {
|
|
73
|
+
if (message.type === 'result') {
|
|
74
|
+
if (message.subtype === 'success') {
|
|
75
|
+
lastResult = message.result
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return lastResult.trim()
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.error('[AiClaudeAgent] Error:', error)
|
|
83
|
+
return ''
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { forEach } from '@dxtmisha/functional-basic'
|
|
2
2
|
import { exec } from 'node:child_process'
|
|
3
3
|
|
|
4
|
-
import { PropertiesFile } from '../Properties/PropertiesFile'
|
|
5
4
|
import { AiAbstract } from './AiAbstract'
|
|
6
|
-
|
|
7
|
-
const TEMPORARY_DIR = './ai-tmp'
|
|
5
|
+
import { ApiTmp } from './ApiTmp'
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
8
|
* Claude AI implementation via CLI.
|
|
@@ -19,24 +17,11 @@ const TEMPORARY_DIR = './ai-tmp'
|
|
|
19
17
|
* - Return stdout as result / Вернуть stdout как результат
|
|
20
18
|
*
|
|
21
19
|
* Notes / Примечания:
|
|
22
|
-
* - Requires 'claude' CLI tool installed
|
|
20
|
+
* - Requires 'claude' CLI tool installed / Требует установленной утилиты 'claude'
|
|
23
21
|
* - API key is passed via environment variable or config / API ключ передается через переменную окружения или конфиг
|
|
24
22
|
*/
|
|
25
23
|
export class AiClaudeCliLite extends AiAbstract<{}> {
|
|
26
|
-
|
|
27
|
-
* Counter for generating unique temporary file names/
|
|
28
|
-
* Счетчик для генерации уникальных имен временных файлов
|
|
29
|
-
*/
|
|
30
|
-
protected idFile = 1
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Generates a unique file path for the temporary prompt.
|
|
34
|
-
*
|
|
35
|
-
* Генерирует уникальный путь к файлу для временного промпта.
|
|
36
|
-
*/
|
|
37
|
-
protected getFileName(): string {
|
|
38
|
-
return `${TEMPORARY_DIR}/Prompt-${this.idFile++}.txt`
|
|
39
|
-
}
|
|
24
|
+
protected readonly tmp = new ApiTmp()
|
|
40
25
|
|
|
41
26
|
/**
|
|
42
27
|
* Initializes the "client".
|
|
@@ -70,7 +55,7 @@ export class AiClaudeCliLite extends AiAbstract<{}> {
|
|
|
70
55
|
protected toContents(): any {
|
|
71
56
|
return forEach(
|
|
72
57
|
this.contents,
|
|
73
|
-
content => this.createFile(content)
|
|
58
|
+
content => this.tmp.createFile(content)
|
|
74
59
|
)
|
|
75
60
|
}
|
|
76
61
|
|
|
@@ -88,58 +73,37 @@ export class AiClaudeCliLite extends AiAbstract<{}> {
|
|
|
88
73
|
return new Promise((resolve) => {
|
|
89
74
|
const fullPrompt = [
|
|
90
75
|
...this.toContents(),
|
|
91
|
-
this.createFile(contents)
|
|
76
|
+
this.tmp.createFile(contents)
|
|
92
77
|
].join('\n\n##################\n\n')
|
|
93
78
|
|
|
94
79
|
const escapedPrompt = fullPrompt.replace(/"/g, '\\"')
|
|
95
80
|
const modelFlag = model ? ` --model "${model}"` : ''
|
|
96
|
-
const command = `claude "${escapedPrompt}
|
|
81
|
+
const command = `claude "${escapedPrompt} -- Output strictly the code/answer. No preamble, no chatter, no reasoning" ${modelFlag}`
|
|
97
82
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
)
|
|
83
|
+
try {
|
|
84
|
+
exec(
|
|
85
|
+
command,
|
|
86
|
+
{
|
|
87
|
+
encoding: 'utf8',
|
|
88
|
+
env: {
|
|
89
|
+
...process.env
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
(error, stdout, stderr) => {
|
|
93
|
+
if (error) {
|
|
94
|
+
console.error('Error executing Claude CLI:', stderr || error.message)
|
|
95
|
+
resolve('')
|
|
96
|
+
} else {
|
|
97
|
+
resolve(stdout.trim())
|
|
98
|
+
}
|
|
116
99
|
|
|
117
|
-
|
|
100
|
+
this.tmp.removeFile()
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
} catch (_) {
|
|
104
|
+
this.tmp.removeFile()
|
|
105
|
+
}
|
|
118
106
|
})
|
|
119
107
|
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Creates a temporary file with the prompt content and returns the path formatted for the CLI.
|
|
123
|
-
*
|
|
124
|
-
* Создает временный файл с содержимым промпта и возвращает путь, отформатированный для CLI.
|
|
125
|
-
* @param content Prompt content / Содержимое промпта
|
|
126
|
-
* @returns Formatted file path (e.g., @./ai-tmp/Prompt-1.txt) / Отформатированный путь к файлу
|
|
127
|
-
*/
|
|
128
|
-
protected createFile(content: string): string {
|
|
129
|
-
const name = this.getFileName()
|
|
130
|
-
|
|
131
|
-
PropertiesFile.writeByPath(name, content)
|
|
132
|
-
|
|
133
|
-
return `Please read the following file as it contains the prompt instructions: @${name}`
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Cleans up temporary files and directories.
|
|
138
|
-
*
|
|
139
|
-
* Очищает временные файлы и директории.
|
|
140
|
-
* @protected
|
|
141
|
-
*/
|
|
142
|
-
protected removeFile(): void {
|
|
143
|
-
PropertiesFile.removeDir(TEMPORARY_DIR)
|
|
144
|
-
}
|
|
145
108
|
}
|
|
109
|
+
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { Anthropic } from '@anthropic-ai/sdk'
|
|
1
2
|
import { forEach } from '@dxtmisha/functional-basic'
|
|
3
|
+
|
|
2
4
|
import { AiAbstract } from './AiAbstract'
|
|
3
|
-
import { Anthropic } from '@anthropic-ai/sdk'
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Claude AI implementation of AiAbstract.
|
|
@@ -89,12 +90,23 @@ export class AiClaudeLite extends AiAbstract<Anthropic> {
|
|
|
89
90
|
...this.config
|
|
90
91
|
})
|
|
91
92
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
if (message?.content) {
|
|
94
|
+
return forEach(
|
|
95
|
+
message.content,
|
|
96
|
+
(block) => {
|
|
97
|
+
if (
|
|
98
|
+
block.type === 'text'
|
|
99
|
+
&& 'text' in block
|
|
100
|
+
) {
|
|
101
|
+
return block.text
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return undefined
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
.join('\n')
|
|
108
|
+
}
|
|
97
109
|
|
|
98
|
-
return
|
|
110
|
+
return ''
|
|
99
111
|
}
|
|
100
112
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { forEach } from '@dxtmisha/functional-basic'
|
|
2
2
|
import { exec } from 'node:child_process'
|
|
3
3
|
|
|
4
|
-
import { PropertiesFile } from '../Properties/PropertiesFile'
|
|
5
4
|
import { AiAbstract } from './AiAbstract'
|
|
6
|
-
|
|
7
|
-
const TEMPORARY_DIR = './ai-tmp'
|
|
5
|
+
import { ApiTmp } from './ApiTmp'
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
8
|
* Google AI (Gemini) implementation via CLI.
|
|
@@ -23,20 +21,7 @@ const TEMPORARY_DIR = './ai-tmp'
|
|
|
23
21
|
* - API key is passed via environment variable or config / API ключ передается через переменную окружения или конфиг
|
|
24
22
|
*/
|
|
25
23
|
export class AiGoogleCliLite extends AiAbstract<{}> {
|
|
26
|
-
|
|
27
|
-
* Counter for generating unique temporary file names/
|
|
28
|
-
* Счетчик для генерации уникальных имен временных файлов
|
|
29
|
-
*/
|
|
30
|
-
protected idFile = 1
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Generates a unique file path for the temporary prompt.
|
|
34
|
-
*
|
|
35
|
-
* Генерирует уникальный путь к файлу для временного промпта.
|
|
36
|
-
*/
|
|
37
|
-
protected getFileName(): string {
|
|
38
|
-
return `${TEMPORARY_DIR}/Prompt-${this.idFile++}.txt`
|
|
39
|
-
}
|
|
24
|
+
protected readonly tmp = new ApiTmp()
|
|
40
25
|
|
|
41
26
|
/**
|
|
42
27
|
* Initializes the "client".
|
|
@@ -70,7 +55,7 @@ export class AiGoogleCliLite extends AiAbstract<{}> {
|
|
|
70
55
|
protected toContents(): any {
|
|
71
56
|
return forEach(
|
|
72
57
|
this.contents,
|
|
73
|
-
content => this.createFile(content)
|
|
58
|
+
content => this.tmp.createFile(content)
|
|
74
59
|
)
|
|
75
60
|
}
|
|
76
61
|
|
|
@@ -88,58 +73,36 @@ export class AiGoogleCliLite extends AiAbstract<{}> {
|
|
|
88
73
|
return new Promise((resolve) => {
|
|
89
74
|
const fullPrompt = [
|
|
90
75
|
...this.toContents(),
|
|
91
|
-
this.createFile(contents)
|
|
76
|
+
this.tmp.createFile(contents)
|
|
92
77
|
].join('\n\n##################\n\n')
|
|
93
78
|
|
|
94
79
|
const escapedPrompt = fullPrompt.replace(/"/g, '\\"')
|
|
95
80
|
const modelFlag = model ? ` --model "${model}"` : ''
|
|
96
|
-
const command = `gemini "${escapedPrompt}
|
|
81
|
+
const command = `gemini "${escapedPrompt} -- Output strictly the code/answer. No preamble, no chatter, no reasoning" ${modelFlag} --yolo`
|
|
97
82
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
)
|
|
83
|
+
try {
|
|
84
|
+
exec(
|
|
85
|
+
command,
|
|
86
|
+
{
|
|
87
|
+
encoding: 'utf8',
|
|
88
|
+
env: {
|
|
89
|
+
...process.env
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
(error, stdout, stderr) => {
|
|
93
|
+
if (error) {
|
|
94
|
+
console.error('Error executing Gemini CLI:', stderr || error.message)
|
|
95
|
+
resolve('')
|
|
96
|
+
} else {
|
|
97
|
+
resolve(stdout.trim())
|
|
98
|
+
}
|
|
116
99
|
|
|
117
|
-
|
|
100
|
+
this.tmp.removeFile()
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
} catch (_) {
|
|
104
|
+
this.tmp.removeFile()
|
|
105
|
+
}
|
|
118
106
|
})
|
|
119
107
|
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Creates a temporary file with the prompt content and returns the path formatted for the CLI.
|
|
123
|
-
*
|
|
124
|
-
* Создает временный файл с содержимым промпта и возвращает путь, отформатированный для CLI.
|
|
125
|
-
* @param content Prompt content / Содержимое промпта
|
|
126
|
-
* @returns Formatted file path (e.g., @./ai-tmp/Prompt-1.txt) / Отформатированный путь к файлу
|
|
127
|
-
*/
|
|
128
|
-
protected createFile(content: string): string {
|
|
129
|
-
const name = this.getFileName()
|
|
130
|
-
|
|
131
|
-
PropertiesFile.writeByPath(name, content)
|
|
132
|
-
|
|
133
|
-
return `Please read the following file as it contains the prompt instructions: @${name}`
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Cleans up temporary files and directories.
|
|
138
|
-
*
|
|
139
|
-
* Очищает временные файлы и директории.
|
|
140
|
-
* @protected
|
|
141
|
-
*/
|
|
142
|
-
protected removeFile(): void {
|
|
143
|
-
PropertiesFile.removeDir(TEMPORARY_DIR)
|
|
144
|
-
}
|
|
145
108
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AiOpenAiLite } from './AiOpenAiLite'
|
|
2
|
+
import { getConfigAi } from '../../functions/getConfigAi'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* OpenAI implementation of AiAbstract.
|
|
6
|
+
* Initializes OpenAI client and performs text generation requests.
|
|
7
|
+
*
|
|
8
|
+
* Реализация OpenAI поверх AiAbstract.
|
|
9
|
+
* Инициализирует клиент OpenAI и выполняет запросы генерации текста.
|
|
10
|
+
*
|
|
11
|
+
* Responsibilities / Ответственности:
|
|
12
|
+
* - Provide API key / Предоставить API ключ
|
|
13
|
+
* - Initialize low-level client / Инициализировать низкоуровневый клиент
|
|
14
|
+
* - Call chat.completions.create and extract plain text / Вызвать chat.completions.create и извлечь текст
|
|
15
|
+
*
|
|
16
|
+
* Notes / Примечания:
|
|
17
|
+
* - Model must be set via setModel() before generate() / Модель нужно задать через setModel()
|
|
18
|
+
* - Returns empty string if response is missing / Возвращает пустую строку при отсутствии результата
|
|
19
|
+
*/
|
|
20
|
+
export class AiOpenAi extends AiOpenAiLite {
|
|
21
|
+
constructor() {
|
|
22
|
+
super(
|
|
23
|
+
...getConfigAi()
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { OpenAI } from 'openai'
|
|
2
|
+
import { forEach } from '@dxtmisha/functional-basic'
|
|
3
|
+
|
|
4
|
+
import { AiAbstract } from './AiAbstract'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* OpenAI implementation of AiAbstract.
|
|
8
|
+
* Initializes OpenAI client and performs text generation requests.
|
|
9
|
+
*
|
|
10
|
+
* Реализация OpenAI поверх AiAbstract.
|
|
11
|
+
* Инициализирует клиент OpenAI и выполняет запросы генерации текста.
|
|
12
|
+
*
|
|
13
|
+
* Responsibilities / Ответственности:
|
|
14
|
+
* - Provide API key / Предоставить API ключ
|
|
15
|
+
* - Initialize OpenAI client / Инициализировать клиент OpenAI
|
|
16
|
+
* - Call chat.completions.create and extract text content / Вызвать chat.completions.create и извлечь текст
|
|
17
|
+
*
|
|
18
|
+
* Notes / Примечания:
|
|
19
|
+
* - Model must be set via setModel() before generate() / Модель нужно задать через setModel()
|
|
20
|
+
* - Returns empty string if response is missing / Возвращает пустую строку при отсутствии результата
|
|
21
|
+
*/
|
|
22
|
+
export class AiOpenAiLite extends AiAbstract<OpenAI> {
|
|
23
|
+
/**
|
|
24
|
+
* Initializes OpenAI client instance.
|
|
25
|
+
*
|
|
26
|
+
* Инициализирует экземпляр клиента OpenAI.
|
|
27
|
+
*/
|
|
28
|
+
protected init(): void {
|
|
29
|
+
this.ai = new OpenAI({
|
|
30
|
+
apiKey: this.key
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Implementation hook: convert accumulated images to model-specific format.
|
|
36
|
+
* OpenAI expects images as content blocks with type 'image_url'.
|
|
37
|
+
*
|
|
38
|
+
* Хук реализации: преобразовать накопленные изображения в формат, специфичный для модели.
|
|
39
|
+
* OpenAI ожидает изображения как блоки контента с типом 'image_url'.
|
|
40
|
+
*/
|
|
41
|
+
protected toImages(): any {
|
|
42
|
+
return forEach(this.images, image => ({
|
|
43
|
+
type: 'image_url',
|
|
44
|
+
image_url: {
|
|
45
|
+
url: `data:${image.mime};base64,${image.base64}`
|
|
46
|
+
}
|
|
47
|
+
}))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Implementation hook: convert accumulated contents to model-specific format.
|
|
52
|
+
* OpenAI expects text as content blocks with type 'text'.
|
|
53
|
+
*
|
|
54
|
+
* Хук реализации: преобразовать накопленное содержимое в формат, специфичный для модели.
|
|
55
|
+
* OpenAI ожидает текст как блоки контента с типом 'text'.
|
|
56
|
+
*/
|
|
57
|
+
protected toContents(): any {
|
|
58
|
+
return forEach(this.contents, content => ({
|
|
59
|
+
type: 'text',
|
|
60
|
+
text: content
|
|
61
|
+
}))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Performs content generation request and returns textual result.
|
|
66
|
+
*
|
|
67
|
+
* Выполняет запрос генерации контента и возвращает текстовый результат.
|
|
68
|
+
* @param model Model identifier (e.g., 'gpt-4o') / Идентификатор модели
|
|
69
|
+
* @param contents Composed contents for generation / Собранный контент для генерации
|
|
70
|
+
*/
|
|
71
|
+
protected async response(
|
|
72
|
+
model: string,
|
|
73
|
+
contents: string
|
|
74
|
+
): Promise<string> {
|
|
75
|
+
console.log('asd', this.ai?.baseURL, JSON.stringify({
|
|
76
|
+
model,
|
|
77
|
+
messages: [
|
|
78
|
+
{
|
|
79
|
+
role: 'user',
|
|
80
|
+
content: [
|
|
81
|
+
...this.toImages(),
|
|
82
|
+
...this.toContents(),
|
|
83
|
+
{ type: 'text', text: contents }
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
...this.config
|
|
88
|
+
}))
|
|
89
|
+
|
|
90
|
+
const response = await this.ai?.chat.completions.create({
|
|
91
|
+
model,
|
|
92
|
+
messages: [
|
|
93
|
+
{
|
|
94
|
+
role: 'user',
|
|
95
|
+
content: [
|
|
96
|
+
...this.toImages(),
|
|
97
|
+
...this.toContents(),
|
|
98
|
+
{ type: 'text', text: contents }
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
],
|
|
102
|
+
...this.config
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
return response?.choices?.[0]?.message?.content ?? ''
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getConfigAi } from '../../functions/getConfigAi'
|
|
2
|
+
import { AiZAiLite } from './AiZAiLite'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Z.ai (Zhipu AI) implementation extending AiZAiLite.
|
|
6
|
+
* Automatically configured using project environment settings.
|
|
7
|
+
*
|
|
8
|
+
* Реализация Z.ai (Zhipu AI) расширяющая AiZAiLite.
|
|
9
|
+
* Автоматически настраивается с использованием настроек окружения проекта.
|
|
10
|
+
*/
|
|
11
|
+
export class AiZAi extends AiZAiLite {
|
|
12
|
+
constructor() {
|
|
13
|
+
super(
|
|
14
|
+
...getConfigAi()
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { OpenAI } from 'openai'
|
|
2
|
+
import { AiOpenAiLite } from './AiOpenAiLite'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Z.ai (Zhipu AI) implementation extending AiOpenAiLite.
|
|
6
|
+
* Performs requests to the OpenAI-compatible Z.ai endpoint.
|
|
7
|
+
*
|
|
8
|
+
* Реализация Z.ai (Zhipu AI) расширяющая AiOpenAiLite.
|
|
9
|
+
* Выполняет запросы к OpenAI-совместимому эндпоинту Z.ai.
|
|
10
|
+
*
|
|
11
|
+
* Responsibilities / Ответственности:
|
|
12
|
+
* - Initialize OpenAI client with Z.ai baseURL / Инициализировать клиент OpenAI с baseURL Z.ai
|
|
13
|
+
*/
|
|
14
|
+
export class AiZAiLite extends AiOpenAiLite {
|
|
15
|
+
/**
|
|
16
|
+
* Initializes OpenAI client instance configured for Z.ai.
|
|
17
|
+
*
|
|
18
|
+
* Инициализирует экземпляр клиента OpenAI, настроенный для Z.ai.
|
|
19
|
+
*/
|
|
20
|
+
protected override init(): void {
|
|
21
|
+
this.ai = new OpenAI({
|
|
22
|
+
apiKey: this.key,
|
|
23
|
+
baseURL: 'https://api.z.ai/api/paas/v4'
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { PropertiesFile } from '../Properties/PropertiesFile'
|
|
2
|
+
|
|
3
|
+
const TEMPORARY_DIR = './ai-tmp'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ApiTmp
|
|
7
|
+
*/
|
|
8
|
+
export class ApiTmp {
|
|
9
|
+
protected idFile = 1
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generates a unique file path for the temporary prompt.
|
|
13
|
+
*
|
|
14
|
+
* Генерирует уникальный путь к файлу для временного промпта.
|
|
15
|
+
*/
|
|
16
|
+
protected getFileName(): string {
|
|
17
|
+
return `${TEMPORARY_DIR}/Prompt-${this.idFile++}.txt`
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Creates a temporary file with the prompt content and returns the path formatted for the CLI.
|
|
22
|
+
*
|
|
23
|
+
* Создает временный файл с содержимым промпта и возвращает путь, отформатированный для CLI.
|
|
24
|
+
* @param content Prompt content / Содержимое промпта
|
|
25
|
+
* @returns Formatted file path (e.g., @./ai-tmp/Prompt-1.txt) / Отформатированный путь к файлу
|
|
26
|
+
*/
|
|
27
|
+
createFile(content: string): string {
|
|
28
|
+
const name = this.getFileName()
|
|
29
|
+
|
|
30
|
+
PropertiesFile.writeByPath(name, content.trim())
|
|
31
|
+
|
|
32
|
+
return `Please read the following file as it contains the prompt instructions: @${name}`
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Cleans up temporary files and directories.
|
|
37
|
+
*
|
|
38
|
+
* Очищает временные файлы и директории.
|
|
39
|
+
*/
|
|
40
|
+
removeFile(): void {
|
|
41
|
+
PropertiesFile.removeDir(TEMPORARY_DIR)
|
|
42
|
+
}
|
|
43
|
+
}
|