cast-code 1.0.3 → 1.0.5
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/README.md +150 -150
- package/dist/common/services/llm.service.js +1 -1
- package/dist/common/services/llm.service.js.map +1 -1
- package/dist/common/services/multi-llm.service.js +2 -2
- package/dist/common/services/multi-llm.service.js.map +1 -1
- package/dist/modules/config/services/config-commands.service.js +9 -3
- package/dist/modules/config/services/config-commands.service.js.map +1 -1
- package/dist/modules/config/services/init-config.service.js +8 -3
- package/dist/modules/config/services/init-config.service.js.map +1 -1
- package/dist/modules/core/services/deep-agent.service.js +27 -7
- package/dist/modules/core/services/deep-agent.service.js.map +1 -1
- package/dist/modules/git/services/commit-generator.service.js +21 -5
- package/dist/modules/git/services/commit-generator.service.js.map +1 -1
- package/dist/modules/repl/services/repl.service.js +2 -0
- package/dist/modules/repl/services/repl.service.js.map +1 -1
- package/dist/modules/repl/services/smart-input.js +30 -30
- package/dist/modules/repl/services/smart-input.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,217 +1,217 @@
|
|
|
1
1
|
# Cast Code
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
It is designed to feel like an in-terminal AI teammate that can read your codebase, plan work, use tools, and delegate to specialist sub-agents.
|
|
3
|
+
A multi-agent coding CLI for day-to-day engineering work. Cast feels like an AI teammate living inside your terminal — it reads your codebase, plans work, uses tools, and delegates to specialist sub-agents.
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
Inspired by [Claude Code](https://claude.ai/code), [OpenAI Codex](https://openai.com/codex), and [Kimi](https://kimi.ai).
|
|
6
|
+
Built by [pedrocastanha](https://github.com/pedrocastanha).
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
---
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
- connect Figma MCP,
|
|
12
|
-
- map project context,
|
|
13
|
-
- ask Cast to scaffold screens/components/styles,
|
|
14
|
-
- let frontend engineers focus on integration and complex business flows.
|
|
10
|
+
## Why
|
|
15
11
|
|
|
16
|
-
|
|
12
|
+
The main goal is to accelerate product delivery, especially frontend work from design prototypes.
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
14
|
+
Typical workflow:
|
|
15
|
+
- connect Figma Desktop MCP
|
|
16
|
+
- map project context with `/init`
|
|
17
|
+
- ask Cast to scaffold screens, components, and styles
|
|
18
|
+
- let engineers focus on integration and business logic
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
25
|
npm install -g cast-code
|
|
26
26
|
cast
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
> Requires Node.js >= 20. Works on
|
|
29
|
+
> Requires Node.js >= 20. Works on bash, zsh, fish, dash, ksh and any POSIX-compatible shell on Linux and macOS.
|
|
30
30
|
|
|
31
|
-
###
|
|
31
|
+
### `cast` not found after install?
|
|
32
32
|
|
|
33
|
-
The npm global bin directory may not be in your PATH.
|
|
33
|
+
The npm global bin directory may not be in your PATH. Find it with `npm prefix -g`, then add `<prefix>/bin` to your shell config:
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
export PATH="$(npm prefix -g)/bin:$PATH"
|
|
38
|
-
|
|
35
|
+
| Shell | File | Line |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| bash | `~/.bashrc` or `~/.bash_profile` | `export PATH="$(npm prefix -g)/bin:$PATH"` |
|
|
38
|
+
| zsh | `~/.zshrc` | `export PATH="$(npm prefix -g)/bin:$PATH"` |
|
|
39
|
+
| fish | `~/.config/fish/config.fish` | `fish_add_path (npm prefix -g)/bin` |
|
|
40
|
+
| dash / ksh | `~/.profile` | `export PATH="$(npm prefix -g)/bin:$PATH"` |
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
```zsh
|
|
42
|
-
export PATH="$(npm prefix -g)/bin:$PATH"
|
|
43
|
-
```
|
|
42
|
+
Reload your shell (`source ~/.zshrc`, `source ~/.bashrc`, or open a new terminal), then run `cast`.
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
```fish
|
|
47
|
-
fish_add_path (npm prefix -g)/bin
|
|
48
|
-
```
|
|
44
|
+
---
|
|
49
45
|
|
|
50
|
-
|
|
51
|
-
```sh
|
|
52
|
-
export PATH="$(npm prefix -g)/bin:$PATH"
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
After editing, reload your shell (`source ~/.zshrc`, `source ~/.bashrc`, or open a new terminal), then run `cast`.
|
|
46
|
+
## First Run
|
|
56
47
|
|
|
57
|
-
|
|
48
|
+
On first launch the setup wizard runs automatically. To reconfigure at any time:
|
|
58
49
|
|
|
59
50
|
```bash
|
|
60
|
-
|
|
61
|
-
npm run build
|
|
62
|
-
npm run start
|
|
51
|
+
/config init
|
|
63
52
|
```
|
|
64
53
|
|
|
65
|
-
|
|
54
|
+
Config is stored at `~/.cast/config.yaml`.
|
|
66
55
|
|
|
67
|
-
|
|
68
|
-
npm run start:dev
|
|
69
|
-
```
|
|
56
|
+
---
|
|
70
57
|
|
|
71
|
-
##
|
|
58
|
+
## Providers
|
|
72
59
|
|
|
73
|
-
|
|
60
|
+
Cast supports multiple LLM providers. Configure via `/config init` or set environment variables:
|
|
74
61
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
62
|
+
| Variable | Provider |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `ANTHROPIC_API_KEY` | Anthropic / Claude |
|
|
65
|
+
| `OPENAI_API_KEY` | OpenAI / GPT |
|
|
66
|
+
| `GOOGLE_API_KEY` | Google Gemini |
|
|
78
67
|
|
|
79
|
-
|
|
80
|
-
- `~/.cast/config.yaml`
|
|
68
|
+
You can also assign different models per purpose — `default`, `subAgent`, `coder`, `architect`, `reviewer`, `planner`, `cheap` — to tune cost and performance by task type.
|
|
81
69
|
|
|
82
|
-
|
|
70
|
+
---
|
|
83
71
|
|
|
84
|
-
|
|
72
|
+
## Commands
|
|
85
73
|
|
|
86
|
-
|
|
87
|
-
/mcp add
|
|
88
|
-
```
|
|
74
|
+
### Core
|
|
89
75
|
|
|
90
|
-
|
|
76
|
+
| Command | Description |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `/help` | Show command guide |
|
|
79
|
+
| `/init` | Analyze project and generate context |
|
|
80
|
+
| `/project-deep` | Deep context + specialist brief |
|
|
81
|
+
| `/context` | Show session, tools, agents, skills, MCP status |
|
|
82
|
+
| `/clear` | Clear conversation history |
|
|
83
|
+
| `/compact` | Compact context window |
|
|
84
|
+
| `/exit` | Exit CLI |
|
|
91
85
|
|
|
92
|
-
|
|
93
|
-
/init
|
|
94
|
-
```
|
|
86
|
+
### Config
|
|
95
87
|
|
|
96
|
-
|
|
88
|
+
| Command | Description |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `/config` | Config menu |
|
|
91
|
+
| `/config show` | Show current config |
|
|
92
|
+
| `/config path` | Print config file path |
|
|
93
|
+
| `/config add-provider` | Add a new LLM provider |
|
|
94
|
+
| `/config set-model` | Set model by purpose |
|
|
97
95
|
|
|
98
|
-
|
|
96
|
+
### MCP
|
|
99
97
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
98
|
+
| Command | Description |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `/mcp` | MCP hub menu |
|
|
101
|
+
| `/mcp list` | List configured servers |
|
|
102
|
+
| `/mcp tools` | List available tools |
|
|
103
|
+
| `/mcp add` | Add server (from templates or custom) |
|
|
104
|
+
| `/mcp remove` | Remove a server |
|
|
105
|
+
| `/mcp what` | Explain what MCP is |
|
|
105
106
|
|
|
106
|
-
|
|
107
|
+
### Git
|
|
107
108
|
|
|
108
|
-
|
|
109
|
+
| Command | Description |
|
|
110
|
+
|---|---|
|
|
111
|
+
| `/status`, `/diff`, `/log` | Git status, diff, log |
|
|
112
|
+
| `/commit` | AI-generated commit message |
|
|
113
|
+
| `/up`, `/split-up` | Push / push with split commits |
|
|
114
|
+
| `/pr` | Generate pull request description |
|
|
115
|
+
| `/review` | Code review |
|
|
116
|
+
| `/fix`, `/ident`, `/release` | Fix issues, identify patterns, generate release notes |
|
|
109
117
|
|
|
110
|
-
|
|
111
|
-
Use Figma to extract main screens and create a full frontend scaffold:
|
|
112
|
-
- routes
|
|
113
|
-
- page skeletons
|
|
114
|
-
- reusable UI components (button, table, modal, form)
|
|
115
|
-
- design tokens and global styling
|
|
116
|
-
- responsive behavior
|
|
117
|
-
```
|
|
118
|
+
### Agents & Skills
|
|
118
119
|
|
|
119
|
-
|
|
120
|
+
| Command | Description |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `/agents` | List specialist agents |
|
|
123
|
+
| `/agents create` | Create a custom agent |
|
|
124
|
+
| `/skills` | List skills |
|
|
125
|
+
| `/skills create` | Create a custom skill |
|
|
120
126
|
|
|
121
|
-
|
|
122
|
-
- `/help` show command guide
|
|
123
|
-
- `/init` analyze project and generate context
|
|
124
|
-
- `/project-deep` generate deep context + specialist brief
|
|
125
|
-
- `/context` show session, tools, agents, skills, MCP status
|
|
126
|
-
- `/clear` clear conversation history
|
|
127
|
-
- `/compact` compact context window
|
|
128
|
-
- `/exit` exit CLI
|
|
127
|
+
---
|
|
129
128
|
|
|
130
|
-
|
|
131
|
-
- `/config` config menu
|
|
132
|
-
- `/config show` show current config
|
|
133
|
-
- `/config path` print config path
|
|
134
|
-
- `/config add-provider` add provider
|
|
135
|
-
- `/config set-model` set model by purpose
|
|
129
|
+
## Mentions
|
|
136
130
|
|
|
137
|
-
|
|
138
|
-
- `/mcp` MCP hub menu
|
|
139
|
-
- `/mcp list` list servers
|
|
140
|
-
- `/mcp tools` list tools
|
|
141
|
-
- `/mcp add` add server from templates or custom
|
|
142
|
-
- `/mcp remove` remove server
|
|
143
|
-
- `/mcp what` explain MCP
|
|
131
|
+
Inject context directly into any prompt:
|
|
144
132
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
133
|
+
```
|
|
134
|
+
@src/components/Button.tsx — single file
|
|
135
|
+
@src/components/ — entire directory
|
|
136
|
+
@git:status — current git status
|
|
137
|
+
@git:diff — current diff
|
|
138
|
+
```
|
|
149
139
|
|
|
150
|
-
|
|
151
|
-
- `/agents`, `/agents create`
|
|
152
|
-
- `/skills`, `/skills create`
|
|
140
|
+
---
|
|
153
141
|
|
|
154
|
-
##
|
|
142
|
+
## Plan Mode
|
|
155
143
|
|
|
156
|
-
|
|
144
|
+
For complex requests Cast enters plan mode:
|
|
145
|
+
- asks clarifying questions
|
|
146
|
+
- generates a structured plan
|
|
147
|
+
- lets you refine, approve, or cancel
|
|
148
|
+
- executes with the approved plan as context
|
|
157
149
|
|
|
158
|
-
|
|
159
|
-
- `@path/to/dir/`
|
|
160
|
-
- `@git:status`
|
|
161
|
-
- `@git:diff`
|
|
150
|
+
---
|
|
162
151
|
|
|
163
|
-
##
|
|
152
|
+
## MCP — Model Context Protocol
|
|
164
153
|
|
|
165
|
-
|
|
166
|
-
- asks clarifying questions,
|
|
167
|
-
- generates a structured plan,
|
|
168
|
-
- allows refine/approve/cancel,
|
|
169
|
-
- executes with the approved plan as context.
|
|
154
|
+
Cast ships with templates for 30+ MCP servers across categories: Dev Tools, Design, Data, Search, Cloud, Productivity, Payments, and Browser.
|
|
170
155
|
|
|
171
|
-
|
|
156
|
+
### Figma Desktop (recommended)
|
|
172
157
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
- `reviewer`
|
|
179
|
-
- `planner`
|
|
180
|
-
- `cheap`
|
|
158
|
+
1. Install [Figma Desktop](https://www.figma.com/downloads/)
|
|
159
|
+
2. Open a Design file and enter Dev Mode (`<>` button, top right)
|
|
160
|
+
3. In the Inspect panel, enable **"Enable desktop MCP server"**
|
|
161
|
+
4. In Cast: `/mcp add` → Design → Figma Desktop
|
|
162
|
+
5. Restart Cast, then `/mcp` → Conectar servidores
|
|
181
163
|
|
|
182
|
-
|
|
164
|
+
For HTTP servers that require OAuth, Cast handles the full OAuth 2.0 + PKCE flow automatically and stores tokens in `~/.cast/mcp-auth/`.
|
|
183
165
|
|
|
184
|
-
|
|
166
|
+
---
|
|
185
167
|
|
|
186
|
-
|
|
187
|
-
- `src/modules/core` deep agent orchestration and system prompt
|
|
188
|
-
- `src/modules/agents` specialist sub-agents
|
|
189
|
-
- `src/modules/skills` skill definitions and knowledge
|
|
190
|
-
- `src/modules/mcp` MCP integration
|
|
191
|
-
- `src/modules/project` project analysis/context generation
|
|
192
|
-
- `src/modules/tasks` task and plan tools
|
|
168
|
+
## Technical Stack
|
|
193
169
|
|
|
194
|
-
|
|
170
|
+
- **Runtime**: Node.js >= 20, TypeScript
|
|
171
|
+
- **Framework**: NestJS (dependency injection, modular architecture)
|
|
172
|
+
- **LLM**: LangChain + LangGraph (multi-agent orchestration, streaming)
|
|
173
|
+
- **MCP**: `@modelcontextprotocol/sdk` (stdio and HTTP/SSE transports, OAuth 2.0 + PKCE)
|
|
174
|
+
- **Providers**: Anthropic, OpenAI, Google Gemini, Ollama
|
|
175
|
+
- **Config**: YAML stored at `~/.cast/config.yaml`
|
|
176
|
+
- **Auth tokens**: stored at `~/.cast/mcp-auth/<server>/`
|
|
195
177
|
|
|
196
|
-
|
|
197
|
-
- For MCP servers requiring OAuth (like Figma), authenticate after adding and restarting Cast.
|
|
198
|
-
- If no agents/skills appear, run `/context` and verify project-level `.cast/agents` and `.cast/skills`.
|
|
178
|
+
### Project layout
|
|
199
179
|
|
|
200
|
-
|
|
180
|
+
```
|
|
181
|
+
src/modules/
|
|
182
|
+
repl/ interactive CLI, commands, SmartInput
|
|
183
|
+
core/ deep agent orchestration, system prompt, plan mode
|
|
184
|
+
agents/ specialist sub-agents (coder, architect, reviewer…)
|
|
185
|
+
skills/ skill definitions and knowledge loading
|
|
186
|
+
mcp/ MCP client, OAuth provider, server registry, templates
|
|
187
|
+
project/ project analysis and context generation
|
|
188
|
+
tasks/ task management and plan execution tools
|
|
189
|
+
git/ commit, PR, review, and release generators
|
|
190
|
+
config/ provider and model configuration
|
|
191
|
+
memory/ session memory tools
|
|
192
|
+
mentions/ @-mention context injection
|
|
193
|
+
```
|
|
201
194
|
|
|
202
|
-
|
|
195
|
+
---
|
|
203
196
|
|
|
204
|
-
|
|
205
|
-
|---|---|
|
|
206
|
-
| `ANTHROPIC_API_KEY` | Anthropic / Claude |
|
|
207
|
-
| `OPENAI_API_KEY` | OpenAI |
|
|
208
|
-
| `GOOGLE_API_KEY` | Google Gemini |
|
|
197
|
+
## Local Development
|
|
209
198
|
|
|
210
|
-
|
|
199
|
+
```bash
|
|
200
|
+
npm install
|
|
201
|
+
npm run build
|
|
202
|
+
npm run start
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Watch mode:
|
|
211
206
|
|
|
212
207
|
```bash
|
|
213
|
-
|
|
214
|
-
cast
|
|
208
|
+
npm run start:dev
|
|
215
209
|
```
|
|
216
210
|
|
|
217
|
-
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Notes
|
|
214
|
+
|
|
215
|
+
- Keep `.cast/context.md` updated — the richer the context, the better the answers.
|
|
216
|
+
- Project-level agents and skills live in `.cast/agents/` and `.cast/skills/` at the repo root.
|
|
217
|
+
- Run `/context` to verify what Cast can currently see.
|
|
@@ -34,7 +34,7 @@ let LlmService = class LlmService {
|
|
|
34
34
|
return new _openai.ChatOpenAI({
|
|
35
35
|
modelName: this.configService.getModel(),
|
|
36
36
|
temperature: this.configService.getTemperature(),
|
|
37
|
-
|
|
37
|
+
apiKey: this.configService.getApiKey(),
|
|
38
38
|
streaming
|
|
39
39
|
});
|
|
40
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/common/services/llm.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { ChatOpenAI } from '@langchain/openai';\nimport { ChatOllama } from '@langchain/ollama';\nimport { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport { ConfigService } from './config.service';\n\n@Injectable()\nexport class LlmService {\n constructor(private readonly configService: ConfigService) {}\n\n createModel(streaming = false): BaseChatModel {\n const provider = this.configService.getProvider();\n\n if (provider === 'ollama') {\n return new ChatOllama({\n model: this.configService.getModel(),\n temperature: this.configService.getTemperature(),\n baseUrl: this.configService.getOllamaBaseUrl(),\n });\n }\n\n return new ChatOpenAI({\n modelName: this.configService.getModel(),\n temperature: this.configService.getTemperature(),\n
|
|
1
|
+
{"version":3,"sources":["../../../src/common/services/llm.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { ChatOpenAI } from '@langchain/openai';\nimport { ChatOllama } from '@langchain/ollama';\nimport { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport { ConfigService } from './config.service';\n\n@Injectable()\nexport class LlmService {\n constructor(private readonly configService: ConfigService) {}\n\n createModel(streaming = false): BaseChatModel {\n const provider = this.configService.getProvider();\n\n if (provider === 'ollama') {\n return new ChatOllama({\n model: this.configService.getModel(),\n temperature: this.configService.getTemperature(),\n baseUrl: this.configService.getOllamaBaseUrl(),\n });\n }\n\n return new ChatOpenAI({\n modelName: this.configService.getModel(),\n temperature: this.configService.getTemperature(),\n apiKey: this.configService.getApiKey(),\n streaming,\n });\n }\n\n createStreamingModel(): BaseChatModel {\n return this.createModel(true);\n }\n}\n"],"names":["LlmService","createModel","streaming","provider","configService","getProvider","ChatOllama","model","getModel","temperature","getTemperature","baseUrl","getOllamaBaseUrl","ChatOpenAI","modelName","apiKey","getApiKey","createStreamingModel"],"mappings":";;;;+BAOaA;;;eAAAA;;;wBAPc;wBACA;wBACA;+BAEG;;;;;;;;;;AAGvB,IAAA,AAAMA,aAAN,MAAMA;IAGXC,YAAYC,YAAY,KAAK,EAAiB;QAC5C,MAAMC,WAAW,IAAI,CAACC,aAAa,CAACC,WAAW;QAE/C,IAAIF,aAAa,UAAU;YACzB,OAAO,IAAIG,kBAAU,CAAC;gBACpBC,OAAO,IAAI,CAACH,aAAa,CAACI,QAAQ;gBAClCC,aAAa,IAAI,CAACL,aAAa,CAACM,cAAc;gBAC9CC,SAAS,IAAI,CAACP,aAAa,CAACQ,gBAAgB;YAC9C;QACF;QAEA,OAAO,IAAIC,kBAAU,CAAC;YACpBC,WAAW,IAAI,CAACV,aAAa,CAACI,QAAQ;YACtCC,aAAa,IAAI,CAACL,aAAa,CAACM,cAAc;YAC9CK,QAAQ,IAAI,CAACX,aAAa,CAACY,SAAS;YACpCd;QACF;IACF;IAEAe,uBAAsC;QACpC,OAAO,IAAI,CAAChB,WAAW,CAAC;IAC1B;IAvBA,YAAY,AAAiBG,aAA4B,CAAE;aAA9BA,gBAAAA;IAA+B;AAwB9D"}
|
|
@@ -49,7 +49,7 @@ let MultiLlmService = class MultiLlmService {
|
|
|
49
49
|
...temperature !== undefined ? {
|
|
50
50
|
temperature
|
|
51
51
|
} : {},
|
|
52
|
-
|
|
52
|
+
apiKey: config.apiKey,
|
|
53
53
|
configuration: {
|
|
54
54
|
baseURL: config.baseUrl
|
|
55
55
|
},
|
|
@@ -81,7 +81,7 @@ let MultiLlmService = class MultiLlmService {
|
|
|
81
81
|
...temperature !== undefined ? {
|
|
82
82
|
temperature
|
|
83
83
|
} : {},
|
|
84
|
-
|
|
84
|
+
apiKey: config.apiKey,
|
|
85
85
|
configuration: {
|
|
86
86
|
baseURL: config.baseUrl || 'https://api.moonshot.cn/v1'
|
|
87
87
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/common/services/multi-llm.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { ChatOpenAI } from '@langchain/openai';\nimport { ChatOllama } from '@langchain/ollama';\nimport { ChatAnthropic } from '@langchain/anthropic';\nimport { ChatGoogleGenerativeAI } from '@langchain/google-genai';\nimport { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport { ConfigManagerService } from '../../modules/config/services/config-manager.service';\nimport {\n ModelPurpose,\n ProviderType,\n} from '../../modules/config/types/config.types';\n\n@Injectable()\nexport class MultiLlmService {\n constructor(private readonly configManager: ConfigManagerService) {}\n\n createModel(purpose: ModelPurpose = 'default', streaming = false): BaseChatModel {\n const modelConfig = this.configManager.getModelConfig(purpose);\n\n if (!modelConfig) {\n throw new Error(\n `No model configured for purpose \"${purpose}\". ` +\n 'Run \"cast config init\" to configure.'\n );\n }\n\n const { provider, model, temperature } = modelConfig;\n const providerConfig = this.configManager.getProviderConfig(provider);\n\n if (!providerConfig) {\n throw new Error(\n `Provider \"${provider}\" is not configured. ` +\n 'Run \"cast config init\" to configure.'\n );\n }\n\n return this.createModelForProvider(\n provider,\n providerConfig,\n model,\n temperature,\n streaming\n );\n }\n\n createStreamingModel(purpose: ModelPurpose = 'default'): BaseChatModel {\n return this.createModel(purpose, true);\n }\n\n private createModelForProvider(\n provider: ProviderType,\n config: { apiKey?: string; baseUrl?: string },\n model: string,\n temperature: number | undefined,\n streaming: boolean\n ): BaseChatModel {\n switch (provider) {\n case 'openai':\n case 'deepseek':\n case 'openrouter':\n return new ChatOpenAI({\n modelName: model,\n ...(temperature !== undefined ? { temperature } : {}),\n
|
|
1
|
+
{"version":3,"sources":["../../../src/common/services/multi-llm.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { ChatOpenAI } from '@langchain/openai';\nimport { ChatOllama } from '@langchain/ollama';\nimport { ChatAnthropic } from '@langchain/anthropic';\nimport { ChatGoogleGenerativeAI } from '@langchain/google-genai';\nimport { BaseChatModel } from '@langchain/core/language_models/chat_models';\nimport { ConfigManagerService } from '../../modules/config/services/config-manager.service';\nimport {\n ModelPurpose,\n ProviderType,\n} from '../../modules/config/types/config.types';\n\n@Injectable()\nexport class MultiLlmService {\n constructor(private readonly configManager: ConfigManagerService) {}\n\n createModel(purpose: ModelPurpose = 'default', streaming = false): BaseChatModel {\n const modelConfig = this.configManager.getModelConfig(purpose);\n\n if (!modelConfig) {\n throw new Error(\n `No model configured for purpose \"${purpose}\". ` +\n 'Run \"cast config init\" to configure.'\n );\n }\n\n const { provider, model, temperature } = modelConfig;\n const providerConfig = this.configManager.getProviderConfig(provider);\n\n if (!providerConfig) {\n throw new Error(\n `Provider \"${provider}\" is not configured. ` +\n 'Run \"cast config init\" to configure.'\n );\n }\n\n return this.createModelForProvider(\n provider,\n providerConfig,\n model,\n temperature,\n streaming\n );\n }\n\n createStreamingModel(purpose: ModelPurpose = 'default'): BaseChatModel {\n return this.createModel(purpose, true);\n }\n\n private createModelForProvider(\n provider: ProviderType,\n config: { apiKey?: string; baseUrl?: string },\n model: string,\n temperature: number | undefined,\n streaming: boolean\n ): BaseChatModel {\n switch (provider) {\n case 'openai':\n case 'deepseek':\n case 'openrouter':\n return new ChatOpenAI({\n modelName: model,\n ...(temperature !== undefined ? { temperature } : {}),\n apiKey: config.apiKey,\n configuration: {\n baseURL: config.baseUrl,\n },\n streaming,\n streamUsage: streaming,\n });\n\n case 'anthropic':\n return new ChatAnthropic({\n modelName: model,\n ...(temperature !== undefined ? { temperature } : {}),\n anthropicApiKey: config.apiKey,\n anthropicApiUrl: config.baseUrl,\n streaming,\n });\n\n case 'gemini':\n return new ChatGoogleGenerativeAI({\n modelName: model,\n ...(temperature !== undefined ? { temperature } : {}),\n apiKey: config.apiKey,\n streaming,\n });\n\n case 'kimi':\n return new ChatOpenAI({\n modelName: model,\n ...(temperature !== undefined ? { temperature } : {}),\n apiKey: config.apiKey,\n configuration: {\n baseURL: config.baseUrl || 'https://api.moonshot.cn/v1',\n },\n streaming,\n streamUsage: streaming,\n });\n\n case 'ollama':\n return new ChatOllama({\n model,\n ...(temperature !== undefined ? { temperature } : {}),\n baseUrl: config.baseUrl || 'http://localhost:11434',\n });\n\n default:\n throw new Error(`Unsupported provider: ${provider}`);\n }\n }\n}\n"],"names":["MultiLlmService","createModel","purpose","streaming","modelConfig","configManager","getModelConfig","Error","provider","model","temperature","providerConfig","getProviderConfig","createModelForProvider","createStreamingModel","config","ChatOpenAI","modelName","undefined","apiKey","configuration","baseURL","baseUrl","streamUsage","ChatAnthropic","anthropicApiKey","anthropicApiUrl","ChatGoogleGenerativeAI","ChatOllama"],"mappings":";;;;+BAaaA;;;eAAAA;;;wBAbc;wBACA;wBACA;2BACG;6BACS;sCAEF;;;;;;;;;;AAO9B,IAAA,AAAMA,kBAAN,MAAMA;IAGXC,YAAYC,UAAwB,SAAS,EAAEC,YAAY,KAAK,EAAiB;QAC/E,MAAMC,cAAc,IAAI,CAACC,aAAa,CAACC,cAAc,CAACJ;QAEtD,IAAI,CAACE,aAAa;YAChB,MAAM,IAAIG,MACR,CAAC,iCAAiC,EAAEL,QAAQ,GAAG,CAAC,GAC9C;QAEN;QAEA,MAAM,EAAEM,QAAQ,EAAEC,KAAK,EAAEC,WAAW,EAAE,GAAGN;QACzC,MAAMO,iBAAiB,IAAI,CAACN,aAAa,CAACO,iBAAiB,CAACJ;QAE5D,IAAI,CAACG,gBAAgB;YACnB,MAAM,IAAIJ,MACR,CAAC,UAAU,EAAEC,SAAS,qBAAqB,CAAC,GAC1C;QAEN;QAEA,OAAO,IAAI,CAACK,sBAAsB,CAChCL,UACAG,gBACAF,OACAC,aACAP;IAEJ;IAEAW,qBAAqBZ,UAAwB,SAAS,EAAiB;QACrE,OAAO,IAAI,CAACD,WAAW,CAACC,SAAS;IACnC;IAEQW,uBACNL,QAAsB,EACtBO,MAA6C,EAC7CN,KAAa,EACbC,WAA+B,EAC/BP,SAAkB,EACH;QACf,OAAQK;YACN,KAAK;YACL,KAAK;YACL,KAAK;gBACH,OAAO,IAAIQ,kBAAU,CAAC;oBACpBC,WAAWR;oBACX,GAAIC,gBAAgBQ,YAAY;wBAAER;oBAAY,IAAI,CAAC,CAAC;oBACpDS,QAAQJ,OAAOI,MAAM;oBACrBC,eAAe;wBACbC,SAASN,OAAOO,OAAO;oBACzB;oBACAnB;oBACAoB,aAAapB;gBACf;YAEF,KAAK;gBACH,OAAO,IAAIqB,wBAAa,CAAC;oBACvBP,WAAWR;oBACX,GAAIC,gBAAgBQ,YAAY;wBAAER;oBAAY,IAAI,CAAC,CAAC;oBACpDe,iBAAiBV,OAAOI,MAAM;oBAC9BO,iBAAiBX,OAAOO,OAAO;oBAC/BnB;gBACF;YAEF,KAAK;gBACH,OAAO,IAAIwB,mCAAsB,CAAC;oBAChCV,WAAWR;oBACX,GAAIC,gBAAgBQ,YAAY;wBAAER;oBAAY,IAAI,CAAC,CAAC;oBACpDS,QAAQJ,OAAOI,MAAM;oBACrBhB;gBACF;YAEF,KAAK;gBACH,OAAO,IAAIa,kBAAU,CAAC;oBACpBC,WAAWR;oBACX,GAAIC,gBAAgBQ,YAAY;wBAAER;oBAAY,IAAI,CAAC,CAAC;oBACpDS,QAAQJ,OAAOI,MAAM;oBACrBC,eAAe;wBACbC,SAASN,OAAOO,OAAO,IAAI;oBAC7B;oBACAnB;oBACAoB,aAAapB;gBACf;YAEF,KAAK;gBACH,OAAO,IAAIyB,kBAAU,CAAC;oBACpBnB;oBACA,GAAIC,gBAAgBQ,YAAY;wBAAER;oBAAY,IAAI,CAAC,CAAC;oBACpDY,SAASP,OAAOO,OAAO,IAAI;gBAC7B;YAEF;gBACE,MAAM,IAAIf,MAAM,CAAC,sBAAsB,EAAEC,UAAU;QACvD;IACF;IAhGA,YAAY,AAAiBH,aAAmC,CAAE;aAArCA,gBAAAA;IAAsC;AAiGrE"}
|
|
@@ -235,14 +235,20 @@ let ConfigCommandsService = class ConfigCommandsService {
|
|
|
235
235
|
};
|
|
236
236
|
} else {
|
|
237
237
|
console.log(_chalk.default.gray(`→ Obtenha sua API key em: ${meta.websiteUrl}`));
|
|
238
|
-
const
|
|
238
|
+
const apiKeyRaw = await (0, _promptswithesc.inputWithEsc)({
|
|
239
239
|
message: `API Key para ${meta.name}:`,
|
|
240
|
-
validate: (v)=>
|
|
240
|
+
validate: (v)=>{
|
|
241
|
+
const clean = v.trim();
|
|
242
|
+
if (clean.length <= 5) return 'API key muito curta';
|
|
243
|
+
if (/[\s%]/.test(clean)) return 'API key contém caracteres inválidos (espaços ou %)';
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
241
246
|
});
|
|
242
|
-
if (
|
|
247
|
+
if (apiKeyRaw === null) {
|
|
243
248
|
console.log(_chalk.default.yellow('\n❌ Cancelado.\n'));
|
|
244
249
|
return;
|
|
245
250
|
}
|
|
251
|
+
const apiKey = apiKeyRaw.trim();
|
|
246
252
|
const useCustom = await (0, _promptswithesc.confirmWithEsc)({
|
|
247
253
|
message: 'Usar URL customizada?',
|
|
248
254
|
default: false
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/modules/config/services/config-commands.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport chalk from 'chalk';\nimport { ConfigManagerService } from './config-manager.service';\nimport { InitConfigService } from './init-config.service';\nimport {\n ProviderType,\n PROVIDER_METADATA,\n MODEL_PURPOSES,\n ModelPurpose,\n} from '../types/config.types';\nimport {\n selectWithEsc,\n inputWithEsc,\n confirmWithEsc,\n CancelledPromptError,\n withEsc,\n} from '../../repl/utils/prompts-with-esc';\n\ninterface SmartInput {\n askChoice: (question: string, choices: { key: string; label: string; description: string }[]) => Promise<string>;\n question: (prompt: string) => Promise<string>;\n pause: () => void;\n resume: () => void;\n}\n\n@Injectable()\nexport class ConfigCommandsService {\n constructor(\n private readonly configManager: ConfigManagerService,\n private readonly initService: InitConfigService\n ) {}\n\n async handleConfigCommand(args: string[], smartInput?: SmartInput): Promise<void> {\n const subcommand = args[0];\n const useInquirerFlow = ['init', 'setup', 'add-provider', 'set-model', 'remove-provider'].includes(subcommand || '');\n\n if (useInquirerFlow) {\n smartInput?.pause();\n }\n\n try {\n switch (subcommand) {\n case 'init':\n case 'setup':\n await this.withEscHandler(() => this.initService.runInitialSetup());\n break;\n\n case 'show':\n await this.showConfig();\n break;\n\n case 'add-provider':\n await this.withEscHandler(() => this.addProviderInteractive());\n break;\n\n case 'set-model':\n await this.withEscHandler(() => this.setModelInteractive());\n break;\n\n case 'remove-provider':\n await this.withEscHandler(() => this.removeProviderInteractive());\n break;\n\n case 'path':\n console.log(this.configManager.getConfigPath());\n break;\n\n default:\n if (smartInput) {\n await this.showConfigMenu(smartInput);\n } else {\n await this.showConfig();\n }\n }\n } finally {\n if (useInquirerFlow) {\n smartInput?.resume();\n }\n }\n }\n\n private async withEscHandler<T>(fn: () => Promise<T>): Promise<void> {\n const result = await withEsc(fn);\n if (result === null) {\n console.log(chalk.yellow('\\n\\n❌ Cancelado. Voltando ao menu...\\n'));\n }\n }\n\n private async showConfigMenu(smartInput: SmartInput): Promise<void> {\n const w = (s: string) => process.stdout.write(s);\n const Colors = {\n cyan: '\\x1b[38;5;51m',\n green: '\\x1b[38;5;82m',\n yellow: '\\x1b[38;5;220m',\n gray: '\\x1b[38;5;245m',\n bold: '\\x1b[1m',\n reset: '\\x1b[0m',\n };\n\n await this.configManager.loadConfig();\n\n while (true) {\n w(`\\n${Colors.cyan}${Colors.bold}⚙️ Configuração Cast Code${Colors.reset}\\n`);\n w(`${Colors.gray}${'─'.repeat(30)}${Colors.reset}\\n\\n`);\n\n const action = await withEsc(() => smartInput.askChoice('O que deseja fazer?', [\n { key: '1', label: 'Ver configuração atual', description: 'Mostrar provedores e modelos' },\n { key: '2', label: 'Configuração inicial completa', description: 'Wizard de setup' },\n { key: '3', label: 'Adicionar provedor', description: 'Novo serviço de IA' },\n { key: '4', label: 'Remover provedor', description: 'Remover serviço' },\n { key: '5', label: 'Configurar modelo', description: 'Definir modelo para finalidade' },\n { key: '6', label: 'Ver caminho do arquivo', description: 'Local do config.yaml' },\n { key: '7', label: 'Sair', description: 'Voltar ao chat' },\n ]));\n\n if (action === null) {\n console.log(chalk.yellow('\\nSaindo do menu de configuração...\\n'));\n return;\n }\n\n switch (action) {\n case '1':\n await this.showConfig();\n break;\n case '2':\n await this.withEscHandler(() => this.initService.runInitialSetup());\n return;\n case '3':\n await this.withEscHandler(() => this.addProviderInteractive());\n break;\n case '4':\n await this.withEscHandler(() => this.removeProviderInteractive());\n break;\n case '5':\n await this.withEscHandler(() => this.setModelInteractive());\n break;\n case '6':\n console.log(`\\n📁 ${this.configManager.getConfigPath()}\\n`);\n break;\n case '7':\n return;\n }\n }\n }\n\n private async showConfig(): Promise<void> {\n await this.configManager.loadConfig();\n const config = this.configManager.getConfig();\n\n const w = (s: string) => process.stdout.write(s);\n const Colors = {\n cyan: '\\x1b[38;5;51m',\n green: '\\x1b[38;5;82m',\n red: '\\x1b[38;5;196m',\n yellow: '\\x1b[38;5;220m',\n gray: '\\x1b[38;5;245m',\n bold: '\\x1b[1m',\n reset: '\\x1b[0m',\n };\n\n w(`\\n${Colors.cyan}${Colors.bold}⚙️ Configuração Atual${Colors.reset}\\n`);\n w(`${Colors.gray}${'─'.repeat(40)}${Colors.reset}\\n\\n`);\n\n w(`${Colors.yellow}📦 Provedores configurados:${Colors.reset}\\n`);\n const providers = this.configManager.getConfiguredProviders();\n if (providers.length === 0) {\n w(`${Colors.gray} Nenhum provedor configurado${Colors.reset}\\n`);\n w(`${Colors.gray} Use \"cast config init\" ou /config add-provider${Colors.reset}\\n`);\n } else {\n for (const provider of providers) {\n const meta = PROVIDER_METADATA[provider];\n const isConfigured = this.configManager.isProviderConfigured(provider);\n const status = isConfigured \n ? `${Colors.green}✓` \n : `${Colors.red}✗`;\n w(` ${status} ${meta.name} ${Colors.gray}(${provider})${Colors.reset}\\n`);\n }\n }\n\n w(`\\n${Colors.yellow}🤖 Modelos configurados:${Colors.reset}\\n`);\n for (const purpose of MODEL_PURPOSES) {\n const modelConfig = config.models[purpose.value];\n if (modelConfig) {\n const providerName = PROVIDER_METADATA[modelConfig.provider].name;\n w(` ${Colors.cyan}${purpose.label.padEnd(12)}${Colors.reset} → ${modelConfig.model}\\n`);\n w(` ${Colors.gray}${' '.repeat(12)} ${providerName}${Colors.reset}\\n`);\n }\n }\n\n w(`\\n${Colors.gray}📁 Arquivo: ${this.configManager.getConfigPath()}${Colors.reset}\\n\\n`);\n }\n\n private async addProviderInteractive(): Promise<void> {\n await this.configManager.loadConfig();\n\n const availableProviders = Object.keys(PROVIDER_METADATA).filter(\n (p) => !this.configManager.isProviderConfigured(p as ProviderType)\n ) as ProviderType[];\n\n if (availableProviders.length === 0) {\n console.log(chalk.yellow('\\n⚠️ Todos os provedores já estão configurados!\\n'));\n return;\n }\n\n console.log(chalk.cyan('\\n📦 Adicionar Provedor'));\n console.log(chalk.gray('(pressione ESC para cancelar)\\n'));\n\n const provider = await selectWithEsc<ProviderType>({\n message: 'Qual provedor deseja adicionar?',\n choices: availableProviders.map((p) => ({\n name: `${PROVIDER_METADATA[p].name} - ${PROVIDER_METADATA[p].description}`,\n value: p,\n })),\n });\n\n if (provider === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n const meta = PROVIDER_METADATA[provider];\n\n let config: { apiKey?: string; baseUrl?: string } = {};\n\n if (provider === 'ollama') {\n const baseUrl = await inputWithEsc({\n message: 'URL do servidor Ollama:',\n default: meta.defaultBaseUrl,\n });\n if (baseUrl === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n config = { baseUrl };\n } else {\n console.log(chalk.gray(`→ Obtenha sua API key em: ${meta.websiteUrl}`));\n \n const apiKey = await inputWithEsc({\n message: `API Key para ${meta.name}:`,\n validate: (v) => v.length > 5 || 'API key muito curta',\n });\n\n if (apiKey === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n const useCustom = await confirmWithEsc({\n message: 'Usar URL customizada?',\n default: false,\n });\n\n if (useCustom === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n let baseUrl: string | undefined;\n if (useCustom) {\n baseUrl = await inputWithEsc({\n message: 'URL da API:',\n default: meta.defaultBaseUrl,\n });\n if (baseUrl === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n }\n\n config = { apiKey, baseUrl };\n }\n\n await this.configManager.addProvider(provider, config);\n console.log(chalk.green(`\\n✓ Provedor ${meta.name} adicionado com sucesso!\\n`));\n }\n\n private async removeProviderInteractive(): Promise<void> {\n await this.configManager.loadConfig();\n\n const configuredProviders = this.configManager.getConfiguredProviders();\n if (configuredProviders.length === 0) {\n console.log(chalk.yellow('\\n⚠️ Nenhum provedor configurado para remover.\\n'));\n return;\n }\n\n console.log(chalk.gray('(pressione ESC para cancelar)\\n'));\n\n const provider = await selectWithEsc<ProviderType>({\n message: 'Qual provedor deseja remover?',\n choices: configuredProviders.map((p) => ({\n name: PROVIDER_METADATA[p].name,\n value: p,\n })),\n });\n\n if (provider === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n const confirmRemove = await confirmWithEsc({\n message: `Tem certeza que deseja remover ${PROVIDER_METADATA[provider].name}?`,\n default: false,\n });\n\n if (confirmRemove === null || !confirmRemove) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n const config = this.configManager.getConfig();\n delete config.providers[provider];\n await this.configManager.saveConfig(config);\n console.log(chalk.green(`\\n✓ Provedor removido.\\n`));\n }\n\n private async setModelInteractive(): Promise<void> {\n await this.configManager.loadConfig();\n\n const availableProviders = this.configManager.getConfiguredProviders();\n if (availableProviders.length === 0) {\n console.log(\n chalk.red('\\n❌ Nenhum provedor configurado. Configure um provedor primeiro.\\n')\n );\n return;\n }\n\n console.log(chalk.cyan('\\n🤖 Configurar Modelo'));\n console.log(chalk.gray('(pressione ESC para cancelar)\\n'));\n\n const purpose = await selectWithEsc<ModelPurpose>({\n message: 'Para qual finalidade?',\n choices: MODEL_PURPOSES.map((p) => ({\n name: `${p.label} - ${p.description}`,\n value: p.value,\n })),\n });\n\n if (purpose === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n const provider = await selectWithEsc<ProviderType>({\n message: 'Qual provedor?',\n choices: availableProviders.map((p) => ({\n name: PROVIDER_METADATA[p].name,\n value: p,\n })),\n });\n\n if (provider === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n const meta = PROVIDER_METADATA[provider];\n\n const usePopular = await confirmWithEsc({\n message: `Usar um dos modelos populares do ${meta.name}?`,\n default: true,\n });\n\n if (usePopular === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n let model: string | null;\n\n if (usePopular) {\n model = await selectWithEsc<string>({\n message: 'Escolha o modelo:',\n choices: [\n ...meta.popularModels.map((m) => ({ name: m, value: m })),\n { name: '➕ Outro modelo...', value: '__custom__' },\n ],\n });\n\n if (model === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n if (model === '__custom__') {\n model = await inputWithEsc({\n message: 'Nome do modelo:',\n default: meta.popularModels[0],\n });\n if (model === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n }\n } else {\n model = await inputWithEsc({\n message: 'Nome do modelo:',\n default: meta.popularModels[0],\n });\n if (model === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n }\n\n await this.configManager.setModel(purpose, {\n provider,\n model,\n });\n\n const purposeLabel = MODEL_PURPOSES.find((p) => p.value === purpose)?.label;\n console.log(\n chalk.green(`\\n✓ Modelo para \"${purposeLabel}\" configurado: ${model}\\n`)\n );\n }\n}\n"],"names":["ConfigCommandsService","handleConfigCommand","args","smartInput","subcommand","useInquirerFlow","includes","pause","withEscHandler","initService","runInitialSetup","showConfig","addProviderInteractive","setModelInteractive","removeProviderInteractive","console","log","configManager","getConfigPath","showConfigMenu","resume","fn","result","withEsc","chalk","yellow","w","s","process","stdout","write","Colors","cyan","green","gray","bold","reset","loadConfig","repeat","action","askChoice","key","label","description","config","getConfig","red","providers","getConfiguredProviders","length","provider","meta","PROVIDER_METADATA","isConfigured","isProviderConfigured","status","name","purpose","MODEL_PURPOSES","modelConfig","models","value","providerName","padEnd","model","availableProviders","Object","keys","filter","p","selectWithEsc","message","choices","map","baseUrl","inputWithEsc","default","defaultBaseUrl","websiteUrl","apiKey","validate","v","useCustom","confirmWithEsc","addProvider","configuredProviders","confirmRemove","saveConfig","usePopular","popularModels","m","setModel","purposeLabel","find"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/modules/config/services/config-commands.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport chalk from 'chalk';\nimport { ConfigManagerService } from './config-manager.service';\nimport { InitConfigService } from './init-config.service';\nimport {\n ProviderType,\n PROVIDER_METADATA,\n MODEL_PURPOSES,\n ModelPurpose,\n} from '../types/config.types';\nimport {\n selectWithEsc,\n inputWithEsc,\n confirmWithEsc,\n CancelledPromptError,\n withEsc,\n} from '../../repl/utils/prompts-with-esc';\n\ninterface SmartInput {\n askChoice: (question: string, choices: { key: string; label: string; description: string }[]) => Promise<string>;\n question: (prompt: string) => Promise<string>;\n pause: () => void;\n resume: () => void;\n}\n\n@Injectable()\nexport class ConfigCommandsService {\n constructor(\n private readonly configManager: ConfigManagerService,\n private readonly initService: InitConfigService\n ) {}\n\n async handleConfigCommand(args: string[], smartInput?: SmartInput): Promise<void> {\n const subcommand = args[0];\n const useInquirerFlow = ['init', 'setup', 'add-provider', 'set-model', 'remove-provider'].includes(subcommand || '');\n\n if (useInquirerFlow) {\n smartInput?.pause();\n }\n\n try {\n switch (subcommand) {\n case 'init':\n case 'setup':\n await this.withEscHandler(() => this.initService.runInitialSetup());\n break;\n\n case 'show':\n await this.showConfig();\n break;\n\n case 'add-provider':\n await this.withEscHandler(() => this.addProviderInteractive());\n break;\n\n case 'set-model':\n await this.withEscHandler(() => this.setModelInteractive());\n break;\n\n case 'remove-provider':\n await this.withEscHandler(() => this.removeProviderInteractive());\n break;\n\n case 'path':\n console.log(this.configManager.getConfigPath());\n break;\n\n default:\n if (smartInput) {\n await this.showConfigMenu(smartInput);\n } else {\n await this.showConfig();\n }\n }\n } finally {\n if (useInquirerFlow) {\n smartInput?.resume();\n }\n }\n }\n\n private async withEscHandler<T>(fn: () => Promise<T>): Promise<void> {\n const result = await withEsc(fn);\n if (result === null) {\n console.log(chalk.yellow('\\n\\n❌ Cancelado. Voltando ao menu...\\n'));\n }\n }\n\n private async showConfigMenu(smartInput: SmartInput): Promise<void> {\n const w = (s: string) => process.stdout.write(s);\n const Colors = {\n cyan: '\\x1b[38;5;51m',\n green: '\\x1b[38;5;82m',\n yellow: '\\x1b[38;5;220m',\n gray: '\\x1b[38;5;245m',\n bold: '\\x1b[1m',\n reset: '\\x1b[0m',\n };\n\n await this.configManager.loadConfig();\n\n while (true) {\n w(`\\n${Colors.cyan}${Colors.bold}⚙️ Configuração Cast Code${Colors.reset}\\n`);\n w(`${Colors.gray}${'─'.repeat(30)}${Colors.reset}\\n\\n`);\n\n const action = await withEsc(() => smartInput.askChoice('O que deseja fazer?', [\n { key: '1', label: 'Ver configuração atual', description: 'Mostrar provedores e modelos' },\n { key: '2', label: 'Configuração inicial completa', description: 'Wizard de setup' },\n { key: '3', label: 'Adicionar provedor', description: 'Novo serviço de IA' },\n { key: '4', label: 'Remover provedor', description: 'Remover serviço' },\n { key: '5', label: 'Configurar modelo', description: 'Definir modelo para finalidade' },\n { key: '6', label: 'Ver caminho do arquivo', description: 'Local do config.yaml' },\n { key: '7', label: 'Sair', description: 'Voltar ao chat' },\n ]));\n\n if (action === null) {\n console.log(chalk.yellow('\\nSaindo do menu de configuração...\\n'));\n return;\n }\n\n switch (action) {\n case '1':\n await this.showConfig();\n break;\n case '2':\n await this.withEscHandler(() => this.initService.runInitialSetup());\n return;\n case '3':\n await this.withEscHandler(() => this.addProviderInteractive());\n break;\n case '4':\n await this.withEscHandler(() => this.removeProviderInteractive());\n break;\n case '5':\n await this.withEscHandler(() => this.setModelInteractive());\n break;\n case '6':\n console.log(`\\n📁 ${this.configManager.getConfigPath()}\\n`);\n break;\n case '7':\n return;\n }\n }\n }\n\n private async showConfig(): Promise<void> {\n await this.configManager.loadConfig();\n const config = this.configManager.getConfig();\n\n const w = (s: string) => process.stdout.write(s);\n const Colors = {\n cyan: '\\x1b[38;5;51m',\n green: '\\x1b[38;5;82m',\n red: '\\x1b[38;5;196m',\n yellow: '\\x1b[38;5;220m',\n gray: '\\x1b[38;5;245m',\n bold: '\\x1b[1m',\n reset: '\\x1b[0m',\n };\n\n w(`\\n${Colors.cyan}${Colors.bold}⚙️ Configuração Atual${Colors.reset}\\n`);\n w(`${Colors.gray}${'─'.repeat(40)}${Colors.reset}\\n\\n`);\n\n w(`${Colors.yellow}📦 Provedores configurados:${Colors.reset}\\n`);\n const providers = this.configManager.getConfiguredProviders();\n if (providers.length === 0) {\n w(`${Colors.gray} Nenhum provedor configurado${Colors.reset}\\n`);\n w(`${Colors.gray} Use \"cast config init\" ou /config add-provider${Colors.reset}\\n`);\n } else {\n for (const provider of providers) {\n const meta = PROVIDER_METADATA[provider];\n const isConfigured = this.configManager.isProviderConfigured(provider);\n const status = isConfigured \n ? `${Colors.green}✓` \n : `${Colors.red}✗`;\n w(` ${status} ${meta.name} ${Colors.gray}(${provider})${Colors.reset}\\n`);\n }\n }\n\n w(`\\n${Colors.yellow}🤖 Modelos configurados:${Colors.reset}\\n`);\n for (const purpose of MODEL_PURPOSES) {\n const modelConfig = config.models[purpose.value];\n if (modelConfig) {\n const providerName = PROVIDER_METADATA[modelConfig.provider].name;\n w(` ${Colors.cyan}${purpose.label.padEnd(12)}${Colors.reset} → ${modelConfig.model}\\n`);\n w(` ${Colors.gray}${' '.repeat(12)} ${providerName}${Colors.reset}\\n`);\n }\n }\n\n w(`\\n${Colors.gray}📁 Arquivo: ${this.configManager.getConfigPath()}${Colors.reset}\\n\\n`);\n }\n\n private async addProviderInteractive(): Promise<void> {\n await this.configManager.loadConfig();\n\n const availableProviders = Object.keys(PROVIDER_METADATA).filter(\n (p) => !this.configManager.isProviderConfigured(p as ProviderType)\n ) as ProviderType[];\n\n if (availableProviders.length === 0) {\n console.log(chalk.yellow('\\n⚠️ Todos os provedores já estão configurados!\\n'));\n return;\n }\n\n console.log(chalk.cyan('\\n📦 Adicionar Provedor'));\n console.log(chalk.gray('(pressione ESC para cancelar)\\n'));\n\n const provider = await selectWithEsc<ProviderType>({\n message: 'Qual provedor deseja adicionar?',\n choices: availableProviders.map((p) => ({\n name: `${PROVIDER_METADATA[p].name} - ${PROVIDER_METADATA[p].description}`,\n value: p,\n })),\n });\n\n if (provider === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n const meta = PROVIDER_METADATA[provider];\n\n let config: { apiKey?: string; baseUrl?: string } = {};\n\n if (provider === 'ollama') {\n const baseUrl = await inputWithEsc({\n message: 'URL do servidor Ollama:',\n default: meta.defaultBaseUrl,\n });\n if (baseUrl === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n config = { baseUrl };\n } else {\n console.log(chalk.gray(`→ Obtenha sua API key em: ${meta.websiteUrl}`));\n \n const apiKeyRaw = await inputWithEsc({\n message: `API Key para ${meta.name}:`,\n validate: (v) => {\n const clean = v.trim();\n if (clean.length <= 5) return 'API key muito curta';\n if (/[\\s%]/.test(clean)) return 'API key contém caracteres inválidos (espaços ou %)';\n return true;\n },\n });\n\n if (apiKeyRaw === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n const apiKey = apiKeyRaw.trim();\n\n const useCustom = await confirmWithEsc({\n message: 'Usar URL customizada?',\n default: false,\n });\n\n if (useCustom === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n let baseUrl: string | undefined;\n if (useCustom) {\n baseUrl = await inputWithEsc({\n message: 'URL da API:',\n default: meta.defaultBaseUrl,\n });\n if (baseUrl === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n }\n\n config = { apiKey, baseUrl };\n }\n\n await this.configManager.addProvider(provider, config);\n console.log(chalk.green(`\\n✓ Provedor ${meta.name} adicionado com sucesso!\\n`));\n }\n\n private async removeProviderInteractive(): Promise<void> {\n await this.configManager.loadConfig();\n\n const configuredProviders = this.configManager.getConfiguredProviders();\n if (configuredProviders.length === 0) {\n console.log(chalk.yellow('\\n⚠️ Nenhum provedor configurado para remover.\\n'));\n return;\n }\n\n console.log(chalk.gray('(pressione ESC para cancelar)\\n'));\n\n const provider = await selectWithEsc<ProviderType>({\n message: 'Qual provedor deseja remover?',\n choices: configuredProviders.map((p) => ({\n name: PROVIDER_METADATA[p].name,\n value: p,\n })),\n });\n\n if (provider === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n const confirmRemove = await confirmWithEsc({\n message: `Tem certeza que deseja remover ${PROVIDER_METADATA[provider].name}?`,\n default: false,\n });\n\n if (confirmRemove === null || !confirmRemove) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n const config = this.configManager.getConfig();\n delete config.providers[provider];\n await this.configManager.saveConfig(config);\n console.log(chalk.green(`\\n✓ Provedor removido.\\n`));\n }\n\n private async setModelInteractive(): Promise<void> {\n await this.configManager.loadConfig();\n\n const availableProviders = this.configManager.getConfiguredProviders();\n if (availableProviders.length === 0) {\n console.log(\n chalk.red('\\n❌ Nenhum provedor configurado. Configure um provedor primeiro.\\n')\n );\n return;\n }\n\n console.log(chalk.cyan('\\n🤖 Configurar Modelo'));\n console.log(chalk.gray('(pressione ESC para cancelar)\\n'));\n\n const purpose = await selectWithEsc<ModelPurpose>({\n message: 'Para qual finalidade?',\n choices: MODEL_PURPOSES.map((p) => ({\n name: `${p.label} - ${p.description}`,\n value: p.value,\n })),\n });\n\n if (purpose === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n const provider = await selectWithEsc<ProviderType>({\n message: 'Qual provedor?',\n choices: availableProviders.map((p) => ({\n name: PROVIDER_METADATA[p].name,\n value: p,\n })),\n });\n\n if (provider === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n const meta = PROVIDER_METADATA[provider];\n\n const usePopular = await confirmWithEsc({\n message: `Usar um dos modelos populares do ${meta.name}?`,\n default: true,\n });\n\n if (usePopular === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n let model: string | null;\n\n if (usePopular) {\n model = await selectWithEsc<string>({\n message: 'Escolha o modelo:',\n choices: [\n ...meta.popularModels.map((m) => ({ name: m, value: m })),\n { name: '➕ Outro modelo...', value: '__custom__' },\n ],\n });\n\n if (model === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n\n if (model === '__custom__') {\n model = await inputWithEsc({\n message: 'Nome do modelo:',\n default: meta.popularModels[0],\n });\n if (model === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n }\n } else {\n model = await inputWithEsc({\n message: 'Nome do modelo:',\n default: meta.popularModels[0],\n });\n if (model === null) {\n console.log(chalk.yellow('\\n❌ Cancelado.\\n'));\n return;\n }\n }\n\n await this.configManager.setModel(purpose, {\n provider,\n model,\n });\n\n const purposeLabel = MODEL_PURPOSES.find((p) => p.value === purpose)?.label;\n console.log(\n chalk.green(`\\n✓ Modelo para \"${purposeLabel}\" configurado: ${model}\\n`)\n );\n }\n}\n"],"names":["ConfigCommandsService","handleConfigCommand","args","smartInput","subcommand","useInquirerFlow","includes","pause","withEscHandler","initService","runInitialSetup","showConfig","addProviderInteractive","setModelInteractive","removeProviderInteractive","console","log","configManager","getConfigPath","showConfigMenu","resume","fn","result","withEsc","chalk","yellow","w","s","process","stdout","write","Colors","cyan","green","gray","bold","reset","loadConfig","repeat","action","askChoice","key","label","description","config","getConfig","red","providers","getConfiguredProviders","length","provider","meta","PROVIDER_METADATA","isConfigured","isProviderConfigured","status","name","purpose","MODEL_PURPOSES","modelConfig","models","value","providerName","padEnd","model","availableProviders","Object","keys","filter","p","selectWithEsc","message","choices","map","baseUrl","inputWithEsc","default","defaultBaseUrl","websiteUrl","apiKeyRaw","validate","v","clean","trim","test","apiKey","useCustom","confirmWithEsc","addProvider","configuredProviders","confirmRemove","saveConfig","usePopular","popularModels","m","setModel","purposeLabel","find"],"mappings":"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"}
|
|
@@ -111,16 +111,21 @@ let InitConfigService = class InitConfigService {
|
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
113
|
console.log(_chalk.default.gray(` → Obtenha sua API key em: ${meta.websiteUrl}`));
|
|
114
|
-
const
|
|
114
|
+
const apiKeyRaw = await (0, _promptswithesc.inputWithEsc)({
|
|
115
115
|
message: `API Key para ${meta.name}:`,
|
|
116
116
|
validate: (value)=>{
|
|
117
|
-
|
|
117
|
+
const clean = value.trim();
|
|
118
|
+
if (!clean || clean.length < 10) {
|
|
118
119
|
return 'Por favor, insira uma API key válida';
|
|
119
120
|
}
|
|
121
|
+
if (/[\s%]/.test(clean)) {
|
|
122
|
+
return 'API key contém caracteres inválidos (espaços ou %)';
|
|
123
|
+
}
|
|
120
124
|
return true;
|
|
121
125
|
}
|
|
122
126
|
});
|
|
123
|
-
if (
|
|
127
|
+
if (apiKeyRaw === null) return null;
|
|
128
|
+
const apiKey = apiKeyRaw.trim();
|
|
124
129
|
const useCustomUrl = await (0, _promptswithesc.confirmWithEsc)({
|
|
125
130
|
message: 'Usar URL de API customizada (ex: OpenRouter, proxy)?',
|
|
126
131
|
default: false
|