codeep 1.2.17 → 1.2.18
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 +20 -7
- package/dist/api/index.d.ts +7 -0
- package/dist/api/index.js +21 -17
- package/dist/renderer/App.d.ts +1 -5
- package/dist/renderer/App.js +106 -486
- package/dist/renderer/agentExecution.d.ts +36 -0
- package/dist/renderer/agentExecution.js +394 -0
- package/dist/renderer/commands.d.ts +16 -0
- package/dist/renderer/commands.js +838 -0
- package/dist/renderer/handlers.d.ts +87 -0
- package/dist/renderer/handlers.js +260 -0
- package/dist/renderer/highlight.d.ts +18 -0
- package/dist/renderer/highlight.js +130 -0
- package/dist/renderer/main.d.ts +4 -2
- package/dist/renderer/main.js +103 -1550
- package/dist/utils/agent.d.ts +5 -15
- package/dist/utils/agent.js +9 -693
- package/dist/utils/agentChat.d.ts +46 -0
- package/dist/utils/agentChat.js +343 -0
- package/dist/utils/agentStream.d.ts +23 -0
- package/dist/utils/agentStream.js +216 -0
- package/dist/utils/keychain.js +3 -2
- package/dist/utils/learning.js +9 -3
- package/dist/utils/mcpIntegration.d.ts +61 -0
- package/dist/utils/mcpIntegration.js +154 -0
- package/dist/utils/project.js +8 -3
- package/dist/utils/skills.js +21 -11
- package/dist/utils/smartContext.d.ts +4 -0
- package/dist/utils/smartContext.js +51 -14
- package/dist/utils/toolExecution.d.ts +27 -0
- package/dist/utils/toolExecution.js +525 -0
- package/dist/utils/toolParsing.d.ts +18 -0
- package/dist/utils/toolParsing.js +302 -0
- package/dist/utils/tools.d.ts +11 -24
- package/dist/utils/tools.js +22 -1187
- package/package.json +3 -1
- package/dist/config/config.test.d.ts +0 -1
- package/dist/config/config.test.js +0 -157
- package/dist/config/providers.test.d.ts +0 -1
- package/dist/config/providers.test.js +0 -187
- package/dist/hooks/index.d.ts +0 -4
- package/dist/hooks/index.js +0 -4
- package/dist/hooks/useAgent.d.ts +0 -29
- package/dist/hooks/useAgent.js +0 -148
- package/dist/utils/agent.test.d.ts +0 -1
- package/dist/utils/agent.test.js +0 -315
- package/dist/utils/git.test.d.ts +0 -1
- package/dist/utils/git.test.js +0 -193
- package/dist/utils/gitignore.test.d.ts +0 -1
- package/dist/utils/gitignore.test.js +0 -167
- package/dist/utils/project.test.d.ts +0 -1
- package/dist/utils/project.test.js +0 -212
- package/dist/utils/ratelimit.test.d.ts +0 -1
- package/dist/utils/ratelimit.test.js +0 -131
- package/dist/utils/retry.test.d.ts +0 -1
- package/dist/utils/retry.test.js +0 -163
- package/dist/utils/smartContext.test.d.ts +0 -1
- package/dist/utils/smartContext.test.js +0 -382
- package/dist/utils/tools.test.d.ts +0 -1
- package/dist/utils/tools.test.js +0 -681
- package/dist/utils/validation.test.d.ts +0 -1
- package/dist/utils/validation.test.js +0 -164
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key event handlers for inline UI panels.
|
|
3
|
+
*
|
|
4
|
+
* Each handler receives a context object that exposes only the state slices
|
|
5
|
+
* and callbacks it needs, keeping the handlers decoupled from App internals.
|
|
6
|
+
*/
|
|
7
|
+
import { KeyEvent } from './Input';
|
|
8
|
+
import { SelectItem } from './components/SelectScreen';
|
|
9
|
+
import { ConfirmOptions } from './App';
|
|
10
|
+
export interface StatusHandlerContext {
|
|
11
|
+
close(): void;
|
|
12
|
+
render(): void;
|
|
13
|
+
}
|
|
14
|
+
export declare function handleInlineStatusKey(event: KeyEvent, ctx: StatusHandlerContext): void;
|
|
15
|
+
export interface HelpHandlerContext {
|
|
16
|
+
scrollIndex: number;
|
|
17
|
+
setScrollIndex(v: number): void;
|
|
18
|
+
close(): void;
|
|
19
|
+
render(): void;
|
|
20
|
+
}
|
|
21
|
+
export declare function handleInlineHelpKey(event: KeyEvent, ctx: HelpHandlerContext): void;
|
|
22
|
+
export interface MenuHandlerContext {
|
|
23
|
+
index: number;
|
|
24
|
+
items: SelectItem[];
|
|
25
|
+
setIndex(v: number): void;
|
|
26
|
+
close(callback: ((item: SelectItem) => void) | null, selected: SelectItem | null): void;
|
|
27
|
+
render(): void;
|
|
28
|
+
}
|
|
29
|
+
export declare function handleMenuKey(event: KeyEvent, ctx: MenuHandlerContext): void;
|
|
30
|
+
declare const PERMISSION_OPTIONS: readonly ["read", "write", "none"];
|
|
31
|
+
type PermissionLevel = typeof PERMISSION_OPTIONS[number];
|
|
32
|
+
export interface PermissionHandlerContext {
|
|
33
|
+
index: number;
|
|
34
|
+
setIndex(v: number): void;
|
|
35
|
+
close(level: PermissionLevel): void;
|
|
36
|
+
render(): void;
|
|
37
|
+
}
|
|
38
|
+
export declare function handleInlinePermissionKey(event: KeyEvent, ctx: PermissionHandlerContext): void;
|
|
39
|
+
export interface SessionItem {
|
|
40
|
+
name: string;
|
|
41
|
+
messageCount: number;
|
|
42
|
+
createdAt: string;
|
|
43
|
+
}
|
|
44
|
+
export interface SessionPickerHandlerContext {
|
|
45
|
+
index: number;
|
|
46
|
+
items: SessionItem[];
|
|
47
|
+
deleteMode: boolean;
|
|
48
|
+
hasDeleteCallback: boolean;
|
|
49
|
+
setIndex(v: number): void;
|
|
50
|
+
setItems(items: SessionItem[]): void;
|
|
51
|
+
setDeleteMode(v: boolean): void;
|
|
52
|
+
close(sessionName: string | null): void;
|
|
53
|
+
onDelete(sessionName: string): void;
|
|
54
|
+
notify(msg: string): void;
|
|
55
|
+
render(): void;
|
|
56
|
+
}
|
|
57
|
+
export declare function handleInlineSessionPickerKey(event: KeyEvent, ctx: SessionPickerHandlerContext): void;
|
|
58
|
+
export interface ConfirmHandlerContext {
|
|
59
|
+
options: ConfirmOptions;
|
|
60
|
+
selection: 'yes' | 'no';
|
|
61
|
+
setSelection(v: 'yes' | 'no'): void;
|
|
62
|
+
close(confirmed: boolean): void;
|
|
63
|
+
render(): void;
|
|
64
|
+
}
|
|
65
|
+
export declare function handleInlineConfirmKey(event: KeyEvent, ctx: ConfirmHandlerContext): void;
|
|
66
|
+
export interface LoginProvider {
|
|
67
|
+
id: string;
|
|
68
|
+
name: string;
|
|
69
|
+
subscribeUrl?: string;
|
|
70
|
+
}
|
|
71
|
+
export interface LoginHandlerContext {
|
|
72
|
+
step: 'provider' | 'apikey';
|
|
73
|
+
providerIndex: number;
|
|
74
|
+
providers: LoginProvider[];
|
|
75
|
+
apiKey: string;
|
|
76
|
+
setStep(v: 'provider' | 'apikey'): void;
|
|
77
|
+
setProviderIndex(v: number): void;
|
|
78
|
+
setApiKey(v: string): void;
|
|
79
|
+
setError(msg: string): void;
|
|
80
|
+
close(result: {
|
|
81
|
+
providerId: string;
|
|
82
|
+
apiKey: string;
|
|
83
|
+
} | null): void;
|
|
84
|
+
render(): void;
|
|
85
|
+
}
|
|
86
|
+
export declare function handleLoginKey(event: KeyEvent, ctx: LoginHandlerContext): void;
|
|
87
|
+
export {};
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key event handlers for inline UI panels.
|
|
3
|
+
*
|
|
4
|
+
* Each handler receives a context object that exposes only the state slices
|
|
5
|
+
* and callbacks it needs, keeping the handlers decoupled from App internals.
|
|
6
|
+
*/
|
|
7
|
+
import { helpCategories, keyboardShortcuts } from './components/Help.js';
|
|
8
|
+
import { spawn } from 'child_process';
|
|
9
|
+
import clipboardy from 'clipboardy';
|
|
10
|
+
export function handleInlineStatusKey(event, ctx) {
|
|
11
|
+
if (event.key === 'escape' || event.key === 'q') {
|
|
12
|
+
ctx.close();
|
|
13
|
+
ctx.render();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function handleInlineHelpKey(event, ctx) {
|
|
17
|
+
if (event.key === 'escape' || event.key === 'q') {
|
|
18
|
+
ctx.close();
|
|
19
|
+
ctx.render();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
let totalItems = 0;
|
|
23
|
+
for (const cat of helpCategories) {
|
|
24
|
+
totalItems += 1 + cat.items.length;
|
|
25
|
+
}
|
|
26
|
+
totalItems += 1 + keyboardShortcuts.length;
|
|
27
|
+
if (event.key === 'down') {
|
|
28
|
+
ctx.setScrollIndex(Math.min(ctx.scrollIndex + 1, Math.max(0, totalItems - 5)));
|
|
29
|
+
ctx.render();
|
|
30
|
+
}
|
|
31
|
+
else if (event.key === 'up') {
|
|
32
|
+
ctx.setScrollIndex(Math.max(0, ctx.scrollIndex - 1));
|
|
33
|
+
ctx.render();
|
|
34
|
+
}
|
|
35
|
+
else if (event.key === 'pagedown') {
|
|
36
|
+
ctx.setScrollIndex(Math.min(ctx.scrollIndex + 5, Math.max(0, totalItems - 5)));
|
|
37
|
+
ctx.render();
|
|
38
|
+
}
|
|
39
|
+
else if (event.key === 'pageup') {
|
|
40
|
+
ctx.setScrollIndex(Math.max(0, ctx.scrollIndex - 5));
|
|
41
|
+
ctx.render();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function handleMenuKey(event, ctx) {
|
|
45
|
+
if (event.key === 'escape') {
|
|
46
|
+
ctx.close(null, null);
|
|
47
|
+
ctx.render();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (event.key === 'up') {
|
|
51
|
+
ctx.setIndex(Math.max(0, ctx.index - 1));
|
|
52
|
+
ctx.render();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (event.key === 'down') {
|
|
56
|
+
ctx.setIndex(Math.min(ctx.items.length - 1, ctx.index + 1));
|
|
57
|
+
ctx.render();
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (event.key === 'pageup') {
|
|
61
|
+
ctx.setIndex(Math.max(0, ctx.index - 5));
|
|
62
|
+
ctx.render();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (event.key === 'pagedown') {
|
|
66
|
+
ctx.setIndex(Math.min(ctx.items.length - 1, ctx.index + 5));
|
|
67
|
+
ctx.render();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (event.key === 'enter') {
|
|
71
|
+
const selected = ctx.items[ctx.index];
|
|
72
|
+
ctx.close(null, selected);
|
|
73
|
+
ctx.render();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// ─── Permission ──────────────────────────────────────────────────────────────
|
|
77
|
+
const PERMISSION_OPTIONS = ['read', 'write', 'none'];
|
|
78
|
+
export function handleInlinePermissionKey(event, ctx) {
|
|
79
|
+
if (event.key === 'escape') {
|
|
80
|
+
ctx.close('none');
|
|
81
|
+
ctx.render();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (event.key === 'up') {
|
|
85
|
+
ctx.setIndex(Math.max(0, ctx.index - 1));
|
|
86
|
+
ctx.render();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (event.key === 'down') {
|
|
90
|
+
ctx.setIndex(Math.min(PERMISSION_OPTIONS.length - 1, ctx.index + 1));
|
|
91
|
+
ctx.render();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (event.key === 'enter') {
|
|
95
|
+
ctx.close(PERMISSION_OPTIONS[ctx.index]);
|
|
96
|
+
ctx.render();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export function handleInlineSessionPickerKey(event, ctx) {
|
|
100
|
+
if (event.key === 'n' && !ctx.deleteMode) {
|
|
101
|
+
ctx.close(null);
|
|
102
|
+
ctx.render();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (event.key === 'd' && ctx.hasDeleteCallback && ctx.items.length > 0) {
|
|
106
|
+
ctx.setDeleteMode(!ctx.deleteMode);
|
|
107
|
+
ctx.render();
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (event.key === 'escape') {
|
|
111
|
+
if (ctx.deleteMode) {
|
|
112
|
+
ctx.setDeleteMode(false);
|
|
113
|
+
ctx.render();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
ctx.close(null);
|
|
117
|
+
ctx.render();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (event.key === 'up') {
|
|
121
|
+
ctx.setIndex(Math.max(0, ctx.index - 1));
|
|
122
|
+
ctx.render();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (event.key === 'down') {
|
|
126
|
+
ctx.setIndex(Math.min(ctx.items.length - 1, ctx.index + 1));
|
|
127
|
+
ctx.render();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (event.key === 'enter' && ctx.items.length > 0) {
|
|
131
|
+
const selected = ctx.items[ctx.index];
|
|
132
|
+
if (ctx.deleteMode) {
|
|
133
|
+
ctx.onDelete(selected.name);
|
|
134
|
+
const newItems = ctx.items.filter(s => s.name !== selected.name);
|
|
135
|
+
ctx.setItems(newItems);
|
|
136
|
+
ctx.setIndex(Math.min(ctx.index, Math.max(0, newItems.length - 1)));
|
|
137
|
+
if (newItems.length === 0)
|
|
138
|
+
ctx.setDeleteMode(false);
|
|
139
|
+
ctx.notify(`Deleted: ${selected.name}`);
|
|
140
|
+
ctx.render();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
ctx.close(selected.name);
|
|
144
|
+
ctx.render();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
export function handleInlineConfirmKey(event, ctx) {
|
|
148
|
+
if (event.key === 'escape') {
|
|
149
|
+
ctx.close(false);
|
|
150
|
+
ctx.render();
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (event.key === 'left' || event.key === 'right' || event.key === 'tab') {
|
|
154
|
+
ctx.setSelection(ctx.selection === 'yes' ? 'no' : 'yes');
|
|
155
|
+
ctx.render();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (event.key === 'y') {
|
|
159
|
+
ctx.setSelection('yes');
|
|
160
|
+
ctx.render();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (event.key === 'n') {
|
|
164
|
+
ctx.setSelection('no');
|
|
165
|
+
ctx.render();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (event.key === 'enter') {
|
|
169
|
+
ctx.close(ctx.selection === 'yes');
|
|
170
|
+
ctx.render();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
export function handleLoginKey(event, ctx) {
|
|
174
|
+
if (ctx.step === 'provider') {
|
|
175
|
+
if (event.key === 'escape') {
|
|
176
|
+
ctx.close(null);
|
|
177
|
+
ctx.render();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (event.key === 'up') {
|
|
181
|
+
ctx.setProviderIndex(Math.max(0, ctx.providerIndex - 1));
|
|
182
|
+
ctx.render();
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (event.key === 'down') {
|
|
186
|
+
ctx.setProviderIndex(Math.min(ctx.providers.length - 1, ctx.providerIndex + 1));
|
|
187
|
+
ctx.render();
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (event.key === 'enter') {
|
|
191
|
+
ctx.setStep('apikey');
|
|
192
|
+
ctx.setApiKey('');
|
|
193
|
+
ctx.setError('');
|
|
194
|
+
ctx.render();
|
|
195
|
+
}
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
// apikey step
|
|
199
|
+
if (event.key === 'escape') {
|
|
200
|
+
ctx.setStep('provider');
|
|
201
|
+
ctx.setApiKey('');
|
|
202
|
+
ctx.setError('');
|
|
203
|
+
ctx.render();
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (event.key === 'enter') {
|
|
207
|
+
if (ctx.apiKey.length < 10) {
|
|
208
|
+
ctx.setError('API key too short (min 10 characters)');
|
|
209
|
+
ctx.render();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
ctx.close({ providerId: ctx.providers[ctx.providerIndex].id, apiKey: ctx.apiKey });
|
|
213
|
+
ctx.render();
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (event.key === 'backspace') {
|
|
217
|
+
ctx.setApiKey(ctx.apiKey.slice(0, -1));
|
|
218
|
+
ctx.setError('');
|
|
219
|
+
ctx.render();
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (event.ctrl && event.key === 'v') {
|
|
223
|
+
clipboardy.read().then(text => {
|
|
224
|
+
if (text) {
|
|
225
|
+
ctx.setApiKey(text.trim());
|
|
226
|
+
ctx.setError('');
|
|
227
|
+
ctx.render();
|
|
228
|
+
}
|
|
229
|
+
}).catch(() => {
|
|
230
|
+
ctx.setError('Could not read clipboard');
|
|
231
|
+
ctx.render();
|
|
232
|
+
});
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (event.ctrl && event.key === 'b') {
|
|
236
|
+
const provider = ctx.providers[ctx.providerIndex];
|
|
237
|
+
if (provider.subscribeUrl) {
|
|
238
|
+
try {
|
|
239
|
+
const cmd = process.platform === 'darwin' ? 'open'
|
|
240
|
+
: process.platform === 'win32' ? 'start'
|
|
241
|
+
: 'xdg-open';
|
|
242
|
+
const child = spawn(cmd, [provider.subscribeUrl], { detached: true, stdio: 'ignore' });
|
|
243
|
+
child.unref();
|
|
244
|
+
}
|
|
245
|
+
catch { /* ignore */ }
|
|
246
|
+
}
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
if (event.isPaste && event.key.length > 1) {
|
|
250
|
+
ctx.setApiKey(ctx.apiKey + event.key.trim());
|
|
251
|
+
ctx.setError('');
|
|
252
|
+
ctx.render();
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (event.key.length === 1 && !event.ctrl) {
|
|
256
|
+
ctx.setApiKey(ctx.apiKey + event.key);
|
|
257
|
+
ctx.setError('');
|
|
258
|
+
ctx.render();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syntax highlighting for the terminal renderer.
|
|
3
|
+
* Supports 12+ languages with One Dark theme colors.
|
|
4
|
+
*/
|
|
5
|
+
export declare const SYNTAX: {
|
|
6
|
+
keyword: string;
|
|
7
|
+
string: string;
|
|
8
|
+
number: string;
|
|
9
|
+
comment: string;
|
|
10
|
+
function: string;
|
|
11
|
+
type: string;
|
|
12
|
+
operator: string;
|
|
13
|
+
variable: string;
|
|
14
|
+
punctuation: string;
|
|
15
|
+
codeFrame: string;
|
|
16
|
+
codeLang: string;
|
|
17
|
+
};
|
|
18
|
+
export declare function highlightCode(code: string, lang: string): string;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Syntax highlighting for the terminal renderer.
|
|
3
|
+
* Supports 12+ languages with One Dark theme colors.
|
|
4
|
+
*/
|
|
5
|
+
import { fg } from './ansi.js';
|
|
6
|
+
export const SYNTAX = {
|
|
7
|
+
keyword: fg.rgb(198, 120, 221),
|
|
8
|
+
string: fg.rgb(152, 195, 121),
|
|
9
|
+
number: fg.rgb(209, 154, 102),
|
|
10
|
+
comment: fg.rgb(92, 99, 112),
|
|
11
|
+
function: fg.rgb(97, 175, 239),
|
|
12
|
+
type: fg.rgb(229, 192, 123),
|
|
13
|
+
operator: fg.rgb(86, 182, 194),
|
|
14
|
+
variable: fg.white,
|
|
15
|
+
punctuation: fg.gray,
|
|
16
|
+
codeFrame: fg.rgb(100, 105, 115),
|
|
17
|
+
codeLang: fg.rgb(150, 155, 165),
|
|
18
|
+
};
|
|
19
|
+
const KEYWORDS = {
|
|
20
|
+
js: ['const', 'let', 'var', 'function', 'return', 'if', 'else', 'for', 'while', 'do', 'switch', 'case', 'break', 'continue', 'try', 'catch', 'throw', 'finally', 'new', 'class', 'extends', 'import', 'export', 'from', 'default', 'async', 'await', 'yield', 'typeof', 'instanceof', 'in', 'of', 'delete', 'void', 'this', 'super', 'null', 'undefined', 'true', 'false', 'NaN', 'Infinity'],
|
|
21
|
+
ts: ['const', 'let', 'var', 'function', 'return', 'if', 'else', 'for', 'while', 'do', 'switch', 'case', 'break', 'continue', 'try', 'catch', 'throw', 'finally', 'new', 'class', 'extends', 'import', 'export', 'from', 'default', 'async', 'await', 'yield', 'typeof', 'instanceof', 'in', 'of', 'delete', 'void', 'this', 'super', 'null', 'undefined', 'true', 'false', 'type', 'interface', 'enum', 'namespace', 'module', 'declare', 'abstract', 'implements', 'private', 'public', 'protected', 'readonly', 'static', 'as', 'is', 'keyof', 'infer', 'never', 'unknown', 'any'],
|
|
22
|
+
py: ['def', 'class', 'return', 'if', 'elif', 'else', 'for', 'while', 'try', 'except', 'finally', 'raise', 'import', 'from', 'as', 'with', 'yield', 'lambda', 'pass', 'break', 'continue', 'and', 'or', 'not', 'in', 'is', 'None', 'True', 'False', 'global', 'nonlocal', 'assert', 'del', 'async', 'await'],
|
|
23
|
+
go: ['func', 'return', 'if', 'else', 'for', 'range', 'switch', 'case', 'break', 'continue', 'fallthrough', 'default', 'go', 'select', 'chan', 'defer', 'panic', 'recover', 'type', 'struct', 'interface', 'map', 'package', 'import', 'const', 'var', 'nil', 'true', 'false', 'iota', 'make', 'new', 'append', 'len', 'cap', 'copy', 'delete'],
|
|
24
|
+
rust: ['fn', 'let', 'mut', 'const', 'static', 'return', 'if', 'else', 'match', 'for', 'while', 'loop', 'break', 'continue', 'struct', 'enum', 'trait', 'impl', 'type', 'where', 'use', 'mod', 'pub', 'crate', 'self', 'super', 'async', 'await', 'move', 'ref', 'true', 'false', 'Some', 'None', 'Ok', 'Err', 'Self', 'dyn', 'unsafe', 'extern'],
|
|
25
|
+
sh: ['if', 'then', 'else', 'elif', 'fi', 'case', 'esac', 'for', 'while', 'until', 'do', 'done', 'in', 'function', 'return', 'local', 'export', 'readonly', 'declare', 'typeset', 'unset', 'shift', 'exit', 'break', 'continue', 'source', 'alias', 'echo', 'printf', 'read', 'test', 'true', 'false'],
|
|
26
|
+
html: ['html', 'head', 'body', 'div', 'span', 'p', 'a', 'img', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'table', 'tr', 'td', 'th', 'form', 'input', 'button', 'select', 'option', 'textarea', 'label', 'section', 'article', 'nav', 'header', 'footer', 'main', 'aside', 'meta', 'link', 'script', 'style', 'title', 'DOCTYPE'],
|
|
27
|
+
css: ['import', 'media', 'keyframes', 'font-face', 'supports', 'charset', 'namespace', 'page', 'inherit', 'initial', 'unset', 'none', 'auto', 'block', 'inline', 'flex', 'grid', 'absolute', 'relative', 'fixed', 'sticky', 'static', 'hidden', 'visible', 'solid', 'dashed', 'dotted', 'transparent', 'important'],
|
|
28
|
+
};
|
|
29
|
+
const LANG_ALIASES = {
|
|
30
|
+
javascript: 'js', typescript: 'ts', python: 'py', golang: 'go',
|
|
31
|
+
bash: 'sh', shell: 'sh', zsh: 'sh', tsx: 'ts', jsx: 'js',
|
|
32
|
+
htm: 'html', scss: 'css', sass: 'css', less: 'css',
|
|
33
|
+
};
|
|
34
|
+
export function highlightCode(code, lang) {
|
|
35
|
+
const normalizedLang = LANG_ALIASES[lang.toLowerCase()] || lang.toLowerCase();
|
|
36
|
+
const keywords = KEYWORDS[normalizedLang] || KEYWORDS['js'] || [];
|
|
37
|
+
if (normalizedLang === 'html' || normalizedLang === 'xml' || normalizedLang === 'svg') {
|
|
38
|
+
return code.replace(/(<\/?)(\w[\w-]*)((?:\s+[\w-]+(?:=(?:"[^"]*"|'[^']*'|\S+))?)*)(\s*\/?>)/g, (_match, open, tag, attrs, close) => {
|
|
39
|
+
const highlightedAttrs = attrs.replace(/([\w-]+)(=)("[^"]*"|'[^']*')/g, (_m, attr, eq, val) => SYNTAX.function + attr + '\x1b[0m' + SYNTAX.operator + eq + '\x1b[0m' + SYNTAX.string + val + '\x1b[0m');
|
|
40
|
+
return SYNTAX.punctuation + open + '\x1b[0m' + SYNTAX.keyword + tag + '\x1b[0m' + highlightedAttrs + SYNTAX.punctuation + close + '\x1b[0m';
|
|
41
|
+
}).replace(/<!--[\s\S]*?-->/g, (comment) => SYNTAX.comment + comment + '\x1b[0m');
|
|
42
|
+
}
|
|
43
|
+
if (normalizedLang === 'css') {
|
|
44
|
+
return code
|
|
45
|
+
.replace(/\/\*[\s\S]*?\*\//g, (comment) => SYNTAX.comment + comment + '\x1b[0m')
|
|
46
|
+
.replace(/([\w-]+)(\s*:\s*)([^;{}]+)/g, (_m, prop, colon, val) => SYNTAX.function + prop + '\x1b[0m' + colon + SYNTAX.string + val + '\x1b[0m')
|
|
47
|
+
.replace(/([.#]?[\w-]+(?:\s*[,>+~]\s*[.#]?[\w-]+)*)\s*\{/g, (match, selector) => SYNTAX.keyword + selector + '\x1b[0m' + ' {');
|
|
48
|
+
}
|
|
49
|
+
let result = '';
|
|
50
|
+
let i = 0;
|
|
51
|
+
while (i < code.length) {
|
|
52
|
+
if (code.slice(i, i + 2) === '//' || (normalizedLang === 'py' && code[i] === '#') ||
|
|
53
|
+
(normalizedLang === 'sh' && code[i] === '#')) {
|
|
54
|
+
let end = code.indexOf('\n', i);
|
|
55
|
+
if (end === -1)
|
|
56
|
+
end = code.length;
|
|
57
|
+
result += SYNTAX.comment + code.slice(i, end) + '\x1b[0m';
|
|
58
|
+
i = end;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (code.slice(i, i + 2) === '/*') {
|
|
62
|
+
let end = code.indexOf('*/', i + 2);
|
|
63
|
+
if (end === -1)
|
|
64
|
+
end = code.length;
|
|
65
|
+
else
|
|
66
|
+
end += 2;
|
|
67
|
+
result += SYNTAX.comment + code.slice(i, end) + '\x1b[0m';
|
|
68
|
+
i = end;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (code[i] === '"' || code[i] === "'" || code[i] === '`') {
|
|
72
|
+
const quote = code[i];
|
|
73
|
+
let end = i + 1;
|
|
74
|
+
while (end < code.length) {
|
|
75
|
+
if (code[end] === '\\') {
|
|
76
|
+
end += 2;
|
|
77
|
+
}
|
|
78
|
+
else if (code[end] === quote) {
|
|
79
|
+
end++;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
end++;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
result += SYNTAX.string + code.slice(i, end) + '\x1b[0m';
|
|
87
|
+
i = end;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const numMatch = code.slice(i).match(/^(0x[0-9a-fA-F]+|0b[01]+|0o[0-7]+|\d+\.?\d*(?:e[+-]?\d+)?)/);
|
|
91
|
+
if (numMatch && (i === 0 || !/[a-zA-Z_]/.test(code[i - 1]))) {
|
|
92
|
+
result += SYNTAX.number + numMatch[1] + '\x1b[0m';
|
|
93
|
+
i += numMatch[1].length;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const identMatch = code.slice(i).match(/^[a-zA-Z_][a-zA-Z0-9_]*/);
|
|
97
|
+
if (identMatch) {
|
|
98
|
+
const ident = identMatch[0];
|
|
99
|
+
const nextChar = code[i + ident.length];
|
|
100
|
+
if (keywords.includes(ident)) {
|
|
101
|
+
result += SYNTAX.keyword + ident + '\x1b[0m';
|
|
102
|
+
}
|
|
103
|
+
else if (nextChar === '(') {
|
|
104
|
+
result += SYNTAX.function + ident + '\x1b[0m';
|
|
105
|
+
}
|
|
106
|
+
else if (/^[A-Z]/.test(ident)) {
|
|
107
|
+
result += SYNTAX.type + ident + '\x1b[0m';
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
result += ident;
|
|
111
|
+
}
|
|
112
|
+
i += ident.length;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const opMatch = code.slice(i).match(/^(===|!==|==|!=|<=|>=|=>|->|\+\+|--|&&|\|\||<<|>>|\+=|-=|\*=|\/=|[+\-*/%=<>!&|^~?:])/);
|
|
116
|
+
if (opMatch) {
|
|
117
|
+
result += SYNTAX.operator + opMatch[1] + '\x1b[0m';
|
|
118
|
+
i += opMatch[1].length;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if ('{}[]();,.'.includes(code[i])) {
|
|
122
|
+
result += SYNTAX.punctuation + code[i] + '\x1b[0m';
|
|
123
|
+
i++;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
result += code[i];
|
|
127
|
+
i++;
|
|
128
|
+
}
|
|
129
|
+
return result;
|
|
130
|
+
}
|
package/dist/renderer/main.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Codeep
|
|
4
|
-
*
|
|
3
|
+
* Codeep — entry point.
|
|
4
|
+
*
|
|
5
|
+
* This file contains only startup/init logic. Command dispatch lives in
|
|
6
|
+
* commands.ts and agent execution in agentExecution.ts.
|
|
5
7
|
*/
|
|
6
8
|
export {};
|