acmecode 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/.acmecode/config.json +6 -0
- package/README.md +124 -0
- package/dist/agent/index.js +161 -0
- package/dist/cli/bin/acmecode.js +3 -0
- package/dist/cli/package.json +25 -0
- package/dist/cli/src/index.d.ts +1 -0
- package/dist/cli/src/index.js +53 -0
- package/dist/config/index.js +92 -0
- package/dist/context/index.js +30 -0
- package/dist/core/src/agent/index.d.ts +52 -0
- package/dist/core/src/agent/index.js +476 -0
- package/dist/core/src/config/index.d.ts +83 -0
- package/dist/core/src/config/index.js +318 -0
- package/dist/core/src/context/index.d.ts +1 -0
- package/dist/core/src/context/index.js +30 -0
- package/dist/core/src/llm/provider.d.ts +27 -0
- package/dist/core/src/llm/provider.js +202 -0
- package/dist/core/src/llm/vision.d.ts +7 -0
- package/dist/core/src/llm/vision.js +37 -0
- package/dist/core/src/mcp/index.d.ts +10 -0
- package/dist/core/src/mcp/index.js +84 -0
- package/dist/core/src/prompt/anthropic.d.ts +1 -0
- package/dist/core/src/prompt/anthropic.js +32 -0
- package/dist/core/src/prompt/architect.d.ts +1 -0
- package/dist/core/src/prompt/architect.js +17 -0
- package/dist/core/src/prompt/autopilot.d.ts +1 -0
- package/dist/core/src/prompt/autopilot.js +18 -0
- package/dist/core/src/prompt/beast.d.ts +1 -0
- package/dist/core/src/prompt/beast.js +83 -0
- package/dist/core/src/prompt/gemini.d.ts +1 -0
- package/dist/core/src/prompt/gemini.js +45 -0
- package/dist/core/src/prompt/index.d.ts +18 -0
- package/dist/core/src/prompt/index.js +239 -0
- package/dist/core/src/prompt/zen.d.ts +1 -0
- package/dist/core/src/prompt/zen.js +13 -0
- package/dist/core/src/session/index.d.ts +18 -0
- package/dist/core/src/session/index.js +97 -0
- package/dist/core/src/skills/index.d.ts +6 -0
- package/dist/core/src/skills/index.js +72 -0
- package/dist/core/src/tools/batch.d.ts +2 -0
- package/dist/core/src/tools/batch.js +65 -0
- package/dist/core/src/tools/browser.d.ts +7 -0
- package/dist/core/src/tools/browser.js +86 -0
- package/dist/core/src/tools/edit.d.ts +11 -0
- package/dist/core/src/tools/edit.js +312 -0
- package/dist/core/src/tools/index.d.ts +13 -0
- package/dist/core/src/tools/index.js +980 -0
- package/dist/core/src/tools/lsp-client.d.ts +11 -0
- package/dist/core/src/tools/lsp-client.js +224 -0
- package/dist/index.js +41 -0
- package/dist/llm/provider.js +34 -0
- package/dist/mcp/index.js +84 -0
- package/dist/session/index.js +74 -0
- package/dist/skills/index.js +32 -0
- package/dist/tools/index.js +96 -0
- package/dist/tui/App.js +297 -0
- package/dist/tui/Spinner.js +16 -0
- package/dist/tui/TextInput.js +98 -0
- package/dist/tui/src/App.d.ts +11 -0
- package/dist/tui/src/App.js +1211 -0
- package/dist/tui/src/CatLogo.d.ts +10 -0
- package/dist/tui/src/CatLogo.js +99 -0
- package/dist/tui/src/OptionList.d.ts +15 -0
- package/dist/tui/src/OptionList.js +60 -0
- package/dist/tui/src/Spinner.d.ts +7 -0
- package/dist/tui/src/Spinner.js +18 -0
- package/dist/tui/src/TextInput.d.ts +28 -0
- package/dist/tui/src/TextInput.js +139 -0
- package/dist/tui/src/Tips.d.ts +2 -0
- package/dist/tui/src/Tips.js +62 -0
- package/dist/tui/src/Toast.d.ts +19 -0
- package/dist/tui/src/Toast.js +39 -0
- package/dist/tui/src/TodoItem.d.ts +7 -0
- package/dist/tui/src/TodoItem.js +21 -0
- package/dist/tui/src/i18n.d.ts +172 -0
- package/dist/tui/src/i18n.js +189 -0
- package/dist/tui/src/markdown.d.ts +6 -0
- package/dist/tui/src/markdown.js +356 -0
- package/dist/tui/src/theme.d.ts +31 -0
- package/dist/tui/src/theme.js +239 -0
- package/output.txt +0 -0
- package/package.json +44 -0
- package/packages/cli/package.json +25 -0
- package/packages/cli/src/index.ts +59 -0
- package/packages/cli/tsconfig.json +26 -0
- package/packages/core/package.json +39 -0
- package/packages/core/src/agent/index.ts +588 -0
- package/packages/core/src/config/index.ts +383 -0
- package/packages/core/src/context/index.ts +34 -0
- package/packages/core/src/llm/provider.ts +237 -0
- package/packages/core/src/llm/vision.ts +43 -0
- package/packages/core/src/mcp/index.ts +110 -0
- package/packages/core/src/prompt/anthropic.ts +32 -0
- package/packages/core/src/prompt/architect.ts +17 -0
- package/packages/core/src/prompt/autopilot.ts +18 -0
- package/packages/core/src/prompt/beast.ts +83 -0
- package/packages/core/src/prompt/gemini.ts +45 -0
- package/packages/core/src/prompt/index.ts +267 -0
- package/packages/core/src/prompt/zen.ts +13 -0
- package/packages/core/src/session/index.ts +129 -0
- package/packages/core/src/skills/index.ts +86 -0
- package/packages/core/src/tools/batch.ts +73 -0
- package/packages/core/src/tools/browser.ts +95 -0
- package/packages/core/src/tools/edit.ts +317 -0
- package/packages/core/src/tools/index.ts +1112 -0
- package/packages/core/src/tools/lsp-client.ts +303 -0
- package/packages/core/tsconfig.json +19 -0
- package/packages/tui/package.json +24 -0
- package/packages/tui/src/App.tsx +1702 -0
- package/packages/tui/src/CatLogo.tsx +134 -0
- package/packages/tui/src/OptionList.tsx +95 -0
- package/packages/tui/src/Spinner.tsx +28 -0
- package/packages/tui/src/TextInput.tsx +202 -0
- package/packages/tui/src/Tips.tsx +64 -0
- package/packages/tui/src/Toast.tsx +60 -0
- package/packages/tui/src/TodoItem.tsx +29 -0
- package/packages/tui/src/i18n.ts +203 -0
- package/packages/tui/src/markdown.ts +403 -0
- package/packages/tui/src/theme.ts +287 -0
- package/packages/tui/tsconfig.json +24 -0
- package/tsconfig.json +18 -0
- package/vscode-acmecode/.vscodeignore +11 -0
- package/vscode-acmecode/README.md +57 -0
- package/vscode-acmecode/esbuild.js +46 -0
- package/vscode-acmecode/images/button-dark.svg +5 -0
- package/vscode-acmecode/images/button-light.svg +5 -0
- package/vscode-acmecode/images/icon.png +1 -0
- package/vscode-acmecode/package-lock.json +490 -0
- package/vscode-acmecode/package.json +87 -0
- package/vscode-acmecode/src/extension.ts +128 -0
- package/vscode-acmecode/tsconfig.json +16 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import { theme } from "./theme.js";
|
|
2
|
+
import pc from "picocolors"; // Keep pc for some low-level things if needed, but primarily use theme
|
|
3
|
+
/**
|
|
4
|
+
* Lightweight terminal markdown renderer.
|
|
5
|
+
* Converts common markdown syntax to ANSI-styled text for terminal display.
|
|
6
|
+
* Handles: headers, bold, italic, inline code, code blocks, lists, checkboxes, horizontal rules.
|
|
7
|
+
*/
|
|
8
|
+
export function renderMarkdown(input) {
|
|
9
|
+
const lines = input.split("\n");
|
|
10
|
+
const result = [];
|
|
11
|
+
let inCodeBlock = false;
|
|
12
|
+
let codeBlockLang = "";
|
|
13
|
+
let codeBuffer = [];
|
|
14
|
+
for (let i = 0; i < lines.length; i++) {
|
|
15
|
+
const line = lines[i];
|
|
16
|
+
// ── Code block toggle ──
|
|
17
|
+
if (line.trimStart().startsWith("```")) {
|
|
18
|
+
if (!inCodeBlock) {
|
|
19
|
+
inCodeBlock = true;
|
|
20
|
+
codeBlockLang = line.trimStart().slice(3).trim();
|
|
21
|
+
codeBuffer = [];
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
// End code block — render it
|
|
26
|
+
inCodeBlock = false;
|
|
27
|
+
if (codeBlockLang === "diff" || codeBlockLang === "patch") {
|
|
28
|
+
// Diff-specific rendering — colored lines, no box border
|
|
29
|
+
for (const codeLine of codeBuffer) {
|
|
30
|
+
result.push(renderDiffLine(codeLine));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const header = codeBlockLang
|
|
35
|
+
? theme.muted(`┌─ ${codeBlockLang} ${"─".repeat(Math.max(0, 36 - codeBlockLang.length))}`)
|
|
36
|
+
: theme.muted(`┌${"─".repeat(40)}`);
|
|
37
|
+
const footer = theme.muted(`└${"─".repeat(40)}`);
|
|
38
|
+
result.push(header);
|
|
39
|
+
for (const codeLine of codeBuffer) {
|
|
40
|
+
result.push(theme.muted("│ ") + highlightCode(codeLine, codeBlockLang));
|
|
41
|
+
}
|
|
42
|
+
result.push(footer);
|
|
43
|
+
}
|
|
44
|
+
codeBlockLang = "";
|
|
45
|
+
codeBuffer = [];
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (inCodeBlock) {
|
|
50
|
+
codeBuffer.push(line);
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
// ── Horizontal rule ──
|
|
54
|
+
if (/^(\s*[-*_]){3,}\s*$/.test(line)) {
|
|
55
|
+
result.push(theme.muted("─".repeat(40)));
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// ── Headers ──
|
|
59
|
+
const h1Match = line.match(/^# (.+)/);
|
|
60
|
+
if (h1Match) {
|
|
61
|
+
result.push("");
|
|
62
|
+
result.push(theme.highlight(theme.primary(`█ ${h1Match[1]}`)));
|
|
63
|
+
result.push(theme.muted("─".repeat(Math.min(40, (h1Match[1]?.length || 0) + 4))));
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const h2Match = line.match(/^## (.+)/);
|
|
67
|
+
if (h2Match) {
|
|
68
|
+
result.push("");
|
|
69
|
+
result.push(theme.highlight(theme.info(`▌ ${h2Match[1]}`)));
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const h3Match = line.match(/^### (.+)/);
|
|
73
|
+
if (h3Match) {
|
|
74
|
+
result.push(theme.highlight(theme.secondary(` ▸ ${h3Match[1]}`)));
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const h4Match = line.match(/^#### (.+)/);
|
|
78
|
+
if (h4Match) {
|
|
79
|
+
result.push(theme.highlight(` ${h4Match[1]}`));
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
// ── Checkbox lists ──
|
|
83
|
+
const checkMatch = line.match(/^(\s*)- \[([ xX])\] (.+)/);
|
|
84
|
+
if (checkMatch) {
|
|
85
|
+
const indent = checkMatch[1] || "";
|
|
86
|
+
const checked = checkMatch[2].toLowerCase() === "x";
|
|
87
|
+
const text = formatInline(checkMatch[3]);
|
|
88
|
+
const icon = checked ? theme.success("✔") : theme.muted("○");
|
|
89
|
+
result.push(`${indent} ${icon} ${checked ? theme.muted(pc.strikethrough(text)) : text}`);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
// ── Unordered lists ──
|
|
93
|
+
const ulMatch = line.match(/^(\s*)[-*] (.+)/);
|
|
94
|
+
if (ulMatch) {
|
|
95
|
+
const indent = ulMatch[1] || "";
|
|
96
|
+
const text = formatInline(ulMatch[2]);
|
|
97
|
+
result.push(`${indent} ${theme.primary("•")} ${text}`);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
// ── Ordered lists ──
|
|
101
|
+
const olMatch = line.match(/^(\s*)(\d+)\. (.+)/);
|
|
102
|
+
if (olMatch) {
|
|
103
|
+
const indent = olMatch[1] || "";
|
|
104
|
+
const num = olMatch[2];
|
|
105
|
+
const text = formatInline(olMatch[3]);
|
|
106
|
+
result.push(`${indent} ${theme.primary(num + ".")} ${text}`);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
// ── Blockquotes ──
|
|
110
|
+
const bqMatch = line.match(/^>\s?(.*)/);
|
|
111
|
+
if (bqMatch) {
|
|
112
|
+
result.push(` ${theme.muted("│")} ${theme.muted(pc.italic(bqMatch[1] || ""))}`);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
// ── Regular text with inline formatting ──
|
|
116
|
+
result.push(formatInline(line));
|
|
117
|
+
}
|
|
118
|
+
// Handle unclosed code block
|
|
119
|
+
if (inCodeBlock && codeBuffer.length > 0) {
|
|
120
|
+
result.push(theme.muted(`┌${"─".repeat(40)}`));
|
|
121
|
+
for (const codeLine of codeBuffer) {
|
|
122
|
+
result.push(theme.muted("│ ") + highlightCode(codeLine, codeBlockLang));
|
|
123
|
+
}
|
|
124
|
+
result.push(theme.muted(`└${"─".repeat(40)}`));
|
|
125
|
+
}
|
|
126
|
+
return result.join("\n");
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Format inline markdown: bold, italic, inline code, strikethrough, links
|
|
130
|
+
*/
|
|
131
|
+
function formatInline(text) {
|
|
132
|
+
// Inline code (must be first to prevent inner formatting)
|
|
133
|
+
text = text.replace(/`([^`]+)`/g, (_, code) => theme.warning(pc.bgBlack(` ${code} `)));
|
|
134
|
+
// Bold + italic
|
|
135
|
+
text = text.replace(/\*\*\*(.+?)\*\*\*/g, (_, t) => theme.highlight(pc.italic(t)));
|
|
136
|
+
// Bold
|
|
137
|
+
text = text.replace(/\*\*(.+?)\*\*/g, (_, t) => theme.highlight(t));
|
|
138
|
+
// Italic
|
|
139
|
+
text = text.replace(/\*(.+?)\*/g, (_, t) => pc.italic(t));
|
|
140
|
+
text = text.replace(/_(.+?)_/g, (_, t) => pc.italic(t));
|
|
141
|
+
// Strikethrough
|
|
142
|
+
text = text.replace(/~~(.+?)~~/g, (_, t) => theme.muted(pc.strikethrough(t)));
|
|
143
|
+
// Links [text](url) → text (url)
|
|
144
|
+
text = text.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, label, url) => `${pc.underline(theme.info(label))} ${theme.muted(`(${url})`)}`);
|
|
145
|
+
return text;
|
|
146
|
+
}
|
|
147
|
+
// ── Syntax highlighting keywords ──
|
|
148
|
+
const KEYWORDS = new Set([
|
|
149
|
+
// JS/TS
|
|
150
|
+
"const",
|
|
151
|
+
"let",
|
|
152
|
+
"var",
|
|
153
|
+
"function",
|
|
154
|
+
"return",
|
|
155
|
+
"if",
|
|
156
|
+
"else",
|
|
157
|
+
"for",
|
|
158
|
+
"while",
|
|
159
|
+
"do",
|
|
160
|
+
"switch",
|
|
161
|
+
"case",
|
|
162
|
+
"break",
|
|
163
|
+
"continue",
|
|
164
|
+
"new",
|
|
165
|
+
"this",
|
|
166
|
+
"class",
|
|
167
|
+
"extends",
|
|
168
|
+
"super",
|
|
169
|
+
"import",
|
|
170
|
+
"export",
|
|
171
|
+
"from",
|
|
172
|
+
"default",
|
|
173
|
+
"async",
|
|
174
|
+
"await",
|
|
175
|
+
"try",
|
|
176
|
+
"catch",
|
|
177
|
+
"finally",
|
|
178
|
+
"throw",
|
|
179
|
+
"typeof",
|
|
180
|
+
"instanceof",
|
|
181
|
+
"in",
|
|
182
|
+
"of",
|
|
183
|
+
"yield",
|
|
184
|
+
"delete",
|
|
185
|
+
"void",
|
|
186
|
+
// Python
|
|
187
|
+
"def",
|
|
188
|
+
"lambda",
|
|
189
|
+
"pass",
|
|
190
|
+
"raise",
|
|
191
|
+
"with",
|
|
192
|
+
"as",
|
|
193
|
+
"global",
|
|
194
|
+
"nonlocal",
|
|
195
|
+
"assert",
|
|
196
|
+
"elif",
|
|
197
|
+
"except",
|
|
198
|
+
"is",
|
|
199
|
+
"not",
|
|
200
|
+
"and",
|
|
201
|
+
"or",
|
|
202
|
+
"True",
|
|
203
|
+
"False",
|
|
204
|
+
"None",
|
|
205
|
+
"print",
|
|
206
|
+
// Common
|
|
207
|
+
"true",
|
|
208
|
+
"false",
|
|
209
|
+
"null",
|
|
210
|
+
"undefined",
|
|
211
|
+
"nil",
|
|
212
|
+
]);
|
|
213
|
+
const TYPES = new Set([
|
|
214
|
+
"string",
|
|
215
|
+
"number",
|
|
216
|
+
"boolean",
|
|
217
|
+
"object",
|
|
218
|
+
"any",
|
|
219
|
+
"void",
|
|
220
|
+
"never",
|
|
221
|
+
"unknown",
|
|
222
|
+
"int",
|
|
223
|
+
"float",
|
|
224
|
+
"double",
|
|
225
|
+
"char",
|
|
226
|
+
"long",
|
|
227
|
+
"short",
|
|
228
|
+
"byte",
|
|
229
|
+
"bool",
|
|
230
|
+
"String",
|
|
231
|
+
"Number",
|
|
232
|
+
"Boolean",
|
|
233
|
+
"Array",
|
|
234
|
+
"Object",
|
|
235
|
+
"Map",
|
|
236
|
+
"Set",
|
|
237
|
+
"Promise",
|
|
238
|
+
"Record",
|
|
239
|
+
"Partial",
|
|
240
|
+
"Required",
|
|
241
|
+
"Readonly",
|
|
242
|
+
"interface",
|
|
243
|
+
"type",
|
|
244
|
+
"enum",
|
|
245
|
+
"struct",
|
|
246
|
+
"impl",
|
|
247
|
+
"trait",
|
|
248
|
+
"pub",
|
|
249
|
+
"fn",
|
|
250
|
+
"mod",
|
|
251
|
+
"use",
|
|
252
|
+
"crate",
|
|
253
|
+
]);
|
|
254
|
+
/**
|
|
255
|
+
* Simple token-based syntax highlighter for code blocks.
|
|
256
|
+
*/
|
|
257
|
+
function highlightCode(line, _lang) {
|
|
258
|
+
// Line-level comment detection
|
|
259
|
+
const trimmed = line.trimStart();
|
|
260
|
+
if (trimmed.startsWith("//") ||
|
|
261
|
+
trimmed.startsWith("#") ||
|
|
262
|
+
trimmed.startsWith("--")) {
|
|
263
|
+
return theme.muted(pc.italic(line));
|
|
264
|
+
}
|
|
265
|
+
let result = "";
|
|
266
|
+
let i = 0;
|
|
267
|
+
while (i < line.length) {
|
|
268
|
+
const ch = line[i];
|
|
269
|
+
// ── String literals ──
|
|
270
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
271
|
+
const quote = ch;
|
|
272
|
+
let end = i + 1;
|
|
273
|
+
while (end < line.length && line[end] !== quote) {
|
|
274
|
+
if (line[end] === "\\")
|
|
275
|
+
end++; // skip escaped
|
|
276
|
+
end++;
|
|
277
|
+
}
|
|
278
|
+
end = Math.min(end + 1, line.length);
|
|
279
|
+
result += theme.success(line.slice(i, end));
|
|
280
|
+
i = end;
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
// ── Numbers ──
|
|
284
|
+
if (/\d/.test(ch) &&
|
|
285
|
+
(i === 0 || /[\s(,=:+\-*/<>[\]{}!&|^~%]/.test(line[i - 1] || " "))) {
|
|
286
|
+
let end = i;
|
|
287
|
+
while (end < line.length && /[\d.xXa-fA-FeEoObB_]/.test(line[end]))
|
|
288
|
+
end++;
|
|
289
|
+
result += theme.warning(line.slice(i, end));
|
|
290
|
+
i = end;
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
// ── Words (keywords/types/identifiers) ──
|
|
294
|
+
if (/[a-zA-Z_$@]/.test(ch)) {
|
|
295
|
+
let end = i;
|
|
296
|
+
while (end < line.length && /[a-zA-Z0-9_$]/.test(line[end]))
|
|
297
|
+
end++;
|
|
298
|
+
const word = line.slice(i, end);
|
|
299
|
+
if (KEYWORDS.has(word)) {
|
|
300
|
+
result += theme.secondary(word);
|
|
301
|
+
}
|
|
302
|
+
else if (TYPES.has(word)) {
|
|
303
|
+
result += theme.primary(word);
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
result += word;
|
|
307
|
+
}
|
|
308
|
+
i = end;
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
// ── Operators/punctuation ──
|
|
312
|
+
if (/[(){}[\];,.<>+\-*/%=!&|^~?:]/.test(ch)) {
|
|
313
|
+
result += theme.muted(ch);
|
|
314
|
+
i++;
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
result += ch;
|
|
318
|
+
i++;
|
|
319
|
+
}
|
|
320
|
+
return result;
|
|
321
|
+
}
|
|
322
|
+
// ANSI truecolor background helpers (terminals supporting 24-bit color)
|
|
323
|
+
function bgRgb(r, g, b, text) {
|
|
324
|
+
return `\x1b[48;2;${r};${g};${b}m${text}\x1b[49m`;
|
|
325
|
+
}
|
|
326
|
+
// Diff background colors — matching opencode's diffAddedBg / diffRemovedBg
|
|
327
|
+
const DIFF_ADDED_BG = (t) => bgRgb(32, 48, 59, t); // #20303b deep teal-green
|
|
328
|
+
const DIFF_REMOVED_BG = (t) => bgRgb(55, 34, 44, t); // #37222c deep rose-red
|
|
329
|
+
/**
|
|
330
|
+
* Render a single line of a unified diff with appropriate colors.
|
|
331
|
+
* + added lines → green fg + deep green bg
|
|
332
|
+
* - removed lines → red fg + deep red bg
|
|
333
|
+
* @@ hunk headers → cyan
|
|
334
|
+
* --- / +++ file headers → bold dim
|
|
335
|
+
* context lines → dim
|
|
336
|
+
*/
|
|
337
|
+
function renderDiffLine(line) {
|
|
338
|
+
if (line.startsWith("+++") || line.startsWith("---")) {
|
|
339
|
+
return theme.muted(theme.highlight(line));
|
|
340
|
+
}
|
|
341
|
+
if (line.startsWith("@@")) {
|
|
342
|
+
const match = line.match(/^(@@ .+? @@)(.*)/);
|
|
343
|
+
if (match) {
|
|
344
|
+
return theme.info(match[1]) + theme.muted(match[2] || "");
|
|
345
|
+
}
|
|
346
|
+
return theme.info(line);
|
|
347
|
+
}
|
|
348
|
+
if (line.startsWith("+")) {
|
|
349
|
+
return DIFF_ADDED_BG(theme.success(line));
|
|
350
|
+
}
|
|
351
|
+
if (line.startsWith("-")) {
|
|
352
|
+
return DIFF_REMOVED_BG(theme.danger(line));
|
|
353
|
+
}
|
|
354
|
+
// Context line
|
|
355
|
+
return theme.muted(line);
|
|
356
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface ThemeColors {
|
|
2
|
+
primary: (text: string) => string;
|
|
3
|
+
secondary: (text: string) => string;
|
|
4
|
+
muted: (text: string) => string;
|
|
5
|
+
success: (text: string) => string;
|
|
6
|
+
danger: (text: string) => string;
|
|
7
|
+
warning: (text: string) => string;
|
|
8
|
+
info: (text: string) => string;
|
|
9
|
+
highlight: (text: string) => string;
|
|
10
|
+
border: string;
|
|
11
|
+
borderDim: string;
|
|
12
|
+
logo: string;
|
|
13
|
+
/** Hex color for the header card background */
|
|
14
|
+
bgHeader: string;
|
|
15
|
+
/** Hex color for the input card background */
|
|
16
|
+
bgInput: string;
|
|
17
|
+
/** Hex color for the accent bar on the left of the input */
|
|
18
|
+
accentIdle: string;
|
|
19
|
+
/** Hex color for the accent bar when generating */
|
|
20
|
+
accentBusy: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function getTheme(): ThemeColors;
|
|
23
|
+
export declare function setTheme(name: string): boolean;
|
|
24
|
+
export declare function onThemeChange(listener: (name: string) => void): void;
|
|
25
|
+
export declare function getThemeName(): string;
|
|
26
|
+
export declare function listThemes(): string[];
|
|
27
|
+
export declare const theme: ThemeColors;
|
|
28
|
+
export declare function formatToolIcon(toolName: string): string;
|
|
29
|
+
export declare function formatToolName(toolName: string): string;
|
|
30
|
+
export declare function formatBorder(width: number, char?: string): string;
|
|
31
|
+
export declare function formatKeyHint(key: string, label: string): string;
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import pc from "picocolors";
|
|
2
|
+
import { t } from "./i18n.js";
|
|
3
|
+
import { loadThemeConfig, saveGlobalThemeConfig, } from "@acmecode/core/config/index.js";
|
|
4
|
+
// Helper: ANSI 256-color foreground
|
|
5
|
+
const c256 = (n) => (text) => `\x1b[38;5;${n}m${text}\x1b[0m`;
|
|
6
|
+
// ── Built-in Themes ──
|
|
7
|
+
const themes = {
|
|
8
|
+
dark: {
|
|
9
|
+
primary: pc.cyan,
|
|
10
|
+
secondary: pc.magenta,
|
|
11
|
+
muted: pc.gray,
|
|
12
|
+
success: pc.green,
|
|
13
|
+
danger: pc.red,
|
|
14
|
+
warning: pc.yellow,
|
|
15
|
+
info: pc.blue,
|
|
16
|
+
highlight: pc.bold,
|
|
17
|
+
border: "─",
|
|
18
|
+
borderDim: "┄",
|
|
19
|
+
logo: `${pc.cyan(pc.bold("AcmeCode"))} ${pc.gray("v1.0")}`,
|
|
20
|
+
bgHeader: "#141414",
|
|
21
|
+
bgInput: "#1e1e1e",
|
|
22
|
+
accentIdle: "cyan",
|
|
23
|
+
accentBusy: "yellow",
|
|
24
|
+
},
|
|
25
|
+
dracula: {
|
|
26
|
+
primary: c256(141), // purple
|
|
27
|
+
secondary: c256(212), // pink
|
|
28
|
+
muted: c256(103), // comment gray
|
|
29
|
+
success: c256(84), // green
|
|
30
|
+
danger: c256(203), // red
|
|
31
|
+
warning: c256(228), // yellow
|
|
32
|
+
info: c256(117), // cyan
|
|
33
|
+
highlight: pc.bold,
|
|
34
|
+
border: "─",
|
|
35
|
+
borderDim: "┄",
|
|
36
|
+
logo: `\x1b[38;5;141m\x1b[1mAcmeCode\x1b[0m \x1b[38;5;103mv1.0\x1b[0m`,
|
|
37
|
+
bgHeader: "#21222c",
|
|
38
|
+
bgInput: "#282a36",
|
|
39
|
+
accentIdle: "#bd93f9",
|
|
40
|
+
accentBusy: "#ffb86c",
|
|
41
|
+
},
|
|
42
|
+
tokyonight: {
|
|
43
|
+
primary: c256(111), // blue
|
|
44
|
+
secondary: c256(176), // magenta
|
|
45
|
+
muted: c256(60), // dark comment
|
|
46
|
+
success: c256(115), // green
|
|
47
|
+
danger: c256(210), // red
|
|
48
|
+
warning: c256(222), // yellow
|
|
49
|
+
info: c256(81), // cyan
|
|
50
|
+
highlight: pc.bold,
|
|
51
|
+
border: "─",
|
|
52
|
+
borderDim: "┄",
|
|
53
|
+
logo: `\x1b[38;5;111m\x1b[1mAcmeCode\x1b[0m \x1b[38;5;60mv1.0\x1b[0m`,
|
|
54
|
+
bgHeader: "#16161e",
|
|
55
|
+
bgInput: "#1a1b26",
|
|
56
|
+
accentIdle: "#7aa2f7",
|
|
57
|
+
accentBusy: "#e0af68",
|
|
58
|
+
},
|
|
59
|
+
nord: {
|
|
60
|
+
primary: c256(110), // frost blue
|
|
61
|
+
secondary: c256(139), // purple
|
|
62
|
+
muted: c256(59), // polar night
|
|
63
|
+
success: c256(108), // aurora green
|
|
64
|
+
danger: c256(174), // aurora red
|
|
65
|
+
warning: c256(179), // aurora yellow
|
|
66
|
+
info: c256(67), // frost darker
|
|
67
|
+
highlight: pc.bold,
|
|
68
|
+
border: "─",
|
|
69
|
+
borderDim: "┄",
|
|
70
|
+
logo: `\x1b[38;5;110m\x1b[1mAcmeCode\x1b[0m \x1b[38;5;59mv1.0\x1b[0m`,
|
|
71
|
+
bgHeader: "#2e3440",
|
|
72
|
+
bgInput: "#3b4252",
|
|
73
|
+
accentIdle: "#88c0d0",
|
|
74
|
+
accentBusy: "#ebcb8b",
|
|
75
|
+
},
|
|
76
|
+
catppuccin: {
|
|
77
|
+
primary: c256(183), // lavender
|
|
78
|
+
secondary: c256(211), // pink
|
|
79
|
+
muted: c256(244), // overlay
|
|
80
|
+
success: c256(120), // green
|
|
81
|
+
danger: c256(210), // red
|
|
82
|
+
warning: c256(223), // peach
|
|
83
|
+
info: c256(152), // teal
|
|
84
|
+
highlight: pc.bold,
|
|
85
|
+
border: "─",
|
|
86
|
+
borderDim: "┄",
|
|
87
|
+
logo: `\x1b[38;5;183m\x1b[1mAcmeCode\x1b[0m \x1b[38;5;244mv1.0\x1b[0m`,
|
|
88
|
+
bgHeader: "#1e1e2e",
|
|
89
|
+
bgInput: "#24273a",
|
|
90
|
+
accentIdle: "#cba6f7",
|
|
91
|
+
accentBusy: "#fab387",
|
|
92
|
+
},
|
|
93
|
+
monokai: {
|
|
94
|
+
primary: c256(81), // cyan
|
|
95
|
+
secondary: c256(148), // green
|
|
96
|
+
muted: c256(242), // comment
|
|
97
|
+
success: c256(148), // green
|
|
98
|
+
danger: c256(204), // pink/red
|
|
99
|
+
warning: c256(186), // yellow
|
|
100
|
+
info: c256(141), // purple
|
|
101
|
+
highlight: pc.bold,
|
|
102
|
+
border: "─",
|
|
103
|
+
borderDim: "┄",
|
|
104
|
+
logo: `\x1b[38;5;81m\x1b[1mAcmeCode\x1b[0m \x1b[38;5;242mv1.0\x1b[0m`,
|
|
105
|
+
bgHeader: "#1e1e1e",
|
|
106
|
+
bgInput: "#272822",
|
|
107
|
+
accentIdle: "#66d9e8",
|
|
108
|
+
accentBusy: "#e6db74",
|
|
109
|
+
},
|
|
110
|
+
gruvbox: {
|
|
111
|
+
primary: c256(214), // orange
|
|
112
|
+
secondary: c256(108), // aqua
|
|
113
|
+
muted: c256(243), // gray
|
|
114
|
+
success: c256(142), // green
|
|
115
|
+
danger: c256(167), // red
|
|
116
|
+
warning: c256(214), // orange
|
|
117
|
+
info: c256(108), // aqua
|
|
118
|
+
highlight: pc.bold,
|
|
119
|
+
border: "─",
|
|
120
|
+
borderDim: "┄",
|
|
121
|
+
logo: `\x1b[38;5;214m\x1b[1mAcmeCode\x1b[0m \x1b[38;5;243mv1.0\x1b[0m`,
|
|
122
|
+
bgHeader: "#1d2021",
|
|
123
|
+
bgInput: "#282828",
|
|
124
|
+
accentIdle: "#fabd2f",
|
|
125
|
+
accentBusy: "#fe8019",
|
|
126
|
+
},
|
|
127
|
+
everforest: {
|
|
128
|
+
primary: c256(108), // green
|
|
129
|
+
secondary: c256(175), // purple
|
|
130
|
+
muted: c256(243), // gray
|
|
131
|
+
success: c256(142), // green
|
|
132
|
+
danger: c256(167), // red
|
|
133
|
+
warning: c256(214), // yellow
|
|
134
|
+
info: c256(109), // blue
|
|
135
|
+
highlight: pc.bold,
|
|
136
|
+
border: "─",
|
|
137
|
+
borderDim: "┄",
|
|
138
|
+
logo: `\x1b[38;5;108m\x1b[1mAcmeCode\x1b[0m \x1b[38;5;243mv1.0\x1b[0m`,
|
|
139
|
+
bgHeader: "#1e2326",
|
|
140
|
+
bgInput: "#272e33",
|
|
141
|
+
accentIdle: "#a7c080",
|
|
142
|
+
accentBusy: "#e69875",
|
|
143
|
+
},
|
|
144
|
+
rosepine: {
|
|
145
|
+
primary: c256(189), // iris
|
|
146
|
+
secondary: c256(217), // rose
|
|
147
|
+
muted: c256(60), // muted
|
|
148
|
+
success: c256(115), // foam
|
|
149
|
+
danger: c256(210), // love
|
|
150
|
+
warning: c256(222), // gold
|
|
151
|
+
info: c256(116), // pine
|
|
152
|
+
highlight: pc.bold,
|
|
153
|
+
border: "─",
|
|
154
|
+
borderDim: "┄",
|
|
155
|
+
logo: `\x1b[38;5;189m\x1b[1mAcmeCode\x1b[0m \x1b[38;5;60mv1.0\x1b[0m`,
|
|
156
|
+
bgHeader: "#191724",
|
|
157
|
+
bgInput: "#1f1d2e",
|
|
158
|
+
accentIdle: "#c4a7e7",
|
|
159
|
+
accentBusy: "#ebbcba",
|
|
160
|
+
},
|
|
161
|
+
solarized: {
|
|
162
|
+
primary: c256(37), // cyan
|
|
163
|
+
secondary: c256(61), // violet
|
|
164
|
+
muted: c256(240), // base01
|
|
165
|
+
success: c256(64), // green
|
|
166
|
+
danger: c256(160), // red
|
|
167
|
+
warning: c256(136), // yellow
|
|
168
|
+
info: c256(33), // blue
|
|
169
|
+
highlight: pc.bold,
|
|
170
|
+
border: "─",
|
|
171
|
+
borderDim: "┄",
|
|
172
|
+
logo: `\x1b[38;5;37m\x1b[1mAcmeCode\x1b[0m \x1b[38;5;240mv1.0\x1b[0m`,
|
|
173
|
+
bgHeader: "#002731",
|
|
174
|
+
bgInput: "#00212b",
|
|
175
|
+
accentIdle: "#2aa198",
|
|
176
|
+
accentBusy: "#b58900",
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
// ── Active theme state ──
|
|
180
|
+
let activeThemeName = loadThemeConfig();
|
|
181
|
+
const listeners = [];
|
|
182
|
+
export function getTheme() {
|
|
183
|
+
return themes[activeThemeName] || themes["dark"];
|
|
184
|
+
}
|
|
185
|
+
export function setTheme(name) {
|
|
186
|
+
if (themes[name]) {
|
|
187
|
+
activeThemeName = name;
|
|
188
|
+
saveGlobalThemeConfig(name);
|
|
189
|
+
listeners.forEach((l) => l(name));
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
export function onThemeChange(listener) {
|
|
195
|
+
listeners.push(listener);
|
|
196
|
+
}
|
|
197
|
+
export function getThemeName() {
|
|
198
|
+
return activeThemeName;
|
|
199
|
+
}
|
|
200
|
+
export function listThemes() {
|
|
201
|
+
return Object.keys(themes);
|
|
202
|
+
}
|
|
203
|
+
// ── Re-export active theme (backward compatible) ──
|
|
204
|
+
export const theme = new Proxy({}, {
|
|
205
|
+
get(_target, prop) {
|
|
206
|
+
return getTheme()[prop];
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
// ── Formatting helpers ──
|
|
210
|
+
export function formatToolIcon(toolName) {
|
|
211
|
+
const icons = {
|
|
212
|
+
read_file: "📖",
|
|
213
|
+
write_file: "📝",
|
|
214
|
+
run_command: "⚡",
|
|
215
|
+
list_dir: "📂",
|
|
216
|
+
edit_file: "✏️",
|
|
217
|
+
grep_search: "🔍",
|
|
218
|
+
webfetch: "🌐",
|
|
219
|
+
websearch: "🔎",
|
|
220
|
+
codesearch: "💻",
|
|
221
|
+
lsp: "🧠",
|
|
222
|
+
switch_mode: "⚙️",
|
|
223
|
+
batch: "📦",
|
|
224
|
+
browser_action: "🖥️",
|
|
225
|
+
};
|
|
226
|
+
return icons[toolName] || "🔧";
|
|
227
|
+
}
|
|
228
|
+
export function formatToolName(toolName) {
|
|
229
|
+
const key = `tool.${toolName}`;
|
|
230
|
+
const translated = t(key);
|
|
231
|
+
return translated !== key ? translated : toolName;
|
|
232
|
+
}
|
|
233
|
+
export function formatBorder(width, char) {
|
|
234
|
+
return (char || getTheme().border).repeat(width);
|
|
235
|
+
}
|
|
236
|
+
export function formatKeyHint(key, label) {
|
|
237
|
+
const t = getTheme();
|
|
238
|
+
return `${t.muted("[")}${t.primary(key)}${t.muted("]")} ${t.muted(label)}`;
|
|
239
|
+
}
|
package/output.txt
ADDED
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "acmecode",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "AI Coding Assistant CLI",
|
|
6
|
+
"main": "dist/cli/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"acmecode": "dist/cli/bin/acmecode.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc -p tsconfig.json",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"dev": "tsx bin/acmecode.ts",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"ai": "^4.1.0",
|
|
18
|
+
"@ai-sdk/anthropic": "^1.1.0",
|
|
19
|
+
"@ai-sdk/deepinfra": "^0.1.0",
|
|
20
|
+
"@ai-sdk/google": "^1.2.0",
|
|
21
|
+
"@ai-sdk/groq": "^0.1.0",
|
|
22
|
+
"@ai-sdk/mistral": "^0.1.0",
|
|
23
|
+
"@ai-sdk/openai": "^1.1.0",
|
|
24
|
+
"@ai-sdk/xai": "^0.1.0",
|
|
25
|
+
"@openrouter/ai-sdk-provider": "^0.1.0",
|
|
26
|
+
"better-sqlite3": "^11.8.1",
|
|
27
|
+
"chalk": "^5.4.1",
|
|
28
|
+
"commander": "^14.0.3",
|
|
29
|
+
"dotenv": "^16.5.0",
|
|
30
|
+
"ink": "^6.8.0",
|
|
31
|
+
"react": "^19.2.4",
|
|
32
|
+
"zod": "^3.25.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
36
|
+
"@types/node": "^25.3.0",
|
|
37
|
+
"@types/react": "^19.2.14",
|
|
38
|
+
"tsx": "^4.21.0",
|
|
39
|
+
"typescript": "^5.9.3"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@acmecode/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"acmecode": "bin/acmecode.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"start": "node dist/index.js",
|
|
12
|
+
"dev": "tsx src/index.ts"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@acmecode/core": "^1.0.0",
|
|
16
|
+
"@acmecode/tui": "^1.0.0",
|
|
17
|
+
"commander": "^14.0.3",
|
|
18
|
+
"ink": "^6.8.0",
|
|
19
|
+
"react": "^19.2.4"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "^25.3.0",
|
|
23
|
+
"@types/react": "^19.2.14"
|
|
24
|
+
}
|
|
25
|
+
}
|