claude-alfred 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +283 -0
- package/README.md +283 -0
- package/content/hooks/hooks.json +41 -0
- package/content/mcp/.mcp.json +12 -0
- package/dist/audit-DujZ6YAy.mjs +18 -0
- package/dist/cli.mjs +509 -0
- package/dist/dispatcher-BzOdcjaa.mjs +93 -0
- package/dist/embedder-BshPIMrW.mjs +215 -0
- package/dist/epic-CdRKNGvP.mjs +227 -0
- package/dist/fts-BDdUbNfM.mjs +195 -0
- package/dist/helpers-BsdW4kgn.mjs +94 -0
- package/dist/knowledge-CCCixwb8.mjs +156 -0
- package/dist/post-tool-qemgso2b.mjs +88 -0
- package/dist/postinstall.mjs +49 -0
- package/dist/pre-compact-Cmg9kprV.mjs +181 -0
- package/dist/project-CpgK3fwQ.mjs +79 -0
- package/dist/schema-CcIFwr_0.mjs +289 -0
- package/dist/server-DF7CXxKi.mjs +2635 -0
- package/dist/server-Dsf47Pd4.mjs +19220 -0
- package/dist/session-start-DUYF6E0V.mjs +209 -0
- package/dist/store-Clcihees.mjs +338 -0
- package/dist/types-C3butmI8.mjs +6823 -0
- package/dist/user-prompt-BDeST0mR.mjs +144 -0
- package/dist/vectors-DvuAqDeO.mjs +83 -0
- package/package.json +46 -0
- package/web/dist/assets/activity-UyW12k7Z.js +1 -0
- package/web/dist/assets/api-BI8AW-mC.js +1 -0
- package/web/dist/assets/dist-BHj_gZG8.js +1 -0
- package/web/dist/assets/dist-DDZSXOC-.js +1 -0
- package/web/dist/assets/index-B9C85vN2.js +10 -0
- package/web/dist/assets/index-bIyYMf1a.css +1 -0
- package/web/dist/assets/knowledge-DmvXTX67.js +5 -0
- package/web/dist/assets/link-BSgD_zxQ.js +1 -0
- package/web/dist/assets/matchContext-CO01nzZ3.js +1 -0
- package/web/dist/assets/progress-DBmt_Ww6.js +6 -0
- package/web/dist/assets/routes-zEN1XNFl.js +1 -0
- package/web/dist/assets/scroll-area-DPCDB42s.js +45 -0
- package/web/dist/assets/separator-5sy8HYz5.js +1 -0
- package/web/dist/assets/skeleton-D7GRd6oJ.js +1 -0
- package/web/dist/assets/tabs-VSkG1f0-.js +1 -0
- package/web/dist/assets/tasks-CKNc1U7M.js +1 -0
- package/web/dist/assets/tasks._slug-DPzi78wf.js +8 -0
- package/web/dist/assets/utils-Dw49HYRP.js +1 -0
- package/web/dist/index.html +17 -0
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs } from "node:util";
|
|
3
|
+
//#region node_modules/citty/dist/_chunks/libs/scule.mjs
|
|
4
|
+
const NUMBER_CHAR_RE = /\d/;
|
|
5
|
+
const STR_SPLITTERS = [
|
|
6
|
+
"-",
|
|
7
|
+
"_",
|
|
8
|
+
"/",
|
|
9
|
+
"."
|
|
10
|
+
];
|
|
11
|
+
function isUppercase(char = "") {
|
|
12
|
+
if (NUMBER_CHAR_RE.test(char)) return;
|
|
13
|
+
return char !== char.toLowerCase();
|
|
14
|
+
}
|
|
15
|
+
function splitByCase(str, separators) {
|
|
16
|
+
const splitters = separators ?? STR_SPLITTERS;
|
|
17
|
+
const parts = [];
|
|
18
|
+
if (!str || typeof str !== "string") return parts;
|
|
19
|
+
let buff = "";
|
|
20
|
+
let previousUpper;
|
|
21
|
+
let previousSplitter;
|
|
22
|
+
for (const char of str) {
|
|
23
|
+
const isSplitter = splitters.includes(char);
|
|
24
|
+
if (isSplitter === true) {
|
|
25
|
+
parts.push(buff);
|
|
26
|
+
buff = "";
|
|
27
|
+
previousUpper = void 0;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const isUpper = isUppercase(char);
|
|
31
|
+
if (previousSplitter === false) {
|
|
32
|
+
if (previousUpper === false && isUpper === true) {
|
|
33
|
+
parts.push(buff);
|
|
34
|
+
buff = char;
|
|
35
|
+
previousUpper = isUpper;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (previousUpper === true && isUpper === false && buff.length > 1) {
|
|
39
|
+
const lastChar = buff.at(-1);
|
|
40
|
+
parts.push(buff.slice(0, Math.max(0, buff.length - 1)));
|
|
41
|
+
buff = lastChar + char;
|
|
42
|
+
previousUpper = isUpper;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
buff += char;
|
|
47
|
+
previousUpper = isUpper;
|
|
48
|
+
previousSplitter = isSplitter;
|
|
49
|
+
}
|
|
50
|
+
parts.push(buff);
|
|
51
|
+
return parts;
|
|
52
|
+
}
|
|
53
|
+
function upperFirst(str) {
|
|
54
|
+
return str ? str[0].toUpperCase() + str.slice(1) : "";
|
|
55
|
+
}
|
|
56
|
+
function lowerFirst(str) {
|
|
57
|
+
return str ? str[0].toLowerCase() + str.slice(1) : "";
|
|
58
|
+
}
|
|
59
|
+
function pascalCase(str, opts) {
|
|
60
|
+
return str ? (Array.isArray(str) ? str : splitByCase(str)).map((p) => upperFirst(opts?.normalize ? p.toLowerCase() : p)).join("") : "";
|
|
61
|
+
}
|
|
62
|
+
function camelCase(str, opts) {
|
|
63
|
+
return lowerFirst(pascalCase(str || "", opts));
|
|
64
|
+
}
|
|
65
|
+
function kebabCase(str, joiner) {
|
|
66
|
+
return str ? (Array.isArray(str) ? str : splitByCase(str)).map((p) => p.toLowerCase()).join(joiner ?? "-") : "";
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region node_modules/citty/dist/index.mjs
|
|
70
|
+
function toArray(val) {
|
|
71
|
+
if (Array.isArray(val)) return val;
|
|
72
|
+
return val === void 0 ? [] : [val];
|
|
73
|
+
}
|
|
74
|
+
function formatLineColumns(lines, linePrefix = "") {
|
|
75
|
+
const maxLength = [];
|
|
76
|
+
for (const line of lines) for (const [i, element] of line.entries()) maxLength[i] = Math.max(maxLength[i] || 0, element.length);
|
|
77
|
+
return lines.map((l) => l.map((c, i) => linePrefix + c[i === 0 ? "padStart" : "padEnd"](maxLength[i])).join(" ")).join("\n");
|
|
78
|
+
}
|
|
79
|
+
function resolveValue(input) {
|
|
80
|
+
return typeof input === "function" ? input() : input;
|
|
81
|
+
}
|
|
82
|
+
var CLIError = class extends Error {
|
|
83
|
+
code;
|
|
84
|
+
constructor(message, code) {
|
|
85
|
+
super(message);
|
|
86
|
+
this.name = "CLIError";
|
|
87
|
+
this.code = code;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
function parseRawArgs(args = [], opts = {}) {
|
|
91
|
+
const booleans = new Set(opts.boolean || []);
|
|
92
|
+
const strings = new Set(opts.string || []);
|
|
93
|
+
const aliasMap = opts.alias || {};
|
|
94
|
+
const defaults = opts.default || {};
|
|
95
|
+
const aliasToMain = /* @__PURE__ */ new Map();
|
|
96
|
+
const mainToAliases = /* @__PURE__ */ new Map();
|
|
97
|
+
for (const [key, value] of Object.entries(aliasMap)) {
|
|
98
|
+
const targets = value;
|
|
99
|
+
for (const target of targets) {
|
|
100
|
+
aliasToMain.set(key, target);
|
|
101
|
+
if (!mainToAliases.has(target)) mainToAliases.set(target, []);
|
|
102
|
+
mainToAliases.get(target).push(key);
|
|
103
|
+
aliasToMain.set(target, key);
|
|
104
|
+
if (!mainToAliases.has(key)) mainToAliases.set(key, []);
|
|
105
|
+
mainToAliases.get(key).push(target);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const options = {};
|
|
109
|
+
function getType(name) {
|
|
110
|
+
if (booleans.has(name)) return "boolean";
|
|
111
|
+
const aliases = mainToAliases.get(name) || [];
|
|
112
|
+
for (const alias of aliases) if (booleans.has(alias)) return "boolean";
|
|
113
|
+
return "string";
|
|
114
|
+
}
|
|
115
|
+
const allOptions = new Set([
|
|
116
|
+
...booleans,
|
|
117
|
+
...strings,
|
|
118
|
+
...Object.keys(aliasMap),
|
|
119
|
+
...Object.values(aliasMap).flat(),
|
|
120
|
+
...Object.keys(defaults)
|
|
121
|
+
]);
|
|
122
|
+
for (const name of allOptions) if (!options[name]) options[name] = {
|
|
123
|
+
type: getType(name),
|
|
124
|
+
default: defaults[name]
|
|
125
|
+
};
|
|
126
|
+
for (const [alias, main] of aliasToMain.entries()) if (alias.length === 1 && options[main] && !options[main].short) options[main].short = alias;
|
|
127
|
+
const processedArgs = [];
|
|
128
|
+
const negatedFlags = {};
|
|
129
|
+
for (let i = 0; i < args.length; i++) {
|
|
130
|
+
const arg = args[i];
|
|
131
|
+
if (arg === "--") {
|
|
132
|
+
processedArgs.push(...args.slice(i));
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
if (arg.startsWith("--no-")) {
|
|
136
|
+
const flagName = arg.slice(5);
|
|
137
|
+
negatedFlags[flagName] = true;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
processedArgs.push(arg);
|
|
141
|
+
}
|
|
142
|
+
let parsed;
|
|
143
|
+
try {
|
|
144
|
+
parsed = parseArgs({
|
|
145
|
+
args: processedArgs,
|
|
146
|
+
options: Object.keys(options).length > 0 ? options : void 0,
|
|
147
|
+
allowPositionals: true,
|
|
148
|
+
strict: false
|
|
149
|
+
});
|
|
150
|
+
} catch {
|
|
151
|
+
parsed = {
|
|
152
|
+
values: {},
|
|
153
|
+
positionals: processedArgs
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
const out = { _: [] };
|
|
157
|
+
out._ = parsed.positionals;
|
|
158
|
+
for (const [key, value] of Object.entries(parsed.values)) out[key] = value;
|
|
159
|
+
for (const [name] of Object.entries(negatedFlags)) {
|
|
160
|
+
out[name] = false;
|
|
161
|
+
const mainName = aliasToMain.get(name);
|
|
162
|
+
if (mainName) out[mainName] = false;
|
|
163
|
+
const aliases = mainToAliases.get(name);
|
|
164
|
+
if (aliases) for (const alias of aliases) out[alias] = false;
|
|
165
|
+
}
|
|
166
|
+
for (const [alias, main] of aliasToMain.entries()) {
|
|
167
|
+
if (out[alias] !== void 0 && out[main] === void 0) out[main] = out[alias];
|
|
168
|
+
if (out[main] !== void 0 && out[alias] === void 0) out[alias] = out[main];
|
|
169
|
+
}
|
|
170
|
+
return out;
|
|
171
|
+
}
|
|
172
|
+
const noColor = /* @__PURE__ */ (() => {
|
|
173
|
+
const env = globalThis.process?.env ?? {};
|
|
174
|
+
return env.NO_COLOR === "1" || env.TERM === "dumb" || env.TEST || env.CI;
|
|
175
|
+
})();
|
|
176
|
+
const _c = (c, r = 39) => (t) => noColor ? t : `\u001B[${c}m${t}\u001B[${r}m`;
|
|
177
|
+
const bold = /* @__PURE__ */ _c(1, 22);
|
|
178
|
+
const cyan = /* @__PURE__ */ _c(36);
|
|
179
|
+
const gray = /* @__PURE__ */ _c(90);
|
|
180
|
+
const underline = /* @__PURE__ */ _c(4, 24);
|
|
181
|
+
function parseArgs$1(rawArgs, argsDef) {
|
|
182
|
+
const parseOptions = {
|
|
183
|
+
boolean: [],
|
|
184
|
+
string: [],
|
|
185
|
+
alias: {},
|
|
186
|
+
default: {}
|
|
187
|
+
};
|
|
188
|
+
const args = resolveArgs(argsDef);
|
|
189
|
+
for (const arg of args) {
|
|
190
|
+
if (arg.type === "positional") continue;
|
|
191
|
+
if (arg.type === "string" || arg.type === "enum") parseOptions.string.push(arg.name);
|
|
192
|
+
else if (arg.type === "boolean") parseOptions.boolean.push(arg.name);
|
|
193
|
+
if (arg.default !== void 0) parseOptions.default[arg.name] = arg.default;
|
|
194
|
+
if (arg.alias) parseOptions.alias[arg.name] = arg.alias;
|
|
195
|
+
const camelName = camelCase(arg.name);
|
|
196
|
+
const kebabName = kebabCase(arg.name);
|
|
197
|
+
if (camelName !== arg.name || kebabName !== arg.name) {
|
|
198
|
+
const existingAliases = toArray(parseOptions.alias[arg.name] || []);
|
|
199
|
+
if (camelName !== arg.name && !existingAliases.includes(camelName)) existingAliases.push(camelName);
|
|
200
|
+
if (kebabName !== arg.name && !existingAliases.includes(kebabName)) existingAliases.push(kebabName);
|
|
201
|
+
if (existingAliases.length > 0) parseOptions.alias[arg.name] = existingAliases;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const parsed = parseRawArgs(rawArgs, parseOptions);
|
|
205
|
+
const [ ...positionalArguments] = parsed._;
|
|
206
|
+
const parsedArgsProxy = new Proxy(parsed, { get(target, prop) {
|
|
207
|
+
return target[prop] ?? target[camelCase(prop)] ?? target[kebabCase(prop)];
|
|
208
|
+
} });
|
|
209
|
+
for (const [, arg] of args.entries()) if (arg.type === "positional") {
|
|
210
|
+
const nextPositionalArgument = positionalArguments.shift();
|
|
211
|
+
if (nextPositionalArgument !== void 0) parsedArgsProxy[arg.name] = nextPositionalArgument;
|
|
212
|
+
else if (arg.default === void 0 && arg.required !== false) throw new CLIError(`Missing required positional argument: ${arg.name.toUpperCase()}`, "EARG");
|
|
213
|
+
else parsedArgsProxy[arg.name] = arg.default;
|
|
214
|
+
} else if (arg.type === "enum") {
|
|
215
|
+
const argument = parsedArgsProxy[arg.name];
|
|
216
|
+
const options = arg.options || [];
|
|
217
|
+
if (argument !== void 0 && options.length > 0 && !options.includes(argument)) throw new CLIError(`Invalid value for argument: ${cyan(`--${arg.name}`)} (${cyan(argument)}). Expected one of: ${options.map((o) => cyan(o)).join(", ")}.`, "EARG");
|
|
218
|
+
} else if (arg.required && parsedArgsProxy[arg.name] === void 0) throw new CLIError(`Missing required argument: --${arg.name}`, "EARG");
|
|
219
|
+
return parsedArgsProxy;
|
|
220
|
+
}
|
|
221
|
+
function resolveArgs(argsDef) {
|
|
222
|
+
const args = [];
|
|
223
|
+
for (const [name, argDef] of Object.entries(argsDef || {})) args.push({
|
|
224
|
+
...argDef,
|
|
225
|
+
name,
|
|
226
|
+
alias: toArray(argDef.alias)
|
|
227
|
+
});
|
|
228
|
+
return args;
|
|
229
|
+
}
|
|
230
|
+
function defineCommand(def) {
|
|
231
|
+
return def;
|
|
232
|
+
}
|
|
233
|
+
async function runCommand(cmd, opts) {
|
|
234
|
+
const cmdArgs = await resolveValue(cmd.args || {});
|
|
235
|
+
const parsedArgs = parseArgs$1(opts.rawArgs, cmdArgs);
|
|
236
|
+
const context = {
|
|
237
|
+
rawArgs: opts.rawArgs,
|
|
238
|
+
args: parsedArgs,
|
|
239
|
+
data: opts.data,
|
|
240
|
+
cmd
|
|
241
|
+
};
|
|
242
|
+
if (typeof cmd.setup === "function") await cmd.setup(context);
|
|
243
|
+
let result;
|
|
244
|
+
try {
|
|
245
|
+
const subCommands = await resolveValue(cmd.subCommands);
|
|
246
|
+
if (subCommands && Object.keys(subCommands).length > 0) {
|
|
247
|
+
const subCommandArgIndex = opts.rawArgs.findIndex((arg) => !arg.startsWith("-"));
|
|
248
|
+
const subCommandName = opts.rawArgs[subCommandArgIndex];
|
|
249
|
+
if (subCommandName) {
|
|
250
|
+
if (!subCommands[subCommandName]) throw new CLIError(`Unknown command ${cyan(subCommandName)}`, "E_UNKNOWN_COMMAND");
|
|
251
|
+
const subCommand = await resolveValue(subCommands[subCommandName]);
|
|
252
|
+
if (subCommand) await runCommand(subCommand, { rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1) });
|
|
253
|
+
} else if (!cmd.run) throw new CLIError(`No command specified.`, "E_NO_COMMAND");
|
|
254
|
+
}
|
|
255
|
+
if (typeof cmd.run === "function") result = await cmd.run(context);
|
|
256
|
+
} finally {
|
|
257
|
+
if (typeof cmd.cleanup === "function") await cmd.cleanup(context);
|
|
258
|
+
}
|
|
259
|
+
return { result };
|
|
260
|
+
}
|
|
261
|
+
async function resolveSubCommand(cmd, rawArgs, parent) {
|
|
262
|
+
const subCommands = await resolveValue(cmd.subCommands);
|
|
263
|
+
if (subCommands && Object.keys(subCommands).length > 0) {
|
|
264
|
+
const subCommandArgIndex = rawArgs.findIndex((arg) => !arg.startsWith("-"));
|
|
265
|
+
const subCommandName = rawArgs[subCommandArgIndex];
|
|
266
|
+
const subCommand = await resolveValue(subCommands[subCommandName]);
|
|
267
|
+
if (subCommand) return resolveSubCommand(subCommand, rawArgs.slice(subCommandArgIndex + 1), cmd);
|
|
268
|
+
}
|
|
269
|
+
return [cmd, parent];
|
|
270
|
+
}
|
|
271
|
+
async function showUsage(cmd, parent) {
|
|
272
|
+
try {
|
|
273
|
+
console.log(await renderUsage(cmd, parent) + "\n");
|
|
274
|
+
} catch (error) {
|
|
275
|
+
console.error(error);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const negativePrefixRe = /^no[-A-Z]/;
|
|
279
|
+
async function renderUsage(cmd, parent) {
|
|
280
|
+
const cmdMeta = await resolveValue(cmd.meta || {});
|
|
281
|
+
const cmdArgs = resolveArgs(await resolveValue(cmd.args || {}));
|
|
282
|
+
const parentMeta = await resolveValue(parent?.meta || {});
|
|
283
|
+
const commandName = `${parentMeta.name ? `${parentMeta.name} ` : ""}` + (cmdMeta.name || process.argv[1]);
|
|
284
|
+
const argLines = [];
|
|
285
|
+
const posLines = [];
|
|
286
|
+
const commandsLines = [];
|
|
287
|
+
const usageLine = [];
|
|
288
|
+
for (const arg of cmdArgs) if (arg.type === "positional") {
|
|
289
|
+
const name = arg.name.toUpperCase();
|
|
290
|
+
const isRequired = arg.required !== false && arg.default === void 0;
|
|
291
|
+
const defaultHint = arg.default ? `="${arg.default}"` : "";
|
|
292
|
+
posLines.push([
|
|
293
|
+
cyan(name + defaultHint),
|
|
294
|
+
arg.description || "",
|
|
295
|
+
arg.valueHint ? `<${arg.valueHint}>` : ""
|
|
296
|
+
]);
|
|
297
|
+
usageLine.push(isRequired ? `<${name}>` : `[${name}]`);
|
|
298
|
+
} else {
|
|
299
|
+
const isRequired = arg.required === true && arg.default === void 0;
|
|
300
|
+
const argStr = [...(arg.alias || []).map((a) => `-${a}`), `--${arg.name}`].join(", ") + (arg.type === "string" && (arg.valueHint || arg.default) ? `=${arg.valueHint ? `<${arg.valueHint}>` : `"${arg.default || ""}"`}` : "") + (arg.type === "enum" && arg.options ? `=<${arg.options.join("|")}>` : "");
|
|
301
|
+
argLines.push([cyan(argStr + (isRequired ? " (required)" : "")), arg.description || ""]);
|
|
302
|
+
if (arg.type === "boolean" && (arg.default === true || arg.negativeDescription) && !negativePrefixRe.test(arg.name)) {
|
|
303
|
+
const negativeArgStr = [...(arg.alias || []).map((a) => `--no-${a}`), `--no-${arg.name}`].join(", ");
|
|
304
|
+
argLines.push([cyan(negativeArgStr + (isRequired ? " (required)" : "")), arg.negativeDescription || ""]);
|
|
305
|
+
}
|
|
306
|
+
if (isRequired) usageLine.push(argStr);
|
|
307
|
+
}
|
|
308
|
+
if (cmd.subCommands) {
|
|
309
|
+
const commandNames = [];
|
|
310
|
+
const subCommands = await resolveValue(cmd.subCommands);
|
|
311
|
+
for (const [name, sub] of Object.entries(subCommands)) {
|
|
312
|
+
const meta = await resolveValue((await resolveValue(sub))?.meta);
|
|
313
|
+
if (meta?.hidden) continue;
|
|
314
|
+
commandsLines.push([cyan(name), meta?.description || ""]);
|
|
315
|
+
commandNames.push(name);
|
|
316
|
+
}
|
|
317
|
+
usageLine.push(commandNames.join("|"));
|
|
318
|
+
}
|
|
319
|
+
const usageLines = [];
|
|
320
|
+
const version = cmdMeta.version || parentMeta.version;
|
|
321
|
+
usageLines.push(gray(`${cmdMeta.description} (${commandName + (version ? ` v${version}` : "")})`), "");
|
|
322
|
+
const hasOptions = argLines.length > 0 || posLines.length > 0;
|
|
323
|
+
usageLines.push(`${underline(bold("USAGE"))} ${cyan(`${commandName}${hasOptions ? " [OPTIONS]" : ""} ${usageLine.join(" ")}`)}`, "");
|
|
324
|
+
if (posLines.length > 0) {
|
|
325
|
+
usageLines.push(underline(bold("ARGUMENTS")), "");
|
|
326
|
+
usageLines.push(formatLineColumns(posLines, " "));
|
|
327
|
+
usageLines.push("");
|
|
328
|
+
}
|
|
329
|
+
if (argLines.length > 0) {
|
|
330
|
+
usageLines.push(underline(bold("OPTIONS")), "");
|
|
331
|
+
usageLines.push(formatLineColumns(argLines, " "));
|
|
332
|
+
usageLines.push("");
|
|
333
|
+
}
|
|
334
|
+
if (commandsLines.length > 0) {
|
|
335
|
+
usageLines.push(underline(bold("COMMANDS")), "");
|
|
336
|
+
usageLines.push(formatLineColumns(commandsLines, " "));
|
|
337
|
+
usageLines.push("", `Use ${cyan(`${commandName} <command> --help`)} for more information about a command.`);
|
|
338
|
+
}
|
|
339
|
+
return usageLines.filter((l) => typeof l === "string").join("\n");
|
|
340
|
+
}
|
|
341
|
+
async function runMain(cmd, opts = {}) {
|
|
342
|
+
const rawArgs = opts.rawArgs || process.argv.slice(2);
|
|
343
|
+
const showUsage$1 = opts.showUsage || showUsage;
|
|
344
|
+
try {
|
|
345
|
+
if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
|
|
346
|
+
await showUsage$1(...await resolveSubCommand(cmd, rawArgs));
|
|
347
|
+
process.exit(0);
|
|
348
|
+
} else if (rawArgs.length === 1 && rawArgs[0] === "--version") {
|
|
349
|
+
const meta = typeof cmd.meta === "function" ? await cmd.meta() : await cmd.meta;
|
|
350
|
+
if (!meta?.version) throw new CLIError("No version specified", "E_NO_VERSION");
|
|
351
|
+
console.log(meta.version);
|
|
352
|
+
} else await runCommand(cmd, { rawArgs });
|
|
353
|
+
} catch (error) {
|
|
354
|
+
if (error instanceof CLIError) {
|
|
355
|
+
await showUsage$1(...await resolveSubCommand(cmd, rawArgs));
|
|
356
|
+
console.error(error.message);
|
|
357
|
+
} else console.error(error, "\n");
|
|
358
|
+
process.exit(1);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
//#endregion
|
|
362
|
+
//#region src/cli.ts
|
|
363
|
+
const main = defineCommand({
|
|
364
|
+
meta: {
|
|
365
|
+
name: "alfred",
|
|
366
|
+
description: "Development butler for Claude Code"
|
|
367
|
+
},
|
|
368
|
+
subCommands: {
|
|
369
|
+
serve: defineCommand({
|
|
370
|
+
meta: { description: "Start MCP server (stdio)" },
|
|
371
|
+
async run() {
|
|
372
|
+
const { Store } = await import("./store-Clcihees.mjs");
|
|
373
|
+
const { Embedder } = await import("./embedder-BshPIMrW.mjs");
|
|
374
|
+
const { serveMCP } = await import("./server-Dsf47Pd4.mjs");
|
|
375
|
+
const store = Store.openDefault();
|
|
376
|
+
let emb = null;
|
|
377
|
+
try {
|
|
378
|
+
emb = Embedder.create();
|
|
379
|
+
} catch {}
|
|
380
|
+
if (emb) store.expectedDims = emb.dims;
|
|
381
|
+
const version = await resolveVersion();
|
|
382
|
+
await serveMCP(store, emb, version);
|
|
383
|
+
}
|
|
384
|
+
}),
|
|
385
|
+
dashboard: defineCommand({
|
|
386
|
+
meta: { description: "Open browser dashboard" },
|
|
387
|
+
args: {
|
|
388
|
+
port: {
|
|
389
|
+
type: "string",
|
|
390
|
+
default: "7575",
|
|
391
|
+
description: "Port number"
|
|
392
|
+
},
|
|
393
|
+
"url-only": {
|
|
394
|
+
type: "boolean",
|
|
395
|
+
default: false,
|
|
396
|
+
description: "Print URL only"
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
async run({ args }) {
|
|
400
|
+
const { Store } = await import("./store-Clcihees.mjs");
|
|
401
|
+
const { Embedder } = await import("./embedder-BshPIMrW.mjs");
|
|
402
|
+
const { startDashboard } = await import("./server-DF7CXxKi.mjs");
|
|
403
|
+
const projectPath = process.cwd();
|
|
404
|
+
const store = Store.openDefault();
|
|
405
|
+
let emb = null;
|
|
406
|
+
try {
|
|
407
|
+
emb = Embedder.create();
|
|
408
|
+
} catch {}
|
|
409
|
+
if (emb) store.expectedDims = emb.dims;
|
|
410
|
+
const version = await resolveVersion();
|
|
411
|
+
await startDashboard(projectPath, store, emb, {
|
|
412
|
+
port: parseInt(args.port, 10),
|
|
413
|
+
urlOnly: args["url-only"],
|
|
414
|
+
version
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
}),
|
|
418
|
+
hook: defineCommand({
|
|
419
|
+
meta: { description: "Handle hook event" },
|
|
420
|
+
args: { event: {
|
|
421
|
+
type: "positional",
|
|
422
|
+
description: "Event name"
|
|
423
|
+
} },
|
|
424
|
+
async run({ args }) {
|
|
425
|
+
const { runHook } = await import("./dispatcher-BzOdcjaa.mjs");
|
|
426
|
+
await runHook(args.event);
|
|
427
|
+
}
|
|
428
|
+
}),
|
|
429
|
+
"plugin-bundle": defineCommand({
|
|
430
|
+
meta: { description: "Generate plugin bundle" },
|
|
431
|
+
args: { output: {
|
|
432
|
+
type: "positional",
|
|
433
|
+
description: "Output directory",
|
|
434
|
+
default: "plugin"
|
|
435
|
+
} },
|
|
436
|
+
async run({ args }) {
|
|
437
|
+
console.log(`plugin-bundle: output=${args.output} (not yet implemented)`);
|
|
438
|
+
}
|
|
439
|
+
}),
|
|
440
|
+
doctor: defineCommand({
|
|
441
|
+
meta: { description: "Check installation health" },
|
|
442
|
+
async run() {
|
|
443
|
+
const { existsSync, readdirSync } = await import("node:fs");
|
|
444
|
+
const { join } = await import("node:path");
|
|
445
|
+
const { homedir } = await import("node:os");
|
|
446
|
+
const home = homedir();
|
|
447
|
+
const version = await resolveVersion();
|
|
448
|
+
console.log(`alfred doctor (v${version})\n`);
|
|
449
|
+
const nodeVer = process.version;
|
|
450
|
+
check(parseInt(nodeVer.slice(1), 10) >= 22, `Node.js ${nodeVer}`, ">=22 required");
|
|
451
|
+
try {
|
|
452
|
+
await import("better-sqlite3");
|
|
453
|
+
check(true, "better-sqlite3 loaded");
|
|
454
|
+
} catch {
|
|
455
|
+
check(false, "better-sqlite3", "not found — run npm rebuild");
|
|
456
|
+
}
|
|
457
|
+
const dbPath = join(home, ".claude-alfred", "alfred.db");
|
|
458
|
+
check(existsSync(dbPath), `DB: ${dbPath}`, "not found — run: alfred (any command) to create");
|
|
459
|
+
check(!!process.env["VOYAGE_API_KEY"], "VOYAGE_API_KEY set", "not set — semantic search disabled, FTS5 fallback active");
|
|
460
|
+
const lang = process.env["ALFRED_LANG"];
|
|
461
|
+
check(true, `ALFRED_LANG: ${lang || "(not set, default: en)"}`);
|
|
462
|
+
const rulesDir = join(home, ".claude", "rules");
|
|
463
|
+
try {
|
|
464
|
+
const rules = readdirSync(rulesDir).filter((f) => f.startsWith("alfred"));
|
|
465
|
+
check(rules.length > 0, `Rules: ${rulesDir} (${rules.length} alfred files)`, "no alfred rules found");
|
|
466
|
+
} catch {
|
|
467
|
+
check(false, "Rules", `${rulesDir} not found`);
|
|
468
|
+
}
|
|
469
|
+
const cwd = process.cwd();
|
|
470
|
+
check(existsSync(join(cwd, ".alfred")), `Project: .alfred/ exists in ${cwd}`, "not initialized — run /alfred:init in Claude Code");
|
|
471
|
+
}
|
|
472
|
+
}),
|
|
473
|
+
version: defineCommand({
|
|
474
|
+
meta: { description: "Show version" },
|
|
475
|
+
args: { short: {
|
|
476
|
+
type: "boolean",
|
|
477
|
+
default: false,
|
|
478
|
+
description: "Version only"
|
|
479
|
+
} },
|
|
480
|
+
async run({ args }) {
|
|
481
|
+
const version = await resolveVersion();
|
|
482
|
+
if (args.short) console.log(version);
|
|
483
|
+
else console.log(`alfred ${version}`);
|
|
484
|
+
}
|
|
485
|
+
})
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
function check(ok, label, hint) {
|
|
489
|
+
if (ok) console.log(` ✓ ${label}`);
|
|
490
|
+
else console.log(` ✗ ${label}${hint ? ` — ${hint}` : ""}`);
|
|
491
|
+
}
|
|
492
|
+
async function resolveVersion() {
|
|
493
|
+
try {
|
|
494
|
+
const { readFileSync } = await import("node:fs");
|
|
495
|
+
const { join } = await import("node:path");
|
|
496
|
+
const { fileURLToPath } = await import("node:url");
|
|
497
|
+
const thisDir = fileURLToPath(new URL(".", import.meta.url));
|
|
498
|
+
for (const rel of ["..", "../.."]) try {
|
|
499
|
+
const pkg = JSON.parse(readFileSync(join(thisDir, rel, "package.json"), "utf-8"));
|
|
500
|
+
if (pkg.version) return pkg.version;
|
|
501
|
+
} catch {
|
|
502
|
+
continue;
|
|
503
|
+
}
|
|
504
|
+
} catch {}
|
|
505
|
+
return "dev";
|
|
506
|
+
}
|
|
507
|
+
runMain(main);
|
|
508
|
+
//#endregion
|
|
509
|
+
export {};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
//#region src/hooks/dispatcher.ts
|
|
4
|
+
function notifyUser(format, ...args) {
|
|
5
|
+
let i = 0;
|
|
6
|
+
const msg = format.replace(/%[svd]/g, () => i < args.length ? String(args[i++]) : "");
|
|
7
|
+
process.stderr.write(`[alfred] ${msg}\n`);
|
|
8
|
+
}
|
|
9
|
+
function emitAdditionalContext(eventName, context) {
|
|
10
|
+
const out = { hookSpecificOutput: {
|
|
11
|
+
hookEventName: eventName,
|
|
12
|
+
additionalContext: context
|
|
13
|
+
} };
|
|
14
|
+
try {
|
|
15
|
+
process.stdout.write(JSON.stringify(out) + "\n");
|
|
16
|
+
} catch {}
|
|
17
|
+
}
|
|
18
|
+
function extractSection(content, heading) {
|
|
19
|
+
const lines = content.split("\n");
|
|
20
|
+
const result = [];
|
|
21
|
+
let inSection = false;
|
|
22
|
+
for (const line of lines) {
|
|
23
|
+
if (line === heading || line.startsWith(heading + " ")) {
|
|
24
|
+
inSection = true;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (inSection && line.startsWith("## ")) break;
|
|
28
|
+
if (inSection) result.push(line);
|
|
29
|
+
}
|
|
30
|
+
return result.join("\n").trim();
|
|
31
|
+
}
|
|
32
|
+
async function runHook(event) {
|
|
33
|
+
const chunks = [];
|
|
34
|
+
let totalLen = 0;
|
|
35
|
+
for await (const chunk of process.stdin) {
|
|
36
|
+
chunks.push(chunk);
|
|
37
|
+
totalLen += chunk.length;
|
|
38
|
+
if (totalLen > 2 * 1024 * 1024) break;
|
|
39
|
+
}
|
|
40
|
+
const input = Buffer.concat(chunks).toString("utf-8");
|
|
41
|
+
let ev;
|
|
42
|
+
try {
|
|
43
|
+
ev = JSON.parse(input);
|
|
44
|
+
} catch {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (ev.stop_hook_active) return;
|
|
48
|
+
if (ev.cwd) ev.cwd = resolve(ev.cwd);
|
|
49
|
+
const timeout = {
|
|
50
|
+
SessionStart: 4500,
|
|
51
|
+
PreCompact: 9e3,
|
|
52
|
+
UserPromptSubmit: 9e3,
|
|
53
|
+
PostToolUse: 5e3
|
|
54
|
+
}[event] ?? 5e3;
|
|
55
|
+
const controller = new AbortController();
|
|
56
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
57
|
+
try {
|
|
58
|
+
switch (event) {
|
|
59
|
+
case "SessionStart":
|
|
60
|
+
await handleSessionStart(ev, controller.signal);
|
|
61
|
+
break;
|
|
62
|
+
case "PreCompact":
|
|
63
|
+
if (ev.cwd) await handlePreCompact(ev, controller.signal);
|
|
64
|
+
break;
|
|
65
|
+
case "UserPromptSubmit":
|
|
66
|
+
await handleUserPromptSubmit(ev, controller.signal);
|
|
67
|
+
break;
|
|
68
|
+
case "PostToolUse":
|
|
69
|
+
await handlePostToolUse(ev, controller.signal);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
} finally {
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function handleSessionStart(ev, signal) {
|
|
77
|
+
const { sessionStart } = await import("./session-start-DUYF6E0V.mjs");
|
|
78
|
+
await sessionStart(ev, signal);
|
|
79
|
+
}
|
|
80
|
+
async function handlePreCompact(ev, signal) {
|
|
81
|
+
const { preCompact } = await import("./pre-compact-Cmg9kprV.mjs");
|
|
82
|
+
await preCompact(ev, signal);
|
|
83
|
+
}
|
|
84
|
+
async function handleUserPromptSubmit(ev, signal) {
|
|
85
|
+
const { userPromptSubmit } = await import("./user-prompt-BDeST0mR.mjs");
|
|
86
|
+
await userPromptSubmit(ev, signal);
|
|
87
|
+
}
|
|
88
|
+
async function handlePostToolUse(ev, signal) {
|
|
89
|
+
const { postToolUse } = await import("./post-tool-qemgso2b.mjs");
|
|
90
|
+
await postToolUse(ev, signal);
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
93
|
+
export { emitAdditionalContext, extractSection, notifyUser, runHook };
|