agen-vektor 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +212 -0
- package/dist/agent/agent.js +90 -0
- package/dist/agent/context.js +106 -0
- package/dist/agent/loop.js +152 -0
- package/dist/agent/memory.js +87 -0
- package/dist/agent/planner.js +38 -0
- package/dist/agent/prompts.js +41 -0
- package/dist/agent/session.js +125 -0
- package/dist/cli/index.js +304 -0
- package/dist/cli/keyboard.js +283 -0
- package/dist/config/config.js +92 -0
- package/dist/config/credentials.js +127 -0
- package/dist/config/models.js +47 -0
- package/dist/providers/anthropic.js +276 -0
- package/dist/providers/custom.js +24 -0
- package/dist/providers/factory.js +58 -0
- package/dist/providers/gemini.js +223 -0
- package/dist/providers/ollama.js +195 -0
- package/dist/providers/openai-compat.js +296 -0
- package/dist/providers/openai.js +17 -0
- package/dist/providers/openrouter.js +23 -0
- package/dist/providers/provider.js +39 -0
- package/dist/security/command-policy.js +99 -0
- package/dist/security/permissions.js +66 -0
- package/dist/tools/filesystem.js +297 -0
- package/dist/tools/git.js +66 -0
- package/dist/tools/registry.js +39 -0
- package/dist/tools/search.js +184 -0
- package/dist/tools/shell.js +108 -0
- package/dist/tools/web.js +76 -0
- package/dist/tui/app.js +913 -0
- package/dist/tui/chat.js +76 -0
- package/dist/tui/components.js +85 -0
- package/dist/tui/diff.js +105 -0
- package/dist/tui/input.js +121 -0
- package/dist/tui/statusbar.js +32 -0
- package/dist/utils/logger.js +96 -0
- package/dist/utils/paths.js +90 -0
- package/dist/utils/terminal.js +191 -0
- package/package.json +56 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.parseKey = parseKey;
|
|
37
|
+
exports.enableRawMode = enableRawMode;
|
|
38
|
+
exports.keyStream = keyStream;
|
|
39
|
+
exports.setupReadline = setupReadline;
|
|
40
|
+
/**
|
|
41
|
+
* Keyboard — raw-mode input parsing into semantic key events.
|
|
42
|
+
* Supports ASCII, control keys, arrows, page up/down, home/end,
|
|
43
|
+
* and mouse (SGR + X10) scroll events when the terminal supports it.
|
|
44
|
+
*/
|
|
45
|
+
const readline = __importStar(require("node:readline"));
|
|
46
|
+
const SEQ_MAP = {
|
|
47
|
+
'\x1b[A': 'up',
|
|
48
|
+
'\x1b[B': 'down',
|
|
49
|
+
'\x1b[C': 'right',
|
|
50
|
+
'\x1b[D': 'left',
|
|
51
|
+
'\x1b[5~': 'pageup',
|
|
52
|
+
'\x1b[6~': 'pagedown',
|
|
53
|
+
'\x1b[3~': 'delete',
|
|
54
|
+
'\x1b[H': 'home',
|
|
55
|
+
'\x1b[F': 'end',
|
|
56
|
+
'\x1b[1~': 'home',
|
|
57
|
+
'\x1b[4~': 'end',
|
|
58
|
+
'\x1b[7~': 'home',
|
|
59
|
+
'\x1b[8~': 'end',
|
|
60
|
+
'\x1b[Z': 'shift_tab',
|
|
61
|
+
'\x1bOA': 'up',
|
|
62
|
+
'\x1bOB': 'down',
|
|
63
|
+
'\x1bOC': 'right',
|
|
64
|
+
'\x1bOD': 'left',
|
|
65
|
+
};
|
|
66
|
+
function parseKey(data) {
|
|
67
|
+
const events = [];
|
|
68
|
+
let i = 0;
|
|
69
|
+
const s = data.toString('utf8');
|
|
70
|
+
while (i < s.length) {
|
|
71
|
+
const ch = s[i];
|
|
72
|
+
const code = ch.charCodeAt(0);
|
|
73
|
+
// Multi-byte UTF-8 (already decoded in `s`): a BMP char is 1 code unit,
|
|
74
|
+
// an astral char (emoji etc.) is a surrogate pair of 2 code units.
|
|
75
|
+
if (code >= 0x80) {
|
|
76
|
+
const codeUnitLen = code >= 0xd800 && code <= 0xdbff ? 2 : 1;
|
|
77
|
+
const full = s.slice(i, i + codeUnitLen);
|
|
78
|
+
if (full) {
|
|
79
|
+
events.push({ name: 'char', char: full });
|
|
80
|
+
i += codeUnitLen;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Mouse SGR: ESC [ < b ; x ; y M or m
|
|
85
|
+
if (ch === '\x1b' && s.startsWith('\x1b[<', i)) {
|
|
86
|
+
const end = s.indexOf('M', i + 3);
|
|
87
|
+
const end2 = s.indexOf('m', i + 3);
|
|
88
|
+
const e = end === -1 ? end2 : end;
|
|
89
|
+
if (e !== -1) {
|
|
90
|
+
const parts = s.slice(i + 3, e).split(';').map(Number);
|
|
91
|
+
if (parts.length >= 3) {
|
|
92
|
+
const [b, x, y] = parts;
|
|
93
|
+
const kind = b !== undefined && (b & 64) !== 0 ? 'scroll_up' : b !== undefined && (b & 65) === 65 ? 'scroll_down' : 'click';
|
|
94
|
+
events.push({ name: 'mouse', kind, x, y });
|
|
95
|
+
}
|
|
96
|
+
i = e + 1;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// CSI sequence
|
|
101
|
+
if (ch === '\x1b' && i + 1 < s.length && s[i + 1] === '[') {
|
|
102
|
+
// Find the terminating char
|
|
103
|
+
let j = i + 2;
|
|
104
|
+
while (j < s.length && !/[A-Za-z~]/.test(s[j]))
|
|
105
|
+
j++;
|
|
106
|
+
if (j < s.length) {
|
|
107
|
+
const seq = s.slice(i, j + 1);
|
|
108
|
+
const mapped = SEQ_MAP[seq];
|
|
109
|
+
if (mapped) {
|
|
110
|
+
events.push({ name: mapped });
|
|
111
|
+
}
|
|
112
|
+
else if (seq.startsWith('\x1b[<')) {
|
|
113
|
+
// X10-style mouse
|
|
114
|
+
const m = seq.match(/^<(\d+);(\d+);(\d+)([Mm])$/);
|
|
115
|
+
if (m) {
|
|
116
|
+
const b = Number(m[1]);
|
|
117
|
+
events.push({
|
|
118
|
+
name: 'mouse',
|
|
119
|
+
kind: b === 64 ? 'scroll_up' : b === 65 ? 'scroll_down' : 'click',
|
|
120
|
+
x: Number(m[2]),
|
|
121
|
+
y: Number(m[3]),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
events.push({ name: 'unknown' });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
events.push({ name: 'unknown' });
|
|
130
|
+
}
|
|
131
|
+
i = j + 1;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Alt+arrow: ESC then letter
|
|
136
|
+
if (ch === '\x1b' && i + 2 < s.length && /[a-zA-Z]/.test(s[i + 2] || '')) {
|
|
137
|
+
const seq = s.slice(i, i + 3);
|
|
138
|
+
const mapped = SEQ_MAP[seq];
|
|
139
|
+
events.push(mapped ? { name: mapped } : { name: 'unknown' });
|
|
140
|
+
i += 3;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
// Bare ESC
|
|
144
|
+
if (ch === '\x1b') {
|
|
145
|
+
// If it's the last char, treat as escape (or as alt+char prefix)
|
|
146
|
+
if (i === s.length - 1) {
|
|
147
|
+
events.push({ name: 'escape' });
|
|
148
|
+
i++;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const next = s[i + 1];
|
|
152
|
+
if (/[\x20-\x7e]/.test(next)) {
|
|
153
|
+
// Alt+char: treat as escape then char (most apps treat as escape)
|
|
154
|
+
events.push({ name: 'escape' });
|
|
155
|
+
i += 2;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
events.push({ name: 'escape' });
|
|
159
|
+
i++;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
// Control characters
|
|
163
|
+
if (code === 13 || code === 10) {
|
|
164
|
+
events.push({ name: 'enter' });
|
|
165
|
+
i++;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (code === 9) {
|
|
169
|
+
events.push({ name: 'tab' });
|
|
170
|
+
i++;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (code === 127 || code === 8) {
|
|
174
|
+
events.push({ name: 'backspace' });
|
|
175
|
+
i++;
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (code === 27) {
|
|
179
|
+
events.push({ name: 'escape' });
|
|
180
|
+
i++;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (code === 3) {
|
|
184
|
+
events.push({ name: 'ctrl_c' });
|
|
185
|
+
i++;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
if (code === 4) {
|
|
189
|
+
events.push({ name: 'ctrl_d' });
|
|
190
|
+
i++;
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (code === 12) {
|
|
194
|
+
events.push({ name: 'ctrl_l' });
|
|
195
|
+
i++;
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (code === 21) {
|
|
199
|
+
events.push({ name: 'ctrl_u' });
|
|
200
|
+
i++;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (code === 23) {
|
|
204
|
+
events.push({ name: 'ctrl_w' });
|
|
205
|
+
i++;
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (code === 1) {
|
|
209
|
+
events.push({ name: 'ctrl_a' });
|
|
210
|
+
i++;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (code === 5) {
|
|
214
|
+
events.push({ name: 'ctrl_e' });
|
|
215
|
+
i++;
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (code === 11) {
|
|
219
|
+
events.push({ name: 'ctrl_k' });
|
|
220
|
+
i++;
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (code === 18) {
|
|
224
|
+
events.push({ name: 'ctrl_r' });
|
|
225
|
+
i++;
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (code === 14) {
|
|
229
|
+
events.push({ name: 'ctrl_n' });
|
|
230
|
+
i++;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (code === 16) {
|
|
234
|
+
events.push({ name: 'ctrl_p' });
|
|
235
|
+
i++;
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
if (code === 7) {
|
|
239
|
+
events.push({ name: 'ctrl_g' });
|
|
240
|
+
i++;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
// Printable
|
|
244
|
+
if (code >= 32 && code <= 126) {
|
|
245
|
+
events.push({ name: 'char', char: ch });
|
|
246
|
+
i++;
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
events.push({ name: 'unknown' });
|
|
250
|
+
i++;
|
|
251
|
+
}
|
|
252
|
+
return events;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Enter raw mode. Returns a cleanup function.
|
|
256
|
+
* Works with process.stdin on Linux, macOS, and Termux.
|
|
257
|
+
*/
|
|
258
|
+
function enableRawMode() {
|
|
259
|
+
const wasRaw = process.stdin.isRaw;
|
|
260
|
+
process.stdin.setRawMode(true);
|
|
261
|
+
process.stdin.resume();
|
|
262
|
+
process.stdin.setEncoding('utf8');
|
|
263
|
+
return () => {
|
|
264
|
+
try {
|
|
265
|
+
process.stdin.setRawMode(wasRaw);
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
/* ignore */
|
|
269
|
+
}
|
|
270
|
+
if (process.stdin.isTTY)
|
|
271
|
+
process.stdin.pause();
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
/** Create a key stream (async iterable of KeyEvent). */
|
|
275
|
+
function keyStream(onKey) {
|
|
276
|
+
process.stdin.on('data', (data) => {
|
|
277
|
+
for (const ev of parseKey(data))
|
|
278
|
+
onKey(ev);
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
function setupReadline(stream) {
|
|
282
|
+
return readline.createInterface({ input: stream, terminal: false });
|
|
283
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.DEFAULT_CONFIG = void 0;
|
|
37
|
+
exports.loadConfig = loadConfig;
|
|
38
|
+
exports.saveConfig = saveConfig;
|
|
39
|
+
exports.effectiveConfig = effectiveConfig;
|
|
40
|
+
/**
|
|
41
|
+
* VECTOR configuration — stored in ~/.vector/config.json
|
|
42
|
+
*
|
|
43
|
+
* Config is deliberately minimal and JSON-based. All secrets live in
|
|
44
|
+
* credentials.json (0600) or environment variables, never in config.json.
|
|
45
|
+
*/
|
|
46
|
+
const fs = __importStar(require("node:fs"));
|
|
47
|
+
const paths_1 = require("../utils/paths");
|
|
48
|
+
const logger_1 = require("../utils/logger");
|
|
49
|
+
exports.DEFAULT_CONFIG = {
|
|
50
|
+
provider: 'openrouter',
|
|
51
|
+
model: 'deepseek/deepseek-chat',
|
|
52
|
+
protocol: 'openai',
|
|
53
|
+
permissionMode: 'ask',
|
|
54
|
+
maxIterations: 25,
|
|
55
|
+
maxRetries: 3,
|
|
56
|
+
requestTimeoutMs: 120_000,
|
|
57
|
+
extraModels: {},
|
|
58
|
+
compactionThreshold: 80_000,
|
|
59
|
+
};
|
|
60
|
+
function loadConfig() {
|
|
61
|
+
(0, paths_1.ensureDirs)();
|
|
62
|
+
const p = (0, paths_1.getConfigPath)();
|
|
63
|
+
try {
|
|
64
|
+
if (fs.existsSync(p)) {
|
|
65
|
+
const raw = fs.readFileSync(p, 'utf8');
|
|
66
|
+
const parsed = JSON.parse(raw);
|
|
67
|
+
return { ...exports.DEFAULT_CONFIG, ...parsed };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
logger_1.logger.warn(`config load failed: ${err.message}`);
|
|
72
|
+
}
|
|
73
|
+
return { ...exports.DEFAULT_CONFIG };
|
|
74
|
+
}
|
|
75
|
+
function saveConfig(config) {
|
|
76
|
+
(0, paths_1.ensureDirs)();
|
|
77
|
+
fs.writeFileSync((0, paths_1.getConfigPath)(), JSON.stringify(config, null, 2) + '\n');
|
|
78
|
+
}
|
|
79
|
+
/** Effective config, applying environment variable overrides. */
|
|
80
|
+
function effectiveConfig(base) {
|
|
81
|
+
const cfg = base || loadConfig();
|
|
82
|
+
const out = { ...cfg };
|
|
83
|
+
if (process.env.VECTOR_PROVIDER)
|
|
84
|
+
out.provider = process.env.VECTOR_PROVIDER;
|
|
85
|
+
if (process.env.VECTOR_MODEL)
|
|
86
|
+
out.model = process.env.VECTOR_MODEL;
|
|
87
|
+
if (process.env.VECTOR_API_URL)
|
|
88
|
+
out.apiUrl = process.env.VECTOR_API_URL;
|
|
89
|
+
if (process.env.VECTOR_YOLO === '1')
|
|
90
|
+
out.permissionMode = 'yolo';
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ENV_KEY_MAP = void 0;
|
|
37
|
+
exports.getApiKey = getApiKey;
|
|
38
|
+
exports.setApiKey = setApiKey;
|
|
39
|
+
exports.hasApiKey = hasApiKey;
|
|
40
|
+
exports.redact = redact;
|
|
41
|
+
/**
|
|
42
|
+
* Credential management.
|
|
43
|
+
*
|
|
44
|
+
* - API keys are read from environment variables first (VECTOR_API_KEY,
|
|
45
|
+
* OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, OPENROUTER_API_KEY).
|
|
46
|
+
* - As a convenience fallback, keys may be stored in ~/.vector/credentials.json
|
|
47
|
+
* with restrictive file permissions (0600). Keys are NEVER printed to the
|
|
48
|
+
* terminal, logs, diffs, or session history.
|
|
49
|
+
*/
|
|
50
|
+
const fs = __importStar(require("node:fs"));
|
|
51
|
+
const paths_1 = require("../utils/paths");
|
|
52
|
+
exports.ENV_KEY_MAP = {
|
|
53
|
+
openai: 'OPENAI_API_KEY',
|
|
54
|
+
anthropic: 'ANTHROPIC_API_KEY',
|
|
55
|
+
gemini: 'GEMINI_API_KEY',
|
|
56
|
+
openrouter: 'OPENROUTER_API_KEY',
|
|
57
|
+
custom: 'VECTOR_API_KEY',
|
|
58
|
+
};
|
|
59
|
+
function readFile() {
|
|
60
|
+
const p = (0, paths_1.getCredentialsPath)();
|
|
61
|
+
try {
|
|
62
|
+
if (fs.existsSync(p)) {
|
|
63
|
+
return JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
/* ignore */
|
|
68
|
+
}
|
|
69
|
+
return {};
|
|
70
|
+
}
|
|
71
|
+
function writeFile(map) {
|
|
72
|
+
(0, paths_1.ensureDirs)();
|
|
73
|
+
const p = (0, paths_1.getCredentialsPath)();
|
|
74
|
+
fs.writeFileSync(p, JSON.stringify(map, null, 2) + '\n', { mode: 0o600 });
|
|
75
|
+
try {
|
|
76
|
+
fs.chmodSync(p, 0o600);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
/* some filesystems (e.g. some Termux setups) ignore chmod */
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Resolve an API key for a provider.
|
|
84
|
+
* Order: env var > credentials.json. Returns null when unset.
|
|
85
|
+
*/
|
|
86
|
+
function getApiKey(providerId) {
|
|
87
|
+
// Explicit per-provider env first
|
|
88
|
+
const envKey = exports.ENV_KEY_MAP[providerId];
|
|
89
|
+
if (envKey) {
|
|
90
|
+
const v = process.env[envKey];
|
|
91
|
+
if (v && v.trim() !== '')
|
|
92
|
+
return v;
|
|
93
|
+
}
|
|
94
|
+
// Generic fallback
|
|
95
|
+
if (process.env.VECTOR_API_KEY && providerId !== 'custom') {
|
|
96
|
+
// VECTOR_API_KEY should not override the dedicated provider vars
|
|
97
|
+
if (!exports.ENV_KEY_MAP[providerId] || !process.env[exports.ENV_KEY_MAP[providerId]]) {
|
|
98
|
+
const v = process.env.VECTOR_API_KEY;
|
|
99
|
+
if (v && v.trim() !== '')
|
|
100
|
+
return v;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const map = readFile();
|
|
104
|
+
return map[providerId] || null;
|
|
105
|
+
}
|
|
106
|
+
/** Set (or remove) a stored key for a provider. */
|
|
107
|
+
function setApiKey(providerId, key) {
|
|
108
|
+
const map = readFile();
|
|
109
|
+
if (key === null || key === '') {
|
|
110
|
+
delete map[providerId];
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
map[providerId] = key;
|
|
114
|
+
}
|
|
115
|
+
writeFile(map);
|
|
116
|
+
}
|
|
117
|
+
function hasApiKey(providerId) {
|
|
118
|
+
return getApiKey(providerId) !== null;
|
|
119
|
+
}
|
|
120
|
+
/** Sanitize a string so it never leaks secrets into logs. */
|
|
121
|
+
function redact(text) {
|
|
122
|
+
// Replace any likely bearer token / API key patterns
|
|
123
|
+
return text
|
|
124
|
+
.replace(/(sk-[A-Za-z0-9_-]{8,})/g, 'sk-***REDACTED***')
|
|
125
|
+
.replace(/(Bearer\s+)[A-Za-z0-9._-]{12,}/gi, '$1***REDACTED***')
|
|
126
|
+
.replace(/(api[_-]?key["']?\s*[:=]\s*["']?)[^"'\s,;]+/gi, '$1***REDACTED***');
|
|
127
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Model catalog + known model lists per provider.
|
|
4
|
+
* Users can add custom models via `vector /model` or editing models.json.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.KNOWN_MODELS = void 0;
|
|
8
|
+
exports.modelsForProvider = modelsForProvider;
|
|
9
|
+
exports.KNOWN_MODELS = {
|
|
10
|
+
openai: [
|
|
11
|
+
{ id: 'gpt-4o', contextWindow: 128000, supportsTools: true, supportsStreaming: true },
|
|
12
|
+
{ id: 'gpt-4o-mini', contextWindow: 128000, supportsTools: true, supportsStreaming: true },
|
|
13
|
+
{ id: 'gpt-4-turbo', contextWindow: 128000, supportsTools: true, supportsStreaming: true },
|
|
14
|
+
{ id: 'o3-mini', contextWindow: 200000, supportsTools: true, supportsStreaming: true },
|
|
15
|
+
{ id: 'gpt-4.1', contextWindow: 1047576, supportsTools: true, supportsStreaming: true },
|
|
16
|
+
],
|
|
17
|
+
anthropic: [
|
|
18
|
+
{ id: 'claude-sonnet-4-20250514', label: 'Claude Sonnet 4', contextWindow: 200000, supportsTools: true, supportsStreaming: true },
|
|
19
|
+
{ id: 'claude-opus-4-20250514', label: 'Claude Opus 4', contextWindow: 200000, supportsTools: true, supportsStreaming: true },
|
|
20
|
+
{ id: 'claude-3-5-haiku-20241022', label: 'Claude 3.5 Haiku', contextWindow: 200000, supportsTools: true, supportsStreaming: true },
|
|
21
|
+
],
|
|
22
|
+
gemini: [
|
|
23
|
+
{ id: 'gemini-2.5-pro', contextWindow: 1048576, supportsTools: true, supportsStreaming: true },
|
|
24
|
+
{ id: 'gemini-2.5-flash', contextWindow: 1048576, supportsTools: true, supportsStreaming: true },
|
|
25
|
+
{ id: 'gemini-2.0-flash', contextWindow: 1048576, supportsTools: true, supportsStreaming: true },
|
|
26
|
+
],
|
|
27
|
+
openrouter: [
|
|
28
|
+
{ id: 'deepseek/deepseek-chat', label: 'DeepSeek V3', contextWindow: 64000, supportsTools: true, supportsStreaming: true },
|
|
29
|
+
{ id: 'deepseek/deepseek-reasoner', label: 'DeepSeek R1', contextWindow: 64000, supportsTools: false, supportsStreaming: true },
|
|
30
|
+
{ id: 'anthropic/claude-sonnet-4', contextWindow: 200000, supportsTools: true, supportsStreaming: true },
|
|
31
|
+
{ id: 'openai/gpt-4o', contextWindow: 128000, supportsTools: true, supportsStreaming: true },
|
|
32
|
+
{ id: 'google/gemini-2.5-pro', contextWindow: 1048576, supportsTools: true, supportsStreaming: true },
|
|
33
|
+
],
|
|
34
|
+
ollama: [
|
|
35
|
+
{ id: 'llama3.1', contextWindow: 128000, supportsTools: true, supportsStreaming: true },
|
|
36
|
+
{ id: 'llama3.2', contextWindow: 128000, supportsTools: true, supportsStreaming: true },
|
|
37
|
+
{ id: 'qwen2.5-coder', contextWindow: 32768, supportsTools: true, supportsStreaming: true },
|
|
38
|
+
{ id: 'deepseek-coder-v2', contextWindow: 128000, supportsTools: true, supportsStreaming: true },
|
|
39
|
+
{ id: 'mistral', contextWindow: 32768, supportsTools: true, supportsStreaming: true },
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
/** Get a model list for a provider, falling back to a generic entry. */
|
|
43
|
+
function modelsForProvider(providerId) {
|
|
44
|
+
return exports.KNOWN_MODELS[providerId] || [
|
|
45
|
+
{ id: 'default', supportsTools: true, supportsStreaming: true },
|
|
46
|
+
];
|
|
47
|
+
}
|