codeep 1.0.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 +201 -0
- package/README.md +576 -0
- package/dist/api/index.d.ts +8 -0
- package/dist/api/index.js +421 -0
- package/dist/app.d.ts +2 -0
- package/dist/app.js +1406 -0
- package/dist/components/AgentProgress.d.ts +33 -0
- package/dist/components/AgentProgress.js +97 -0
- package/dist/components/Export.d.ts +8 -0
- package/dist/components/Export.js +27 -0
- package/dist/components/Help.d.ts +2 -0
- package/dist/components/Help.js +3 -0
- package/dist/components/Input.d.ts +9 -0
- package/dist/components/Input.js +89 -0
- package/dist/components/Loading.d.ts +9 -0
- package/dist/components/Loading.js +31 -0
- package/dist/components/Login.d.ts +7 -0
- package/dist/components/Login.js +77 -0
- package/dist/components/Logo.d.ts +8 -0
- package/dist/components/Logo.js +89 -0
- package/dist/components/LogoutPicker.d.ts +8 -0
- package/dist/components/LogoutPicker.js +61 -0
- package/dist/components/Message.d.ts +10 -0
- package/dist/components/Message.js +234 -0
- package/dist/components/MessageList.d.ts +10 -0
- package/dist/components/MessageList.js +8 -0
- package/dist/components/ProjectPermission.d.ts +7 -0
- package/dist/components/ProjectPermission.js +52 -0
- package/dist/components/Search.d.ts +10 -0
- package/dist/components/Search.js +30 -0
- package/dist/components/SessionPicker.d.ts +9 -0
- package/dist/components/SessionPicker.js +88 -0
- package/dist/components/Sessions.d.ts +12 -0
- package/dist/components/Sessions.js +102 -0
- package/dist/components/Settings.d.ts +7 -0
- package/dist/components/Settings.js +162 -0
- package/dist/components/Status.d.ts +2 -0
- package/dist/components/Status.js +12 -0
- package/dist/config/config.test.d.ts +1 -0
- package/dist/config/config.test.js +157 -0
- package/dist/config/index.d.ts +121 -0
- package/dist/config/index.js +555 -0
- package/dist/config/providers.d.ts +43 -0
- package/dist/config/providers.js +82 -0
- package/dist/config/providers.test.d.ts +1 -0
- package/dist/config/providers.test.js +132 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +38 -0
- package/dist/utils/agent.d.ts +37 -0
- package/dist/utils/agent.js +627 -0
- package/dist/utils/codeReview.d.ts +36 -0
- package/dist/utils/codeReview.js +390 -0
- package/dist/utils/context.d.ts +49 -0
- package/dist/utils/context.js +216 -0
- package/dist/utils/diffPreview.d.ts +57 -0
- package/dist/utils/diffPreview.js +335 -0
- package/dist/utils/export.d.ts +19 -0
- package/dist/utils/export.js +94 -0
- package/dist/utils/git.d.ts +85 -0
- package/dist/utils/git.js +399 -0
- package/dist/utils/git.test.d.ts +1 -0
- package/dist/utils/git.test.js +193 -0
- package/dist/utils/history.d.ts +93 -0
- package/dist/utils/history.js +348 -0
- package/dist/utils/interactive.d.ts +34 -0
- package/dist/utils/interactive.js +206 -0
- package/dist/utils/keychain.d.ts +17 -0
- package/dist/utils/keychain.js +160 -0
- package/dist/utils/learning.d.ts +89 -0
- package/dist/utils/learning.js +330 -0
- package/dist/utils/logger.d.ts +33 -0
- package/dist/utils/logger.js +130 -0
- package/dist/utils/project.d.ts +86 -0
- package/dist/utils/project.js +415 -0
- package/dist/utils/project.test.d.ts +1 -0
- package/dist/utils/project.test.js +212 -0
- package/dist/utils/ratelimit.d.ts +26 -0
- package/dist/utils/ratelimit.js +132 -0
- package/dist/utils/ratelimit.test.d.ts +1 -0
- package/dist/utils/ratelimit.test.js +131 -0
- package/dist/utils/retry.d.ts +28 -0
- package/dist/utils/retry.js +109 -0
- package/dist/utils/retry.test.d.ts +1 -0
- package/dist/utils/retry.test.js +163 -0
- package/dist/utils/search.d.ts +11 -0
- package/dist/utils/search.js +29 -0
- package/dist/utils/shell.d.ts +45 -0
- package/dist/utils/shell.js +242 -0
- package/dist/utils/skills.d.ts +144 -0
- package/dist/utils/skills.js +1137 -0
- package/dist/utils/smartContext.d.ts +29 -0
- package/dist/utils/smartContext.js +441 -0
- package/dist/utils/tools.d.ts +224 -0
- package/dist/utils/tools.js +731 -0
- package/dist/utils/update.d.ts +22 -0
- package/dist/utils/update.js +128 -0
- package/dist/utils/validation.d.ts +28 -0
- package/dist/utils/validation.js +141 -0
- package/dist/utils/validation.test.d.ts +1 -0
- package/dist/utils/validation.test.js +164 -0
- package/dist/utils/verify.d.ts +78 -0
- package/dist/utils/verify.js +464 -0
- package/package.json +68 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Box, Text, useInput } from 'ink';
|
|
4
|
+
import { config } from '../config/index';
|
|
5
|
+
import { updateRateLimits } from '../utils/ratelimit';
|
|
6
|
+
const SETTINGS = [
|
|
7
|
+
{
|
|
8
|
+
key: 'temperature',
|
|
9
|
+
label: 'Temperature',
|
|
10
|
+
value: () => config.get('temperature'),
|
|
11
|
+
type: 'number',
|
|
12
|
+
min: 0,
|
|
13
|
+
max: 2,
|
|
14
|
+
step: 0.1,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
key: 'maxTokens',
|
|
18
|
+
label: 'Max Tokens',
|
|
19
|
+
value: () => config.get('maxTokens'),
|
|
20
|
+
type: 'number',
|
|
21
|
+
min: 256,
|
|
22
|
+
max: 32768,
|
|
23
|
+
step: 256,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
key: 'apiTimeout',
|
|
27
|
+
label: 'API Timeout (ms)',
|
|
28
|
+
value: () => config.get('apiTimeout'),
|
|
29
|
+
type: 'number',
|
|
30
|
+
min: 5000,
|
|
31
|
+
max: 120000,
|
|
32
|
+
step: 5000,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
key: 'rateLimitApi',
|
|
36
|
+
label: 'API Rate Limit (/min)',
|
|
37
|
+
value: () => config.get('rateLimitApi'),
|
|
38
|
+
type: 'number',
|
|
39
|
+
min: 1,
|
|
40
|
+
max: 300,
|
|
41
|
+
step: 5,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
key: 'rateLimitCommands',
|
|
45
|
+
label: 'Command Rate Limit (/min)',
|
|
46
|
+
value: () => config.get('rateLimitCommands'),
|
|
47
|
+
type: 'number',
|
|
48
|
+
min: 10,
|
|
49
|
+
max: 1000,
|
|
50
|
+
step: 10,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
key: 'autoSave',
|
|
54
|
+
label: 'Auto Save Sessions',
|
|
55
|
+
value: () => config.get('autoSave') ? 'On' : 'Off',
|
|
56
|
+
type: 'select',
|
|
57
|
+
options: [
|
|
58
|
+
{ value: true, label: 'On' },
|
|
59
|
+
{ value: false, label: 'Off' },
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
key: 'agentMode',
|
|
64
|
+
label: 'Agent Mode',
|
|
65
|
+
value: () => config.get('agentMode') === 'auto' ? 'Auto' : 'Manual',
|
|
66
|
+
type: 'select',
|
|
67
|
+
options: [
|
|
68
|
+
{ value: 'auto', label: 'Auto' },
|
|
69
|
+
{ value: 'manual', label: 'Manual' },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
export const Settings = ({ onClose, notify }) => {
|
|
74
|
+
const [selected, setSelected] = useState(0);
|
|
75
|
+
const [editing, setEditing] = useState(false);
|
|
76
|
+
const [editValue, setEditValue] = useState('');
|
|
77
|
+
useInput((input, key) => {
|
|
78
|
+
if (key.escape) {
|
|
79
|
+
if (editing) {
|
|
80
|
+
setEditing(false);
|
|
81
|
+
setEditValue('');
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
onClose();
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (editing) {
|
|
89
|
+
// Handle editing mode
|
|
90
|
+
if (key.return) {
|
|
91
|
+
const setting = SETTINGS[selected];
|
|
92
|
+
if (setting.type === 'number') {
|
|
93
|
+
const num = parseFloat(editValue);
|
|
94
|
+
if (!isNaN(num)) {
|
|
95
|
+
const clamped = Math.max(setting.min || 0, Math.min(setting.max || Infinity, num));
|
|
96
|
+
config.set(setting.key, clamped);
|
|
97
|
+
// Update rate limiters if changed
|
|
98
|
+
if (setting.key === 'rateLimitApi' || setting.key === 'rateLimitCommands') {
|
|
99
|
+
updateRateLimits();
|
|
100
|
+
}
|
|
101
|
+
notify(`${setting.label}: ${clamped}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
setEditing(false);
|
|
105
|
+
setEditValue('');
|
|
106
|
+
}
|
|
107
|
+
else if (key.backspace || key.delete) {
|
|
108
|
+
setEditValue(v => v.slice(0, -1));
|
|
109
|
+
}
|
|
110
|
+
else if (/^[0-9.]$/.test(input)) {
|
|
111
|
+
setEditValue(v => v + input);
|
|
112
|
+
}
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Navigation mode
|
|
116
|
+
if (key.upArrow) {
|
|
117
|
+
setSelected(s => Math.max(0, s - 1));
|
|
118
|
+
}
|
|
119
|
+
else if (key.downArrow) {
|
|
120
|
+
setSelected(s => Math.min(SETTINGS.length - 1, s + 1));
|
|
121
|
+
}
|
|
122
|
+
else if (key.leftArrow || key.rightArrow) {
|
|
123
|
+
// Adjust value with arrows
|
|
124
|
+
const setting = SETTINGS[selected];
|
|
125
|
+
if (setting.type === 'number') {
|
|
126
|
+
const current = setting.value();
|
|
127
|
+
const step = setting.step || 1;
|
|
128
|
+
const delta = key.leftArrow ? -step : step;
|
|
129
|
+
const newValue = Math.max(setting.min || 0, Math.min(setting.max || Infinity, current + delta));
|
|
130
|
+
config.set(setting.key, newValue);
|
|
131
|
+
// Update rate limiters if changed
|
|
132
|
+
if (setting.key === 'rateLimitApi' || setting.key === 'rateLimitCommands') {
|
|
133
|
+
updateRateLimits();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else if (setting.type === 'select' && setting.options) {
|
|
137
|
+
const current = config.get(setting.key);
|
|
138
|
+
const currentIdx = setting.options.findIndex(o => o.value === current);
|
|
139
|
+
const newIdx = key.leftArrow
|
|
140
|
+
? Math.max(0, currentIdx - 1)
|
|
141
|
+
: Math.min(setting.options.length - 1, currentIdx + 1);
|
|
142
|
+
config.set(setting.key, setting.options[newIdx].value);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else if (key.return) {
|
|
146
|
+
const setting = SETTINGS[selected];
|
|
147
|
+
if (setting.type === 'number') {
|
|
148
|
+
setEditing(true);
|
|
149
|
+
setEditValue(String(setting.value()));
|
|
150
|
+
}
|
|
151
|
+
else if (setting.type === 'select' && setting.options) {
|
|
152
|
+
// Toggle select options
|
|
153
|
+
const current = config.get(setting.key);
|
|
154
|
+
const currentIdx = setting.options.findIndex(o => o.value === current);
|
|
155
|
+
const newIdx = (currentIdx + 1) % setting.options.length;
|
|
156
|
+
config.set(setting.key, setting.options[newIdx].value);
|
|
157
|
+
notify(`${setting.label}: ${setting.options[newIdx].label}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "#f02a30", padding: 1, children: [_jsx(Text, { color: "#f02a30", bold: true, children: "Settings" }), _jsx(Text, { children: " " }), SETTINGS.map((setting, i) => (_jsx(Box, { children: _jsxs(Text, { children: [i === selected ? _jsx(Text, { color: "#f02a30", children: "\u25B8 " }) : ' ', _jsxs(Text, { color: i === selected ? '#f02a30' : undefined, children: [setting.label, ":"] }), _jsx(Text, { children: " " }), editing && i === selected ? (_jsx(Text, { color: "cyan", inverse: true, children: editValue || ' ' })) : (_jsx(Text, { color: "green", children: setting.value() })), i === selected && setting.type === 'number' && !editing && (_jsx(Text, { children: " (\u2190/\u2192 adjust, Enter to type)" })), i === selected && setting.type === 'select' && (_jsx(Text, { children: " (\u2190/\u2192 or Enter to toggle)" }))] }) }, setting.key))), _jsx(Text, { children: " " }), _jsx(Text, { children: "\u2191/\u2193 Navigate | \u2190/\u2192 Adjust | Enter Edit | Esc Close" })] }));
|
|
162
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Text, Box } from 'ink';
|
|
3
|
+
import { config, getMaskedApiKey, getModelsForCurrentProvider, getCurrentProvider, PROTOCOLS, LANGUAGES } from '../config/index';
|
|
4
|
+
export const Status = () => {
|
|
5
|
+
const model = config.get('model');
|
|
6
|
+
const protocol = config.get('protocol');
|
|
7
|
+
const plan = config.get('plan');
|
|
8
|
+
const language = config.get('language');
|
|
9
|
+
const provider = getCurrentProvider();
|
|
10
|
+
const models = getModelsForCurrentProvider();
|
|
11
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "#f02a30", padding: 1, children: [_jsx(Text, { color: "#f02a30", bold: true, children: "Status" }), _jsx(Text, { children: " " }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "Provider:" }), " ", provider.name] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "Model:" }), " ", models[model] || model] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "Protocol:" }), " ", PROTOCOLS[protocol] || protocol] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "Language:" }), " ", LANGUAGES[language] || language] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "Plan:" }), " ", plan.toUpperCase()] }), _jsxs(Text, { children: [_jsx(Text, { color: "#f02a30", children: "API Key:" }), " ", getMaskedApiKey()] })] }));
|
|
12
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { mkdirSync, rmSync, writeFileSync, existsSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
5
|
+
// We need to test the config functions
|
|
6
|
+
// Since config uses Conf which has side effects, we'll test the utility functions
|
|
7
|
+
describe('config utilities', () => {
|
|
8
|
+
const TEST_DIR = join(tmpdir(), 'codeep-config-test-' + Date.now());
|
|
9
|
+
const SESSIONS_DIR = join(TEST_DIR, '.codeep', 'sessions');
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
mkdirSync(SESSIONS_DIR, { recursive: true });
|
|
12
|
+
});
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
try {
|
|
15
|
+
rmSync(TEST_DIR, { recursive: true, force: true });
|
|
16
|
+
}
|
|
17
|
+
catch { }
|
|
18
|
+
});
|
|
19
|
+
describe('session file operations', () => {
|
|
20
|
+
it('should create sessions directory structure', () => {
|
|
21
|
+
expect(existsSync(SESSIONS_DIR)).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
it('should handle session JSON files', () => {
|
|
24
|
+
const sessionId = 'test-session';
|
|
25
|
+
const sessionFile = join(SESSIONS_DIR, `${sessionId}.json`);
|
|
26
|
+
const sessionData = {
|
|
27
|
+
name: sessionId,
|
|
28
|
+
history: [
|
|
29
|
+
{ role: 'user', content: 'Hello' },
|
|
30
|
+
{ role: 'assistant', content: 'Hi there!' },
|
|
31
|
+
],
|
|
32
|
+
createdAt: new Date().toISOString(),
|
|
33
|
+
};
|
|
34
|
+
writeFileSync(sessionFile, JSON.stringify(sessionData, null, 2));
|
|
35
|
+
expect(existsSync(sessionFile)).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
describe('language codes', () => {
|
|
39
|
+
const LANGUAGES = {
|
|
40
|
+
'auto': 'Auto-detect',
|
|
41
|
+
'en': 'English',
|
|
42
|
+
'zh': 'Chinese (中文)',
|
|
43
|
+
'es': 'Spanish (Español)',
|
|
44
|
+
'hi': 'Hindi (हिन्दी)',
|
|
45
|
+
'ar': 'Arabic (العربية)',
|
|
46
|
+
'pt': 'Portuguese (Português)',
|
|
47
|
+
'fr': 'French (Français)',
|
|
48
|
+
'de': 'German (Deutsch)',
|
|
49
|
+
'ja': 'Japanese (日本語)',
|
|
50
|
+
'ru': 'Russian (Русский)',
|
|
51
|
+
'hr': 'Croatian (Hrvatski)',
|
|
52
|
+
};
|
|
53
|
+
it('should have all supported languages', () => {
|
|
54
|
+
expect(Object.keys(LANGUAGES)).toContain('auto');
|
|
55
|
+
expect(Object.keys(LANGUAGES)).toContain('en');
|
|
56
|
+
expect(Object.keys(LANGUAGES)).toContain('hr');
|
|
57
|
+
});
|
|
58
|
+
it('should have display names for all languages', () => {
|
|
59
|
+
for (const [code, name] of Object.entries(LANGUAGES)) {
|
|
60
|
+
expect(typeof name).toBe('string');
|
|
61
|
+
expect(name.length).toBeGreaterThan(0);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('protocols', () => {
|
|
66
|
+
const PROTOCOLS = {
|
|
67
|
+
'openai': 'OpenAI Compatible',
|
|
68
|
+
'anthropic': 'Anthropic Protocol',
|
|
69
|
+
};
|
|
70
|
+
it('should support openai protocol', () => {
|
|
71
|
+
expect(PROTOCOLS['openai']).toBe('OpenAI Compatible');
|
|
72
|
+
});
|
|
73
|
+
it('should support anthropic protocol', () => {
|
|
74
|
+
expect(PROTOCOLS['anthropic']).toBe('Anthropic Protocol');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
describe('config schema validation', () => {
|
|
78
|
+
it('should have valid default values', () => {
|
|
79
|
+
const defaults = {
|
|
80
|
+
apiKey: '',
|
|
81
|
+
provider: 'z.ai',
|
|
82
|
+
model: 'glm-4.7',
|
|
83
|
+
protocol: 'openai',
|
|
84
|
+
plan: 'lite',
|
|
85
|
+
language: 'en',
|
|
86
|
+
autoSave: true,
|
|
87
|
+
currentSessionId: '',
|
|
88
|
+
temperature: 0.7,
|
|
89
|
+
maxTokens: 4096,
|
|
90
|
+
apiTimeout: 30000,
|
|
91
|
+
rateLimitApi: 30,
|
|
92
|
+
rateLimitCommands: 100,
|
|
93
|
+
projectPermissions: [],
|
|
94
|
+
providerApiKeys: [],
|
|
95
|
+
};
|
|
96
|
+
// Validate types
|
|
97
|
+
expect(typeof defaults.apiKey).toBe('string');
|
|
98
|
+
expect(typeof defaults.provider).toBe('string');
|
|
99
|
+
expect(typeof defaults.model).toBe('string');
|
|
100
|
+
expect(['openai', 'anthropic']).toContain(defaults.protocol);
|
|
101
|
+
expect(['lite', 'pro', 'max']).toContain(defaults.plan);
|
|
102
|
+
expect(typeof defaults.autoSave).toBe('boolean');
|
|
103
|
+
expect(typeof defaults.temperature).toBe('number');
|
|
104
|
+
expect(defaults.temperature).toBeGreaterThanOrEqual(0);
|
|
105
|
+
expect(defaults.temperature).toBeLessThanOrEqual(2);
|
|
106
|
+
expect(typeof defaults.maxTokens).toBe('number');
|
|
107
|
+
expect(defaults.maxTokens).toBeGreaterThan(0);
|
|
108
|
+
expect(typeof defaults.apiTimeout).toBe('number');
|
|
109
|
+
expect(defaults.apiTimeout).toBeGreaterThan(0);
|
|
110
|
+
expect(typeof defaults.rateLimitApi).toBe('number');
|
|
111
|
+
expect(typeof defaults.rateLimitCommands).toBe('number');
|
|
112
|
+
expect(Array.isArray(defaults.projectPermissions)).toBe(true);
|
|
113
|
+
expect(Array.isArray(defaults.providerApiKeys)).toBe(true);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('project permissions structure', () => {
|
|
117
|
+
it('should validate permission structure', () => {
|
|
118
|
+
const permission = {
|
|
119
|
+
path: '/Users/test/project',
|
|
120
|
+
readPermission: true,
|
|
121
|
+
writePermission: false,
|
|
122
|
+
grantedAt: new Date().toISOString(),
|
|
123
|
+
};
|
|
124
|
+
expect(typeof permission.path).toBe('string');
|
|
125
|
+
expect(typeof permission.readPermission).toBe('boolean');
|
|
126
|
+
expect(typeof permission.writePermission).toBe('boolean');
|
|
127
|
+
expect(typeof permission.grantedAt).toBe('string');
|
|
128
|
+
// Validate ISO date string
|
|
129
|
+
expect(() => new Date(permission.grantedAt)).not.toThrow();
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe('provider API keys structure', () => {
|
|
133
|
+
it('should validate API key structure', () => {
|
|
134
|
+
const apiKey = {
|
|
135
|
+
providerId: 'z.ai',
|
|
136
|
+
apiKey: 'test-api-key-123',
|
|
137
|
+
};
|
|
138
|
+
expect(typeof apiKey.providerId).toBe('string');
|
|
139
|
+
expect(typeof apiKey.apiKey).toBe('string');
|
|
140
|
+
expect(apiKey.providerId.length).toBeGreaterThan(0);
|
|
141
|
+
expect(apiKey.apiKey.length).toBeGreaterThan(0);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
describe('message structure', () => {
|
|
145
|
+
it('should validate message structure', () => {
|
|
146
|
+
const userMessage = { role: 'user', content: 'Hello' };
|
|
147
|
+
const assistantMessage = { role: 'assistant', content: 'Hi!' };
|
|
148
|
+
const systemMessage = { role: 'system', content: 'You are a helpful assistant' };
|
|
149
|
+
expect(['user', 'assistant', 'system']).toContain(userMessage.role);
|
|
150
|
+
expect(['user', 'assistant', 'system']).toContain(assistantMessage.role);
|
|
151
|
+
expect(['user', 'assistant', 'system']).toContain(systemMessage.role);
|
|
152
|
+
expect(typeof userMessage.content).toBe('string');
|
|
153
|
+
expect(typeof assistantMessage.content).toBe('string');
|
|
154
|
+
expect(typeof systemMessage.content).toBe('string');
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
});
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import Conf from 'conf';
|
|
2
|
+
export interface Message {
|
|
3
|
+
role: 'user' | 'assistant' | 'system';
|
|
4
|
+
content: string;
|
|
5
|
+
}
|
|
6
|
+
type LanguageCode = 'auto' | 'en' | 'zh' | 'es' | 'hi' | 'ar' | 'pt' | 'fr' | 'de' | 'ja' | 'ru' | 'hr';
|
|
7
|
+
interface ProjectPermission {
|
|
8
|
+
path: string;
|
|
9
|
+
readPermission: boolean;
|
|
10
|
+
writePermission: boolean;
|
|
11
|
+
grantedAt: string;
|
|
12
|
+
}
|
|
13
|
+
interface ProviderApiKey {
|
|
14
|
+
providerId: string;
|
|
15
|
+
apiKey: string;
|
|
16
|
+
}
|
|
17
|
+
type AgentMode = 'auto' | 'manual';
|
|
18
|
+
interface ConfigSchema {
|
|
19
|
+
apiKey: string;
|
|
20
|
+
provider: string;
|
|
21
|
+
model: string;
|
|
22
|
+
protocol: 'openai' | 'anthropic';
|
|
23
|
+
plan: 'lite' | 'pro' | 'max';
|
|
24
|
+
language: LanguageCode;
|
|
25
|
+
autoSave: boolean;
|
|
26
|
+
currentSessionId: string;
|
|
27
|
+
temperature: number;
|
|
28
|
+
maxTokens: number;
|
|
29
|
+
apiTimeout: number;
|
|
30
|
+
rateLimitApi: number;
|
|
31
|
+
rateLimitCommands: number;
|
|
32
|
+
agentMode: AgentMode;
|
|
33
|
+
agentConfirmation: 'always' | 'dangerous' | 'never';
|
|
34
|
+
agentAutoCommit: boolean;
|
|
35
|
+
agentAutoCommitBranch: boolean;
|
|
36
|
+
agentAutoVerify: boolean;
|
|
37
|
+
agentMaxFixAttempts: number;
|
|
38
|
+
projectPermissions: ProjectPermission[];
|
|
39
|
+
providerApiKeys: ProviderApiKey[];
|
|
40
|
+
}
|
|
41
|
+
export type { AgentMode };
|
|
42
|
+
export type { LanguageCode };
|
|
43
|
+
export declare const config: Conf<ConfigSchema>;
|
|
44
|
+
export declare const LANGUAGES: Record<string, string>;
|
|
45
|
+
export declare const PROTOCOLS: Record<string, string>;
|
|
46
|
+
/**
|
|
47
|
+
* Load API key from config into cache
|
|
48
|
+
*/
|
|
49
|
+
export declare function loadApiKey(providerId?: string): Promise<string>;
|
|
50
|
+
/**
|
|
51
|
+
* Load API keys for ALL providers into cache
|
|
52
|
+
* Should be called at app startup
|
|
53
|
+
*/
|
|
54
|
+
export declare function loadAllApiKeys(): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Get API key synchronously from cache (must call loadAllApiKeys first)
|
|
57
|
+
*/
|
|
58
|
+
export declare function getApiKey(providerId?: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Set API key - stores in config file
|
|
61
|
+
*/
|
|
62
|
+
export declare function setApiKey(key: string, providerId?: string): void;
|
|
63
|
+
export declare function getMaskedApiKey(providerId?: string): string;
|
|
64
|
+
/**
|
|
65
|
+
* Get list of providers that have API keys configured
|
|
66
|
+
*/
|
|
67
|
+
export declare function getConfiguredProviders(): {
|
|
68
|
+
id: string;
|
|
69
|
+
name: string;
|
|
70
|
+
}[];
|
|
71
|
+
/**
|
|
72
|
+
* Clear API key for a specific provider
|
|
73
|
+
*/
|
|
74
|
+
export declare function clearApiKey(providerId: string): void;
|
|
75
|
+
export declare function isConfiguredAsync(providerId?: string): Promise<boolean>;
|
|
76
|
+
export declare function isConfigured(providerId?: string): boolean;
|
|
77
|
+
export declare function getCurrentProvider(): {
|
|
78
|
+
id: string;
|
|
79
|
+
name: string;
|
|
80
|
+
};
|
|
81
|
+
export declare function setProvider(providerId: string): boolean;
|
|
82
|
+
export declare function getModelsForCurrentProvider(): Record<string, string>;
|
|
83
|
+
export { PROVIDERS } from './providers';
|
|
84
|
+
export declare function getCurrentSessionId(): string;
|
|
85
|
+
export declare function startNewSession(): string;
|
|
86
|
+
export declare function autoSaveSession(history: Message[], projectPath?: string): boolean;
|
|
87
|
+
export declare function flushAutoSave(): boolean;
|
|
88
|
+
export declare function saveSession(name: string, history: Message[], projectPath?: string): boolean;
|
|
89
|
+
export declare function loadSession(name: string, projectPath?: string): Message[] | null;
|
|
90
|
+
export declare function listSessions(projectPath?: string): string[];
|
|
91
|
+
export declare function deleteSession(name: string, projectPath?: string): boolean;
|
|
92
|
+
export declare function renameSession(oldName: string, newName: string, projectPath?: string): boolean;
|
|
93
|
+
export declare function getSessionInfo(name: string, projectPath?: string): {
|
|
94
|
+
name: string;
|
|
95
|
+
createdAt: string;
|
|
96
|
+
messageCount: number;
|
|
97
|
+
} | null;
|
|
98
|
+
export interface SessionInfo {
|
|
99
|
+
name: string;
|
|
100
|
+
createdAt: string;
|
|
101
|
+
messageCount: number;
|
|
102
|
+
fileSize: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* List all sessions with metadata, sorted by date (newest first)
|
|
106
|
+
*/
|
|
107
|
+
export declare function listSessionsWithInfo(projectPath?: string): SessionInfo[];
|
|
108
|
+
/**
|
|
109
|
+
* Get project permission from local .codeep/config.json
|
|
110
|
+
*/
|
|
111
|
+
export declare function getProjectPermission(projectPath: string): ProjectPermission | null;
|
|
112
|
+
/**
|
|
113
|
+
* Set project permission in local .codeep/config.json
|
|
114
|
+
*/
|
|
115
|
+
export declare function setProjectPermission(projectPath: string, read: boolean, write: boolean): void;
|
|
116
|
+
/**
|
|
117
|
+
* Remove project permission from local .codeep/config.json
|
|
118
|
+
*/
|
|
119
|
+
export declare function removeProjectPermission(projectPath: string): boolean;
|
|
120
|
+
export declare function hasReadPermission(projectPath: string): boolean;
|
|
121
|
+
export declare function hasWritePermission(projectPath: string): boolean;
|