noiton 2.0.0 → 2.0.2
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 +2 -12
- package/package.json +2 -7
- package/src/commands/init.js +82 -30
- package/src/index.js +0 -5
- package/src/lib/agents/hermes.js +20 -1
- package/src/lib/agents/index.js +42 -12
- package/src/lib/agents/opencode.js +19 -1
- package/src/lib/detect.js +47 -107
- package/src/lib/install.js +0 -2
- package/src/octopus.js +163 -181
- package/src/ui.js +34 -0
- package/src/lib/agents/aider.js +0 -141
- package/src/lib/agents/cline.js +0 -128
- package/src/lib/agents/kilo.js +0 -140
- package/src/lib/agents/kimi.js +0 -149
- package/src/lib/agents/openclaw.js +0 -155
package/src/octopus.js
CHANGED
|
@@ -1,257 +1,241 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* NOITON Octopus Mascot - "O Polvo NOITON"
|
|
3
|
-
* A beautiful refined octopus that appears throughout the CLI.
|
|
4
3
|
*
|
|
5
4
|
* Design philosophy:
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
* - Brand gradient: purple → magenta → cyan
|
|
5
|
+
* - Smooth organic curves using ╭╮╰╯ ◠ ◡ ⌒ ~ characters
|
|
6
|
+
* - Round bulbous head with expressive eyes
|
|
7
|
+
* - 8 graceful flowing tentacles (not blocky)
|
|
8
|
+
* - Brand gradient: purple → magenta → pink → cyan
|
|
10
9
|
*/
|
|
11
10
|
|
|
12
11
|
import gradient from "gradient-string";
|
|
13
12
|
|
|
14
|
-
// NOITON brand gradient
|
|
13
|
+
// NOITON brand gradient
|
|
15
14
|
const brandGradient = gradient([
|
|
16
15
|
"#A78BFA", // light purple
|
|
17
16
|
"#C084FC", // purple
|
|
18
17
|
"#E879F9", // magenta
|
|
19
18
|
"#F472B6", // pink
|
|
20
19
|
"#22D3EE", // cyan
|
|
21
|
-
"#2DD4BF", // teal
|
|
22
20
|
]);
|
|
23
21
|
|
|
24
|
-
const successGradient = gradient(["#
|
|
25
|
-
const errorGradient = gradient(["#F87171", "#EF4444"
|
|
26
|
-
const warningGradient = gradient(["#FBBF24", "#F59E0B", "#FB923C"]);
|
|
22
|
+
const successGradient = gradient(["#34D399", "#22D3EE", "#A78BFA"]);
|
|
23
|
+
const errorGradient = gradient(["#F87171", "#EF4444"]);
|
|
27
24
|
|
|
28
25
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
26
|
+
* Main happy octopus - graceful, friendly, ready to help
|
|
27
|
+
* Clean organic curves, expressive eyes, flowing tentacles
|
|
31
28
|
*/
|
|
32
29
|
export function octopusHappy() {
|
|
33
30
|
return brandGradient.multiline(`
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
█ ▀▀▀▀▀▀ █ █ █ ▀▀▀▀▀▀ █
|
|
52
|
-
█ █ █ █ █ █
|
|
53
|
-
█ █ █ █
|
|
54
|
-
▀ █ ♥ █ ▀
|
|
55
|
-
█ █
|
|
31
|
+
╭━━━━━━━━━╮
|
|
32
|
+
╱ ╲
|
|
33
|
+
│ ◉ ◉ │
|
|
34
|
+
│ ◡ │
|
|
35
|
+
╲___________╱
|
|
36
|
+
│ ╲___╱ │
|
|
37
|
+
╭┤ ├╮
|
|
38
|
+
╭┘╰┐ ╭━┘╰┐
|
|
39
|
+
╭┘ ╰╮ ╭┘ ╰┐
|
|
40
|
+
╭┘ ◠ ╰━╯ ◠ ╰┐
|
|
41
|
+
╭┘ ╰┐
|
|
42
|
+
╭┘ ♥ ✦ ♥ ╰┐
|
|
43
|
+
│ │
|
|
44
|
+
╰╮ ╭╯
|
|
45
|
+
╰╮ ✦ ♥ ╭╯
|
|
46
|
+
╰╮ ╭╯
|
|
47
|
+
╰─✦───♥─✦─╯
|
|
56
48
|
`);
|
|
57
49
|
}
|
|
58
50
|
|
|
59
51
|
/**
|
|
60
|
-
* Compact octopus for
|
|
52
|
+
* Compact octopus for tight spaces
|
|
61
53
|
*/
|
|
62
54
|
export function octopusMini() {
|
|
63
55
|
return brandGradient.multiline(`
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
▀▄ ███ ▄▀
|
|
73
|
-
▀▀▀▀▀▀▀
|
|
56
|
+
╭━━━━━╮
|
|
57
|
+
╱ ◉ ◉ ╲
|
|
58
|
+
│ ◡ │
|
|
59
|
+
╲_______╱
|
|
60
|
+
╭╯ ╰╮
|
|
61
|
+
╭┘ ◠ ◠ ╰┐
|
|
62
|
+
╰╮ ♥ ╭╯
|
|
63
|
+
╰───╯
|
|
74
64
|
`);
|
|
75
65
|
}
|
|
76
66
|
|
|
77
67
|
/**
|
|
78
|
-
* Curious octopus
|
|
68
|
+
* Curious octopus - looking around with question marks
|
|
79
69
|
*/
|
|
80
70
|
export function octopusCurious() {
|
|
81
71
|
return brandGradient.multiline(`
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
72
|
+
╭━━━━━━━━━╮
|
|
73
|
+
╱ ╲
|
|
74
|
+
│ ? ? │
|
|
75
|
+
│ ◡ │
|
|
76
|
+
╲___________╱
|
|
77
|
+
│ ╲___╱ │
|
|
78
|
+
╭┤ ├╮
|
|
79
|
+
╭┘╰┐ ╭━┘╰┐
|
|
80
|
+
╭┘ ╰╮ ╭┘ ╰┐
|
|
81
|
+
╭┘ ╰━╯ ╰┐
|
|
82
|
+
╭┘ ╰┐
|
|
83
|
+
╭┘ ? ? ? ╰┐
|
|
84
|
+
│ │
|
|
85
|
+
╰╮ ╭╯
|
|
86
|
+
╰╮ ╭╯
|
|
87
|
+
╰╮ ? ? ╭╯
|
|
88
|
+
╰───────────╯
|
|
99
89
|
`);
|
|
100
90
|
}
|
|
101
91
|
|
|
102
92
|
/**
|
|
103
|
-
* Working octopus
|
|
93
|
+
* Working octopus - focused, with swirly eyes
|
|
104
94
|
*/
|
|
105
95
|
export function octopusWorking() {
|
|
106
96
|
return brandGradient.multiline(`
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
█ ██▌ ▐██ █
|
|
125
|
-
▐▄██ ██▄▌
|
|
126
|
-
▀▀ ▀▀
|
|
97
|
+
╭━━━━━━━━━╮
|
|
98
|
+
╱ ╲
|
|
99
|
+
│ @ @ │
|
|
100
|
+
│ ▬ │
|
|
101
|
+
╲___________╱
|
|
102
|
+
│ ╲___╱ │
|
|
103
|
+
╭┤ ├╮
|
|
104
|
+
╭┘╰┐ ╭━┘╰┐
|
|
105
|
+
╭┘ ╰╮ ╭┘ ╰┐
|
|
106
|
+
╭┘ ◠ ╰━╯ ◠ ╰┐
|
|
107
|
+
╭┘ ⚙ ╰┐
|
|
108
|
+
╭┘ ⚙ ⚙ ⚙ ╰┐
|
|
109
|
+
│ ⚙ ⚙ │
|
|
110
|
+
╰╮ ⚙ ⚙ ╭╯
|
|
111
|
+
╰╮ ╭╯
|
|
112
|
+
╰╮──⚙───⚙──⚙─╭╯
|
|
113
|
+
╰───────────╯
|
|
127
114
|
`);
|
|
128
115
|
}
|
|
129
116
|
|
|
130
117
|
/**
|
|
131
|
-
*
|
|
118
|
+
* Dancing/celebrating octopus - happy eyes, hearts and stars
|
|
132
119
|
*/
|
|
133
120
|
export function octopusDancing() {
|
|
134
121
|
return successGradient.multiline(`
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
▀ ▀
|
|
154
|
-
♥ ♪ ♥ ♪ ♥
|
|
122
|
+
╭━━━━━━━━━╮
|
|
123
|
+
╱ ╲
|
|
124
|
+
│ ◠ ◠ │
|
|
125
|
+
│ ◡ │
|
|
126
|
+
╲___________╱
|
|
127
|
+
│ ╲___╱ │
|
|
128
|
+
╭┤ ├╮
|
|
129
|
+
✦ ╭┘╰┐ ╭━┘╰┐ ✦
|
|
130
|
+
╭━━━╭┘ ╰╮ ╭┘ ╰┐━━━╮
|
|
131
|
+
╭━━━╭┘ ◠ ╰━╯ ◠ ╰┐━━━╮
|
|
132
|
+
╭━━━╭┘ ╰┐━━━╮
|
|
133
|
+
╭━━━╭┘ ♥ ★ ♥ ╰┐━━━╮
|
|
134
|
+
│ │
|
|
135
|
+
╰╮ ★ ♥ ★ ♥ ╭╯
|
|
136
|
+
╰╮ ╭╯
|
|
137
|
+
★ ╰╮ ♥ ★ ♥ ╭╯ ★
|
|
138
|
+
╰─★──♥───★──♥──★╯
|
|
139
|
+
♪ ♥ ♪
|
|
155
140
|
`);
|
|
156
141
|
}
|
|
157
142
|
|
|
158
143
|
/**
|
|
159
|
-
* Sad octopus
|
|
144
|
+
* Sad octopus - drooping tentacles
|
|
160
145
|
*/
|
|
161
146
|
export function octopusSad() {
|
|
162
147
|
return errorGradient.multiline(`
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
▀▀▀
|
|
148
|
+
╭━━━━━━━━━╮
|
|
149
|
+
╱ ╲
|
|
150
|
+
│ . . │
|
|
151
|
+
│ ╲ │
|
|
152
|
+
╲___________╱
|
|
153
|
+
│ ╲___╱ │
|
|
154
|
+
╭┤ ├╮
|
|
155
|
+
╭┘╰┐ ╭━┘╰┐
|
|
156
|
+
╭━┘ ╰╮ ╭┘ ╰━╗
|
|
157
|
+
╭┘ ╰━╯ ╰┐
|
|
158
|
+
╭┘ ╰┐
|
|
159
|
+
│ │
|
|
160
|
+
╰╮ ╭╯
|
|
161
|
+
╰╮ ╭╯
|
|
162
|
+
╰╮ ╭╯
|
|
163
|
+
╰╮ ╭╯
|
|
164
|
+
╰──────╯
|
|
181
165
|
`);
|
|
182
166
|
}
|
|
183
167
|
|
|
184
168
|
/**
|
|
185
|
-
* Sleeping octopus
|
|
169
|
+
* Sleeping octopus - zzz floating
|
|
186
170
|
*/
|
|
187
171
|
export function octopusSleeping() {
|
|
188
172
|
return brandGradient.multiline(`
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
▀▀▀▀ zZ
|
|
206
|
-
zZZ
|
|
173
|
+
╭━━━━━━━━━╮
|
|
174
|
+
╱ ╲
|
|
175
|
+
│ - - │
|
|
176
|
+
│ ▬ │
|
|
177
|
+
╲___________╱ z
|
|
178
|
+
│ ╲___╱ │ zZ
|
|
179
|
+
╭┤ ├╮ zZZ
|
|
180
|
+
╭┘╰┐ ╭━┘╰┐
|
|
181
|
+
╭┘ ╰╮ ╭┘ ╰┐
|
|
182
|
+
╭┘ ╰━╯ ╰┐
|
|
183
|
+
╭┘ z ╰┐
|
|
184
|
+
╭┘ zZ ╰┐
|
|
185
|
+
│ zZZ │
|
|
186
|
+
╰╮ ╭╯
|
|
187
|
+
╰╮ ╭╯
|
|
188
|
+
╰──────────────╯
|
|
207
189
|
`);
|
|
208
190
|
}
|
|
209
191
|
|
|
210
192
|
/**
|
|
211
|
-
*
|
|
193
|
+
* Coding octopus - typing on keyboard
|
|
212
194
|
*/
|
|
213
195
|
export function octopusCoding() {
|
|
214
196
|
return brandGradient.multiline(`
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
█ < / > < / > █
|
|
235
|
-
▀ ▟█████████████▙ ▀
|
|
197
|
+
╭━━━━━━━━━╮
|
|
198
|
+
╱ ╲
|
|
199
|
+
│ ◉ ◉ │
|
|
200
|
+
│ ◡ │
|
|
201
|
+
╲___________╱
|
|
202
|
+
│ ╲___╱ │
|
|
203
|
+
╭┤ ├╮
|
|
204
|
+
╭───╭┘╰┐ ╭━┘╰┐───╮
|
|
205
|
+
╭┘ ╭┘ ╰╮ ╭┘ ╰┐ ╰┐
|
|
206
|
+
╭┘ ╭┘ ◠ ╰━╯ ◠ ╰┐ ╰┐
|
|
207
|
+
╭┘ ╭┘ ╰┐ ╰┐
|
|
208
|
+
╭┘ ╭┘ ╰┐ ╰┐
|
|
209
|
+
│ │ [ / / / / ] │ │
|
|
210
|
+
╰╮ ╰╮ ╭╯ ╭╯
|
|
211
|
+
╰╮ ╰╮ ▓▓▓▓▓▓▓ ╭╯ ╭╯
|
|
212
|
+
╰╮ ╰╮ ╭╯ ╭╯
|
|
213
|
+
╰╮╰──────────╯ ╭╯
|
|
214
|
+
╰╮ ▓▓ ╭╯
|
|
215
|
+
╰──────────╯
|
|
236
216
|
`);
|
|
237
217
|
}
|
|
238
218
|
|
|
239
219
|
/**
|
|
240
|
-
* NOITON logo with octopus
|
|
220
|
+
* NOITON wordmark logo with small octopus on top
|
|
241
221
|
*/
|
|
242
222
|
export function octopusLogo() {
|
|
243
223
|
return brandGradient.multiline(`
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
224
|
+
╭━━━━━╮
|
|
225
|
+
╱ ◉ ◉ ╲
|
|
226
|
+
│ ◡ │
|
|
227
|
+
╲_______╱
|
|
228
|
+
╭╯ ╰╮
|
|
229
|
+
╭┘ ◠ ◠ ╰┐
|
|
230
|
+
╰╮ ♥ ╭╯
|
|
231
|
+
╰───╯
|
|
232
|
+
|
|
233
|
+
███╗ ██╗ ██████╗ ██╗████████╗ ██████╗ ███╗ ██╗
|
|
234
|
+
████╗ ██║██╔═══██╗██║╚══██╔══╝██╔═══██╗████╗ ██║
|
|
235
|
+
██╔██╗ ██║██║ ██║██║ ██║ ██║ ██║██╔██╗ ██║
|
|
236
|
+
██║╚██╗██║██║ ██║██║ ██║ ██║ ██║██║╚██╗██║
|
|
237
|
+
██║ ╚████║╚██████╔╝██║ ██║ ╚██████╔╝██║ ╚████║
|
|
238
|
+
╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
|
|
255
239
|
`);
|
|
256
240
|
}
|
|
257
241
|
|
|
@@ -259,14 +243,12 @@ export function octopusLogo() {
|
|
|
259
243
|
* Get a random octopus pose
|
|
260
244
|
*/
|
|
261
245
|
export function randomOctopus() {
|
|
262
|
-
const poses = [octopusHappy, octopusDancing, octopusCoding
|
|
263
|
-
|
|
264
|
-
return pick();
|
|
246
|
+
const poses = [octopusHappy, octopusDancing, octopusCoding];
|
|
247
|
+
return poses[Math.floor(Math.random() * poses.length)]();
|
|
265
248
|
}
|
|
266
249
|
|
|
267
250
|
export {
|
|
268
251
|
brandGradient,
|
|
269
252
|
successGradient,
|
|
270
253
|
errorGradient,
|
|
271
|
-
warningGradient,
|
|
272
254
|
};
|
package/src/ui.js
CHANGED
|
@@ -181,6 +181,40 @@ export function clear() {
|
|
|
181
181
|
process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
// ============= SLEEP =============
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Pause execution for ms milliseconds.
|
|
188
|
+
* @param {number} ms
|
|
189
|
+
* @returns {Promise<void>}
|
|
190
|
+
*/
|
|
191
|
+
export function sleep(ms) {
|
|
192
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Type out text character by character (typewriter effect).
|
|
197
|
+
* @param {string} text
|
|
198
|
+
* @param {number} [delay=8] - ms per char
|
|
199
|
+
*/
|
|
200
|
+
export async function typeOut(text, delay = 8) {
|
|
201
|
+
for (const ch of text) {
|
|
202
|
+
process.stdout.write(ch);
|
|
203
|
+
await sleep(delay);
|
|
204
|
+
}
|
|
205
|
+
process.stdout.write("\n");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Print a line with a small delay (feels like "thinking").
|
|
210
|
+
* @param {string} text
|
|
211
|
+
* @param {number} [delay=150]
|
|
212
|
+
*/
|
|
213
|
+
export async function line(text, delay = 150) {
|
|
214
|
+
await sleep(delay);
|
|
215
|
+
console.log(text);
|
|
216
|
+
}
|
|
217
|
+
|
|
184
218
|
// ============= HEADER (small) =============
|
|
185
219
|
|
|
186
220
|
/**
|
package/src/lib/agents/aider.js
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Aider Agent Adapter
|
|
3
|
-
*
|
|
4
|
-
* Config: ~/.aider.conf.yml (YAML) + env vars
|
|
5
|
-
* Format:
|
|
6
|
-
* openai-api-base: <BASE_URL>
|
|
7
|
-
* model: <model-id>
|
|
8
|
-
* .env: OPENAI_API_KEY=<key>
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
12
|
-
import { join, dirname } from "node:path";
|
|
13
|
-
import { homedir } from "node:os";
|
|
14
|
-
import YAML from "yaml";
|
|
15
|
-
import { BASE_URL } from "../../constants.js";
|
|
16
|
-
|
|
17
|
-
const HOME = homedir();
|
|
18
|
-
const CONFIG_PATH = join(HOME, ".aider.conf.yml");
|
|
19
|
-
const ENV_PATH = join(HOME, ".env");
|
|
20
|
-
|
|
21
|
-
function readYaml() {
|
|
22
|
-
if (!existsSync(CONFIG_PATH)) return { config: {}, path: CONFIG_PATH };
|
|
23
|
-
try {
|
|
24
|
-
const raw = readFileSync(CONFIG_PATH, "utf8");
|
|
25
|
-
return { config: YAML.parse(raw) || {}, path: CONFIG_PATH };
|
|
26
|
-
} catch {
|
|
27
|
-
return { config: {}, path: CONFIG_PATH };
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function writeYaml(config) {
|
|
32
|
-
if (!existsSync(dirname(CONFIG_PATH))) {
|
|
33
|
-
mkdirSync(dirname(CONFIG_PATH), { recursive: true });
|
|
34
|
-
}
|
|
35
|
-
writeFileSync(CONFIG_PATH, YAML.stringify(config, { indent: 2 }), "utf8");
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function readEnvFile() {
|
|
39
|
-
if (!existsSync(ENV_PATH)) return {};
|
|
40
|
-
const raw = readFileSync(ENV_PATH, "utf8");
|
|
41
|
-
const env = {};
|
|
42
|
-
for (const line of raw.split("\n")) {
|
|
43
|
-
const m = line.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/);
|
|
44
|
-
if (m) env[m[1]] = m[2];
|
|
45
|
-
}
|
|
46
|
-
return env;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function writeEnvFile(env) {
|
|
50
|
-
const lines = Object.entries(env).map(([k, v]) => `${k}=${v}`);
|
|
51
|
-
writeFileSync(ENV_PATH, lines.join("\n") + "\n", "utf8");
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// ============= ADAPTER INTERFACE =============
|
|
55
|
-
|
|
56
|
-
export const aiderAgent = {
|
|
57
|
-
id: "aider",
|
|
58
|
-
name: "Aider",
|
|
59
|
-
supportsMultipleModels: false,
|
|
60
|
-
|
|
61
|
-
detect() {
|
|
62
|
-
return existsSync(CONFIG_PATH);
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
isConfigured() {
|
|
66
|
-
const { config } = readYaml();
|
|
67
|
-
return Boolean(config?.["openai-api-base"] === BASE_URL);
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
getStatus() {
|
|
71
|
-
const { config, path } = readYaml();
|
|
72
|
-
const env = readEnvFile();
|
|
73
|
-
const apiKey = env.OPENAI_API_KEY;
|
|
74
|
-
const configured = config?.["openai-api-base"] === BASE_URL;
|
|
75
|
-
const models = config?.model ? [config.model] : [];
|
|
76
|
-
return {
|
|
77
|
-
configured,
|
|
78
|
-
path,
|
|
79
|
-
models,
|
|
80
|
-
apiKey: apiKey ? `${apiKey.slice(0, 6)}...${apiKey.slice(-4)}` : null,
|
|
81
|
-
envPath: ENV_PATH,
|
|
82
|
-
};
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
configure({ apiKey, models, primaryModel }) {
|
|
86
|
-
const { config } = readYaml();
|
|
87
|
-
config["openai-api-base"] = `${BASE_URL}/v1`;
|
|
88
|
-
config.model = primaryModel || models[0]?.id || "gpt-4";
|
|
89
|
-
config["weak-model"] = primaryModel || models[0]?.id || "gpt-4";
|
|
90
|
-
writeYaml(config);
|
|
91
|
-
|
|
92
|
-
// Set API key in .env
|
|
93
|
-
const env = readEnvFile();
|
|
94
|
-
env.OPENAI_API_KEY = apiKey;
|
|
95
|
-
writeEnvFile(env);
|
|
96
|
-
|
|
97
|
-
return { path: CONFIG_PATH, envPath: ENV_PATH, modelsCount: 1 };
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
changeKey(apiKey) {
|
|
101
|
-
if (!this.isConfigured()) {
|
|
102
|
-
throw new Error("NOITON não está configurado no Aider");
|
|
103
|
-
}
|
|
104
|
-
const env = readEnvFile();
|
|
105
|
-
env.OPENAI_API_KEY = apiKey;
|
|
106
|
-
writeEnvFile(env);
|
|
107
|
-
return { path: ENV_PATH };
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
refresh(models) {
|
|
111
|
-
const { config } = readYaml();
|
|
112
|
-
if (!config?.["openai-api-base"]) {
|
|
113
|
-
throw new Error("NOITON não está configurado no Aider");
|
|
114
|
-
}
|
|
115
|
-
if (models.length > 0) {
|
|
116
|
-
config.model = models[0].id;
|
|
117
|
-
config["weak-model"] = models[0].id;
|
|
118
|
-
}
|
|
119
|
-
writeYaml(config);
|
|
120
|
-
return { path: CONFIG_PATH, modelsCount: 1 };
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
remove() {
|
|
124
|
-
const { config } = readYaml();
|
|
125
|
-
let removed = false;
|
|
126
|
-
if (config?.["openai-api-base"] === BASE_URL) {
|
|
127
|
-
delete config["openai-api-base"];
|
|
128
|
-
delete config.model;
|
|
129
|
-
delete config["weak-model"];
|
|
130
|
-
removed = true;
|
|
131
|
-
writeYaml(config);
|
|
132
|
-
}
|
|
133
|
-
const env = readEnvFile();
|
|
134
|
-
if (env.OPENAI_API_KEY) {
|
|
135
|
-
delete env.OPENAI_API_KEY;
|
|
136
|
-
writeEnvFile(env);
|
|
137
|
-
removed = true;
|
|
138
|
-
}
|
|
139
|
-
return { path: CONFIG_PATH, envPath: ENV_PATH, removed };
|
|
140
|
-
},
|
|
141
|
-
};
|