@travisennis/acai 0.0.12 → 0.0.13
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 +3 -2
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +2 -5
- package/dist/commands/history/types.d.ts +3 -2
- package/dist/commands/history/types.d.ts.map +1 -1
- package/dist/commands/init-project/utils.d.ts +0 -1
- package/dist/commands/init-project/utils.d.ts.map +1 -1
- package/dist/commands/init-project/utils.js +1 -1
- package/dist/commands/manager.d.ts.map +1 -1
- package/dist/commands/manager.js +0 -18
- package/dist/commands/share/html-renderer.d.ts.map +1 -1
- package/dist/commands/share/html-renderer.js +54 -48
- package/dist/commands/tools/index.js +39 -38
- package/dist/config/index.d.ts +0 -2
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +2 -6
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +94 -76
- package/dist/models/manager.d.ts +1 -10
- package/dist/models/manager.d.ts.map +1 -1
- package/dist/models/manager.js +2 -2
- package/dist/models/opencode-go-provider.d.ts +4 -4
- package/dist/models/opencode-go-provider.d.ts.map +1 -1
- package/dist/models/opencode-go-provider.js +29 -35
- package/dist/models/providers.d.ts +1 -1
- package/dist/models/providers.d.ts.map +1 -1
- package/dist/prompts/system-prompt.d.ts +0 -2
- package/dist/prompts/system-prompt.d.ts.map +1 -1
- package/dist/prompts/system-prompt.js +6 -10
- package/dist/repl/index.d.ts +27 -11
- package/dist/repl/index.d.ts.map +1 -1
- package/dist/repl/index.js +238 -254
- package/dist/skills/index.d.ts +12 -2
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +123 -73
- package/dist/terminal/control.d.ts +1 -21
- package/dist/terminal/control.d.ts.map +1 -1
- package/dist/terminal/control.js +1 -32
- package/dist/terminal/formatting.d.ts +0 -33
- package/dist/terminal/formatting.d.ts.map +1 -1
- package/dist/terminal/formatting.js +0 -91
- package/dist/terminal/highlight/theme.d.ts +0 -37
- package/dist/terminal/highlight/theme.d.ts.map +1 -1
- package/dist/terminal/highlight/theme.js +1 -79
- package/dist/terminal/keys.d.ts +0 -97
- package/dist/terminal/keys.d.ts.map +1 -1
- package/dist/terminal/keys.js +0 -194
- package/dist/terminal/select-prompt.d.ts.map +1 -1
- package/dist/terminal/select-prompt.js +65 -51
- package/dist/terminal/style.d.ts +1 -1
- package/dist/terminal/style.d.ts.map +1 -1
- package/dist/terminal/supports-color.d.ts.map +1 -1
- package/dist/terminal/supports-color.js +38 -20
- package/dist/terminal/supports-hyperlinks.d.ts +3 -0
- package/dist/terminal/supports-hyperlinks.d.ts.map +1 -1
- package/dist/terminal/supports-hyperlinks.js +72 -31
- package/dist/terminal/table/layout-manager.d.ts +0 -20
- package/dist/terminal/table/layout-manager.d.ts.map +1 -1
- package/dist/terminal/table/layout-manager.js +68 -44
- package/dist/terminal/table/utils.d.ts +0 -1
- package/dist/terminal/table/utils.d.ts.map +1 -1
- package/dist/terminal/table/utils.js +2 -4
- package/dist/tools/apply-patch.d.ts +5 -3
- package/dist/tools/apply-patch.d.ts.map +1 -1
- package/dist/tools/apply-patch.js +154 -123
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +11 -8
- package/dist/tools/dynamic-tool-loader.d.ts +6 -1
- package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-loader.js +154 -135
- package/dist/tools/index.d.ts +3 -133
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +0 -20
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +32 -13
- package/dist/tools/skill.d.ts.map +1 -1
- package/dist/tools/skill.js +20 -13
- package/dist/tools/web-fetch.d.ts +2 -6
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +59 -36
- package/dist/tools/web-search.d.ts +0 -4
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +40 -32
- package/dist/tui/autocomplete/utils.d.ts +0 -15
- package/dist/tui/autocomplete/utils.d.ts.map +1 -1
- package/dist/tui/autocomplete/utils.js +0 -85
- package/dist/tui/autocomplete.d.ts +1 -1
- package/dist/tui/autocomplete.d.ts.map +1 -1
- package/dist/tui/autocomplete.js +1 -1
- package/dist/tui/components/editor.d.ts +12 -0
- package/dist/tui/components/editor.d.ts.map +1 -1
- package/dist/tui/components/editor.js +181 -195
- package/dist/tui/components/input.d.ts +4 -0
- package/dist/tui/components/input.d.ts.map +1 -1
- package/dist/tui/components/input.js +33 -31
- package/dist/tui/components/markdown.d.ts +30 -0
- package/dist/tui/components/markdown.d.ts.map +1 -1
- package/dist/tui/components/markdown.js +274 -242
- package/dist/tui/components/modal.d.ts.map +1 -1
- package/dist/tui/components/modal.js +11 -11
- package/dist/tui/components/select-list.d.ts +5 -0
- package/dist/tui/components/select-list.d.ts.map +1 -1
- package/dist/tui/components/select-list.js +69 -98
- package/dist/tui/components/table.d.ts +6 -0
- package/dist/tui/components/table.d.ts.map +1 -1
- package/dist/tui/components/table.js +61 -52
- package/dist/tui/index.d.ts +1 -8
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +0 -8
- package/dist/tui/tui.d.ts +9 -0
- package/dist/tui/tui.d.ts.map +1 -1
- package/dist/tui/tui.js +78 -48
- package/dist/tui/utils.d.ts +7 -0
- package/dist/tui/utils.d.ts.map +1 -1
- package/dist/tui/utils.js +117 -53
- package/dist/utils/bash.d.ts.map +1 -1
- package/dist/utils/bash.js +121 -104
- package/dist/utils/command-protection.d.ts +3 -2
- package/dist/utils/command-protection.d.ts.map +1 -1
- package/dist/utils/command-protection.js +42 -33
- package/dist/utils/filesystem/operations.d.ts +0 -15
- package/dist/utils/filesystem/operations.d.ts.map +1 -1
- package/dist/utils/filesystem/operations.js +1 -38
- package/dist/utils/filesystem/security.d.ts.map +1 -1
- package/dist/utils/filesystem/security.js +22 -15
- package/dist/utils/filetype-detection.d.ts +0 -1
- package/dist/utils/filetype-detection.d.ts.map +1 -1
- package/dist/utils/filetype-detection.js +0 -12
- package/dist/utils/formatting.d.ts +0 -30
- package/dist/utils/formatting.d.ts.map +1 -1
- package/dist/utils/formatting.js +0 -44
- package/dist/utils/git.d.ts +4 -6
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +36 -46
- package/dist/utils/ignore.d.ts +1 -1
- package/dist/utils/ignore.d.ts.map +1 -1
- package/dist/utils/ignore.js +1 -1
- package/dist/utils/process.d.ts.map +1 -1
- package/dist/utils/process.js +77 -79
- package/dist/utils/yaml.d.ts +0 -1
- package/dist/utils/yaml.d.ts.map +1 -1
- package/dist/utils/yaml.js +80 -89
- package/dist/utils/zod.d.ts +0 -3
- package/dist/utils/zod.d.ts.map +1 -1
- package/dist/utils/zod.js +0 -7
- package/package.json +25 -24
- package/dist/agent/sub-agent.d.ts +0 -23
- package/dist/agent/sub-agent.d.ts.map +0 -1
- package/dist/agent/sub-agent.js +0 -109
- package/dist/commands/add-directory/index.d.ts +0 -3
- package/dist/commands/add-directory/index.d.ts.map +0 -1
- package/dist/commands/add-directory/index.js +0 -50
- package/dist/commands/add-directory/utils.d.ts +0 -3
- package/dist/commands/add-directory/utils.d.ts.map +0 -1
- package/dist/commands/add-directory/utils.js +0 -15
- package/dist/commands/clear/index.d.ts +0 -3
- package/dist/commands/clear/index.d.ts.map +0 -1
- package/dist/commands/clear/index.js +0 -13
- package/dist/commands/generate-rules/index.d.ts +0 -3
- package/dist/commands/generate-rules/index.d.ts.map +0 -1
- package/dist/commands/generate-rules/index.js +0 -206
- package/dist/commands/generate-rules/service.d.ts +0 -22
- package/dist/commands/generate-rules/service.d.ts.map +0 -1
- package/dist/commands/generate-rules/service.js +0 -103
- package/dist/commands/generate-rules/utils.d.ts +0 -5
- package/dist/commands/generate-rules/utils.d.ts.map +0 -1
- package/dist/commands/generate-rules/utils.js +0 -25
- package/dist/commands/handoff/index.d.ts +0 -3
- package/dist/commands/handoff/index.d.ts.map +0 -1
- package/dist/commands/handoff/index.js +0 -97
- package/dist/commands/handoff/utils.d.ts +0 -4
- package/dist/commands/handoff/utils.d.ts.map +0 -1
- package/dist/commands/handoff/utils.js +0 -123
- package/dist/commands/list-directories/index.d.ts +0 -3
- package/dist/commands/list-directories/index.d.ts.map +0 -1
- package/dist/commands/list-directories/index.js +0 -35
- package/dist/commands/pickup/index.d.ts +0 -3
- package/dist/commands/pickup/index.d.ts.map +0 -1
- package/dist/commands/pickup/index.js +0 -141
- package/dist/commands/pickup/types.d.ts +0 -6
- package/dist/commands/pickup/types.d.ts.map +0 -1
- package/dist/commands/pickup/types.js +0 -1
- package/dist/commands/pickup/utils.d.ts +0 -7
- package/dist/commands/pickup/utils.d.ts.map +0 -1
- package/dist/commands/pickup/utils.js +0 -56
- package/dist/commands/remove-directory/index.d.ts +0 -3
- package/dist/commands/remove-directory/index.d.ts.map +0 -1
- package/dist/commands/remove-directory/index.js +0 -55
- package/dist/commands/review/index.d.ts +0 -3
- package/dist/commands/review/index.d.ts.map +0 -1
- package/dist/commands/review/index.js +0 -12
- package/dist/commands/review/review-panel.d.ts +0 -3
- package/dist/commands/review/review-panel.d.ts.map +0 -1
- package/dist/commands/review/review-panel.js +0 -186
- package/dist/commands/review/utils.d.ts +0 -18
- package/dist/commands/review/utils.d.ts.map +0 -1
- package/dist/commands/review/utils.js +0 -146
- package/dist/commands/shell/index.d.ts +0 -3
- package/dist/commands/shell/index.d.ts.map +0 -1
- package/dist/commands/shell/index.js +0 -96
- package/dist/subagents/index.d.ts +0 -16
- package/dist/subagents/index.d.ts.map +0 -1
- package/dist/subagents/index.js +0 -231
- package/dist/terminal/index.d.ts +0 -9
- package/dist/terminal/index.d.ts.map +0 -1
- package/dist/terminal/index.js +0 -8
- package/dist/tools/agent.d.ts +0 -27
- package/dist/tools/agent.d.ts.map +0 -1
- package/dist/tools/agent.js +0 -81
- package/dist/tools/directory-tree.d.ts +0 -28
- package/dist/tools/directory-tree.d.ts.map +0 -1
- package/dist/tools/directory-tree.js +0 -154
- package/dist/tools/glob.d.ts +0 -35
- package/dist/tools/glob.d.ts.map +0 -1
- package/dist/tools/glob.js +0 -167
- package/dist/tools/grep.d.ts +0 -100
- package/dist/tools/grep.d.ts.map +0 -1
- package/dist/tools/grep.js +0 -608
- package/dist/tools/ls.d.ts +0 -26
- package/dist/tools/ls.d.ts.map +0 -1
- package/dist/tools/ls.js +0 -83
- package/dist/tui/components/header.d.ts +0 -21
- package/dist/tui/components/header.d.ts.map +0 -1
- package/dist/tui/components/header.js +0 -63
- package/dist/utils/bash/parse.d.ts +0 -19
- package/dist/utils/bash/parse.d.ts.map +0 -1
- package/dist/utils/bash/parse.js +0 -223
- package/dist/utils/bash/quote.d.ts +0 -6
- package/dist/utils/bash/quote.d.ts.map +0 -1
- package/dist/utils/bash/quote.js +0 -23
- package/dist/utils/generators.d.ts +0 -3
- package/dist/utils/generators.d.ts.map +0 -1
- package/dist/utils/generators.js +0 -25
- package/dist/utils/glob.d.ts +0 -52
- package/dist/utils/glob.d.ts.map +0 -1
- package/dist/utils/glob.js +0 -376
package/dist/skills/index.js
CHANGED
|
@@ -133,66 +133,99 @@ async function shouldSkipEntry(entryPath, entryName) {
|
|
|
133
133
|
}
|
|
134
134
|
return false;
|
|
135
135
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Resolves the real path of a directory and checks for symlink cycles.
|
|
138
|
+
* Returns true if the directory can be safely processed.
|
|
139
|
+
*/
|
|
140
|
+
async function resolveSkillDir(fullDir, visited) {
|
|
140
141
|
try {
|
|
141
142
|
const real = await realpath(fullDir);
|
|
142
143
|
if (visited.has(real)) {
|
|
143
144
|
logger.warn(`Skipping ${fullDir}: symlink cycle detected`);
|
|
144
|
-
return
|
|
145
|
+
return false;
|
|
145
146
|
}
|
|
146
147
|
visited.add(real);
|
|
148
|
+
return true;
|
|
147
149
|
}
|
|
148
150
|
catch {
|
|
149
|
-
return
|
|
151
|
+
return false;
|
|
150
152
|
}
|
|
151
|
-
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Reads directory entries, returning null if the directory doesn't exist
|
|
156
|
+
* or can't be read.
|
|
157
|
+
*/
|
|
158
|
+
async function readSkillDirEntries(fullDir) {
|
|
152
159
|
try {
|
|
153
160
|
// @ts-expect-error - Node.js types have a quirk with withFileTypes
|
|
154
|
-
|
|
161
|
+
return await readdir(fullDir, { withFileTypes: true });
|
|
155
162
|
}
|
|
156
163
|
catch (error) {
|
|
157
|
-
// Directory doesn't exist or can't be read
|
|
158
164
|
if (error.code !== "ENOENT") {
|
|
159
165
|
logger.error(error, `Error reading skills directory ${fullDir}:`);
|
|
160
166
|
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Processes a directory entry in recursive mode: recursively scans subdirectories.
|
|
172
|
+
*/
|
|
173
|
+
async function handleRecursiveDir(entryName, dir, source, mode, subdir, visited) {
|
|
174
|
+
const newSubdir = subdir ? join(subdir, entryName) : entryName;
|
|
175
|
+
return await loadSkillsFromDirInternal(dir, source, mode, false, newSubdir, visited);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Processes a directory entry in claude mode: checks for SKILL.md in the subdirectory.
|
|
179
|
+
*/
|
|
180
|
+
async function handleClaudeDir(entryName, entryPath, source) {
|
|
181
|
+
const skillPath = join(entryPath, "SKILL.md");
|
|
182
|
+
const skill = await tryLoadSkillFromFile(skillPath, entryName, entryPath, source);
|
|
183
|
+
return skill ? [skill] : [];
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Processes a directory entry based on the scan mode.
|
|
187
|
+
*/
|
|
188
|
+
async function handleDirEntry(entryName, entryPath, dir, source, mode, subdir, visited) {
|
|
189
|
+
if (mode === "recursive") {
|
|
190
|
+
return await handleRecursiveDir(entryName, dir, source, mode, subdir, visited);
|
|
191
|
+
}
|
|
192
|
+
return await handleClaudeDir(entryName, entryPath, source);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Processes a SKILL.md file entry, loading it as a skill.
|
|
196
|
+
*/
|
|
197
|
+
async function handleSkillFile(entryPath, dir, subdir, source) {
|
|
198
|
+
const baseDir = subdir ? join(dir, subdir) : dir;
|
|
199
|
+
const skill = await tryLoadSkillFromFile(entryPath, basename(dirname(entryPath)), baseDir, source);
|
|
200
|
+
return skill ? [skill] : [];
|
|
201
|
+
}
|
|
202
|
+
async function loadSkillsFromDirInternal(dir, source, mode, _useColonPath, subdir = "", visited = new Set()) {
|
|
203
|
+
const skills = [];
|
|
204
|
+
const fullDir = join(dir, subdir);
|
|
205
|
+
// Check symlink cycles
|
|
206
|
+
if (!(await resolveSkillDir(fullDir, visited))) {
|
|
161
207
|
return skills;
|
|
162
208
|
}
|
|
209
|
+
// Read directory
|
|
210
|
+
const entries = await readSkillDirEntries(fullDir);
|
|
211
|
+
if (!entries)
|
|
212
|
+
return skills;
|
|
213
|
+
// Process each entry
|
|
163
214
|
for (const entry of entries) {
|
|
164
215
|
const entryName = entry.name.toString();
|
|
165
216
|
const entryPath = join(fullDir, entryName);
|
|
166
|
-
// Skip hidden files, symlinks, etc.
|
|
167
217
|
if (await shouldSkipEntry(entryPath, entryName)) {
|
|
168
218
|
continue;
|
|
169
219
|
}
|
|
170
|
-
// Handle directories
|
|
171
220
|
if (entry.isDirectory()) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
const newSubdir = subdir ? join(subdir, entryName) : entryName;
|
|
175
|
-
const subSkills = await loadSkillsFromDirInternal(dir, source, mode, false, newSubdir, visited);
|
|
176
|
-
skills.push(...subSkills);
|
|
177
|
-
}
|
|
178
|
-
else if (mode === "claude") {
|
|
179
|
-
// Claude mode: only check immediate subdirectories for SKILL.md
|
|
180
|
-
const skillPath = join(entryPath, "SKILL.md");
|
|
181
|
-
const skill = await tryLoadSkillFromFile(skillPath, entryName, entryPath, source);
|
|
182
|
-
if (skill) {
|
|
183
|
-
skills.push(skill);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
continue;
|
|
221
|
+
const subSkills = await handleDirEntry(entryName, entryPath, dir, source, mode, subdir, visited);
|
|
222
|
+
skills.push(...subSkills);
|
|
187
223
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
if (skill) {
|
|
194
|
-
skills.push(skill);
|
|
195
|
-
}
|
|
224
|
+
else if (entry.isFile() &&
|
|
225
|
+
entryName === "SKILL.md" &&
|
|
226
|
+
mode === "recursive") {
|
|
227
|
+
const fileSkills = await handleSkillFile(entryPath, dir, subdir, source);
|
|
228
|
+
skills.push(...fileSkills);
|
|
196
229
|
}
|
|
197
230
|
}
|
|
198
231
|
return skills;
|
|
@@ -201,7 +234,7 @@ export async function loadSkillsFromDir(options, subdir = "") {
|
|
|
201
234
|
const { dir, source, useColonPath = false } = options;
|
|
202
235
|
return await loadSkillsFromDirInternal(dir, source, "recursive", useColonPath, subdir);
|
|
203
236
|
}
|
|
204
|
-
|
|
237
|
+
class Skills {
|
|
205
238
|
skills;
|
|
206
239
|
constructor(skills) {
|
|
207
240
|
this.skills = skills;
|
|
@@ -216,58 +249,75 @@ export class Skills {
|
|
|
216
249
|
return this.skills.filter((s) => !s.disableModelInvocation);
|
|
217
250
|
}
|
|
218
251
|
}
|
|
219
|
-
|
|
220
|
-
const skillMap = new Map();
|
|
221
|
-
// Codex: recursive, simple directory name
|
|
222
|
-
const codexUserDir = join(homedir(), ".codex", "skills");
|
|
223
|
-
for (const skill of await loadSkillsFromDirInternal(codexUserDir, "codex-user", "recursive", false)) {
|
|
224
|
-
skillMap.set(skill.name, skill);
|
|
225
|
-
}
|
|
226
|
-
// Claude: single level only
|
|
227
|
-
const claudeUserDir = join(homedir(), ".claude", "skills");
|
|
228
|
-
for (const skill of await loadSkillsFromDirInternal(claudeUserDir, "claude-user", "claude", false)) {
|
|
229
|
-
skillMap.set(skill.name, skill);
|
|
230
|
-
}
|
|
231
|
-
const claudeProjectDir = resolve(process.cwd(), ".claude", "skills");
|
|
232
|
-
for (const skill of await loadSkillsFromDirInternal(claudeProjectDir, "claude-project", "claude", false)) {
|
|
233
|
-
skillMap.set(skill.name, skill);
|
|
234
|
-
}
|
|
235
|
-
// Deprecated: warn if skills exist in old .acai directories
|
|
236
|
-
const deprecatedGlobalDir = join(homedir(), CONFIG_DIR_NAME, "skills");
|
|
252
|
+
async function warnIfDeprecatedSkillsDir(dirPath, message) {
|
|
237
253
|
try {
|
|
238
|
-
const entries = await readdir(
|
|
254
|
+
const entries = await readdir(dirPath);
|
|
239
255
|
if (entries.length > 0) {
|
|
240
|
-
logger.warn(
|
|
256
|
+
logger.warn(message);
|
|
241
257
|
}
|
|
242
258
|
}
|
|
243
259
|
catch {
|
|
244
260
|
// Directory doesn't exist, no warning needed
|
|
245
261
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
262
|
+
}
|
|
263
|
+
async function loadAllSkillDirs(configs, skillMap) {
|
|
264
|
+
for (const { dir, source, mode, colonSeparated } of configs) {
|
|
265
|
+
for (const skill of await loadSkillsFromDirInternal(dir, source, mode, colonSeparated)) {
|
|
266
|
+
skillMap.set(skill.name, skill);
|
|
251
267
|
}
|
|
252
268
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
269
|
+
}
|
|
270
|
+
export async function loadSkills(additionalSkillPathsOrOptions) {
|
|
271
|
+
const options = Array.isArray(additionalSkillPathsOrOptions)
|
|
272
|
+
? { additionalSkillPaths: additionalSkillPathsOrOptions }
|
|
273
|
+
: (additionalSkillPathsOrOptions ?? {});
|
|
274
|
+
const additionalSkillPaths = options.additionalSkillPaths ?? [];
|
|
275
|
+
const dirs = options.dirs ?? {};
|
|
276
|
+
const skillMap = new Map();
|
|
277
|
+
await warnIfDeprecatedSkillsDir(join(homedir(), CONFIG_DIR_NAME, "skills"), "Skills found in ~/.acai/skills/ are deprecated and will not be loaded. Move them to ~/.agents/skills/ to continue using them.");
|
|
278
|
+
await warnIfDeprecatedSkillsDir(resolve(process.cwd(), CONFIG_DIR_NAME, "skills"), "Skills found in .acai/skills/ are deprecated and will not be loaded. Move them to ~/.agents/skills/ to continue using them.");
|
|
279
|
+
// --- User-level skills (lowest priority) ---
|
|
280
|
+
await loadAllSkillDirs([
|
|
281
|
+
{
|
|
282
|
+
dir: dirs.codexUser ?? join(homedir(), ".codex", "skills"),
|
|
283
|
+
source: "codex-user",
|
|
284
|
+
mode: "recursive",
|
|
285
|
+
colonSeparated: false,
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
dir: dirs.claudeUser ?? join(homedir(), ".claude", "skills"),
|
|
289
|
+
source: "claude-user",
|
|
290
|
+
mode: "claude",
|
|
291
|
+
colonSeparated: false,
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
dir: dirs.agentsGlobal ?? join(homedir(), ".agents", "skills"),
|
|
295
|
+
source: "user",
|
|
296
|
+
mode: "recursive",
|
|
297
|
+
colonSeparated: true,
|
|
298
|
+
},
|
|
299
|
+
], skillMap);
|
|
300
|
+
// --- Config-level skills (overrides user-level) ---
|
|
266
301
|
for (const skillPath of additionalSkillPaths) {
|
|
267
302
|
for (const skill of await loadSkillsFromDirInternal(skillPath, "config", "recursive", true)) {
|
|
268
303
|
skillMap.set(skill.name, skill);
|
|
269
304
|
}
|
|
270
305
|
}
|
|
306
|
+
// --- Project-level skills (highest priority, always wins) ---
|
|
307
|
+
await loadAllSkillDirs([
|
|
308
|
+
{
|
|
309
|
+
dir: dirs.claudeProject ?? resolve(process.cwd(), ".claude", "skills"),
|
|
310
|
+
source: "claude-project",
|
|
311
|
+
mode: "claude",
|
|
312
|
+
colonSeparated: false,
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
dir: dirs.agentsProject ?? resolve(process.cwd(), ".agents", "skills"),
|
|
316
|
+
source: "project",
|
|
317
|
+
mode: "recursive",
|
|
318
|
+
colonSeparated: true,
|
|
319
|
+
},
|
|
320
|
+
], skillMap);
|
|
271
321
|
return new Skills(Array.from(skillMap.values()));
|
|
272
322
|
}
|
|
273
323
|
export function formatSkillsForPrompt(skills) {
|
|
@@ -3,35 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides functions for controlling terminal behavior and state.
|
|
5
5
|
*/
|
|
6
|
-
export {
|
|
6
|
+
export { isArrowDown, isArrowUp, isCtrlC, isCtrlD, isCtrlM, isCtrlN, isCtrlO, isCtrlR, isCtrlZ, isEnter, isEscape, isShiftTab, isTab, } from "./keys.ts";
|
|
7
7
|
/**
|
|
8
8
|
* Get the current shell
|
|
9
9
|
*/
|
|
10
10
|
export declare function getShell(): string;
|
|
11
|
-
/**
|
|
12
|
-
* Check if terminal is interactive
|
|
13
|
-
*/
|
|
14
|
-
export declare function isInteractive(): boolean;
|
|
15
11
|
/**
|
|
16
12
|
* Send terminal alert/notification
|
|
17
13
|
*/
|
|
18
14
|
export declare function alert(): Promise<void>;
|
|
19
|
-
/**
|
|
20
|
-
* Clear the terminal screen
|
|
21
|
-
*/
|
|
22
|
-
export declare function clearScreen(): void;
|
|
23
|
-
/**
|
|
24
|
-
* Clear the terminal screen including scrollback buffer
|
|
25
|
-
*
|
|
26
|
-
* Unlike clearScreen, this function:
|
|
27
|
-
* 1. Clears the entire screen (\x1b[2J)
|
|
28
|
-
* 2. Clears the scrollback buffer (\x1b[3J)
|
|
29
|
-
* 3. Moves cursor to home position (\x1b[H)
|
|
30
|
-
* 4. Returns a Promise that resolves when the write operation completes
|
|
31
|
-
*
|
|
32
|
-
* @returns Promise that resolves when the terminal has been cleared
|
|
33
|
-
*/
|
|
34
|
-
export declare function clearTerminal(): Promise<void>;
|
|
35
15
|
/**
|
|
36
16
|
* Sets the terminal title
|
|
37
17
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control.d.ts","sourceRoot":"","sources":["../../source/terminal/control.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"control.d.ts","sourceRoot":"","sources":["../../source/terminal/control.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EACL,WAAW,EACX,SAAS,EACT,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,OAAO,EACP,QAAQ,EACR,UAAU,EACV,KAAK,GACN,MAAM,WAAW,CAAC;AAEnB;;GAEG;AACH,wBAAgB,QAAQ,WAEvB;AAED;;GAEG;AACH,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAkB3C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAYpD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAgBnE;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAQpC;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAQnC"}
|
package/dist/terminal/control.js
CHANGED
|
@@ -6,19 +6,13 @@
|
|
|
6
6
|
import { config } from "../config/index.js";
|
|
7
7
|
import { logger } from "../utils/logger.js";
|
|
8
8
|
// Re-export key functions from keys.ts for convenient imports
|
|
9
|
-
export {
|
|
9
|
+
export { isArrowDown, isArrowUp, isCtrlC, isCtrlD, isCtrlM, isCtrlN, isCtrlO, isCtrlR, isCtrlZ, isEnter, isEscape, isShiftTab, isTab, } from "./keys.js";
|
|
10
10
|
/**
|
|
11
11
|
* Get the current shell
|
|
12
12
|
*/
|
|
13
13
|
export function getShell() {
|
|
14
14
|
return process.env["ZSH_VERSION"] ? "zsh" : process.env["SHELL"] || "bash";
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Check if terminal is interactive
|
|
18
|
-
*/
|
|
19
|
-
export function isInteractive() {
|
|
20
|
-
return Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
21
|
-
}
|
|
22
16
|
/**
|
|
23
17
|
* Send terminal alert/notification
|
|
24
18
|
*/
|
|
@@ -40,31 +34,6 @@ export async function alert() {
|
|
|
40
34
|
logger.warn({ err }, "Failed to emit alert");
|
|
41
35
|
}
|
|
42
36
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Clear the terminal screen
|
|
45
|
-
*/
|
|
46
|
-
export function clearScreen() {
|
|
47
|
-
// Clear screen and move cursor to top-left
|
|
48
|
-
process.stdout.write("\x1b[2J\x1b[0f");
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Clear the terminal screen including scrollback buffer
|
|
52
|
-
*
|
|
53
|
-
* Unlike clearScreen, this function:
|
|
54
|
-
* 1. Clears the entire screen (\x1b[2J)
|
|
55
|
-
* 2. Clears the scrollback buffer (\x1b[3J)
|
|
56
|
-
* 3. Moves cursor to home position (\x1b[H)
|
|
57
|
-
* 4. Returns a Promise that resolves when the write operation completes
|
|
58
|
-
*
|
|
59
|
-
* @returns Promise that resolves when the terminal has been cleared
|
|
60
|
-
*/
|
|
61
|
-
export function clearTerminal() {
|
|
62
|
-
return new Promise((resolve) => {
|
|
63
|
-
process.stdout.write("\x1b[2J\x1b[3J\x1b[H", () => {
|
|
64
|
-
resolve();
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
37
|
/**
|
|
69
38
|
* Sets the terminal title
|
|
70
39
|
*/
|
|
@@ -1,35 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Create a horizontal rule
|
|
3
|
-
*/
|
|
4
|
-
export declare function hr(width: number): string;
|
|
5
|
-
/**
|
|
6
|
-
* Word wrap text to the specified width
|
|
7
|
-
*/
|
|
8
|
-
export declare function wordWrap(text: string, width: number): string;
|
|
9
1
|
export declare const link: (text: string, url: string) => string | null;
|
|
10
|
-
export declare const image: (data: string | Buffer, options?: {
|
|
11
|
-
width?: number | string;
|
|
12
|
-
height?: number | string;
|
|
13
|
-
preserveAspectRatio?: boolean;
|
|
14
|
-
}) => string;
|
|
15
|
-
/**
|
|
16
|
-
* Display a message with emphasis
|
|
17
|
-
*/
|
|
18
|
-
export declare function emphasize(message: string): string;
|
|
19
|
-
/**
|
|
20
|
-
* Display an informational message
|
|
21
|
-
*/
|
|
22
|
-
export declare function info(message: string): string;
|
|
23
|
-
/**
|
|
24
|
-
* Display a success message
|
|
25
|
-
*/
|
|
26
|
-
export declare function success(message: string): string;
|
|
27
|
-
/**
|
|
28
|
-
* Display a warning message
|
|
29
|
-
*/
|
|
30
|
-
export declare function warn(message: string): string;
|
|
31
|
-
/**
|
|
32
|
-
* Display an error message
|
|
33
|
-
*/
|
|
34
|
-
export declare function error(message: string): string;
|
|
35
2
|
//# sourceMappingURL=formatting.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatting.d.ts","sourceRoot":"","sources":["../../source/terminal/formatting.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"formatting.d.ts","sourceRoot":"","sources":["../../source/terminal/formatting.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,EAAE,KAAK,MAAM,kBAO7C,CAAC"}
|
|
@@ -3,55 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides functions for formatting and displaying text in the terminal.
|
|
5
5
|
*/
|
|
6
|
-
import style from "./style.js";
|
|
7
6
|
import { supportsHyperlinks } from "./supports-hyperlinks.js";
|
|
8
|
-
/**
|
|
9
|
-
* Create a horizontal rule
|
|
10
|
-
*/
|
|
11
|
-
export function hr(width) {
|
|
12
|
-
return `${style.gray("─").repeat(width)}`;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Word wrap text to the specified width
|
|
16
|
-
*/
|
|
17
|
-
export function wordWrap(text, width) {
|
|
18
|
-
const lines = text.split("\n");
|
|
19
|
-
return lines.map((line) => wrapLine(line, width)).join("\n");
|
|
20
|
-
}
|
|
21
|
-
function wrapLine(line, width) {
|
|
22
|
-
// If the line is a code block or already shorter than the width, leave it as is
|
|
23
|
-
if (line.trim().startsWith("┃") || line.length <= width) {
|
|
24
|
-
return line;
|
|
25
|
-
}
|
|
26
|
-
// Word wrap the line
|
|
27
|
-
const words = line.split(" ");
|
|
28
|
-
const wrappedLines = [];
|
|
29
|
-
let currentLine = "";
|
|
30
|
-
for (const word of words) {
|
|
31
|
-
// If adding this word would exceed the width
|
|
32
|
-
if (currentLine.length + word.length + 1 > width) {
|
|
33
|
-
// Add the current line to wrapped lines if it's not empty
|
|
34
|
-
if (currentLine) {
|
|
35
|
-
wrappedLines.push(currentLine);
|
|
36
|
-
currentLine = word;
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
// If the current line is empty, it means the word itself is longer than the width
|
|
40
|
-
wrappedLines.push(word);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
// Add the word to the current line
|
|
45
|
-
currentLine = currentLine ? `${currentLine} ${word}` : word;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
// Add the last line if it's not empty
|
|
49
|
-
if (currentLine) {
|
|
50
|
-
wrappedLines.push(currentLine);
|
|
51
|
-
}
|
|
52
|
-
return wrappedLines.join("\n");
|
|
53
|
-
}
|
|
54
|
-
// const ESC = "\u001B[";
|
|
55
7
|
const OSC = "\u001B]";
|
|
56
8
|
const BEL = "\u0007";
|
|
57
9
|
const SEP = ";";
|
|
@@ -61,46 +13,3 @@ export const link = (text, url) => {
|
|
|
61
13
|
}
|
|
62
14
|
return null;
|
|
63
15
|
};
|
|
64
|
-
export const image = (data, options = {}) => {
|
|
65
|
-
let returnValue = `${OSC}1337;File=inline=1`;
|
|
66
|
-
if (options.width) {
|
|
67
|
-
returnValue += `;width=${options.width}`;
|
|
68
|
-
}
|
|
69
|
-
if (options.height) {
|
|
70
|
-
returnValue += `;height=${options.height}`;
|
|
71
|
-
}
|
|
72
|
-
if (options.preserveAspectRatio === false) {
|
|
73
|
-
returnValue += ";preserveAspectRatio=0";
|
|
74
|
-
}
|
|
75
|
-
return `${returnValue}:${Buffer.from(data).toString("base64")}${BEL}`;
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Display a message with emphasis
|
|
79
|
-
*/
|
|
80
|
-
export function emphasize(message) {
|
|
81
|
-
return style.cyan.bold(message);
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Display an informational message
|
|
85
|
-
*/
|
|
86
|
-
export function info(message) {
|
|
87
|
-
return style.blue(`ℹ ${message}`);
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Display a success message
|
|
91
|
-
*/
|
|
92
|
-
export function success(message) {
|
|
93
|
-
return style.green(`✓ ${message}`);
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Display a warning message
|
|
97
|
-
*/
|
|
98
|
-
export function warn(message) {
|
|
99
|
-
return style.yellow(`⚠ ${message}`);
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Display an error message
|
|
103
|
-
*/
|
|
104
|
-
export function error(message) {
|
|
105
|
-
return style.red(`✗ ${message}`);
|
|
106
|
-
}
|
|
@@ -192,42 +192,5 @@ export interface Theme extends Tokens<(codePart: string) => string> {
|
|
|
192
192
|
*/
|
|
193
193
|
default?: (codePart: string) => string;
|
|
194
194
|
}
|
|
195
|
-
/**
|
|
196
|
-
* Stringifies a [[Theme]] with formatter functions to a JSON string.
|
|
197
|
-
*
|
|
198
|
-
* ```ts
|
|
199
|
-
* import style from '../terminal/style.ts';
|
|
200
|
-
* import {stringify} from './highlight/theme.ts';
|
|
201
|
-
* import * as fs from 'node:fs';
|
|
202
|
-
*
|
|
203
|
-
* const myTheme: Theme = {
|
|
204
|
-
* keyword: style.red.bold,
|
|
205
|
-
* addition: style.green,
|
|
206
|
-
* deletion: style.red.strikethrough,
|
|
207
|
-
* number: plain
|
|
208
|
-
* }
|
|
209
|
-
* const json = stringify(myTheme);
|
|
210
|
-
* fs.writeFile('mytheme.json', json, (err: any) => {
|
|
211
|
-
* if (err) throw err;
|
|
212
|
-
* console.log('Theme saved');
|
|
213
|
-
* });
|
|
214
|
-
* ```
|
|
215
|
-
*/
|
|
216
|
-
export declare function stringify(theme: Theme): string;
|
|
217
|
-
/**
|
|
218
|
-
* Parses a JSON string into a [[Theme]] with formatter functions.
|
|
219
|
-
*
|
|
220
|
-
* ```ts
|
|
221
|
-
* import * as fs from 'node:fs';
|
|
222
|
-
* import {parse, highlight} from './highlight/index.ts';
|
|
223
|
-
*
|
|
224
|
-
* fs.readFile('mytheme.json', 'utf-8', (err: any, json: string) => {
|
|
225
|
-
* if (err) throw err;
|
|
226
|
-
* const code = highlight('SELECT * FROM table', {theme: parse(json)});
|
|
227
|
-
* console.log(code);
|
|
228
|
-
* });
|
|
229
|
-
* ```
|
|
230
|
-
*/
|
|
231
|
-
export declare function parse(json: string): Theme;
|
|
232
195
|
export {};
|
|
233
196
|
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../../source/terminal/highlight/theme.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../../source/terminal/highlight/theme.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,UAAU,MAAM,CAAC,CAAC;IAChB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC;IAEZ;;OAEG;IAEH,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEb;;OAEG;IACH,IAAI,CAAC,EAAE,CAAC,CAAC;IAET;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC;IAEZ;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC;IAEX;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC;IAEX;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC;IAEX;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,CAAC;IAEV;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC;IAEX;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,CAAC;IAEV;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEb;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,CAAC;IAEV;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC;IAEX;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC;IAEZ;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC;IAEX;;OAEG;IACH,IAAI,CAAC,EAAE,CAAC,CAAC;IAET;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,CAAC;IAEnB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,CAAC;IAElB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC;IAEZ;;OAEG;IACH,GAAG,CAAC,EAAE,CAAC,CAAC;IAER;;OAEG;IACH,IAAI,CAAC,EAAE,CAAC,CAAC;IAET;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,CAAC;IAEnB;;OAEG;IACH,IAAI,CAAC,EAAE,CAAC,CAAC;IAET;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,CAAC;IAEd;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEb;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC;IAEX;;OAEG;IACH,IAAI,CAAC,EAAE,CAAC,CAAC;IAET;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEb;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC;IAEX;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC;IAEZ;;OAEG;IACH,IAAI,CAAC,EAAE,CAAC,CAAC;IAET;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,CAAC;IAEV;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,CAAC;IAEnB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,CAAC;IAElB;;OAEG;IACH,gBAAgB,CAAC,EAAE,CAAC,CAAC;IAErB;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,CAAC;IAEpB;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,CAAC;IAEtB;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,CAAC;IAEnB;;OAEG;IACH,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAExB;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEb;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,KAAM,SAAQ,MAAM,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;IACjE;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;CACxC"}
|
|
@@ -1,79 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import style from "../style.js";
|
|
3
|
-
/**
|
|
4
|
-
* Converts a [[JsonTheme]] with string values to a [[Theme]] with formatter functions. Used by [[parse]].
|
|
5
|
-
*/
|
|
6
|
-
function fromJson(json) {
|
|
7
|
-
const theme = {};
|
|
8
|
-
for (const key of Object.keys(json)) {
|
|
9
|
-
// biome-ignore lint/suspicious/noExplicitAny: Dynamic theme access needed for highlight compatibility
|
|
10
|
-
const styleValue = json[key];
|
|
11
|
-
if (Array.isArray(styleValue)) {
|
|
12
|
-
// biome-ignore lint/suspicious/noExplicitAny: Dynamic theme access needed for highlight compatibility
|
|
13
|
-
theme[key] = styleValue.reduce((previous, current) =>
|
|
14
|
-
// biome-ignore lint/suspicious/noExplicitAny: Dynamic theme access needed for highlight compatibility
|
|
15
|
-
current === "plain" ? id : previous[current], style);
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
// biome-ignore lint/suspicious/noExplicitAny: Dynamic theme access needed for highlight compatibility
|
|
19
|
-
theme[key] = style[styleValue];
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return theme;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Converts a [[Theme]] with formatter functions to a [[JsonTheme]] with string values. Used by [[stringify]].
|
|
26
|
-
*/
|
|
27
|
-
function toJson(theme) {
|
|
28
|
-
// biome-ignore lint/suspicious/noExplicitAny: Dynamic theme access needed for highlight compatibility
|
|
29
|
-
const jsonTheme = {};
|
|
30
|
-
for (const key of Object.keys(theme)) {
|
|
31
|
-
// biome-ignore lint/suspicious/noExplicitAny: Dynamic theme access needed for highlight compatibility
|
|
32
|
-
const style = theme[key];
|
|
33
|
-
if (style?._styles) {
|
|
34
|
-
jsonTheme[key] = style._styles;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return jsonTheme;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Stringifies a [[Theme]] with formatter functions to a JSON string.
|
|
41
|
-
*
|
|
42
|
-
* ```ts
|
|
43
|
-
* import style from '../terminal/style.ts';
|
|
44
|
-
* import {stringify} from './highlight/theme.ts';
|
|
45
|
-
* import * as fs from 'node:fs';
|
|
46
|
-
*
|
|
47
|
-
* const myTheme: Theme = {
|
|
48
|
-
* keyword: style.red.bold,
|
|
49
|
-
* addition: style.green,
|
|
50
|
-
* deletion: style.red.strikethrough,
|
|
51
|
-
* number: plain
|
|
52
|
-
* }
|
|
53
|
-
* const json = stringify(myTheme);
|
|
54
|
-
* fs.writeFile('mytheme.json', json, (err: any) => {
|
|
55
|
-
* if (err) throw err;
|
|
56
|
-
* console.log('Theme saved');
|
|
57
|
-
* });
|
|
58
|
-
* ```
|
|
59
|
-
*/
|
|
60
|
-
export function stringify(theme) {
|
|
61
|
-
return JSON.stringify(toJson(theme));
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Parses a JSON string into a [[Theme]] with formatter functions.
|
|
65
|
-
*
|
|
66
|
-
* ```ts
|
|
67
|
-
* import * as fs from 'node:fs';
|
|
68
|
-
* import {parse, highlight} from './highlight/index.ts';
|
|
69
|
-
*
|
|
70
|
-
* fs.readFile('mytheme.json', 'utf-8', (err: any, json: string) => {
|
|
71
|
-
* if (err) throw err;
|
|
72
|
-
* const code = highlight('SELECT * FROM table', {theme: parse(json)});
|
|
73
|
-
* console.log(code);
|
|
74
|
-
* });
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export function parse(json) {
|
|
78
|
-
return fromJson(JSON.parse(json));
|
|
79
|
-
}
|
|
1
|
+
export {};
|